1 | //===-- Types.h - API Notes Data Types --------------------------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef LLVM_CLANG_APINOTES_TYPES_H |
10 | #define LLVM_CLANG_APINOTES_TYPES_H |
11 | |
12 | #include "clang/Basic/Specifiers.h" |
13 | #include "llvm/ADT/ArrayRef.h" |
14 | #include "llvm/ADT/StringRef.h" |
15 | #include <climits> |
16 | #include <optional> |
17 | #include <vector> |
18 | |
19 | namespace llvm { |
20 | class raw_ostream; |
21 | } // namespace llvm |
22 | |
23 | namespace clang { |
24 | namespace api_notes { |
25 | enum class RetainCountConventionKind { |
26 | None, |
27 | CFReturnsRetained, |
28 | CFReturnsNotRetained, |
29 | NSReturnsRetained, |
30 | NSReturnsNotRetained, |
31 | }; |
32 | |
33 | /// The payload for an enum_extensibility attribute. This is a tri-state rather |
34 | /// than just a boolean because the presence of the attribute indicates |
35 | /// auditing. |
36 | enum class EnumExtensibilityKind { |
37 | None, |
38 | Open, |
39 | Closed, |
40 | }; |
41 | |
42 | /// The kind of a swift_wrapper/swift_newtype. |
43 | enum class SwiftNewTypeKind { |
44 | None, |
45 | Struct, |
46 | Enum, |
47 | }; |
48 | |
49 | /// Describes API notes data for any entity. |
50 | /// |
51 | /// This is used as the base of all API notes. |
52 | class CommonEntityInfo { |
53 | public: |
54 | /// Message to use when this entity is unavailable. |
55 | std::string UnavailableMsg; |
56 | |
57 | /// Whether this entity is marked unavailable. |
58 | LLVM_PREFERRED_TYPE(bool) |
59 | unsigned Unavailable : 1; |
60 | |
61 | /// Whether this entity is marked unavailable in Swift. |
62 | LLVM_PREFERRED_TYPE(bool) |
63 | unsigned UnavailableInSwift : 1; |
64 | |
65 | private: |
66 | /// Whether SwiftPrivate was specified. |
67 | LLVM_PREFERRED_TYPE(bool) |
68 | unsigned SwiftPrivateSpecified : 1; |
69 | |
70 | /// Whether this entity is considered "private" to a Swift overlay. |
71 | LLVM_PREFERRED_TYPE(bool) |
72 | unsigned SwiftPrivate : 1; |
73 | |
74 | public: |
75 | /// Swift name of this entity. |
76 | std::string SwiftName; |
77 | |
78 | CommonEntityInfo() |
79 | : Unavailable(0), UnavailableInSwift(0), SwiftPrivateSpecified(0), |
80 | SwiftPrivate(0) {} |
81 | |
82 | std::optional<bool> isSwiftPrivate() const { |
83 | return SwiftPrivateSpecified ? std::optional<bool>(SwiftPrivate) |
84 | : std::nullopt; |
85 | } |
86 | |
87 | void setSwiftPrivate(std::optional<bool> Private) { |
88 | SwiftPrivateSpecified = Private.has_value(); |
89 | SwiftPrivate = Private.value_or(u: 0); |
90 | } |
91 | |
92 | friend bool operator==(const CommonEntityInfo &, const CommonEntityInfo &); |
93 | |
94 | CommonEntityInfo &operator|=(const CommonEntityInfo &RHS) { |
95 | // Merge unavailability. |
96 | if (RHS.Unavailable) { |
97 | Unavailable = true; |
98 | if (UnavailableMsg.empty()) |
99 | UnavailableMsg = RHS.UnavailableMsg; |
100 | } |
101 | |
102 | if (RHS.UnavailableInSwift) { |
103 | UnavailableInSwift = true; |
104 | if (UnavailableMsg.empty()) |
105 | UnavailableMsg = RHS.UnavailableMsg; |
106 | } |
107 | |
108 | if (!SwiftPrivateSpecified) |
109 | setSwiftPrivate(RHS.isSwiftPrivate()); |
110 | |
111 | if (SwiftName.empty()) |
112 | SwiftName = RHS.SwiftName; |
113 | |
114 | return *this; |
115 | } |
116 | |
117 | LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const; |
118 | }; |
119 | |
120 | inline bool operator==(const CommonEntityInfo &LHS, |
121 | const CommonEntityInfo &RHS) { |
122 | return LHS.UnavailableMsg == RHS.UnavailableMsg && |
123 | LHS.Unavailable == RHS.Unavailable && |
124 | LHS.UnavailableInSwift == RHS.UnavailableInSwift && |
125 | LHS.SwiftPrivateSpecified == RHS.SwiftPrivateSpecified && |
126 | LHS.SwiftPrivate == RHS.SwiftPrivate && LHS.SwiftName == RHS.SwiftName; |
127 | } |
128 | |
129 | inline bool operator!=(const CommonEntityInfo &LHS, |
130 | const CommonEntityInfo &RHS) { |
131 | return !(LHS == RHS); |
132 | } |
133 | |
134 | /// Describes API notes for types. |
135 | class CommonTypeInfo : public CommonEntityInfo { |
136 | /// The Swift type to which a given type is bridged. |
137 | /// |
138 | /// Reflects the swift_bridge attribute. |
139 | std::optional<std::string> SwiftBridge; |
140 | |
141 | /// The NS error domain for this type. |
142 | std::optional<std::string> NSErrorDomain; |
143 | |
144 | public: |
145 | CommonTypeInfo() {} |
146 | |
147 | const std::optional<std::string> &getSwiftBridge() const { |
148 | return SwiftBridge; |
149 | } |
150 | |
151 | void setSwiftBridge(std::optional<std::string> SwiftType) { |
152 | SwiftBridge = SwiftType; |
153 | } |
154 | |
155 | const std::optional<std::string> &getNSErrorDomain() const { |
156 | return NSErrorDomain; |
157 | } |
158 | |
159 | void setNSErrorDomain(const std::optional<std::string> &Domain) { |
160 | NSErrorDomain = Domain; |
161 | } |
162 | |
163 | void setNSErrorDomain(const std::optional<llvm::StringRef> &Domain) { |
164 | NSErrorDomain = Domain ? std::optional<std::string>(std::string(*Domain)) |
165 | : std::nullopt; |
166 | } |
167 | |
168 | friend bool operator==(const CommonTypeInfo &, const CommonTypeInfo &); |
169 | |
170 | CommonTypeInfo &operator|=(const CommonTypeInfo &RHS) { |
171 | // Merge inherited info. |
172 | static_cast<CommonEntityInfo &>(*this) |= RHS; |
173 | |
174 | if (!SwiftBridge) |
175 | setSwiftBridge(RHS.getSwiftBridge()); |
176 | if (!NSErrorDomain) |
177 | setNSErrorDomain(RHS.getNSErrorDomain()); |
178 | |
179 | return *this; |
180 | } |
181 | |
182 | LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const; |
183 | }; |
184 | |
185 | inline bool operator==(const CommonTypeInfo &LHS, const CommonTypeInfo &RHS) { |
186 | return static_cast<const CommonEntityInfo &>(LHS) == RHS && |
187 | LHS.SwiftBridge == RHS.SwiftBridge && |
188 | LHS.NSErrorDomain == RHS.NSErrorDomain; |
189 | } |
190 | |
191 | inline bool operator!=(const CommonTypeInfo &LHS, const CommonTypeInfo &RHS) { |
192 | return !(LHS == RHS); |
193 | } |
194 | |
195 | /// Describes API notes data for an Objective-C class or protocol. |
196 | class ObjCContextInfo : public CommonTypeInfo { |
197 | /// Whether this class has a default nullability. |
198 | LLVM_PREFERRED_TYPE(bool) |
199 | unsigned HasDefaultNullability : 1; |
200 | |
201 | /// The default nullability. |
202 | LLVM_PREFERRED_TYPE(NullabilityKind) |
203 | unsigned DefaultNullability : 2; |
204 | |
205 | /// Whether this class has designated initializers recorded. |
206 | LLVM_PREFERRED_TYPE(bool) |
207 | unsigned HasDesignatedInits : 1; |
208 | |
209 | LLVM_PREFERRED_TYPE(bool) |
210 | unsigned SwiftImportAsNonGenericSpecified : 1; |
211 | LLVM_PREFERRED_TYPE(bool) |
212 | unsigned SwiftImportAsNonGeneric : 1; |
213 | |
214 | LLVM_PREFERRED_TYPE(bool) |
215 | unsigned : 1; |
216 | LLVM_PREFERRED_TYPE(bool) |
217 | unsigned SwiftObjCMembers : 1; |
218 | |
219 | public: |
220 | ObjCContextInfo() |
221 | : HasDefaultNullability(0), DefaultNullability(0), HasDesignatedInits(0), |
222 | SwiftImportAsNonGenericSpecified(false), SwiftImportAsNonGeneric(false), |
223 | SwiftObjCMembersSpecified(false), SwiftObjCMembers(false) {} |
224 | |
225 | /// Determine the default nullability for properties and methods of this |
226 | /// class. |
227 | /// |
228 | /// Returns the default nullability, if implied, or std::nullopt if there is |
229 | /// none. |
230 | std::optional<NullabilityKind> getDefaultNullability() const { |
231 | return HasDefaultNullability |
232 | ? std::optional<NullabilityKind>( |
233 | static_cast<NullabilityKind>(DefaultNullability)) |
234 | : std::nullopt; |
235 | } |
236 | |
237 | /// Set the default nullability for properties and methods of this class. |
238 | void setDefaultNullability(NullabilityKind Kind) { |
239 | HasDefaultNullability = true; |
240 | DefaultNullability = static_cast<unsigned>(Kind); |
241 | } |
242 | |
243 | bool hasDesignatedInits() const { return HasDesignatedInits; } |
244 | void setHasDesignatedInits(bool Value) { HasDesignatedInits = Value; } |
245 | |
246 | std::optional<bool> getSwiftImportAsNonGeneric() const { |
247 | return SwiftImportAsNonGenericSpecified |
248 | ? std::optional<bool>(SwiftImportAsNonGeneric) |
249 | : std::nullopt; |
250 | } |
251 | void setSwiftImportAsNonGeneric(std::optional<bool> Value) { |
252 | SwiftImportAsNonGenericSpecified = Value.has_value(); |
253 | SwiftImportAsNonGeneric = Value.value_or(u: false); |
254 | } |
255 | |
256 | std::optional<bool> getSwiftObjCMembers() const { |
257 | return SwiftObjCMembersSpecified ? std::optional<bool>(SwiftObjCMembers) |
258 | : std::nullopt; |
259 | } |
260 | void setSwiftObjCMembers(std::optional<bool> Value) { |
261 | SwiftObjCMembersSpecified = Value.has_value(); |
262 | SwiftObjCMembers = Value.value_or(u: false); |
263 | } |
264 | |
265 | /// Strip off any information within the class information structure that is |
266 | /// module-local, such as 'audited' flags. |
267 | void stripModuleLocalInfo() { |
268 | HasDefaultNullability = false; |
269 | DefaultNullability = 0; |
270 | } |
271 | |
272 | friend bool operator==(const ObjCContextInfo &, const ObjCContextInfo &); |
273 | |
274 | ObjCContextInfo &operator|=(const ObjCContextInfo &RHS) { |
275 | // Merge inherited info. |
276 | static_cast<CommonTypeInfo &>(*this) |= RHS; |
277 | |
278 | // Merge nullability. |
279 | if (!getDefaultNullability()) |
280 | if (auto Nullability = RHS.getDefaultNullability()) |
281 | setDefaultNullability(*Nullability); |
282 | |
283 | if (!SwiftImportAsNonGenericSpecified) |
284 | setSwiftImportAsNonGeneric(RHS.getSwiftImportAsNonGeneric()); |
285 | |
286 | if (!SwiftObjCMembersSpecified) |
287 | setSwiftObjCMembers(RHS.getSwiftObjCMembers()); |
288 | |
289 | HasDesignatedInits |= RHS.HasDesignatedInits; |
290 | |
291 | return *this; |
292 | } |
293 | |
294 | LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS); |
295 | }; |
296 | |
297 | inline bool operator==(const ObjCContextInfo &LHS, const ObjCContextInfo &RHS) { |
298 | return static_cast<const CommonTypeInfo &>(LHS) == RHS && |
299 | LHS.getDefaultNullability() == RHS.getDefaultNullability() && |
300 | LHS.HasDesignatedInits == RHS.HasDesignatedInits && |
301 | LHS.getSwiftImportAsNonGeneric() == RHS.getSwiftImportAsNonGeneric() && |
302 | LHS.getSwiftObjCMembers() == RHS.getSwiftObjCMembers(); |
303 | } |
304 | |
305 | inline bool operator!=(const ObjCContextInfo &LHS, const ObjCContextInfo &RHS) { |
306 | return !(LHS == RHS); |
307 | } |
308 | |
309 | /// API notes for a variable/property. |
310 | class VariableInfo : public CommonEntityInfo { |
311 | /// Whether this property has been audited for nullability. |
312 | LLVM_PREFERRED_TYPE(bool) |
313 | unsigned NullabilityAudited : 1; |
314 | |
315 | /// The kind of nullability for this property. Only valid if the nullability |
316 | /// has been audited. |
317 | LLVM_PREFERRED_TYPE(NullabilityKind) |
318 | unsigned Nullable : 2; |
319 | |
320 | /// The C type of the variable, as a string. |
321 | std::string Type; |
322 | |
323 | public: |
324 | VariableInfo() : NullabilityAudited(false), Nullable(0) {} |
325 | |
326 | std::optional<NullabilityKind> getNullability() const { |
327 | return NullabilityAudited ? std::optional<NullabilityKind>( |
328 | static_cast<NullabilityKind>(Nullable)) |
329 | : std::nullopt; |
330 | } |
331 | |
332 | void setNullabilityAudited(NullabilityKind kind) { |
333 | NullabilityAudited = true; |
334 | Nullable = static_cast<unsigned>(kind); |
335 | } |
336 | |
337 | const std::string &getType() const { return Type; } |
338 | void setType(const std::string &type) { Type = type; } |
339 | |
340 | friend bool operator==(const VariableInfo &, const VariableInfo &); |
341 | |
342 | VariableInfo &operator|=(const VariableInfo &RHS) { |
343 | static_cast<CommonEntityInfo &>(*this) |= RHS; |
344 | |
345 | if (!NullabilityAudited && RHS.NullabilityAudited) |
346 | setNullabilityAudited(*RHS.getNullability()); |
347 | if (Type.empty()) |
348 | Type = RHS.Type; |
349 | |
350 | return *this; |
351 | } |
352 | |
353 | LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const; |
354 | }; |
355 | |
356 | inline bool operator==(const VariableInfo &LHS, const VariableInfo &RHS) { |
357 | return static_cast<const CommonEntityInfo &>(LHS) == RHS && |
358 | LHS.NullabilityAudited == RHS.NullabilityAudited && |
359 | LHS.Nullable == RHS.Nullable && LHS.Type == RHS.Type; |
360 | } |
361 | |
362 | inline bool operator!=(const VariableInfo &LHS, const VariableInfo &RHS) { |
363 | return !(LHS == RHS); |
364 | } |
365 | |
366 | /// Describes API notes data for an Objective-C property. |
367 | class ObjCPropertyInfo : public VariableInfo { |
368 | LLVM_PREFERRED_TYPE(bool) |
369 | unsigned : 1; |
370 | LLVM_PREFERRED_TYPE(bool) |
371 | unsigned SwiftImportAsAccessors : 1; |
372 | |
373 | public: |
374 | ObjCPropertyInfo() |
375 | : SwiftImportAsAccessorsSpecified(false), SwiftImportAsAccessors(false) {} |
376 | |
377 | std::optional<bool> getSwiftImportAsAccessors() const { |
378 | return SwiftImportAsAccessorsSpecified |
379 | ? std::optional<bool>(SwiftImportAsAccessors) |
380 | : std::nullopt; |
381 | } |
382 | void setSwiftImportAsAccessors(std::optional<bool> Value) { |
383 | SwiftImportAsAccessorsSpecified = Value.has_value(); |
384 | SwiftImportAsAccessors = Value.value_or(u: false); |
385 | } |
386 | |
387 | friend bool operator==(const ObjCPropertyInfo &, const ObjCPropertyInfo &); |
388 | |
389 | /// Merge class-wide information into the given property. |
390 | ObjCPropertyInfo &operator|=(const ObjCContextInfo &RHS) { |
391 | static_cast<CommonEntityInfo &>(*this) |= RHS; |
392 | |
393 | // Merge nullability. |
394 | if (!getNullability()) |
395 | if (auto Nullable = RHS.getDefaultNullability()) |
396 | setNullabilityAudited(*Nullable); |
397 | |
398 | return *this; |
399 | } |
400 | |
401 | ObjCPropertyInfo &operator|=(const ObjCPropertyInfo &RHS) { |
402 | static_cast<VariableInfo &>(*this) |= RHS; |
403 | |
404 | if (!SwiftImportAsAccessorsSpecified) |
405 | setSwiftImportAsAccessors(RHS.getSwiftImportAsAccessors()); |
406 | |
407 | return *this; |
408 | } |
409 | |
410 | LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const; |
411 | }; |
412 | |
413 | inline bool operator==(const ObjCPropertyInfo &LHS, |
414 | const ObjCPropertyInfo &RHS) { |
415 | return static_cast<const VariableInfo &>(LHS) == RHS && |
416 | LHS.getSwiftImportAsAccessors() == RHS.getSwiftImportAsAccessors(); |
417 | } |
418 | |
419 | inline bool operator!=(const ObjCPropertyInfo &LHS, |
420 | const ObjCPropertyInfo &RHS) { |
421 | return !(LHS == RHS); |
422 | } |
423 | |
424 | /// Describes a function or method parameter. |
425 | class ParamInfo : public VariableInfo { |
426 | /// Whether noescape was specified. |
427 | LLVM_PREFERRED_TYPE(bool) |
428 | unsigned NoEscapeSpecified : 1; |
429 | |
430 | /// Whether the this parameter has the 'noescape' attribute. |
431 | LLVM_PREFERRED_TYPE(bool) |
432 | unsigned NoEscape : 1; |
433 | |
434 | /// A biased RetainCountConventionKind, where 0 means "unspecified". |
435 | /// |
436 | /// Only relevant for out-parameters. |
437 | unsigned RawRetainCountConvention : 3; |
438 | |
439 | public: |
440 | ParamInfo() |
441 | : NoEscapeSpecified(false), NoEscape(false), RawRetainCountConvention() {} |
442 | |
443 | std::optional<bool> isNoEscape() const { |
444 | if (!NoEscapeSpecified) |
445 | return std::nullopt; |
446 | return NoEscape; |
447 | } |
448 | void setNoEscape(std::optional<bool> Value) { |
449 | NoEscapeSpecified = Value.has_value(); |
450 | NoEscape = Value.value_or(u: false); |
451 | } |
452 | |
453 | std::optional<RetainCountConventionKind> getRetainCountConvention() const { |
454 | if (!RawRetainCountConvention) |
455 | return std::nullopt; |
456 | return static_cast<RetainCountConventionKind>(RawRetainCountConvention - 1); |
457 | } |
458 | void |
459 | setRetainCountConvention(std::optional<RetainCountConventionKind> Value) { |
460 | RawRetainCountConvention = Value ? static_cast<unsigned>(*Value) + 1 : 0; |
461 | assert(getRetainCountConvention() == Value && "bitfield too small" ); |
462 | } |
463 | |
464 | ParamInfo &operator|=(const ParamInfo &RHS) { |
465 | static_cast<VariableInfo &>(*this) |= RHS; |
466 | |
467 | if (!NoEscapeSpecified && RHS.NoEscapeSpecified) { |
468 | NoEscapeSpecified = true; |
469 | NoEscape = RHS.NoEscape; |
470 | } |
471 | |
472 | if (!RawRetainCountConvention) |
473 | RawRetainCountConvention = RHS.RawRetainCountConvention; |
474 | |
475 | return *this; |
476 | } |
477 | |
478 | friend bool operator==(const ParamInfo &, const ParamInfo &); |
479 | |
480 | LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const; |
481 | }; |
482 | |
483 | inline bool operator==(const ParamInfo &LHS, const ParamInfo &RHS) { |
484 | return static_cast<const VariableInfo &>(LHS) == RHS && |
485 | LHS.NoEscapeSpecified == RHS.NoEscapeSpecified && |
486 | LHS.NoEscape == RHS.NoEscape && |
487 | LHS.RawRetainCountConvention == RHS.RawRetainCountConvention; |
488 | } |
489 | |
490 | inline bool operator!=(const ParamInfo &LHS, const ParamInfo &RHS) { |
491 | return !(LHS == RHS); |
492 | } |
493 | |
494 | /// API notes for a function or method. |
495 | class FunctionInfo : public CommonEntityInfo { |
496 | private: |
497 | static constexpr const uint64_t NullabilityKindMask = 0x3; |
498 | static constexpr const unsigned NullabilityKindSize = 2; |
499 | |
500 | static constexpr const unsigned ReturnInfoIndex = 0; |
501 | |
502 | public: |
503 | // If yes, we consider all types to be non-nullable unless otherwise noted. |
504 | // If this flag is not set, the pointer types are considered to have |
505 | // unknown nullability. |
506 | |
507 | /// Whether the signature has been audited with respect to nullability. |
508 | LLVM_PREFERRED_TYPE(bool) |
509 | unsigned NullabilityAudited : 1; |
510 | |
511 | /// Number of types whose nullability is encoded with the NullabilityPayload. |
512 | unsigned NumAdjustedNullable : 8; |
513 | |
514 | /// A biased RetainCountConventionKind, where 0 means "unspecified". |
515 | unsigned RawRetainCountConvention : 3; |
516 | |
517 | // NullabilityKindSize bits are used to encode the nullability. The info |
518 | // about the return type is stored at position 0, followed by the nullability |
519 | // of the parameters. |
520 | |
521 | /// Stores the nullability of the return type and the parameters. |
522 | uint64_t NullabilityPayload = 0; |
523 | |
524 | /// The result type of this function, as a C type. |
525 | std::string ResultType; |
526 | |
527 | /// The function parameters. |
528 | std::vector<ParamInfo> Params; |
529 | |
530 | FunctionInfo() |
531 | : NullabilityAudited(false), NumAdjustedNullable(0), |
532 | RawRetainCountConvention() {} |
533 | |
534 | static unsigned getMaxNullabilityIndex() { |
535 | return ((sizeof(NullabilityPayload) * CHAR_BIT) / NullabilityKindSize); |
536 | } |
537 | |
538 | void addTypeInfo(unsigned index, NullabilityKind kind) { |
539 | assert(index <= getMaxNullabilityIndex()); |
540 | assert(static_cast<unsigned>(kind) < NullabilityKindMask); |
541 | |
542 | NullabilityAudited = true; |
543 | if (NumAdjustedNullable < index + 1) |
544 | NumAdjustedNullable = index + 1; |
545 | |
546 | // Mask the bits. |
547 | NullabilityPayload &= |
548 | ~(NullabilityKindMask << (index * NullabilityKindSize)); |
549 | |
550 | // Set the value. |
551 | unsigned kindValue = (static_cast<unsigned>(kind)) |
552 | << (index * NullabilityKindSize); |
553 | NullabilityPayload |= kindValue; |
554 | } |
555 | |
556 | /// Adds the return type info. |
557 | void addReturnTypeInfo(NullabilityKind kind) { |
558 | addTypeInfo(index: ReturnInfoIndex, kind); |
559 | } |
560 | |
561 | /// Adds the parameter type info. |
562 | void addParamTypeInfo(unsigned index, NullabilityKind kind) { |
563 | addTypeInfo(index: index + 1, kind); |
564 | } |
565 | |
566 | NullabilityKind getParamTypeInfo(unsigned index) const { |
567 | return getTypeInfo(index: index + 1); |
568 | } |
569 | |
570 | NullabilityKind getReturnTypeInfo() const { return getTypeInfo(index: 0); } |
571 | |
572 | std::optional<RetainCountConventionKind> getRetainCountConvention() const { |
573 | if (!RawRetainCountConvention) |
574 | return std::nullopt; |
575 | return static_cast<RetainCountConventionKind>(RawRetainCountConvention - 1); |
576 | } |
577 | void |
578 | setRetainCountConvention(std::optional<RetainCountConventionKind> Value) { |
579 | RawRetainCountConvention = Value ? static_cast<unsigned>(*Value) + 1 : 0; |
580 | assert(getRetainCountConvention() == Value && "bitfield too small" ); |
581 | } |
582 | |
583 | friend bool operator==(const FunctionInfo &, const FunctionInfo &); |
584 | |
585 | private: |
586 | NullabilityKind getTypeInfo(unsigned index) const { |
587 | assert(NullabilityAudited && |
588 | "Checking the type adjustment on non-audited method." ); |
589 | |
590 | // If we don't have info about this parameter, return the default. |
591 | if (index > NumAdjustedNullable) |
592 | return NullabilityKind::NonNull; |
593 | auto nullability = NullabilityPayload >> (index * NullabilityKindSize); |
594 | return static_cast<NullabilityKind>(nullability & NullabilityKindMask); |
595 | } |
596 | |
597 | public: |
598 | LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const; |
599 | }; |
600 | |
601 | inline bool operator==(const FunctionInfo &LHS, const FunctionInfo &RHS) { |
602 | return static_cast<const CommonEntityInfo &>(LHS) == RHS && |
603 | LHS.NullabilityAudited == RHS.NullabilityAudited && |
604 | LHS.NumAdjustedNullable == RHS.NumAdjustedNullable && |
605 | LHS.NullabilityPayload == RHS.NullabilityPayload && |
606 | LHS.ResultType == RHS.ResultType && LHS.Params == RHS.Params && |
607 | LHS.RawRetainCountConvention == RHS.RawRetainCountConvention; |
608 | } |
609 | |
610 | inline bool operator!=(const FunctionInfo &LHS, const FunctionInfo &RHS) { |
611 | return !(LHS == RHS); |
612 | } |
613 | |
614 | /// Describes API notes data for an Objective-C method. |
615 | class ObjCMethodInfo : public FunctionInfo { |
616 | public: |
617 | /// Whether this is a designated initializer of its class. |
618 | LLVM_PREFERRED_TYPE(bool) |
619 | unsigned DesignatedInit : 1; |
620 | |
621 | /// Whether this is a required initializer. |
622 | LLVM_PREFERRED_TYPE(bool) |
623 | unsigned RequiredInit : 1; |
624 | |
625 | ObjCMethodInfo() : DesignatedInit(false), RequiredInit(false) {} |
626 | |
627 | friend bool operator==(const ObjCMethodInfo &, const ObjCMethodInfo &); |
628 | |
629 | ObjCMethodInfo &operator|=(const ObjCContextInfo &RHS) { |
630 | // Merge Nullability. |
631 | if (!NullabilityAudited) { |
632 | if (auto Nullable = RHS.getDefaultNullability()) { |
633 | NullabilityAudited = true; |
634 | addTypeInfo(index: 0, kind: *Nullable); |
635 | } |
636 | } |
637 | return *this; |
638 | } |
639 | |
640 | LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS); |
641 | }; |
642 | |
643 | inline bool operator==(const ObjCMethodInfo &LHS, const ObjCMethodInfo &RHS) { |
644 | return static_cast<const FunctionInfo &>(LHS) == RHS && |
645 | LHS.DesignatedInit == RHS.DesignatedInit && |
646 | LHS.RequiredInit == RHS.RequiredInit; |
647 | } |
648 | |
649 | inline bool operator!=(const ObjCMethodInfo &LHS, const ObjCMethodInfo &RHS) { |
650 | return !(LHS == RHS); |
651 | } |
652 | |
653 | /// Describes API notes data for a global variable. |
654 | class GlobalVariableInfo : public VariableInfo { |
655 | public: |
656 | GlobalVariableInfo() {} |
657 | }; |
658 | |
659 | /// Describes API notes data for a global function. |
660 | class GlobalFunctionInfo : public FunctionInfo { |
661 | public: |
662 | GlobalFunctionInfo() {} |
663 | }; |
664 | |
665 | /// Describes API notes data for an enumerator. |
666 | class EnumConstantInfo : public CommonEntityInfo { |
667 | public: |
668 | EnumConstantInfo() {} |
669 | }; |
670 | |
671 | /// Describes API notes data for a tag. |
672 | class TagInfo : public CommonTypeInfo { |
673 | LLVM_PREFERRED_TYPE(bool) |
674 | unsigned HasFlagEnum : 1; |
675 | LLVM_PREFERRED_TYPE(bool) |
676 | unsigned IsFlagEnum : 1; |
677 | |
678 | public: |
679 | std::optional<std::string> SwiftImportAs; |
680 | std::optional<std::string> SwiftRetainOp; |
681 | std::optional<std::string> SwiftReleaseOp; |
682 | |
683 | std::optional<EnumExtensibilityKind> EnumExtensibility; |
684 | |
685 | TagInfo() : HasFlagEnum(0), IsFlagEnum(0) {} |
686 | |
687 | std::optional<bool> isFlagEnum() const { |
688 | if (HasFlagEnum) |
689 | return IsFlagEnum; |
690 | return std::nullopt; |
691 | } |
692 | void setFlagEnum(std::optional<bool> Value) { |
693 | HasFlagEnum = Value.has_value(); |
694 | IsFlagEnum = Value.value_or(u: false); |
695 | } |
696 | |
697 | TagInfo &operator|=(const TagInfo &RHS) { |
698 | static_cast<CommonTypeInfo &>(*this) |= RHS; |
699 | |
700 | if (!SwiftImportAs) |
701 | SwiftImportAs = RHS.SwiftImportAs; |
702 | if (!SwiftRetainOp) |
703 | SwiftRetainOp = RHS.SwiftRetainOp; |
704 | if (!SwiftReleaseOp) |
705 | SwiftReleaseOp = RHS.SwiftReleaseOp; |
706 | |
707 | if (!HasFlagEnum) |
708 | setFlagEnum(RHS.isFlagEnum()); |
709 | |
710 | if (!EnumExtensibility) |
711 | EnumExtensibility = RHS.EnumExtensibility; |
712 | |
713 | return *this; |
714 | } |
715 | |
716 | friend bool operator==(const TagInfo &, const TagInfo &); |
717 | |
718 | LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS); |
719 | }; |
720 | |
721 | inline bool operator==(const TagInfo &LHS, const TagInfo &RHS) { |
722 | return static_cast<const CommonTypeInfo &>(LHS) == RHS && |
723 | LHS.SwiftImportAs == RHS.SwiftImportAs && |
724 | LHS.SwiftRetainOp == RHS.SwiftRetainOp && |
725 | LHS.SwiftReleaseOp == RHS.SwiftReleaseOp && |
726 | LHS.isFlagEnum() == RHS.isFlagEnum() && |
727 | LHS.EnumExtensibility == RHS.EnumExtensibility; |
728 | } |
729 | |
730 | inline bool operator!=(const TagInfo &LHS, const TagInfo &RHS) { |
731 | return !(LHS == RHS); |
732 | } |
733 | |
734 | /// Describes API notes data for a typedef. |
735 | class TypedefInfo : public CommonTypeInfo { |
736 | public: |
737 | std::optional<SwiftNewTypeKind> SwiftWrapper; |
738 | |
739 | TypedefInfo() {} |
740 | |
741 | TypedefInfo &operator|=(const TypedefInfo &RHS) { |
742 | static_cast<CommonTypeInfo &>(*this) |= RHS; |
743 | if (!SwiftWrapper) |
744 | SwiftWrapper = RHS.SwiftWrapper; |
745 | return *this; |
746 | } |
747 | |
748 | friend bool operator==(const TypedefInfo &, const TypedefInfo &); |
749 | |
750 | LLVM_DUMP_METHOD void dump(llvm::raw_ostream &OS) const; |
751 | }; |
752 | |
753 | inline bool operator==(const TypedefInfo &LHS, const TypedefInfo &RHS) { |
754 | return static_cast<const CommonTypeInfo &>(LHS) == RHS && |
755 | LHS.SwiftWrapper == RHS.SwiftWrapper; |
756 | } |
757 | |
758 | inline bool operator!=(const TypedefInfo &LHS, const TypedefInfo &RHS) { |
759 | return !(LHS == RHS); |
760 | } |
761 | |
762 | /// The file extension used for the source representation of API notes. |
763 | static const constexpr char SOURCE_APINOTES_EXTENSION[] = "apinotes" ; |
764 | |
765 | /// Opaque context ID used to refer to an Objective-C class or protocol or a C++ |
766 | /// namespace. |
767 | class ContextID { |
768 | public: |
769 | unsigned Value; |
770 | |
771 | explicit ContextID(unsigned value) : Value(value) {} |
772 | }; |
773 | |
774 | enum class ContextKind : uint8_t { |
775 | ObjCClass = 0, |
776 | ObjCProtocol = 1, |
777 | Namespace = 2, |
778 | }; |
779 | |
780 | struct Context { |
781 | ContextID id; |
782 | ContextKind kind; |
783 | |
784 | Context(ContextID id, ContextKind kind) : id(id), kind(kind) {} |
785 | }; |
786 | |
787 | /// A temporary reference to an Objective-C selector, suitable for |
788 | /// referencing selector data on the stack. |
789 | /// |
790 | /// Instances of this struct do not store references to any of the |
791 | /// data they contain; it is up to the user to ensure that the data |
792 | /// referenced by the identifier list persists. |
793 | struct ObjCSelectorRef { |
794 | unsigned NumArgs; |
795 | llvm::ArrayRef<llvm::StringRef> Identifiers; |
796 | }; |
797 | } // namespace api_notes |
798 | } // namespace clang |
799 | |
800 | #endif |
801 | |