/
Decl.h
4873 lines (3998 loc) · 180 KB
/
Decl.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
//===- Decl.h - Classes for representing declarations -----------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file defines the Decl subclasses.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_AST_DECL_H
#define LLVM_CLANG_AST_DECL_H
#include "clang/AST/APValue.h"
#include "clang/AST/ASTContextAllocate.h"
#include "clang/AST/DeclAccessPair.h"
#include "clang/AST/DeclBase.h"
#include "clang/AST/DeclarationName.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/Redeclarable.h"
#include "clang/AST/Type.h"
#include "clang/Basic/AddressSpaces.h"
#include "clang/Basic/Diagnostic.h"
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/LLVM.h"
#include "clang/Basic/Linkage.h"
#include "clang/Basic/OperatorKinds.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/PragmaKinds.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Specifiers.h"
#include "clang/Basic/Visibility.h"
#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/PointerIntPair.h"
#include "llvm/ADT/PointerUnion.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/TrailingObjects.h"
#include <cassert>
#include <cstddef>
#include <cstdint>
#include <string>
#include <utility>
namespace clang {
class ASTContext;
struct ASTTemplateArgumentListInfo;
class CompoundStmt;
class DependentFunctionTemplateSpecializationInfo;
class EnumDecl;
class Expr;
class FunctionTemplateDecl;
class FunctionTemplateSpecializationInfo;
class FunctionTypeLoc;
class LabelStmt;
class MemberSpecializationInfo;
class Module;
class NamespaceDecl;
class ParmVarDecl;
class RecordDecl;
class Stmt;
class StringLiteral;
class TagDecl;
class TemplateArgumentList;
class TemplateArgumentListInfo;
class TemplateParameterList;
class TypeAliasTemplateDecl;
class UnresolvedSetImpl;
class VarTemplateDecl;
/// The top declaration context.
class TranslationUnitDecl : public Decl,
public DeclContext,
public Redeclarable<TranslationUnitDecl> {
using redeclarable_base = Redeclarable<TranslationUnitDecl>;
TranslationUnitDecl *getNextRedeclarationImpl() override {
return getNextRedeclaration();
}
TranslationUnitDecl *getPreviousDeclImpl() override {
return getPreviousDecl();
}
TranslationUnitDecl *getMostRecentDeclImpl() override {
return getMostRecentDecl();
}
ASTContext &Ctx;
/// The (most recently entered) anonymous namespace for this
/// translation unit, if one has been created.
NamespaceDecl *AnonymousNamespace = nullptr;
explicit TranslationUnitDecl(ASTContext &ctx);
virtual void anchor();
public:
using redecl_range = redeclarable_base::redecl_range;
using redecl_iterator = redeclarable_base::redecl_iterator;
using redeclarable_base::getMostRecentDecl;
using redeclarable_base::getPreviousDecl;
using redeclarable_base::isFirstDecl;
using redeclarable_base::redecls;
using redeclarable_base::redecls_begin;
using redeclarable_base::redecls_end;
ASTContext &getASTContext() const { return Ctx; }
NamespaceDecl *getAnonymousNamespace() const { return AnonymousNamespace; }
void setAnonymousNamespace(NamespaceDecl *D) { AnonymousNamespace = D; }
static TranslationUnitDecl *Create(ASTContext &C);
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == TranslationUnit; }
static DeclContext *castToDeclContext(const TranslationUnitDecl *D) {
return static_cast<DeclContext *>(const_cast<TranslationUnitDecl*>(D));
}
static TranslationUnitDecl *castFromDeclContext(const DeclContext *DC) {
return static_cast<TranslationUnitDecl *>(const_cast<DeclContext*>(DC));
}
};
/// Represents a `#pragma comment` line. Always a child of
/// TranslationUnitDecl.
class PragmaCommentDecl final
: public Decl,
private llvm::TrailingObjects<PragmaCommentDecl, char> {
friend class ASTDeclReader;
friend class ASTDeclWriter;
friend TrailingObjects;
PragmaMSCommentKind CommentKind;
PragmaCommentDecl(TranslationUnitDecl *TU, SourceLocation CommentLoc,
PragmaMSCommentKind CommentKind)
: Decl(PragmaComment, TU, CommentLoc), CommentKind(CommentKind) {}
virtual void anchor();
public:
static PragmaCommentDecl *Create(const ASTContext &C, TranslationUnitDecl *DC,
SourceLocation CommentLoc,
PragmaMSCommentKind CommentKind,
StringRef Arg);
static PragmaCommentDecl *CreateDeserialized(ASTContext &C, unsigned ID,
unsigned ArgSize);
PragmaMSCommentKind getCommentKind() const { return CommentKind; }
StringRef getArg() const { return getTrailingObjects<char>(); }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == PragmaComment; }
};
/// Represents a `#pragma detect_mismatch` line. Always a child of
/// TranslationUnitDecl.
class PragmaDetectMismatchDecl final
: public Decl,
private llvm::TrailingObjects<PragmaDetectMismatchDecl, char> {
friend class ASTDeclReader;
friend class ASTDeclWriter;
friend TrailingObjects;
size_t ValueStart;
PragmaDetectMismatchDecl(TranslationUnitDecl *TU, SourceLocation Loc,
size_t ValueStart)
: Decl(PragmaDetectMismatch, TU, Loc), ValueStart(ValueStart) {}
virtual void anchor();
public:
static PragmaDetectMismatchDecl *Create(const ASTContext &C,
TranslationUnitDecl *DC,
SourceLocation Loc, StringRef Name,
StringRef Value);
static PragmaDetectMismatchDecl *
CreateDeserialized(ASTContext &C, unsigned ID, unsigned NameValueSize);
StringRef getName() const { return getTrailingObjects<char>(); }
StringRef getValue() const { return getTrailingObjects<char>() + ValueStart; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == PragmaDetectMismatch; }
};
/// Declaration context for names declared as extern "C" in C++. This
/// is neither the semantic nor lexical context for such declarations, but is
/// used to check for conflicts with other extern "C" declarations. Example:
///
/// \code
/// namespace N { extern "C" void f(); } // #1
/// void N::f() {} // #2
/// namespace M { extern "C" void f(); } // #3
/// \endcode
///
/// The semantic context of #1 is namespace N and its lexical context is the
/// LinkageSpecDecl; the semantic context of #2 is namespace N and its lexical
/// context is the TU. However, both declarations are also visible in the
/// extern "C" context.
///
/// The declaration at #3 finds it is a redeclaration of \c N::f through
/// lookup in the extern "C" context.
class ExternCContextDecl : public Decl, public DeclContext {
explicit ExternCContextDecl(TranslationUnitDecl *TU)
: Decl(ExternCContext, TU, SourceLocation()),
DeclContext(ExternCContext) {}
virtual void anchor();
public:
static ExternCContextDecl *Create(const ASTContext &C,
TranslationUnitDecl *TU);
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == ExternCContext; }
static DeclContext *castToDeclContext(const ExternCContextDecl *D) {
return static_cast<DeclContext *>(const_cast<ExternCContextDecl*>(D));
}
static ExternCContextDecl *castFromDeclContext(const DeclContext *DC) {
return static_cast<ExternCContextDecl *>(const_cast<DeclContext*>(DC));
}
};
/// This represents a decl that may have a name. Many decls have names such
/// as ObjCMethodDecl, but not \@class, etc.
///
/// Note that not every NamedDecl is actually named (e.g., a struct might
/// be anonymous), and not every name is an identifier.
class NamedDecl : public Decl {
/// The name of this declaration, which is typically a normal
/// identifier but may also be a special kind of name (C++
/// constructor, Objective-C selector, etc.)
DeclarationName Name;
virtual void anchor();
private:
NamedDecl *getUnderlyingDeclImpl() LLVM_READONLY;
protected:
NamedDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N)
: Decl(DK, DC, L), Name(N) {}
public:
/// Get the identifier that names this declaration, if there is one.
///
/// This will return NULL if this declaration has no name (e.g., for
/// an unnamed class) or if the name is a special name (C++ constructor,
/// Objective-C selector, etc.).
IdentifierInfo *getIdentifier() const { return Name.getAsIdentifierInfo(); }
/// Get the name of identifier for this declaration as a StringRef.
///
/// This requires that the declaration have a name and that it be a simple
/// identifier.
StringRef getName() const {
assert(Name.isIdentifier() && "Name is not a simple identifier");
return getIdentifier() ? getIdentifier()->getName() : "";
}
/// Get a human-readable name for the declaration, even if it is one of the
/// special kinds of names (C++ constructor, Objective-C selector, etc).
///
/// Creating this name requires expensive string manipulation, so it should
/// be called only when performance doesn't matter. For simple declarations,
/// getNameAsCString() should suffice.
//
// FIXME: This function should be renamed to indicate that it is not just an
// alternate form of getName(), and clients should move as appropriate.
//
// FIXME: Deprecated, move clients to getName().
std::string getNameAsString() const { return Name.getAsString(); }
/// Pretty-print the unqualified name of this declaration. Can be overloaded
/// by derived classes to provide a more user-friendly name when appropriate.
virtual void printName(raw_ostream &OS, const PrintingPolicy &Policy) const;
/// Calls printName() with the ASTContext printing policy from the decl.
void printName(raw_ostream &OS) const;
/// Get the actual, stored name of the declaration, which may be a special
/// name.
///
/// Note that generally in diagnostics, the non-null \p NamedDecl* itself
/// should be sent into the diagnostic instead of using the result of
/// \p getDeclName().
///
/// A \p DeclarationName in a diagnostic will just be streamed to the output,
/// which will directly result in a call to \p DeclarationName::print.
///
/// A \p NamedDecl* in a diagnostic will also ultimately result in a call to
/// \p DeclarationName::print, but with two customisation points along the
/// way (\p getNameForDiagnostic and \p printName). These are used to print
/// the template arguments if any, and to provide a user-friendly name for
/// some entities (such as unnamed variables and anonymous records).
DeclarationName getDeclName() const { return Name; }
/// Set the name of this declaration.
void setDeclName(DeclarationName N) { Name = N; }
/// Returns a human-readable qualified name for this declaration, like
/// A::B::i, for i being member of namespace A::B.
///
/// If the declaration is not a member of context which can be named (record,
/// namespace), it will return the same result as printName().
///
/// Creating this name is expensive, so it should be called only when
/// performance doesn't matter.
void printQualifiedName(raw_ostream &OS) const;
void printQualifiedName(raw_ostream &OS, const PrintingPolicy &Policy) const;
/// Print only the nested name specifier part of a fully-qualified name,
/// including the '::' at the end. E.g.
/// when `printQualifiedName(D)` prints "A::B::i",
/// this function prints "A::B::".
void printNestedNameSpecifier(raw_ostream &OS) const;
void printNestedNameSpecifier(raw_ostream &OS,
const PrintingPolicy &Policy) const;
// FIXME: Remove string version.
std::string getQualifiedNameAsString() const;
/// Appends a human-readable name for this declaration into the given stream.
///
/// This is the method invoked by Sema when displaying a NamedDecl
/// in a diagnostic. It does not necessarily produce the same
/// result as printName(); for example, class template
/// specializations are printed with their template arguments.
virtual void getNameForDiagnostic(raw_ostream &OS,
const PrintingPolicy &Policy,
bool Qualified) const;
/// Determine whether this declaration, if known to be well-formed within
/// its context, will replace the declaration OldD if introduced into scope.
///
/// A declaration will replace another declaration if, for example, it is
/// a redeclaration of the same variable or function, but not if it is a
/// declaration of a different kind (function vs. class) or an overloaded
/// function.
///
/// \param IsKnownNewer \c true if this declaration is known to be newer
/// than \p OldD (for instance, if this declaration is newly-created).
bool declarationReplaces(NamedDecl *OldD, bool IsKnownNewer = true) const;
/// Determine whether this declaration has linkage.
bool hasLinkage() const;
using Decl::isModulePrivate;
using Decl::setModulePrivate;
/// Determine whether this declaration is a C++ class member.
bool isCXXClassMember() const {
const DeclContext *DC = getDeclContext();
// C++0x [class.mem]p1:
// The enumerators of an unscoped enumeration defined in
// the class are members of the class.
if (isa<EnumDecl>(DC))
DC = DC->getRedeclContext();
return DC->isRecord();
}
/// Determine whether the given declaration is an instance member of
/// a C++ class.
bool isCXXInstanceMember() const;
/// Determine if the declaration obeys the reserved identifier rules of the
/// given language.
ReservedIdentifierStatus isReserved(const LangOptions &LangOpts) const;
/// Determine what kind of linkage this entity has.
///
/// This is not the linkage as defined by the standard or the codegen notion
/// of linkage. It is just an implementation detail that is used to compute
/// those.
Linkage getLinkageInternal() const;
/// Get the linkage from a semantic point of view. Entities in
/// anonymous namespaces are external (in c++98).
Linkage getFormalLinkage() const {
return clang::getFormalLinkage(getLinkageInternal());
}
/// True if this decl has external linkage.
bool hasExternalFormalLinkage() const {
return isExternalFormalLinkage(getLinkageInternal());
}
bool isExternallyVisible() const {
return clang::isExternallyVisible(getLinkageInternal());
}
/// Determine whether this declaration can be redeclared in a
/// different translation unit.
bool isExternallyDeclarable() const {
return isExternallyVisible() && !getOwningModuleForLinkage();
}
/// Determines the visibility of this entity.
Visibility getVisibility() const {
return getLinkageAndVisibility().getVisibility();
}
/// Determines the linkage and visibility of this entity.
LinkageInfo getLinkageAndVisibility() const;
/// Kinds of explicit visibility.
enum ExplicitVisibilityKind {
/// Do an LV computation for, ultimately, a type.
/// Visibility may be restricted by type visibility settings and
/// the visibility of template arguments.
VisibilityForType,
/// Do an LV computation for, ultimately, a non-type declaration.
/// Visibility may be restricted by value visibility settings and
/// the visibility of template arguments.
VisibilityForValue
};
/// If visibility was explicitly specified for this
/// declaration, return that visibility.
Optional<Visibility>
getExplicitVisibility(ExplicitVisibilityKind kind) const;
/// True if the computed linkage is valid. Used for consistency
/// checking. Should always return true.
bool isLinkageValid() const;
/// True if something has required us to compute the linkage
/// of this declaration.
///
/// Language features which can retroactively change linkage (like a
/// typedef name for linkage purposes) may need to consider this,
/// but hopefully only in transitory ways during parsing.
bool hasLinkageBeenComputed() const {
return hasCachedLinkage();
}
/// Looks through UsingDecls and ObjCCompatibleAliasDecls for
/// the underlying named decl.
NamedDecl *getUnderlyingDecl() {
// Fast-path the common case.
if (this->getKind() != UsingShadow &&
this->getKind() != ConstructorUsingShadow &&
this->getKind() != ObjCCompatibleAlias &&
this->getKind() != NamespaceAlias)
return this;
return getUnderlyingDeclImpl();
}
const NamedDecl *getUnderlyingDecl() const {
return const_cast<NamedDecl*>(this)->getUnderlyingDecl();
}
NamedDecl *getMostRecentDecl() {
return cast<NamedDecl>(static_cast<Decl *>(this)->getMostRecentDecl());
}
const NamedDecl *getMostRecentDecl() const {
return const_cast<NamedDecl*>(this)->getMostRecentDecl();
}
ObjCStringFormatFamily getObjCFStringFormattingFamily() const;
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K >= firstNamed && K <= lastNamed; }
};
inline raw_ostream &operator<<(raw_ostream &OS, const NamedDecl &ND) {
ND.printName(OS);
return OS;
}
/// Represents the declaration of a label. Labels also have a
/// corresponding LabelStmt, which indicates the position that the label was
/// defined at. For normal labels, the location of the decl is the same as the
/// location of the statement. For GNU local labels (__label__), the decl
/// location is where the __label__ is.
class LabelDecl : public NamedDecl {
LabelStmt *TheStmt;
StringRef MSAsmName;
bool MSAsmNameResolved = false;
/// For normal labels, this is the same as the main declaration
/// label, i.e., the location of the identifier; for GNU local labels,
/// this is the location of the __label__ keyword.
SourceLocation LocStart;
LabelDecl(DeclContext *DC, SourceLocation IdentL, IdentifierInfo *II,
LabelStmt *S, SourceLocation StartL)
: NamedDecl(Label, DC, IdentL, II), TheStmt(S), LocStart(StartL) {}
void anchor() override;
public:
static LabelDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation IdentL, IdentifierInfo *II);
static LabelDecl *Create(ASTContext &C, DeclContext *DC,
SourceLocation IdentL, IdentifierInfo *II,
SourceLocation GnuLabelL);
static LabelDecl *CreateDeserialized(ASTContext &C, unsigned ID);
LabelStmt *getStmt() const { return TheStmt; }
void setStmt(LabelStmt *T) { TheStmt = T; }
bool isGnuLocal() const { return LocStart != getLocation(); }
void setLocStart(SourceLocation L) { LocStart = L; }
SourceRange getSourceRange() const override LLVM_READONLY {
return SourceRange(LocStart, getLocation());
}
bool isMSAsmLabel() const { return !MSAsmName.empty(); }
bool isResolvedMSAsmLabel() const { return isMSAsmLabel() && MSAsmNameResolved; }
void setMSAsmLabel(StringRef Name);
StringRef getMSAsmLabel() const { return MSAsmName; }
void setMSAsmLabelResolved() { MSAsmNameResolved = true; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Label; }
};
/// Represent a C++ namespace.
class NamespaceDecl : public NamedDecl, public DeclContext,
public Redeclarable<NamespaceDecl>
{
enum Flags : unsigned { F_Inline = 1 << 0, F_Nested = 1 << 1 };
/// The starting location of the source range, pointing
/// to either the namespace or the inline keyword.
SourceLocation LocStart;
/// The ending location of the source range.
SourceLocation RBraceLoc;
/// A pointer to either the anonymous namespace that lives just inside
/// this namespace or to the first namespace in the chain (the latter case
/// only when this is not the first in the chain), along with a
/// boolean value indicating whether this is an inline namespace.
llvm::PointerIntPair<NamespaceDecl *, 2, unsigned>
AnonOrFirstNamespaceAndFlags;
NamespaceDecl(ASTContext &C, DeclContext *DC, bool Inline,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, NamespaceDecl *PrevDecl, bool Nested);
using redeclarable_base = Redeclarable<NamespaceDecl>;
NamespaceDecl *getNextRedeclarationImpl() override;
NamespaceDecl *getPreviousDeclImpl() override;
NamespaceDecl *getMostRecentDeclImpl() override;
public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
static NamespaceDecl *Create(ASTContext &C, DeclContext *DC, bool Inline,
SourceLocation StartLoc, SourceLocation IdLoc,
IdentifierInfo *Id, NamespaceDecl *PrevDecl,
bool Nested);
static NamespaceDecl *CreateDeserialized(ASTContext &C, unsigned ID);
using redecl_range = redeclarable_base::redecl_range;
using redecl_iterator = redeclarable_base::redecl_iterator;
using redeclarable_base::redecls_begin;
using redeclarable_base::redecls_end;
using redeclarable_base::redecls;
using redeclarable_base::getPreviousDecl;
using redeclarable_base::getMostRecentDecl;
using redeclarable_base::isFirstDecl;
/// Returns true if this is an anonymous namespace declaration.
///
/// For example:
/// \code
/// namespace {
/// ...
/// };
/// \endcode
/// q.v. C++ [namespace.unnamed]
bool isAnonymousNamespace() const {
return !getIdentifier();
}
/// Returns true if this is an inline namespace declaration.
bool isInline() const {
return AnonOrFirstNamespaceAndFlags.getInt() & F_Inline;
}
/// Set whether this is an inline namespace declaration.
void setInline(bool Inline) {
unsigned F = AnonOrFirstNamespaceAndFlags.getInt();
if (Inline)
AnonOrFirstNamespaceAndFlags.setInt(F | F_Inline);
else
AnonOrFirstNamespaceAndFlags.setInt(F & ~F_Inline);
}
/// Returns true if this is a nested namespace declaration.
/// \code
/// namespace outer::nested { }
/// \endcode
bool isNested() const {
return AnonOrFirstNamespaceAndFlags.getInt() & F_Nested;
}
/// Set whether this is a nested namespace declaration.
void setNested(bool Nested) {
unsigned F = AnonOrFirstNamespaceAndFlags.getInt();
if (Nested)
AnonOrFirstNamespaceAndFlags.setInt(F | F_Nested);
else
AnonOrFirstNamespaceAndFlags.setInt(F & ~F_Nested);
}
/// Returns true if the inline qualifier for \c Name is redundant.
bool isRedundantInlineQualifierFor(DeclarationName Name) const {
if (!isInline())
return false;
auto X = lookup(Name);
// We should not perform a lookup within a transparent context, so find a
// non-transparent parent context.
auto Y = getParent()->getNonTransparentContext()->lookup(Name);
return std::distance(X.begin(), X.end()) ==
std::distance(Y.begin(), Y.end());
}
/// Get the original (first) namespace declaration.
NamespaceDecl *getOriginalNamespace();
/// Get the original (first) namespace declaration.
const NamespaceDecl *getOriginalNamespace() const;
/// Return true if this declaration is an original (first) declaration
/// of the namespace. This is false for non-original (subsequent) namespace
/// declarations and anonymous namespaces.
bool isOriginalNamespace() const;
/// Retrieve the anonymous namespace nested inside this namespace,
/// if any.
NamespaceDecl *getAnonymousNamespace() const {
return getOriginalNamespace()->AnonOrFirstNamespaceAndFlags.getPointer();
}
void setAnonymousNamespace(NamespaceDecl *D) {
getOriginalNamespace()->AnonOrFirstNamespaceAndFlags.setPointer(D);
}
/// Retrieves the canonical declaration of this namespace.
NamespaceDecl *getCanonicalDecl() override {
return getOriginalNamespace();
}
const NamespaceDecl *getCanonicalDecl() const {
return getOriginalNamespace();
}
SourceRange getSourceRange() const override LLVM_READONLY {
return SourceRange(LocStart, RBraceLoc);
}
SourceLocation getBeginLoc() const LLVM_READONLY { return LocStart; }
SourceLocation getRBraceLoc() const { return RBraceLoc; }
void setLocStart(SourceLocation L) { LocStart = L; }
void setRBraceLoc(SourceLocation L) { RBraceLoc = L; }
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K == Namespace; }
static DeclContext *castToDeclContext(const NamespaceDecl *D) {
return static_cast<DeclContext *>(const_cast<NamespaceDecl*>(D));
}
static NamespaceDecl *castFromDeclContext(const DeclContext *DC) {
return static_cast<NamespaceDecl *>(const_cast<DeclContext*>(DC));
}
};
/// Represent the declaration of a variable (in which case it is
/// an lvalue) a function (in which case it is a function designator) or
/// an enum constant.
class ValueDecl : public NamedDecl {
QualType DeclType;
void anchor() override;
protected:
ValueDecl(Kind DK, DeclContext *DC, SourceLocation L,
DeclarationName N, QualType T)
: NamedDecl(DK, DC, L, N), DeclType(T) {}
public:
QualType getType() const { return DeclType; }
void setType(QualType newType) { DeclType = newType; }
/// Determine whether this symbol is weakly-imported,
/// or declared with the weak or weak-ref attr.
bool isWeak() const;
/// Whether this variable is the implicit variable for a lambda init-capture.
/// Only VarDecl can be init captures, but both VarDecl and BindingDecl
/// can be captured.
bool isInitCapture() const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) { return K >= firstValue && K <= lastValue; }
};
/// A struct with extended info about a syntactic
/// name qualifier, to be used for the case of out-of-line declarations.
struct QualifierInfo {
NestedNameSpecifierLoc QualifierLoc;
/// The number of "outer" template parameter lists.
/// The count includes all of the template parameter lists that were matched
/// against the template-ids occurring into the NNS and possibly (in the
/// case of an explicit specialization) a final "template <>".
unsigned NumTemplParamLists = 0;
/// A new-allocated array of size NumTemplParamLists,
/// containing pointers to the "outer" template parameter lists.
/// It includes all of the template parameter lists that were matched
/// against the template-ids occurring into the NNS and possibly (in the
/// case of an explicit specialization) a final "template <>".
TemplateParameterList** TemplParamLists = nullptr;
QualifierInfo() = default;
QualifierInfo(const QualifierInfo &) = delete;
QualifierInfo& operator=(const QualifierInfo &) = delete;
/// Sets info about "outer" template parameter lists.
void setTemplateParameterListsInfo(ASTContext &Context,
ArrayRef<TemplateParameterList *> TPLists);
};
/// Represents a ValueDecl that came out of a declarator.
/// Contains type source information through TypeSourceInfo.
class DeclaratorDecl : public ValueDecl {
// A struct representing a TInfo, a trailing requires-clause and a syntactic
// qualifier, to be used for the (uncommon) case of out-of-line declarations
// and constrained function decls.
struct ExtInfo : public QualifierInfo {
TypeSourceInfo *TInfo;
Expr *TrailingRequiresClause = nullptr;
};
llvm::PointerUnion<TypeSourceInfo *, ExtInfo *> DeclInfo;
/// The start of the source range for this declaration,
/// ignoring outer template declarations.
SourceLocation InnerLocStart;
bool hasExtInfo() const { return DeclInfo.is<ExtInfo*>(); }
ExtInfo *getExtInfo() { return DeclInfo.get<ExtInfo*>(); }
const ExtInfo *getExtInfo() const { return DeclInfo.get<ExtInfo*>(); }
protected:
DeclaratorDecl(Kind DK, DeclContext *DC, SourceLocation L,
DeclarationName N, QualType T, TypeSourceInfo *TInfo,
SourceLocation StartL)
: ValueDecl(DK, DC, L, N, T), DeclInfo(TInfo), InnerLocStart(StartL) {}
public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
TypeSourceInfo *getTypeSourceInfo() const {
return hasExtInfo()
? getExtInfo()->TInfo
: DeclInfo.get<TypeSourceInfo*>();
}
void setTypeSourceInfo(TypeSourceInfo *TI) {
if (hasExtInfo())
getExtInfo()->TInfo = TI;
else
DeclInfo = TI;
}
/// Return start of source range ignoring outer template declarations.
SourceLocation getInnerLocStart() const { return InnerLocStart; }
void setInnerLocStart(SourceLocation L) { InnerLocStart = L; }
/// Return start of source range taking into account any outer template
/// declarations.
SourceLocation getOuterLocStart() const;
SourceRange getSourceRange() const override LLVM_READONLY;
SourceLocation getBeginLoc() const LLVM_READONLY {
return getOuterLocStart();
}
/// Retrieve the nested-name-specifier that qualifies the name of this
/// declaration, if it was present in the source.
NestedNameSpecifier *getQualifier() const {
return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier()
: nullptr;
}
/// Retrieve the nested-name-specifier (with source-location
/// information) that qualifies the name of this declaration, if it was
/// present in the source.
NestedNameSpecifierLoc getQualifierLoc() const {
return hasExtInfo() ? getExtInfo()->QualifierLoc
: NestedNameSpecifierLoc();
}
void setQualifierInfo(NestedNameSpecifierLoc QualifierLoc);
/// \brief Get the constraint-expression introduced by the trailing
/// requires-clause in the function/member declaration, or null if no
/// requires-clause was provided.
Expr *getTrailingRequiresClause() {
return hasExtInfo() ? getExtInfo()->TrailingRequiresClause
: nullptr;
}
const Expr *getTrailingRequiresClause() const {
return hasExtInfo() ? getExtInfo()->TrailingRequiresClause
: nullptr;
}
void setTrailingRequiresClause(Expr *TrailingRequiresClause);
unsigned getNumTemplateParameterLists() const {
return hasExtInfo() ? getExtInfo()->NumTemplParamLists : 0;
}
TemplateParameterList *getTemplateParameterList(unsigned index) const {
assert(index < getNumTemplateParameterLists());
return getExtInfo()->TemplParamLists[index];
}
void setTemplateParameterListsInfo(ASTContext &Context,
ArrayRef<TemplateParameterList *> TPLists);
SourceLocation getTypeSpecStartLoc() const;
SourceLocation getTypeSpecEndLoc() const;
// Implement isa/cast/dyncast/etc.
static bool classof(const Decl *D) { return classofKind(D->getKind()); }
static bool classofKind(Kind K) {
return K >= firstDeclarator && K <= lastDeclarator;
}
};
/// Structure used to store a statement, the constant value to
/// which it was evaluated (if any), and whether or not the statement
/// is an integral constant expression (if known).
struct EvaluatedStmt {
/// Whether this statement was already evaluated.
bool WasEvaluated : 1;
/// Whether this statement is being evaluated.
bool IsEvaluating : 1;
/// Whether this variable is known to have constant initialization. This is
/// currently only computed in C++, for static / thread storage duration
/// variables that might have constant initialization and for variables that
/// are usable in constant expressions.
bool HasConstantInitialization : 1;
/// Whether this variable is known to have constant destruction. That is,
/// whether running the destructor on the initial value is a side-effect
/// (and doesn't inspect any state that might have changed during program
/// execution). This is currently only computed if the destructor is
/// non-trivial.
bool HasConstantDestruction : 1;
/// In C++98, whether the initializer is an ICE. This affects whether the
/// variable is usable in constant expressions.
bool HasICEInit : 1;
bool CheckedForICEInit : 1;
Stmt *Value;
APValue Evaluated;
EvaluatedStmt()
: WasEvaluated(false), IsEvaluating(false),
HasConstantInitialization(false), HasConstantDestruction(false),
HasICEInit(false), CheckedForICEInit(false) {}
};
/// Represents a variable declaration or definition.
class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> {
public:
/// Initialization styles.
enum InitializationStyle {
/// C-style initialization with assignment
CInit,
/// Call-style initialization (C++98)
CallInit,
/// Direct list-initialization (C++11)
ListInit,
/// Parenthesized list-initialization (C++20)
ParenListInit
};
/// Kinds of thread-local storage.
enum TLSKind {
/// Not a TLS variable.
TLS_None,
/// TLS with a known-constant initializer.
TLS_Static,
/// TLS with a dynamic initializer.
TLS_Dynamic
};
/// Return the string used to specify the storage class \p SC.
///
/// It is illegal to call this function with SC == None.
static const char *getStorageClassSpecifierString(StorageClass SC);
protected:
// A pointer union of Stmt * and EvaluatedStmt *. When an EvaluatedStmt, we
// have allocated the auxiliary struct of information there.
//
// TODO: It is a bit unfortunate to use a PointerUnion inside the VarDecl for
// this as *many* VarDecls are ParmVarDecls that don't have default
// arguments. We could save some space by moving this pointer union to be
// allocated in trailing space when necessary.
using InitType = llvm::PointerUnion<Stmt *, EvaluatedStmt *>;
/// The initializer for this variable or, for a ParmVarDecl, the
/// C++ default argument.
mutable InitType Init;
private:
friend class ASTDeclReader;
friend class ASTNodeImporter;
friend class StmtIteratorBase;
class VarDeclBitfields {
friend class ASTDeclReader;
friend class VarDecl;
unsigned SClass : 3;
unsigned TSCSpec : 2;
unsigned InitStyle : 2;
/// Whether this variable is an ARC pseudo-__strong variable; see
/// isARCPseudoStrong() for details.
unsigned ARCPseudoStrong : 1;
};
enum { NumVarDeclBits = 8 };
protected:
enum { NumParameterIndexBits = 8 };
enum DefaultArgKind {
DAK_None,
DAK_Unparsed,
DAK_Uninstantiated,
DAK_Normal
};
enum { NumScopeDepthOrObjCQualsBits = 7 };
class ParmVarDeclBitfields {
friend class ASTDeclReader;
friend class ParmVarDecl;
unsigned : NumVarDeclBits;
/// Whether this parameter inherits a default argument from a
/// prior declaration.
unsigned HasInheritedDefaultArg : 1;
/// Describes the kind of default argument for this parameter. By default
/// this is none. If this is normal, then the default argument is stored in
/// the \c VarDecl initializer expression unless we were unable to parse
/// (even an invalid) expression for the default argument.
unsigned DefaultArgKind : 2;