/
DeclObjC.h
2899 lines (2296 loc) · 101 KB
/
DeclObjC.h
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
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
//===- DeclObjC.h - Classes for representing declarations -------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the DeclObjC interface and subclasses.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECLOBJC_H
#define LLVM_CLANG_AST_DECLOBJC_H
#include "clang/AST/Decl.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/Redeclarable.h"
#include "clang/AST/SelectorLocationsKind.h"
#include "clang/AST/Type.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/None.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/TrailingObjects.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <iterator>
#include <string>
#include <utility>
namespace clang {
class ASTContext;
class CompoundStmt;
class CXXCtorInitializer;
class Expr;
class ObjCCategoryDecl;
class ObjCCategoryImplDecl;
class ObjCImplementationDecl;
class ObjCInterfaceDecl;
class ObjCIvarDecl;
class ObjCPropertyDecl;
class ObjCPropertyImplDecl;
class ObjCProtocolDecl;
class Stmt;
class ObjCListBase {
protected:
/// List is an array of pointers to objects that are not owned by this object.
void **List = nullptr;
unsigned NumElts = 0;
public:
ObjCListBase() = default;
ObjCListBase(const ObjCListBase &) = delete;
ObjCListBase &operator=(const ObjCListBase &) = delete;
unsigned size() const { return NumElts; }
bool empty() const { return NumElts == 0; }
protected:
void set(void *const* InList, unsigned Elts, ASTContext &Ctx);
};
/// ObjCList - This is a simple template class used to hold various lists of
/// decls etc, which is heavily used by the ObjC front-end. This only use case
/// this supports is setting the list all at once and then reading elements out
/// of it.
template <typename T>
class ObjCList : public ObjCListBase {
public:
void set(T* const* InList, unsigned Elts, ASTContext &Ctx) {
ObjCListBase::set(reinterpret_cast<void*const*>(InList), Elts, Ctx);
}
using iterator = T* const *;
iterator begin() const { return (iterator)List; }
iterator end() const { return (iterator)List+NumElts; }
T* operator[](unsigned Idx) const {
assert(Idx < NumElts && "Invalid access");
return (T*)List[Idx];
}
};
/// A list of Objective-C protocols, along with the source
/// locations at which they were referenced.
class ObjCProtocolList : public ObjCList<ObjCProtocolDecl> {
SourceLocation *Locations = nullptr;
using ObjCList<ObjCProtocolDecl>::set;
public:
ObjCProtocolList() = default;
using loc_iterator = const SourceLocation *;
loc_iterator loc_begin() const { return Locations; }
loc_iterator loc_end() const { return Locations + size(); }
void set(ObjCProtocolDecl* const* InList, unsigned Elts,
const SourceLocation *Locs, ASTContext &Ctx);
};
/// ObjCMethodDecl - Represents an instance or class method declaration.
/// ObjC methods can be declared within 4 contexts: class interfaces,
/// categories, protocols, and class implementations. While C++ member
/// functions leverage C syntax, Objective-C method syntax is modeled after
/// Smalltalk (using colons to specify argument types/expressions).
/// Here are some brief examples:
///
/// Setter/getter instance methods:
/// - (void)setMenu:(NSMenu *)menu;
/// - (NSMenu *)menu;
///
/// Instance method that takes 2 NSView arguments:
/// - (void)replaceSubview:(NSView *)oldView with:(NSView *)newView;
///
/// Getter class method:
/// + (NSMenu *)defaultMenu;
///
/// A selector represents a unique name for a method. The selector names for
/// the above methods are setMenu:, menu, replaceSubview:with:, and defaultMenu.
///
class ObjCMethodDecl : public NamedDecl, public DeclContext {
// This class stores some data in DeclContext::ObjCMethodDeclBits
// to save some space. Use the provided accessors to access it.
public:
enum ImplementationControl { None, Required, Optional };
private:
/// Return type of this method.
QualType MethodDeclType;
/// Type source information for the return type.
TypeSourceInfo *ReturnTInfo;
/// Array of ParmVarDecls for the formal parameters of this method
/// and optionally followed by selector locations.
void *ParamsAndSelLocs = nullptr;
unsigned NumParams = 0;
/// List of attributes for this method declaration.
SourceLocation DeclEndLoc; // the location of the ';' or '{'.
/// The following are only used for method definitions, null otherwise.
LazyDeclStmtPtr Body;
/// SelfDecl - Decl for the implicit self parameter. This is lazily
/// constructed by createImplicitParams.
ImplicitParamDecl *SelfDecl = nullptr;
/// CmdDecl - Decl for the implicit _cmd parameter. This is lazily
/// constructed by createImplicitParams.
ImplicitParamDecl *CmdDecl = nullptr;
ObjCMethodDecl(SourceLocation beginLoc, SourceLocation endLoc,
Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
DeclContext *contextDecl, bool isInstance = true,
bool isVariadic = false, bool isPropertyAccessor = false,
bool isImplicitlyDeclared = false, bool isDefined = false,
ImplementationControl impControl = None,
bool HasRelatedResultType = false);
SelectorLocationsKind getSelLocsKind() const {
return static_cast<SelectorLocationsKind>(ObjCMethodDeclBits.SelLocsKind);
}
void setSelLocsKind(SelectorLocationsKind Kind) {
ObjCMethodDeclBits.SelLocsKind = Kind;
}
bool hasStandardSelLocs() const {
return getSelLocsKind() != SelLoc_NonStandard;
}
/// Get a pointer to the stored selector identifiers locations array.
/// No locations will be stored if HasStandardSelLocs is true.
SourceLocation *getStoredSelLocs() {
return reinterpret_cast<SourceLocation *>(getParams() + NumParams);
}
const SourceLocation *getStoredSelLocs() const {
return reinterpret_cast<const SourceLocation *>(getParams() + NumParams);
}
/// Get a pointer to the stored selector identifiers locations array.
/// No locations will be stored if HasStandardSelLocs is true.
ParmVarDecl **getParams() {
return reinterpret_cast<ParmVarDecl **>(ParamsAndSelLocs);
}
const ParmVarDecl *const *getParams() const {
return reinterpret_cast<const ParmVarDecl *const *>(ParamsAndSelLocs);
}
/// Get the number of stored selector identifiers locations.
/// No locations will be stored if HasStandardSelLocs is true.
unsigned getNumStoredSelLocs() const {
if (hasStandardSelLocs())
return 0;
return getNumSelectorLocs();
}
void setParamsAndSelLocs(ASTContext &C,
ArrayRef<ParmVarDecl*> Params,
ArrayRef<SourceLocation> SelLocs);
/// A definition will return its interface declaration.
/// An interface declaration will return its definition.
/// Otherwise it will return itself.
ObjCMethodDecl *getNextRedeclarationImpl() override;
public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
static ObjCMethodDecl *
Create(ASTContext &C, SourceLocation beginLoc, SourceLocation endLoc,
Selector SelInfo, QualType T, TypeSourceInfo *ReturnTInfo,
DeclContext *contextDecl, bool isInstance = true,
bool isVariadic = false, bool isPropertyAccessor = false,
bool isImplicitlyDeclared = false, bool isDefined = false,
ImplementationControl impControl = None,
bool HasRelatedResultType = false);
static ObjCMethodDecl *CreateDeserialized(ASTContext &C, unsigned ID);
ObjCMethodDecl *getCanonicalDecl() override;
const ObjCMethodDecl *getCanonicalDecl() const {
return const_cast<ObjCMethodDecl*>(this)->getCanonicalDecl();
}
ObjCDeclQualifier getObjCDeclQualifier() const {
return static_cast<ObjCDeclQualifier>(ObjCMethodDeclBits.objcDeclQualifier);
}
void setObjCDeclQualifier(ObjCDeclQualifier QV) {
ObjCMethodDeclBits.objcDeclQualifier = QV;
}
/// Determine whether this method has a result type that is related
/// to the message receiver's type.
bool hasRelatedResultType() const {
return ObjCMethodDeclBits.RelatedResultType;
}
/// Note whether this method has a related result type.
void setRelatedResultType(bool RRT = true) {
ObjCMethodDeclBits.RelatedResultType = RRT;
}
/// True if this is a method redeclaration in the same interface.
bool isRedeclaration() const { return ObjCMethodDeclBits.IsRedeclaration; }
void setIsRedeclaration(bool RD) { ObjCMethodDeclBits.IsRedeclaration = RD; }
void setAsRedeclaration(const ObjCMethodDecl *PrevMethod);
/// True if redeclared in the same interface.
bool hasRedeclaration() const { return ObjCMethodDeclBits.HasRedeclaration; }
void setHasRedeclaration(bool HRD) const {
ObjCMethodDeclBits.HasRedeclaration = HRD;
}
/// Returns the location where the declarator ends. It will be
/// the location of ';' for a method declaration and the location of '{'
/// for a method definition.
SourceLocation getDeclaratorEndLoc() const { return DeclEndLoc; }
// Location information, modeled after the Stmt API.
SourceLocation getBeginLoc() const LLVM_READONLY { return getLocation(); }
SourceLocation getEndLoc() const LLVM_READONLY;
SourceRange getSourceRange() const override LLVM_READONLY {
return SourceRange(getLocation(), getEndLoc());
}
SourceLocation getSelectorStartLoc() const {
if (isImplicit())
return getBeginLoc();
return getSelectorLoc(0);
}
SourceLocation getSelectorLoc(unsigned Index) const {
assert(Index < getNumSelectorLocs() && "Index out of range!");
if (hasStandardSelLocs())
return getStandardSelectorLoc(Index, getSelector(),
getSelLocsKind() == SelLoc_StandardWithSpace,
parameters(),
DeclEndLoc);
return getStoredSelLocs()[Index];
}
void getSelectorLocs(SmallVectorImpl<SourceLocation> &SelLocs) const;
unsigned getNumSelectorLocs() const {
if (isImplicit())
return 0;
Selector Sel = getSelector();
if (Sel.isUnarySelector())
return 1;
return Sel.getNumArgs();
}
ObjCInterfaceDecl *getClassInterface();
const ObjCInterfaceDecl *getClassInterface() const {
return const_cast<ObjCMethodDecl*>(this)->getClassInterface();
}
Selector getSelector() const { return getDeclName().getObjCSelector(); }
QualType getReturnType() const { return MethodDeclType; }
void setReturnType(QualType T) { MethodDeclType = T; }
SourceRange getReturnTypeSourceRange() const;
/// Determine the type of an expression that sends a message to this
/// function. This replaces the type parameters with the types they would
/// get if the receiver was parameterless (e.g. it may replace the type
/// parameter with 'id').
QualType getSendResultType() const;
/// Determine the type of an expression that sends a message to this
/// function with the given receiver type.
QualType getSendResultType(QualType receiverType) const;
TypeSourceInfo *getReturnTypeSourceInfo() const { return ReturnTInfo; }
void setReturnTypeSourceInfo(TypeSourceInfo *TInfo) { ReturnTInfo = TInfo; }
// Iterator access to formal parameters.
unsigned param_size() const { return NumParams; }
using param_const_iterator = const ParmVarDecl *const *;
using param_iterator = ParmVarDecl *const *;
using param_range = llvm::iterator_range<param_iterator>;
using param_const_range = llvm::iterator_range<param_const_iterator>;
param_const_iterator param_begin() const {
return param_const_iterator(getParams());
}
param_const_iterator param_end() const {
return param_const_iterator(getParams() + NumParams);
}
param_iterator param_begin() { return param_iterator(getParams()); }
param_iterator param_end() { return param_iterator(getParams() + NumParams); }
// This method returns and of the parameters which are part of the selector
// name mangling requirements.
param_const_iterator sel_param_end() const {
return param_begin() + getSelector().getNumArgs();
}
// ArrayRef access to formal parameters. This should eventually
// replace the iterator interface above.
ArrayRef<ParmVarDecl*> parameters() const {
return llvm::makeArrayRef(const_cast<ParmVarDecl**>(getParams()),
NumParams);
}
ParmVarDecl *getParamDecl(unsigned Idx) {
assert(Idx < NumParams && "Index out of bounds!");
return getParams()[Idx];
}
const ParmVarDecl *getParamDecl(unsigned Idx) const {
return const_cast<ObjCMethodDecl *>(this)->getParamDecl(Idx);
}
/// Sets the method's parameters and selector source locations.
/// If the method is implicit (not coming from source) \p SelLocs is
/// ignored.
void setMethodParams(ASTContext &C,
ArrayRef<ParmVarDecl*> Params,
ArrayRef<SourceLocation> SelLocs = llvm::None);
// Iterator access to parameter types.
struct GetTypeFn {
QualType operator()(const ParmVarDecl *PD) const { return PD->getType(); }
};
using param_type_iterator =
llvm::mapped_iterator<param_const_iterator, GetTypeFn>;
param_type_iterator param_type_begin() const {
return llvm::map_iterator(param_begin(), GetTypeFn());
}
param_type_iterator param_type_end() const {
return llvm::map_iterator(param_end(), GetTypeFn());
}
/// createImplicitParams - Used to lazily create the self and cmd
/// implict parameters. This must be called prior to using getSelfDecl()
/// or getCmdDecl(). The call is ignored if the implicit parameters
/// have already been created.
void createImplicitParams(ASTContext &Context, const ObjCInterfaceDecl *ID);
/// \return the type for \c self and set \arg selfIsPseudoStrong and
/// \arg selfIsConsumed accordingly.
QualType getSelfType(ASTContext &Context, const ObjCInterfaceDecl *OID,
bool &selfIsPseudoStrong, bool &selfIsConsumed);
ImplicitParamDecl * getSelfDecl() const { return SelfDecl; }
void setSelfDecl(ImplicitParamDecl *SD) { SelfDecl = SD; }
ImplicitParamDecl * getCmdDecl() const { return CmdDecl; }
void setCmdDecl(ImplicitParamDecl *CD) { CmdDecl = CD; }
/// Determines the family of this method.
ObjCMethodFamily getMethodFamily() const;
bool isInstanceMethod() const { return ObjCMethodDeclBits.IsInstance; }
void setInstanceMethod(bool isInst) {
ObjCMethodDeclBits.IsInstance = isInst;
}
bool isVariadic() const { return ObjCMethodDeclBits.IsVariadic; }
void setVariadic(bool isVar) { ObjCMethodDeclBits.IsVariadic = isVar; }
bool isClassMethod() const { return !isInstanceMethod(); }
bool isPropertyAccessor() const {
return ObjCMethodDeclBits.IsPropertyAccessor;
}
void setPropertyAccessor(bool isAccessor) {
ObjCMethodDeclBits.IsPropertyAccessor = isAccessor;
}
bool isDefined() const { return ObjCMethodDeclBits.IsDefined; }
void setDefined(bool isDefined) { ObjCMethodDeclBits.IsDefined = isDefined; }
/// Whether this method overrides any other in the class hierarchy.
///
/// A method is said to override any method in the class's
/// base classes, its protocols, or its categories' protocols, that has
/// the same selector and is of the same kind (class or instance).
/// A method in an implementation is not considered as overriding the same
/// method in the interface or its categories.
bool isOverriding() const { return ObjCMethodDeclBits.IsOverriding; }
void setOverriding(bool IsOver) { ObjCMethodDeclBits.IsOverriding = IsOver; }
/// Return overridden methods for the given \p Method.
///
/// An ObjC method is considered to override any method in the class's
/// base classes (and base's categories), its protocols, or its categories'
/// protocols, that has
/// the same selector and is of the same kind (class or instance).
/// A method in an implementation is not considered as overriding the same
/// method in the interface or its categories.
void getOverriddenMethods(
SmallVectorImpl<const ObjCMethodDecl *> &Overridden) const;
/// True if the method was a definition but its body was skipped.
bool hasSkippedBody() const { return ObjCMethodDeclBits.HasSkippedBody; }
void setHasSkippedBody(bool Skipped = true) {
ObjCMethodDeclBits.HasSkippedBody = Skipped;
}
/// Returns the property associated with this method's selector.
///
/// Note that even if this particular method is not marked as a property
/// accessor, it is still possible for it to match a property declared in a
/// superclass. Pass \c false if you only want to check the current class.
const ObjCPropertyDecl *findPropertyDecl(bool CheckOverrides = true) const;
// Related to protocols declared in \@protocol
void setDeclImplementation(ImplementationControl ic) {
ObjCMethodDeclBits.DeclImplementation = ic;
}
ImplementationControl getImplementationControl() const {
return ImplementationControl(ObjCMethodDeclBits.DeclImplementation);
}
bool isOptional() const {
return getImplementationControl() == Optional;
}
/// Returns true if this specific method declaration is marked with the
/// designated initializer attribute.
bool isThisDeclarationADesignatedInitializer() const;
/// Returns true if the method selector resolves to a designated initializer
/// in the class's interface.
///
/// \param InitMethod if non-null and the function returns true, it receives
/// the method declaration that was marked with the designated initializer
/// attribute.
bool isDesignatedInitializerForTheInterface(
const ObjCMethodDecl **InitMethod = nullptr) const;
/// Determine whether this method has a body.
bool hasBody() const override { return Body.isValid(); }
/// Retrieve the body of this method, if it has one.
Stmt *getBody() const override;
void setLazyBody(uint64_t Offset) { Body = Offset; }
CompoundStmt *getCompoundBody() { return (CompoundStmt*)getBody(); }
void setBody(Stmt *B) { Body = B; }
/// Returns whether this specific method is a definition.
bool isThisDeclarationADefinition() const { return hasBody(); }
/// Is this method defined in the NSObject base class?
bool definedInNSObject(const ASTContext &) const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ObjCMethod; }
static DeclContext *castToDeclContext(const ObjCMethodDecl *D) {
return static_cast<DeclContext *>(const_cast<ObjCMethodDecl*>(D));
}
static ObjCMethodDecl *castFromDeclContext(const DeclContext *DC) {
return static_cast<ObjCMethodDecl *>(const_cast<DeclContext*>(DC));
}
};
/// Describes the variance of a given generic parameter.
enum class ObjCTypeParamVariance : uint8_t {
/// The parameter is invariant: must match exactly.
Invariant,
/// The parameter is covariant, e.g., X<T> is a subtype of X<U> when
/// the type parameter is covariant and T is a subtype of U.
Covariant,
/// The parameter is contravariant, e.g., X<T> is a subtype of X<U>
/// when the type parameter is covariant and U is a subtype of T.
Contravariant,
};
/// Represents the declaration of an Objective-C type parameter.
///
/// \code
/// @interface NSDictionary<Key : id<NSCopying>, Value>
/// @end
/// \endcode
///
/// In the example above, both \c Key and \c Value are represented by
/// \c ObjCTypeParamDecl. \c Key has an explicit bound of \c id<NSCopying>,
/// while \c Value gets an implicit bound of \c id.
///
/// Objective-C type parameters are typedef-names in the grammar,
class ObjCTypeParamDecl : public TypedefNameDecl {
/// Index of this type parameter in the type parameter list.
unsigned Index : 14;
/// The variance of the type parameter.
unsigned Variance : 2;
/// The location of the variance, if any.
SourceLocation VarianceLoc;
/// The location of the ':', which will be valid when the bound was
/// explicitly specified.
SourceLocation ColonLoc;
ObjCTypeParamDecl(ASTContext &ctx, DeclContext *dc,
ObjCTypeParamVariance variance, SourceLocation varianceLoc,
unsigned index,
SourceLocation nameLoc, IdentifierInfo *name,
SourceLocation colonLoc, TypeSourceInfo *boundInfo)
: TypedefNameDecl(ObjCTypeParam, ctx, dc, nameLoc, nameLoc, name,
boundInfo),
Index(index), Variance(static_cast<unsigned>(variance)),
VarianceLoc(varianceLoc), ColonLoc(colonLoc) {}
void anchor() override;
public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
static ObjCTypeParamDecl *Create(ASTContext &ctx, DeclContext *dc,
ObjCTypeParamVariance variance,
SourceLocation varianceLoc,
unsigned index,
SourceLocation nameLoc,
IdentifierInfo *name,
SourceLocation colonLoc,
TypeSourceInfo *boundInfo);
static ObjCTypeParamDecl *CreateDeserialized(ASTContext &ctx, unsigned ID);
SourceRange getSourceRange() const override LLVM_READONLY;
/// Determine the variance of this type parameter.
ObjCTypeParamVariance getVariance() const {
return static_cast<ObjCTypeParamVariance>(Variance);
}
/// Set the variance of this type parameter.
void setVariance(ObjCTypeParamVariance variance) {
Variance = static_cast<unsigned>(variance);
}
/// Retrieve the location of the variance keyword.
SourceLocation getVarianceLoc() const { return VarianceLoc; }
/// Retrieve the index into its type parameter list.
unsigned getIndex() const { return Index; }
/// Whether this type parameter has an explicitly-written type bound, e.g.,
/// "T : NSView".
bool hasExplicitBound() const { return ColonLoc.isValid(); }
/// Retrieve the location of the ':' separating the type parameter name
/// from the explicitly-specified bound.
SourceLocation getColonLoc() const { return ColonLoc; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ObjCTypeParam; }
};
/// Stores a list of Objective-C type parameters for a parameterized class
/// or a category/extension thereof.
///
/// \code
/// @interface NSArray<T> // stores the <T>
/// @end
/// \endcode
class ObjCTypeParamList final
: private llvm::TrailingObjects<ObjCTypeParamList, ObjCTypeParamDecl *> {
/// Stores the components of a SourceRange as a POD.
struct PODSourceRange {
unsigned Begin;
unsigned End;
};
union {
/// Location of the left and right angle brackets.
PODSourceRange Brackets;
// Used only for alignment.
ObjCTypeParamDecl *AlignmentHack;
};
/// The number of parameters in the list, which are tail-allocated.
unsigned NumParams;
ObjCTypeParamList(SourceLocation lAngleLoc,
ArrayRef<ObjCTypeParamDecl *> typeParams,
SourceLocation rAngleLoc);
public:
friend TrailingObjects;
/// Create a new Objective-C type parameter list.
static ObjCTypeParamList *create(ASTContext &ctx,
SourceLocation lAngleLoc,
ArrayRef<ObjCTypeParamDecl *> typeParams,
SourceLocation rAngleLoc);
/// Iterate through the type parameters in the list.
using iterator = ObjCTypeParamDecl **;
iterator begin() { return getTrailingObjects<ObjCTypeParamDecl *>(); }
iterator end() { return begin() + size(); }
/// Determine the number of type parameters in this list.
unsigned size() const { return NumParams; }
// Iterate through the type parameters in the list.
using const_iterator = ObjCTypeParamDecl * const *;
const_iterator begin() const {
return getTrailingObjects<ObjCTypeParamDecl *>();
}
const_iterator end() const {
return begin() + size();
}
ObjCTypeParamDecl *front() const {
assert(size() > 0 && "empty Objective-C type parameter list");
return *begin();
}
ObjCTypeParamDecl *back() const {
assert(size() > 0 && "empty Objective-C type parameter list");
return *(end() - 1);
}
SourceLocation getLAngleLoc() const {
return SourceLocation::getFromRawEncoding(Brackets.Begin);
}
SourceLocation getRAngleLoc() const {
return SourceLocation::getFromRawEncoding(Brackets.End);
}
SourceRange getSourceRange() const {
return SourceRange(getLAngleLoc(), getRAngleLoc());
}
/// Gather the default set of type arguments to be substituted for
/// these type parameters when dealing with an unspecialized type.
void gatherDefaultTypeArgs(SmallVectorImpl<QualType> &typeArgs) const;
};
enum class ObjCPropertyQueryKind : uint8_t {
OBJC_PR_query_unknown = 0x00,
OBJC_PR_query_instance,
OBJC_PR_query_class
};
/// Represents one property declaration in an Objective-C interface.
///
/// For example:
/// \code{.mm}
/// \@property (assign, readwrite) int MyProperty;
/// \endcode
class ObjCPropertyDecl : public NamedDecl {
void anchor() override;
public:
enum PropertyAttributeKind {
OBJC_PR_noattr = 0x00,
OBJC_PR_readonly = 0x01,
OBJC_PR_getter = 0x02,
OBJC_PR_assign = 0x04,
OBJC_PR_readwrite = 0x08,
OBJC_PR_retain = 0x10,
OBJC_PR_copy = 0x20,
OBJC_PR_nonatomic = 0x40,
OBJC_PR_setter = 0x80,
OBJC_PR_atomic = 0x100,
OBJC_PR_weak = 0x200,
OBJC_PR_strong = 0x400,
OBJC_PR_unsafe_unretained = 0x800,
/// Indicates that the nullability of the type was spelled with a
/// property attribute rather than a type qualifier.
OBJC_PR_nullability = 0x1000,
OBJC_PR_null_resettable = 0x2000,
OBJC_PR_class = 0x4000
// Adding a property should change NumPropertyAttrsBits
};
enum {
/// Number of bits fitting all the property attributes.
NumPropertyAttrsBits = 15
};
enum SetterKind { Assign, Retain, Copy, Weak };
enum PropertyControl { None, Required, Optional };
private:
// location of \@property
SourceLocation AtLoc;
// location of '(' starting attribute list or null.
SourceLocation LParenLoc;
QualType DeclType;
TypeSourceInfo *DeclTypeSourceInfo;
unsigned PropertyAttributes : NumPropertyAttrsBits;
unsigned PropertyAttributesAsWritten : NumPropertyAttrsBits;
// \@required/\@optional
unsigned PropertyImplementation : 2;
// getter name of NULL if no getter
Selector GetterName;
// setter name of NULL if no setter
Selector SetterName;
// location of the getter attribute's value
SourceLocation GetterNameLoc;
// location of the setter attribute's value
SourceLocation SetterNameLoc;
// Declaration of getter instance method
ObjCMethodDecl *GetterMethodDecl = nullptr;
// Declaration of setter instance method
ObjCMethodDecl *SetterMethodDecl = nullptr;
// Synthesize ivar for this property
ObjCIvarDecl *PropertyIvarDecl = nullptr;
ObjCPropertyDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id,
SourceLocation AtLocation, SourceLocation LParenLocation,
QualType T, TypeSourceInfo *TSI,
PropertyControl propControl)
: NamedDecl(ObjCProperty, DC, L, Id), AtLoc(AtLocation),
LParenLoc(LParenLocation), DeclType(T), DeclTypeSourceInfo(TSI),
PropertyAttributes(OBJC_PR_noattr),
PropertyAttributesAsWritten(OBJC_PR_noattr),
PropertyImplementation(propControl), GetterName(Selector()),
SetterName(Selector()) {}
public:
static ObjCPropertyDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation L,
IdentifierInfo *Id, SourceLocation AtLocation,
SourceLocation LParenLocation,
QualType T,
TypeSourceInfo *TSI,
PropertyControl propControl = None);
static ObjCPropertyDecl *CreateDeserialized(ASTContext &C, unsigned ID);
SourceLocation getAtLoc() const { return AtLoc; }
void setAtLoc(SourceLocation L) { AtLoc = L; }
SourceLocation getLParenLoc() const { return LParenLoc; }
void setLParenLoc(SourceLocation L) { LParenLoc = L; }
TypeSourceInfo *getTypeSourceInfo() const { return DeclTypeSourceInfo; }
QualType getType() const { return DeclType; }
void setType(QualType T, TypeSourceInfo *TSI) {
DeclType = T;
DeclTypeSourceInfo = TSI;
}
/// Retrieve the type when this property is used with a specific base object
/// type.
QualType getUsageType(QualType objectType) const;
PropertyAttributeKind getPropertyAttributes() const {
return PropertyAttributeKind(PropertyAttributes);
}
void setPropertyAttributes(PropertyAttributeKind PRVal) {
PropertyAttributes |= PRVal;
}
void overwritePropertyAttributes(unsigned PRVal) {
PropertyAttributes = PRVal;
}
PropertyAttributeKind getPropertyAttributesAsWritten() const {
return PropertyAttributeKind(PropertyAttributesAsWritten);
}
void setPropertyAttributesAsWritten(PropertyAttributeKind PRVal) {
PropertyAttributesAsWritten = PRVal;
}
// Helper methods for accessing attributes.
/// isReadOnly - Return true iff the property has a setter.
bool isReadOnly() const {
return (PropertyAttributes & OBJC_PR_readonly);
}
/// isAtomic - Return true if the property is atomic.
bool isAtomic() const {
return (PropertyAttributes & OBJC_PR_atomic);
}
/// isRetaining - Return true if the property retains its value.
bool isRetaining() const {
return (PropertyAttributes &
(OBJC_PR_retain | OBJC_PR_strong | OBJC_PR_copy));
}
bool isInstanceProperty() const { return !isClassProperty(); }
bool isClassProperty() const { return PropertyAttributes & OBJC_PR_class; }
ObjCPropertyQueryKind getQueryKind() const {
return isClassProperty() ? ObjCPropertyQueryKind::OBJC_PR_query_class :
ObjCPropertyQueryKind::OBJC_PR_query_instance;
}
static ObjCPropertyQueryKind getQueryKind(bool isClassProperty) {
return isClassProperty ? ObjCPropertyQueryKind::OBJC_PR_query_class :
ObjCPropertyQueryKind::OBJC_PR_query_instance;
}
/// getSetterKind - Return the method used for doing assignment in
/// the property setter. This is only valid if the property has been
/// defined to have a setter.
SetterKind getSetterKind() const {
if (PropertyAttributes & OBJC_PR_strong)
return getType()->isBlockPointerType() ? Copy : Retain;
if (PropertyAttributes & OBJC_PR_retain)
return Retain;
if (PropertyAttributes & OBJC_PR_copy)
return Copy;
if (PropertyAttributes & OBJC_PR_weak)
return Weak;
return Assign;
}
Selector getGetterName() const { return GetterName; }
SourceLocation getGetterNameLoc() const { return GetterNameLoc; }
void setGetterName(Selector Sel, SourceLocation Loc = SourceLocation()) {
GetterName = Sel;
GetterNameLoc = Loc;
}
Selector getSetterName() const { return SetterName; }
SourceLocation getSetterNameLoc() const { return SetterNameLoc; }
void setSetterName(Selector Sel, SourceLocation Loc = SourceLocation()) {
SetterName = Sel;
SetterNameLoc = Loc;
}
ObjCMethodDecl *getGetterMethodDecl() const { return GetterMethodDecl; }
void setGetterMethodDecl(ObjCMethodDecl *gDecl) { GetterMethodDecl = gDecl; }
ObjCMethodDecl *getSetterMethodDecl() const { return SetterMethodDecl; }
void setSetterMethodDecl(ObjCMethodDecl *gDecl) { SetterMethodDecl = gDecl; }
// Related to \@optional/\@required declared in \@protocol
void setPropertyImplementation(PropertyControl pc) {
PropertyImplementation = pc;
}
PropertyControl getPropertyImplementation() const {
return PropertyControl(PropertyImplementation);
}
bool isOptional() const {
return getPropertyImplementation() == PropertyControl::Optional;
}
void setPropertyIvarDecl(ObjCIvarDecl *Ivar) {
PropertyIvarDecl = Ivar;
}
ObjCIvarDecl *getPropertyIvarDecl() const {
return PropertyIvarDecl;
}
SourceRange getSourceRange() const override LLVM_READONLY {
return SourceRange(AtLoc, getLocation());
}
/// Get the default name of the synthesized ivar.
IdentifierInfo *getDefaultSynthIvarName(ASTContext &Ctx) const;
/// Lookup a property by name in the specified DeclContext.
static ObjCPropertyDecl *findPropertyDecl(const DeclContext *DC,
const IdentifierInfo *propertyID,
ObjCPropertyQueryKind queryKind);
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ObjCProperty; }
};
/// ObjCContainerDecl - Represents a container for method declarations.
/// Current sub-classes are ObjCInterfaceDecl, ObjCCategoryDecl,
/// ObjCProtocolDecl, and ObjCImplDecl.
///
class ObjCContainerDecl : public NamedDecl, public DeclContext {
// This class stores some data in DeclContext::ObjCContainerDeclBits
// to save some space. Use the provided accessors to access it.
// These two locations in the range mark the end of the method container.
// The first points to the '@' token, and the second to the 'end' token.
SourceRange AtEnd;
void anchor() override;
public:
ObjCContainerDecl(Kind DK, DeclContext *DC, IdentifierInfo *Id,
SourceLocation nameLoc, SourceLocation atStartLoc);
// Iterator access to instance/class properties.
using prop_iterator = specific_decl_iterator<ObjCPropertyDecl>;
using prop_range =
llvm::iterator_range<specific_decl_iterator<ObjCPropertyDecl>>;
prop_range properties() const { return prop_range(prop_begin(), prop_end()); }
prop_iterator prop_begin() const {
return prop_iterator(decls_begin());
}
prop_iterator prop_end() const {
return prop_iterator(decls_end());
}
using instprop_iterator =
filtered_decl_iterator<ObjCPropertyDecl,
&ObjCPropertyDecl::isInstanceProperty>;