Contents of /trunk/llvm/patches/llvm-3.8.0-D17567-PR23529-Sema-part-of-attrbute-abi_tag-support.patch
Parent Directory | Revision Log
Revision 2804 -
(show annotations)
(download)
Wed Jun 8 12:54:34 2016 UTC (8 years, 3 months ago) by niro
File size: 12036 byte(s)
Wed Jun 8 12:54:34 2016 UTC (8 years, 3 months ago) by niro
File size: 12036 byte(s)
-llvm-3.8.0 upstream patches
1 | 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}} |