-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathd1245r1.bs
258 lines (194 loc) · 10.4 KB
/
d1245r1.bs
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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
<pre class='metadata'>
Title: <code>export module containing [[attribute]];</code>
Shortname: P1245
Revision: 1
Audience: EWG
Status: P
Group: WG21
<!-- URL: http://wg21.link/p1245r1-->
!Source: <a href="https://github.com/bcardosolopes/cpp-papers/blob/master/d1245r1.bs">github.com/bcardosolopes/cpp-papers/blob/master/d1245r1.bs</a>
Editor: Bruno Cardoso Lopes, Apple, [email protected]
Editor: JF Bastien, Apple, [email protected]
No abstract: true
Date: 2018-10-08
Markup Shorthands: markdown yes
<!--Toggle Diffs: yes-->
</pre>
Edit History {#edit}
============
r0 → r1 {#r0r1}
-------
Address feedback from EWGI on -ext mailing list. See [[#ewgicom|EWGI Q&A]].
Introduction {#intro}
============
C++ supports *attributes* [**dcl.attr.grammar**] ❡9.11 that
can be applied to source code in different ways:
<blockquote>
Attribute syntax and semantics [**dcl.attr.grammar**]
<sup>1</sup> Attributes specify additional information for various source
constructs such as types, variables, names, blocks, or translation units.
</blockquote>
This is useful for fine-grained control of different capabilities and behaviors
in a C++ codebase, but C++ currently lacks language-level constructs to
express coarse-grained versions of the same mechanisms.
Compilers vend different kind of flags to control coarse-grained (translation
unit level) capabilities such as ones that can affect C++ semantics, enforce
restrictions, and the change the quality of code generation. Concrete examples:
: Code generation
:: Global processor specific constraints in the lines of `-mmicromips`, `-mno-micromips` and `-msoft-float`. Global flags in [[Clang]] that change calling convention `-fdefault-calling-conv={cdecl,stdcall,vectorcall,regcall}`.
: Efficiency and debuggability
:: The well known optimization level flags `-O0`, `-O1`, ... and debug `-g`
: C++ semantics
:: Flags such as `-std=c++17`, or `-fno-rtti`, `-fno-exceptions` have the effect of changing or turning off parts of the standard.
: Freestanding
:: The standard mentions *freestanding implementations* and *freestanding environment* [[basic.start.main]], but there's nothing obvious in user code that could enforce it as such, compiler flags like `-ffreestanding` are necessary.
Proposed Solution {#proposal}
=================
In the light of non-standard and implementation defined ways to specify such
capabilities and constraints, we believe [[Modules]] are a great opportunity
to bring some sanity to this madness and pave the road for incremental
adoption of such flags in the form of *module attributes*.
Module attributes stand to remove out-of-band language modes, and make them
official well-supported behavior. They're explicit in the code, removing
sources of surprise. They standardize a pathway to express existing modes and
also lower the number of incompatible options developers need to get from their
compiler. They allow us to simplify our definition of freestanding.
According to [[MergedModulesProposal]] [**Basics**] ❡2.1:
<blockquote>
... The `export` keyword indicates that a module unit is a module interface
unit, which defines the interface for the module. For a module `foo`, there
must be exactly one translation unit whose preamble contains `export module
foo;`. This is the primary module interface unit for `foo`.
</blockquote>
The rules for such *module attributes* are:
* They should be declared as part of *module interface unit*, more precisely
at the end of the declaration that contains the `export` keyword, before `;`.
<xmp>
export module foo [[shiny_new_attribute]];
import a;
export import b;
// ... more imports ...
</xmp>
* Existing attributes with fine-grained scopes (types, variables, names, etc)
can be modified on a case-by-case basis by the Committee to also provide
module-level behavior, as long as the behavior is clearly specified in the
Standard. Example: a function level attribute used at the module level could
turn on a capability or restriction for all functions in the module.
* Attributes at the module-level can be overriden by finer-grained attributes.
* Conflicting module-level and other fine-grained scope attributes should be
diagnosed by the compiler.
* Some compiler settings could *require* that some module-level attributes be
used. For example, targetting an embedded platform which has no support for
floating-point could hard-error on any module which doesn't contain the
`[[no_float]]` attribute.
Issue: It's yet unclear how [[Contracts]] are going to interoperate with
Modules, but this proposal certainly touches some aspect of it that should be
considered in the future.
## Case study ## {#study}
Take the `[[no_float]]` *function attribute* described in [[P1246R0]]. As
the mentioned rationale in [**Introduction**]:
<blockquote>
* Different pieces of a project might want different floating-point code
generation; relying on extra compiler flags for specific translation units
in a project is brittle and also has maintenance and portability costs. For
instance, in an application one might want to opt out from floating-point
only for specific pieces (e.g. cryptography code and kernel level
`printf`-like utilities still want to use floating-point)
</blockquote>
Using `[[no_float]]` as a *module attribute* is a great fit for the
requirements above. Based on the example above:
<xmp>
export module Crypto [[no_float]];
import BigNum;
...
export class MyBlockCipher { ... }
...
</xmp>
This hypothetical cryptography code lives on its own module and is marked
with `[[no_float]]`, meaning every function inside the `Crypto` module shall not
use floating-point (here, maybe vectorization and custom-hardware crypto is
undesirable and only integer instructions are desired). Using this annotation
yield some benefits:
: Readability expectations
:: It's clear from the module interface that one isn't expected to use floating-point. The code is also clean, since there's no need to annotate every function with such attribute.
: Policy enforcement
:: Attempts to use floating-point code will hard-error on the user.
Additionally, `printf`-like utilities, in their own module, can still use
floating-point and be imported by the same translation unit that imports
`Crypto`.
EWGI Q&A {#ewgicom}
========
<blockquote>
Who will be in San Diego to present this paper?
</blockquote>
Both authors, Bruno & JF.
<blockquote>
Is there implementation experience?
</blockquote>
Not in the form of a language feature. However, *Clang Modules* has an analogous (but rudimentary) way of annotating requirements in *module maps* (clang's side file for modules specification), that work in very similar ways as an attribute would work at the module level declaration. For example, it's currently possible to mark modules as `freestanding`, which will require the `-ffreestanding` compiler flag to be used or the module won't build. The same is true for checks like `opencl`, `gnuinlineasm` or `altivec` and also a handful of platform based checks. See [[RequiresDeclaration]] for more information.
<blockquote>
Is there usage experience?
</blockquote>
In *Clang Modules*, yes, for a several years already. There are multiple examples used in Modules descriptions for [[libcxxmodule|libc++ module]], Clang [[clangbuiltins|builtin headers]] and Apple's SDKs.
<blockquote>
What shipping vehicle do you target with this proposal?
</blockquote>
C++20. Why? We believe it provides a good mechanism for expressing constraints at coarse-grained level, which was not possible before modules. Shipping the mechanism in C++20 should allow for further exploration of module level attributes, by providing a mechanism for vendors to experiment.
<blockquote>
Please show a Tony Table of the code before / after your proposal.
</blockquote>
Not relevant here. In [[#proposal|Proposal]] we describe the additions to the language, examples are given in [[#study|Case Study]].
<blockquote>
This isn't providing a particular attribute, but rather suggesting that attributes could be applied to modules instead of as compiler flags. The committee in general would rather avoid attributes which change language semantics. Which compiler flags don't affect semantics yet would be good targets for standardization as module attributes? You have a list of attributes, are all of those semantics-preserving?
</blockquote>
Examples: `freestanding`, `-mno-implicit-float`, `-fvectorize`, `-fstack-protector`, `-ftls-model=<arg>`, `-mstack-alignment=<arg>`, etc. This proposal will only cover potential attributes that are semantics-preserving.
<blockquote>
Do you foresee ODR issues when linking different modules with different such attributes? If yes, can these be resolved?
</blockquote>
ODR issues here are possible in the same degree that linking object files compiled with different flags are, module attributes is not adding any new problem here.
<blockquote>
What do contracts experts think of this?
</blockquote>
Contracts experts haven't been contacted by the time of the last revision of this paper, see Issue 1. Authors are open and willing to do so.
<pre class=biblio>
{
"Clang": {
"href": "http://clang.llvm.org",
"title": "Clang: a C language family frontend for LLVM"
},
"basic.start.main": {
"href": "http://eel.is/c++draft/basic.start#main-1",
"title": "C++ working draft: 6.8.3.1 main function"
},
"Modules": {
"title": "Modules for Standard C++",
"href": "http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1087r0.pdf"
},
"MergedModulesProposal": {
"title": "Merging Modules",
"href": "http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1103r0.pdf"
},
"Contracts": {
"href": "http://eel.is/c++draft/dcl.attr.contract",
"title": "Contracts attributes"
},
"P1246R0": {
"href": "http://wg21.link/p1246r0",
"title": "The no_float function attribute"
},
"libcxxmodule": {
"href": "https://github.com/llvm-mirror/libcxx/blob/6c372355ba83ad4899a66039f32fbca97204cff6/include/module.modulemap#L519",
"title": "Libcxx module map"
},
"clangbuiltins": {
"href": "https://github.com/llvm-mirror/clang/blob/a8770a7e8e8797a860773c2e0959274b1db4fc7a/lib/Headers/module.modulemap#L79",
"title": "Clang builtins module map"
},
"RequiresDeclaration": {
"href": "https://clang.llvm.org/docs/Modules.html#requires-declaration",
"title": "Clang Modules documentation: Requires declaration"
}
}
</pre>
<!--
-->