<!DOCTYPE html>
<html>

<head>

<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<title>A proposal for modular macros</title>


<style type="text/css">
body {
  font-family: Helvetica, arial, sans-serif;
  font-size: 14px;
  line-height: 1.6;
  padding-top: 10px;
  padding-bottom: 10px;
  background-color: white;
  padding: 30px; }

body > *:first-child {
  margin-top: 0 !important; }
body > *:last-child {
  margin-bottom: 0 !important; }

a {
  color: #4183C4; }
a.absent {
  color: #cc0000; }
a.anchor {
  display: block;
  padding-left: 30px;
  margin-left: -30px;
  cursor: pointer;
  position: absolute;
  top: 0;
  left: 0;
  bottom: 0; }

h1, h2, h3, h4, h5, h6 {
  margin: 20px 0 10px;
  padding: 0;
  font-weight: bold;
  -webkit-font-smoothing: antialiased;
  cursor: text;
  position: relative; }

h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, h5:hover a.anchor, h6:hover a.anchor {
  background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA09pVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoMTMuMCAyMDEyMDMwNS5tLjQxNSAyMDEyLzAzLzA1OjIxOjAwOjAwKSAgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OUM2NjlDQjI4ODBGMTFFMTg1ODlEODNERDJBRjUwQTQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OUM2NjlDQjM4ODBGMTFFMTg1ODlEODNERDJBRjUwQTQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo5QzY2OUNCMDg4MEYxMUUxODU4OUQ4M0REMkFGNTBBNCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo5QzY2OUNCMTg4MEYxMUUxODU4OUQ4M0REMkFGNTBBNCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PsQhXeAAAABfSURBVHjaYvz//z8DJYCRUgMYQAbAMBQIAvEqkBQWXI6sHqwHiwG70TTBxGaiWwjCTGgOUgJiF1J8wMRAIUA34B4Q76HUBelAfJYSA0CuMIEaRP8wGIkGMA54bgQIMACAmkXJi0hKJQAAAABJRU5ErkJggg==) no-repeat 10px center;
  text-decoration: none; }

h1 tt, h1 code {
  font-size: inherit; }

h2 tt, h2 code {
  font-size: inherit; }

h3 tt, h3 code {
  font-size: inherit; }

h4 tt, h4 code {
  font-size: inherit; }

h5 tt, h5 code {
  font-size: inherit; }

h6 tt, h6 code {
  font-size: inherit; }

h1 {
  font-size: 28px;
  color: black; }

h2 {
  font-size: 24px;
  border-bottom: 1px solid #cccccc;
  color: black; }

h3 {
  font-size: 18px; }

h4 {
  font-size: 16px; }

h5 {
  font-size: 14px; }

h6 {
  color: #777777;
  font-size: 14px; }

p, blockquote, ul, ol, dl, li, table, pre {
  margin: 15px 0; }

hr {
  background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAECAYAAACtBE5DAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OENDRjNBN0E2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OENDRjNBN0I2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4Q0NGM0E3ODY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4Q0NGM0E3OTY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PqqezsUAAAAfSURBVHjaYmRABcYwBiM2QSA4y4hNEKYDQxAEAAIMAHNGAzhkPOlYAAAAAElFTkSuQmCC) repeat-x 0 0;
  border: 0 none;
  color: #cccccc;
  height: 4px;
  padding: 0;
}

body > h2:first-child {
  margin-top: 0;
  padding-top: 0; }
body > h1:first-child {
  margin-top: 0;
  padding-top: 0; }
  body > h1:first-child + h2 {
    margin-top: 0;
    padding-top: 0; }
body > h3:first-child, body > h4:first-child, body > h5:first-child, body > h6:first-child {
  margin-top: 0;
  padding-top: 0; }

a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 {
  margin-top: 0;
  padding-top: 0; }

h1 p, h2 p, h3 p, h4 p, h5 p, h6 p {
  margin-top: 0; }

li p.first {
  display: inline-block; }
li {
  margin: 0; }
ul, ol {
  padding-left: 30px; }

ul :first-child, ol :first-child {
  margin-top: 0; }

dl {
  padding: 0; }
  dl dt {
    font-size: 14px;
    font-weight: bold;
    font-style: italic;
    padding: 0;
    margin: 15px 0 5px; }
    dl dt:first-child {
      padding: 0; }
    dl dt > :first-child {
      margin-top: 0; }
    dl dt > :last-child {
      margin-bottom: 0; }
  dl dd {
    margin: 0 0 15px;
    padding: 0 15px; }
    dl dd > :first-child {
      margin-top: 0; }
    dl dd > :last-child {
      margin-bottom: 0; }

blockquote {
  border-left: 4px solid #dddddd;
  padding: 0 15px;
  color: #777777; }
  blockquote > :first-child {
    margin-top: 0; }
  blockquote > :last-child {
    margin-bottom: 0; }

table {
  padding: 0;border-collapse: collapse; }
  table tr {
    border-top: 1px solid #cccccc;
    background-color: white;
    margin: 0;
    padding: 0; }
    table tr:nth-child(2n) {
      background-color: #f8f8f8; }
    table tr th {
      font-weight: bold;
      border: 1px solid #cccccc;
      margin: 0;
      padding: 6px 13px; }
    table tr td {
      border: 1px solid #cccccc;
      margin: 0;
      padding: 6px 13px; }
    table tr th :first-child, table tr td :first-child {
      margin-top: 0; }
    table tr th :last-child, table tr td :last-child {
      margin-bottom: 0; }

img {
  max-width: 100%; }

span.frame {
  display: block;
  overflow: hidden; }
  span.frame > span {
    border: 1px solid #dddddd;
    display: block;
    float: left;
    overflow: hidden;
    margin: 13px 0 0;
    padding: 7px;
    width: auto; }
  span.frame span img {
    display: block;
    float: left; }
  span.frame span span {
    clear: both;
    color: #333333;
    display: block;
    padding: 5px 0 0; }
span.align-center {
  display: block;
  overflow: hidden;
  clear: both; }
  span.align-center > span {
    display: block;
    overflow: hidden;
    margin: 13px auto 0;
    text-align: center; }
  span.align-center span img {
    margin: 0 auto;
    text-align: center; }
span.align-right {
  display: block;
  overflow: hidden;
  clear: both; }
  span.align-right > span {
    display: block;
    overflow: hidden;
    margin: 13px 0 0;
    text-align: right; }
  span.align-right span img {
    margin: 0;
    text-align: right; }
span.float-left {
  display: block;
  margin-right: 13px;
  overflow: hidden;
  float: left; }
  span.float-left span {
    margin: 13px 0 0; }
span.float-right {
  display: block;
  margin-left: 13px;
  overflow: hidden;
  float: right; }
  span.float-right > span {
    display: block;
    overflow: hidden;
    margin: 13px auto 0;
    text-align: right; }

code, tt {
  margin: 0 2px;
  padding: 0 5px;
  white-space: nowrap;
  border: 1px solid #eaeaea;
  background-color: #f8f8f8;
  border-radius: 3px; }

pre code {
  margin: 0;
  padding: 0;
  white-space: pre;
  border: none;
  background: transparent; }

.highlight pre {
  background-color: #f8f8f8;
  border: 1px solid #cccccc;
  font-size: 13px;
  line-height: 19px;
  overflow: auto;
  padding: 6px 10px;
  border-radius: 3px; }

pre {
  background-color: #f8f8f8;
  border: 1px solid #cccccc;
  font-size: 13px;
  line-height: 19px;
  overflow: auto;
  padding: 6px 10px;
  border-radius: 3px; }
  pre code, pre tt {
    background-color: transparent;
    border: none; }

sup {
    font-size: 0.83em;
    vertical-align: super;
    line-height: 0;
}

kbd {
  display: inline-block;
  padding: 3px 5px;
  font-size: 11px;
  line-height: 10px;
  color: #555;
  vertical-align: middle;
  background-color: #fcfcfc;
  border: solid 1px #ccc;
  border-bottom-color: #bbb;
  border-radius: 3px;
  box-shadow: inset 0 -1px 0 #bbb
}

* {
	-webkit-print-color-adjust: exact;
}
@media screen and (min-width: 914px) {
    body {
        width: 854px;
        margin:0 auto;
    }
}
@media print {
	table, pre {
		page-break-inside: avoid;
	}
	pre {
		word-wrap: break-word;
	}
}
</style>


</head>

<body>

<h1 id="toc_0">A proposal for modular macros</h1>

<p><em>Document number: P0877R0</em>
</br>
<em>Audience: EWG</em>
</br>
<em>Author: <a href="mailto:blopes@apple.com">Bruno Cardoso Lopes</a></em>
</br>
<em>11 February 2018</em></p>

<hr>

<h2 id="toc_1">Motivation &amp; Background</h2>

<p>An overall description of Apple&#39;s software ecosystem and its association with modules was discussed in Albuquerque&#39;s paper <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0841r0.html">P0841R0</a>.</p>

<p>This paper continues that discussion but focuses specifically on addressing the support for macros. Apple is not at all special in this regard; the whole C++ library ecosystem depends on vending preprocessor macros.</p>

<p>Where Apple is special is in having experience deploying modules at scale across existing mixed C++, C, Objective C, and Objective C++ codebases, of its own and in its ecosystem. We’ve been through a feedback loop after trying to limit/ban macros, which proved that&#39;s too onerous for users to migrate to a C++ world without macro support.</p>

<p>Using the macOS SDK as an example we identified a number of use-cases that are not supported by the Modules TS. Here is a proposal to augment the TS to support these cases.</p>

<h2 id="toc_2">Macros in macOS SDK</h2>

<p>Apple&#39;s library interfaces support different C-based languages, macros are used in order to correctly gather availability information, heterogeneous platform support and to reason on top of features. The macOS SDK is completely modularized and macros are available for consumption at any library interface level, being critical in Apple&#39;s chain of module imports.</p>

<p>For example, as one can see in <code>LinearAlgebra/base.h</code> macOS 10.13 SDK, the header use macros to control availability information for a library:</p>

<div><pre><code class="language-cpp">/*  Define abstractions for a number of attributes that we wish to be able to 
concisely attach to functions in the LinearAlgebra library.             */
#define LA_AVAILABILITY  __OSX_AVAILABLE_STARTING(__MAC_10_10,__IPHONE_8_0)
...
#define LA_FUNCTION      OS_EXPORT OS_NOTHROW
#define LA_CONST         OS_CONST</code></pre></div>

<p>Note that <code>__MAC_10_10</code> is available through another module that provides macros from <code>Availability.h</code>. Another example is the <code>Foundation</code> framework, which has been part of Apple&#39;s ecosystem for decades and define macros that are used in almost all other frameworks in the SDK. Example:</p>

<div><pre><code class="language-none">...
#define NS_AVAILABLE(_mac, _ios) CF_AVAILABLE(_mac, _ios)
#define NS_AVAILABLE_MAC(_mac) CF_AVAILABLE_MAC(_mac)
#define NS_AVAILABLE_IOS(_ios) CF_AVAILABLE_IOS(_ios)

...
#ifndef NS_ASSUME_NONNULL_BEGIN
#define NS_ASSUME_NONNULL_BEGIN _Pragma(&quot;clang assume_nonnull begin&quot;)
#endif
</code></pre></div>

<p>For instance, <code>NS_ASSUME_NONNULL_BEGIN</code> and <code>NS_AVAILABLE</code> are used 16297 and 37929 times respectively by other framework headers in the SDK. Note that <code>NS_AVAILABLE</code> is also defined in terms of the macro <code>CF_AVAILABLE</code>, which is defined in the CoreFoundation framework. The same pattern repeats for hundreds of other macros in several other frameworks.</p>

<p>Additionally, one might argue that a user could import a module for Foundation and still <code>#include</code> the header to have the macro functionality available. However, users are encouraged to use a framework by including its <a href="https://clang.llvm.org/docs/Modules.html#header-declaration">umbrella header</a>, e.g., <code>#include &lt;Foundation/Foundation.h&gt;</code>, and not to directly include other headers from the framework. It seems odd that the user, after importing from Foundation would also need to <code>#include</code> the umbrella header to get such macros; there wouldn&#39;t be any compile time benefit and work is done twice.</p>

<h3 id="toc_3">Usage in Open Source</h3>

<p>The usage of such macros isn&#39;t limited to Apple headers. For instance, <a href="http://www.webkit.org/">WebKit</a> is an open source project that&#39;s representative of large iOS and macOS apps and is a heavy user of macros. Looking at the two Foundation macros mentioned above, <code>NS_ASSUME_NONNULL_BEGIN</code> and <code>NS_AVAILABLE</code>, they are together used 352 times in WebKit&#39;s code base.</p>

<h2 id="toc_4">Problems with the lack of macros in the Modules TS</h2>

<p>The <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2017/n4681.pdf">Modules TS</a> lacks support for macros. According to Section 3.2 in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0142r0.pdf">p0142r0</a>:</p>

<blockquote>
<p>... because the preprocessor is largely independent of the core language, it is impossible for a tool to understand (even grammatically) source code in header files without knowing the set of macros and configurations that a source file including the header file will activate. It is regrettably far too easy and far too common to under-appreciate how much macros are (and have been) stifling development of semantics-aware programming tools and how much of drag they constitute for C++, compared to alternatives...</p>
</blockquote>

<p>While modules may seem like an attractive way to obsolete macros, the reality is that Apple&#39;s platforms depend on macros. Developers on our platform will not benefit from modules unless they work well with macros. Additionally, concerns from others were already outlined in <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0273r1.pdf">P0273R1</a> and <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0837r0.html">P0837R0</a>.</p>

<p>We propose support for macros with the intent of helping with migration. To achieve it, we suggest adding extra syntax that:</p>

<ul>
<li>Adds on top of existing <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2017/n4681.pdf">Modules TS</a> syntax.</li>
<li>Can easily be later deprecated and removed, without polluting the reserved keyword namespace.</li>
</ul>

<h2 id="toc_5">Proposed macro syntax</h2>

<p>To export macros defined in a module, we propose augmenting the <em>module-declaration</em> in a <em>module interface unit</em> with a special suffix naming:</p>

<div><pre><code class="language-cpp">export module M; // declare module M
...

#define INFINITY ...
#define HUGE_VAL ...

...

export M.#*; // M export INFINITY, HUGE_VAL, etc</code></pre></div>

<p>In the code snippet above, all macros in <code>M</code>&#39;s <em>module interface unit</em> are exported. To select macros to export, a macro identifier is specified with <code>export M.#&lt;MACRO_NAME&gt;</code>. As illustrated in the example above, globbing is also supported, making the task of exporting groups of macros handy.</p>

<div><pre><code class="language-cpp">export M.#INFINITY; // M exports macro INFINITY
...
export M.#HUGE_*; // M exports macro HUGE_VAL</code></pre></div>

<p>On the module consumer side, no fine grained approach is available and one can only import the complete set of macros exported by module <code>M</code>:</p>

<div><pre><code class="language-cpp">import M; // import M with macros exported in module M (considering M exported any)</code></pre></div>

<p>Exporting macros in module <code>M</code> are the only way to control what macros will show up in the importer side, that&#39;s where the judicious use of macros should be controlled.</p>

<p>It&#39;s also important to note that the dotted module names in the Modules TS don&#39;t indicate a module-submodule relationship or filename hierarchy, which also has been the subject of other papers (see <a href="http://open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0778r0.pdf">P0778R0</a>). However, we propose that the suffix <code>.#</code> has special meaning, regardless of the amount of dots prior to the end of the module name.</p>

<p>The use of <code>export M.#&lt;MACRO_NAME&gt;</code> is only valid if the macro is visible at the point of export. Same applies after glob expansion, only the visible ones are selected.</p>

<p>Representing macros by wrapping them up under a specific suffix naming provides the necessary syntactic sugar that allows for deprecation of the mechanism later on; there&#39;s no pollution of the top-level reserved keywords.</p>

<h2 id="toc_6">Rules for macro definitions</h2>

<p>Different modules can have opposing definitions for the same macro, for example, one module might <code>#define</code> a macro while the other <code>#undef</code> it. We need a model with some rules on how it should behave. This paper proposes to reuse a mechanism model similar to the one defined in the <a href="http://clang.llvm.org/docs/Modules.html#macros">Clang Modules documentation</a>. The relevant rules extracted from the document follow:</p>

<ul>
<li>Each <code>#define</code> and <code>#undef</code> of a macro is considered to be a distinct entity.</li>
<li>A <code>#define X</code> or <code>#undef X</code> directive <strong>overrides</strong> all definitions of X that are visible at the point of the directive.</li>
<li>A <code>#define</code> or <code>#undef</code> directive is <strong>active</strong> if it is visible and no visible directive overrides it.</li>
<li>A set of macro directives is consistent if it consists of only <code>#undef</code> directives, or if all <code>#define</code> directives in the set define the macro name to the same sequence of tokens (following the usual rules for macro redefinitions).</li>
<li>If a macro name is used and the set of active directives is not consistent, the program is ill-formed. Otherwise, the (unique) meaning of the macro name is used.</li>
</ul>

<h3 id="toc_7">Example A</h3>

<p>Also extracted from that document, suppose this example:</p>

<ul>
<li><code>&lt;stdio.h&gt;</code> defines a macro <code>getc</code> (and exports its <code>#define</code>)</li>
<li><code>&lt;cstdio&gt;</code> imports the <code>&lt;stdio.h&gt;</code> module and undefines the macro (and exports its <code>#undef</code>)</li>
</ul>

<p>The <code>#undef</code> <strong>overrides</strong> the <code>#define</code>, and a source file that imports both modules in any order will not see <code>getc</code> defined as a macro.</p>

<h3 id="toc_8">Example B</h3>

<p>Also suppose a module <code>M</code> exporting macros <code>FOO</code> and <code>BAR</code>:</p>

<div><pre><code class="language-cpp">export module M;

#define FOO puts(&quot;hello&quot;)
#define BAR FOO
#undef FOO
#define FOO puts(&quot;world&quot;)
...

export M.#*;</code></pre></div>

<p>Both <code>FOO</code> and <code>BAR</code> macros contain <code>puts(&quot;world&quot;)</code> as a result of importing; <code>BAR</code> will contain whatever <code>FOO</code> contains at the end of module, since both are <strong>active</strong> at that point.</p>

<h3 id="toc_9">X-Macros</h3>

<p>The proposed model, as the paper title suggests, is intended to support <em>modular macros</em>, meaning that this paper has no intent to support idioms that are intrinsically <em>non-modular</em>.</p>

<p><a href="https://en.wikibooks.org/wiki/C_Programming/Preprocessor_directives_and_macros#X-Macros">X-Macros</a> is a popular non-modular idiom where a macro is defined and subsequently expanded by a <code>#include</code>. For instance, take a look at LLVM&#39;s <code>include/llvm/BinaryFormat/Dwarf.h</code>:</p>

<div><pre><code class="language-cpp">...
enum LineNumberOps : uint8_t {
#define HANDLE_DW_LNS(ID, NAME) DW_LNS_##NAME = ID,
#include &quot;llvm/BinaryFormat/Dwarf.def&quot;
};</code></pre></div>

<p>where <code>include/llvm/BinaryFormat/Dwarf.def</code> contains:</p>

<div><pre><code class="language-cpp">...
// Line Number Standard Opcode Encodings.
HANDLE_DW_LNS(0x00, extended_op)
HANDLE_DW_LNS(0x01, copy)
HANDLE_DW_LNS(0x02, advance_pc)
...
#undef HANDLE_DW_LNS</code></pre></div>

<p>The expansion for <code>HANDLE_DW_LNS</code> in <code>Dwarf.def</code> is highly dependent on the context and macro definition in <code>Dwarf.h</code>. Such idioms must continue to rely on plain <code>#include</code>s.</p>

<h2 id="toc_10">Acknowledgments</h2>

<p>Thanks to Vassil Vassilev, JF Bastien, Adrian Prantl, Duncan P. Exon Smith and Richard Smith for comments and reviews.</p>




</body>

</html>
