Annotation of /trunk/llvm/patches/llvm-3.8.0-D17567-PR23529-Sema-part-of-attrbute-abi_tag-support.patch
Parent Directory | Revision Log
Revision 2804 -
(hide annotations)
(download)
Wed Jun 8 12:54:34 2016 UTC (8 years ago) by niro
File size: 12036 byte(s)
Wed Jun 8 12:54:34 2016 UTC (8 years ago) by niro
File size: 12036 byte(s)
-llvm-3.8.0 upstream patches
1 | niro | 2804 | Index: cfe/trunk/docs/ItaniumMangleAbiTags.rst |
2 | =================================================================== | ||
3 | --- cfe/trunk/docs/ItaniumMangleAbiTags.rst | ||
4 | +++ cfe/trunk/docs/ItaniumMangleAbiTags.rst | ||
5 | @@ -0,0 +1,101 @@ | ||
6 | +======== | ||
7 | +ABI tags | ||
8 | +======== | ||
9 | + | ||
10 | +Introduction | ||
11 | +============ | ||
12 | + | ||
13 | +This text tries to describe gcc semantic for mangling "abi_tag" attributes | ||
14 | +described in https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html | ||
15 | + | ||
16 | +There is no guarantee the following rules are correct, complete or make sense | ||
17 | +in any way as they were determined empirically by experiments with gcc5. | ||
18 | + | ||
19 | +Declaration | ||
20 | +=========== | ||
21 | + | ||
22 | +ABI tags are declared in an abi_tag attribute and can be applied to a | ||
23 | +function, variable, class or inline namespace declaration. The attribute takes | ||
24 | +one or more strings (called tags); the order does not matter. | ||
25 | + | ||
26 | +See https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html for | ||
27 | +details. | ||
28 | + | ||
29 | +Tags on an inline namespace are called "implicit tags", all other tags are | ||
30 | +"explicit tags". | ||
31 | + | ||
32 | +Mangling | ||
33 | +======== | ||
34 | + | ||
35 | +All tags that are "active" on an <unqualified-name> are emitted after the | ||
36 | +<unqualified-name>, before <template-args> or <discriminator>, and are part of | ||
37 | +the same <substitution> the <unqualified-name> is. | ||
38 | + | ||
39 | +They are mangled as: | ||
40 | + | ||
41 | + <abi-tags> ::= <abi-tag>* # sort by name | ||
42 | + <abi-tag> ::= B <tag source-name> | ||
43 | + | ||
44 | +Example: | ||
45 | + | ||
46 | + __attribute__((abi_tag("test"))) | ||
47 | + void Func(); | ||
48 | + | ||
49 | + gets mangled as: _Z4FuncB4testv (prettified as `Func[abi:test]()`) | ||
50 | + | ||
51 | +Active tags | ||
52 | +=========== | ||
53 | + | ||
54 | +A namespace does not have any active tags. For types (class / struct / union / | ||
55 | +enum), the explicit tags are the active tags. | ||
56 | + | ||
57 | +For variables and functions, the active tags are the explicit tags plus any | ||
58 | +"required tags" which are not in the "available tags" set: | ||
59 | + | ||
60 | + derived-tags := (required-tags - available-tags) | ||
61 | + active-tags := explicit-tags + derived-tags | ||
62 | + | ||
63 | +Required tags for a function | ||
64 | +============================ | ||
65 | + | ||
66 | +If a function is used as a local scope for another name, and is part of | ||
67 | +another function as local scope, it doesn't have any required tags. | ||
68 | + | ||
69 | +If a function is used as a local scope for a guard variable name, it doesn't | ||
70 | +have any required tags. | ||
71 | + | ||
72 | +Otherwise the function requires any implicit or explicit tag used in the name | ||
73 | +for the return type. | ||
74 | + | ||
75 | +Example: | ||
76 | + namespace A { | ||
77 | + inline namespace B __attribute__((abi_tag)) { | ||
78 | + struct C { int x; }; | ||
79 | + } | ||
80 | + } | ||
81 | + | ||
82 | + A::C foo(); | ||
83 | + | ||
84 | + gets mangled as: _Z3fooB1Bv (prettified as `foo[abi:B]()`) | ||
85 | + | ||
86 | +Required tags for a variable | ||
87 | +============================ | ||
88 | + | ||
89 | +A variable requires any implicit or explicit tag used in its type. | ||
90 | + | ||
91 | +Available tags | ||
92 | +============== | ||
93 | + | ||
94 | +All tags used in the prefix and in the template arguments for a name are | ||
95 | +available. Also, for functions, all tags from the <bare-function-type> | ||
96 | +(which might include the return type for template functions) are available. | ||
97 | + | ||
98 | +For <local-name>s all active tags used in the local part (<function- | ||
99 | +encoding>) are available, but not implicit tags which were not active. | ||
100 | + | ||
101 | +Implicit and explicit tags used in the <unqualified-name> for a function (as | ||
102 | +in the type of a cast operator) are NOT available. | ||
103 | + | ||
104 | +Example: a cast operator to std::string (which is | ||
105 | +std::__cxx11::basic_string<...>) will use 'cxx11' as an active tag, as it is | ||
106 | +required from the return type `std::string` but not available. | ||
107 | Index: cfe/trunk/include/clang/Basic/Attr.td | ||
108 | =================================================================== | ||
109 | --- cfe/trunk/include/clang/Basic/Attr.td | ||
110 | +++ cfe/trunk/include/clang/Basic/Attr.td | ||
111 | @@ -358,6 +358,14 @@ | ||
112 | // Attributes begin here | ||
113 | // | ||
114 | |||
115 | +def AbiTag : Attr { | ||
116 | + let Spellings = [GCC<"abi_tag">]; | ||
117 | + let Args = [VariadicStringArgument<"Tags">]; | ||
118 | + let Subjects = SubjectList<[Struct, Var, Function, Namespace], ErrorDiag, | ||
119 | + "ExpectedStructClassVariableFunctionOrInlineNamespace">; | ||
120 | + let Documentation = [AbiTagsDocs]; | ||
121 | +} | ||
122 | + | ||
123 | def AddressSpace : TypeAttr { | ||
124 | let Spellings = [GNU<"address_space">]; | ||
125 | let Args = [IntArgument<"AddressSpace">]; | ||
126 | Index: cfe/trunk/include/clang/Basic/AttrDocs.td | ||
127 | =================================================================== | ||
128 | --- cfe/trunk/include/clang/Basic/AttrDocs.td | ||
129 | +++ cfe/trunk/include/clang/Basic/AttrDocs.td | ||
130 | @@ -2132,3 +2132,16 @@ | ||
131 | optimizations like C++'s named return value optimization (NRVO). | ||
132 | }]; | ||
133 | } | ||
134 | + | ||
135 | +def AbiTagsDocs : Documentation { | ||
136 | + let Content = [{ | ||
137 | +The ``abi_tag`` attribute can be applied to a function, variable, class or | ||
138 | +inline namespace declaration to modify the mangled name of the entity. It gives | ||
139 | +the ability to distinguish between different versions of the same entity but | ||
140 | +with different ABI versions supported. For example, a newer version of a class | ||
141 | +could have a different set of data members and thus have a different size. Using | ||
142 | +the ``abi_tag`` attribute, it is possible to have different mangled names for | ||
143 | +a global variable of the class type. Therefor, the old code could keep using | ||
144 | +the old manged name and the new code will use the new mangled name with tags. | ||
145 | + }]; | ||
146 | +} | ||
147 | Index: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td | ||
148 | =================================================================== | ||
149 | --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td | ||
150 | +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td | ||
151 | @@ -2477,7 +2477,8 @@ | ||
152 | "Objective-C instance methods|init methods of interface or class extension declarations|" | ||
153 | "variables, functions and classes|Objective-C protocols|" | ||
154 | "functions and global variables|structs, unions, and typedefs|structs and typedefs|" | ||
155 | - "interface or protocol declarations|kernel functions|non-K&R-style functions}1">, | ||
156 | + "interface or protocol declarations|kernel functions|non-K&R-style functions|" | ||
157 | + "structs, classes, variables, functions, and inline namespaces}1">, | ||
158 | InGroup<IgnoredAttributes>; | ||
159 | def err_attribute_wrong_decl_type : Error<warn_attribute_wrong_decl_type.Text>; | ||
160 | def warn_type_attribute_wrong_type : Warning< | ||
161 | @@ -4195,6 +4196,13 @@ | ||
162 | def err_redefinition_extern_inline : Error< | ||
163 | "redefinition of a 'extern inline' function %0 is not supported in " | ||
164 | "%select{C99 mode|C++}1">; | ||
165 | +def warn_attr_abi_tag_namespace : Warning< | ||
166 | + "'abi_tag' attribute on %select{non-inline|anonymous}0 namespace ignored">, | ||
167 | + InGroup<IgnoredAttributes>; | ||
168 | +def err_abi_tag_on_redeclaration : Error< | ||
169 | + "cannot add 'abi_tag' attribute in a redeclaration">; | ||
170 | +def err_new_abi_tag_on_redeclaration : Error< | ||
171 | + "'abi_tag' %0 missing in original declaration">; | ||
172 | |||
173 | def note_deleted_dtor_no_operator_delete : Note< | ||
174 | "virtual destructor requires an unambiguous, accessible 'operator delete'">; | ||
175 | Index: cfe/trunk/include/clang/Sema/AttributeList.h | ||
176 | =================================================================== | ||
177 | --- cfe/trunk/include/clang/Sema/AttributeList.h | ||
178 | +++ cfe/trunk/include/clang/Sema/AttributeList.h | ||
179 | @@ -895,7 +895,8 @@ | ||
180 | ExpectedStructOrTypedef, | ||
181 | ExpectedObjectiveCInterfaceOrProtocol, | ||
182 | ExpectedKernelFunction, | ||
183 | - ExpectedFunctionWithProtoType | ||
184 | + ExpectedFunctionWithProtoType, | ||
185 | + ExpectedStructClassVariableFunctionOrInlineNamespace | ||
186 | }; | ||
187 | |||
188 | } // end namespace clang | ||
189 | Index: cfe/trunk/lib/Sema/SemaDecl.cpp | ||
190 | =================================================================== | ||
191 | --- cfe/trunk/lib/Sema/SemaDecl.cpp | ||
192 | +++ cfe/trunk/lib/Sema/SemaDecl.cpp | ||
193 | @@ -2398,6 +2398,24 @@ | ||
194 | } | ||
195 | } | ||
196 | |||
197 | + // Re-declaration cannot add abi_tag's. | ||
198 | + if (const auto *NewAbiTagAttr = New->getAttr<AbiTagAttr>()) { | ||
199 | + if (const auto *OldAbiTagAttr = Old->getAttr<AbiTagAttr>()) { | ||
200 | + for (const auto &NewTag : NewAbiTagAttr->tags()) { | ||
201 | + if (std::find(OldAbiTagAttr->tags_begin(), OldAbiTagAttr->tags_end(), | ||
202 | + NewTag) == OldAbiTagAttr->tags_end()) { | ||
203 | + Diag(NewAbiTagAttr->getLocation(), | ||
204 | + diag::err_new_abi_tag_on_redeclaration) | ||
205 | + << NewTag; | ||
206 | + Diag(OldAbiTagAttr->getLocation(), diag::note_previous_declaration); | ||
207 | + } | ||
208 | + } | ||
209 | + } else { | ||
210 | + Diag(NewAbiTagAttr->getLocation(), diag::err_abi_tag_on_redeclaration); | ||
211 | + Diag(Old->getLocation(), diag::note_previous_declaration); | ||
212 | + } | ||
213 | + } | ||
214 | + | ||
215 | if (!Old->hasAttrs()) | ||
216 | return; | ||
217 | |||
218 | Index: cfe/trunk/lib/Sema/SemaDeclAttr.cpp | ||
219 | =================================================================== | ||
220 | --- cfe/trunk/lib/Sema/SemaDeclAttr.cpp | ||
221 | +++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp | ||
222 | @@ -4615,6 +4615,42 @@ | ||
223 | Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); | ||
224 | } | ||
225 | |||
226 | +static void handleAbiTagAttr(Sema &S, Decl *D, const AttributeList &Attr) { | ||
227 | + SmallVector<std::string, 4> Tags; | ||
228 | + for (unsigned I = 0, E = Attr.getNumArgs(); I != E; ++I) { | ||
229 | + StringRef Tag; | ||
230 | + if (!S.checkStringLiteralArgumentAttr(Attr, I, Tag)) | ||
231 | + return; | ||
232 | + Tags.push_back(Tag); | ||
233 | + } | ||
234 | + | ||
235 | + if (const auto *NS = dyn_cast<NamespaceDecl>(D)) { | ||
236 | + if (!NS->isInline()) { | ||
237 | + S.Diag(Attr.getLoc(), diag::warn_attr_abi_tag_namespace) << 0; | ||
238 | + return; | ||
239 | + } | ||
240 | + if (NS->isAnonymousNamespace()) { | ||
241 | + S.Diag(Attr.getLoc(), diag::warn_attr_abi_tag_namespace) << 1; | ||
242 | + return; | ||
243 | + } | ||
244 | + if (Attr.getNumArgs() == 0) | ||
245 | + Tags.push_back(NS->getName()); | ||
246 | + } else if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) | ||
247 | + return; | ||
248 | + | ||
249 | + // Store tags sorted and without duplicates. | ||
250 | + std::sort(Tags.begin(), Tags.end()); | ||
251 | + Tags.erase(std::unique(Tags.begin(), Tags.end()), Tags.end()); | ||
252 | + | ||
253 | + D->addAttr(::new (S.Context) | ||
254 | + AbiTagAttr(Attr.getRange(), S.Context, Tags.data(), Tags.size(), | ||
255 | + Attr.getAttributeSpellingListIndex())); | ||
256 | + | ||
257 | + // FIXME: remove this warning as soon as mangled part is ready. | ||
258 | + S.Diag(Attr.getRange().getBegin(), diag::warn_attribute_ignored) | ||
259 | + << Attr.getName(); | ||
260 | +} | ||
261 | + | ||
262 | static void handleARMInterruptAttr(Sema &S, Decl *D, | ||
263 | const AttributeList &Attr) { | ||
264 | // Check the attribute arguments. | ||
265 | @@ -5637,6 +5673,9 @@ | ||
266 | case AttributeList::AT_Thread: | ||
267 | handleDeclspecThreadAttr(S, D, Attr); | ||
268 | break; | ||
269 | + case AttributeList::AT_AbiTag: | ||
270 | + handleAbiTagAttr(S, D, Attr); | ||
271 | + break; | ||
272 | |||
273 | // Thread safety attributes: | ||
274 | case AttributeList::AT_AssertExclusiveLock: | ||
275 | Index: cfe/trunk/test/SemaCXX/attr-abi-tag-syntax.cpp | ||
276 | =================================================================== | ||
277 | --- cfe/trunk/test/SemaCXX/attr-abi-tag-syntax.cpp | ||
278 | +++ cfe/trunk/test/SemaCXX/attr-abi-tag-syntax.cpp | ||
279 | @@ -0,0 +1,43 @@ | ||
280 | +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s | ||
281 | + | ||
282 | +namespace N1 { | ||
283 | + | ||
284 | +namespace __attribute__((__abi_tag__)) {} | ||
285 | +// expected-warning@-1 {{'abi_tag' attribute on non-inline namespace ignored}} | ||
286 | + | ||
287 | +namespace N __attribute__((__abi_tag__)) {} | ||
288 | +// expected-warning@-1 {{'abi_tag' attribute on non-inline namespace ignored}} | ||
289 | + | ||
290 | +} // namespace N1 | ||
291 | + | ||
292 | +namespace N2 { | ||
293 | + | ||
294 | +inline namespace __attribute__((__abi_tag__)) {} | ||
295 | +// expected-warning@-1 {{'abi_tag' attribute on anonymous namespace ignored}} | ||
296 | + | ||
297 | +inline namespace N __attribute__((__abi_tag__)) {} | ||
298 | +// FIXME: remove this warning as soon as attribute fully supported. | ||
299 | +// expected-warning@-2 {{'__abi_tag__' attribute ignored}} | ||
300 | + | ||
301 | +} // namespcace N2 | ||
302 | + | ||
303 | +__attribute__((abi_tag("B", "A"))) extern int a1; | ||
304 | +// FIXME: remove this warning as soon as attribute fully supported. | ||
305 | +// expected-warning@-2 {{'abi_tag' attribute ignored}} | ||
306 | + | ||
307 | +__attribute__((abi_tag("A", "B"))) extern int a1; | ||
308 | +// expected-note@-1 {{previous declaration is here}} | ||
309 | +// FIXME: remove this warning as soon as attribute fully supported. | ||
310 | +// expected-warning@-3 {{'abi_tag' attribute ignored}} | ||
311 | + | ||
312 | +__attribute__((abi_tag("A", "C"))) extern int a1; | ||
313 | +// expected-error@-1 {{'abi_tag' C missing in original declaration}} | ||
314 | +// FIXME: remove this warning as soon as attribute fully supported. | ||
315 | +// expected-warning@-3 {{'abi_tag' attribute ignored}} | ||
316 | + | ||
317 | +extern int a2; | ||
318 | +// expected-note@-1 {{previous declaration is here}} | ||
319 | +__attribute__((abi_tag("A")))extern int a2; | ||
320 | +// expected-error@-1 {{cannot add 'abi_tag' attribute in a redeclaration}} | ||
321 | +// FIXME: remove this warning as soon as attribute fully supported. | ||
322 | +// expected-warning@-3 {{'abi_tag' attribute ignored}} |