aboutsummaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorErich Keane <erich.keane@intel.com>2018-08-01 20:48:16 +0000
committerErich Keane <erich.keane@intel.com>2018-08-01 20:48:16 +0000
commitf2421d2e1b6bd17f5e60af599807dba00a4fe81f (patch)
treed732d10cf1164737ca2604ef3a86a38698dda263 /include
parente3ad384baa5c07d555b5740aade030e1af758675 (diff)
downloadclang-f2421d2e1b6bd17f5e60af599807dba00a4fe81f.tar.gz
[AST][1/4] Move the bit-fields from TagDecl, EnumDecl and RecordDecl into DeclContext
DeclContext has a little less than 8 bytes free due to the alignment requirements on 64 bits archs. This set of patches moves the bit-fields from classes deriving from DeclContext into DeclContext. On 32 bits archs this increases the size of DeclContext by 4 bytes but this is balanced by an equal or larger reduction in the size of the classes deriving from it. On 64 bits archs the size of DeclContext stays the same but most of the classes deriving from it shrink by 8/16 bytes. (-print-stats diff here https://reviews.llvm.org/D49728) When doing an -fsyntax-only on all of Boost this result in a 3.6% reduction in the size of all Decls and a 1% reduction in the run time due to the lower cache miss rate. For now CXXRecordDecl is not touched but there is an easy 6 (if I count correctly) bytes gain available there by moving some bits from DefinitionData into the free space of DeclContext. This will be the subject of another patch. This patch sequence also enable the possibility of refactoring FunctionDecl: To save space some bits from classes deriving from FunctionDecl were moved to FunctionDecl. This resulted in a lot of stuff in FunctionDecl which do not belong logically to it. After this set of patches however it is just a simple matter of adding a SomethingDeclBitfields in DeclContext and moving the bits to it from FunctionDecl. This first patch introduces the anonymous union in DeclContext and all the *DeclBitfields classes holding the bit-fields, and moves the bits from TagDecl, EnumDecl and RecordDecl into DeclContext. This patch is followed by https://reviews.llvm.org/D49732, https://reviews.llvm.org/D49733 and https://reviews.llvm.org/D49734. Differential Revision: https://reviews.llvm.org/D49729 Patch By: bricci git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338630 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include')
-rw-r--r--include/clang/AST/Decl.h304
-rw-r--r--include/clang/AST/DeclBase.h584
2 files changed, 648 insertions, 240 deletions
diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h
index ebdb2890da..879a49eccb 100644
--- a/include/clang/AST/Decl.h
+++ b/include/clang/AST/Decl.h
@@ -3014,64 +3014,16 @@ public:
};
/// Represents the declaration of a struct/union/class/enum.
-class TagDecl
- : public TypeDecl, public DeclContext, public Redeclarable<TagDecl> {
+class TagDecl : public TypeDecl,
+ public DeclContext,
+ public Redeclarable<TagDecl> {
+ // This class stores some data in DeclContext::TagDeclBits
+ // to save some space. Use the provided accessors to access it.
public:
// This is really ugly.
using TagKind = TagTypeKind;
private:
- // FIXME: This can be packed into the bitfields in Decl.
- /// The TagKind enum.
- unsigned TagDeclKind : 3;
-
- /// True if this is a definition ("struct foo {};"), false if it is a
- /// declaration ("struct foo;"). It is not considered a definition
- /// until the definition has been fully processed.
- unsigned IsCompleteDefinition : 1;
-
-protected:
- /// True if this is currently being defined.
- unsigned IsBeingDefined : 1;
-
-private:
- /// True if this tag declaration is "embedded" (i.e., defined or declared
- /// for the very first time) in the syntax of a declarator.
- unsigned IsEmbeddedInDeclarator : 1;
-
- /// True if this tag is free standing, e.g. "struct foo;".
- unsigned IsFreeStanding : 1;
-
-protected:
- // These are used by (and only defined for) EnumDecl.
- unsigned NumPositiveBits : 8;
- unsigned NumNegativeBits : 8;
-
- /// True if this tag declaration is a scoped enumeration. Only
- /// possible in C++11 mode.
- unsigned IsScoped : 1;
-
- /// If this tag declaration is a scoped enum,
- /// then this is true if the scoped enum was declared using the class
- /// tag, false if it was declared with the struct tag. No meaning is
- /// associated if this tag declaration is not a scoped enum.
- unsigned IsScopedUsingClassTag : 1;
-
- /// True if this is an enumeration with fixed underlying type. Only
- /// possible in C++11, Microsoft extensions, or Objective C mode.
- unsigned IsFixed : 1;
-
- /// Indicates whether it is possible for declarations of this kind
- /// to have an out-of-date definition.
- ///
- /// This option is only enabled when modules are enabled.
- unsigned MayHaveOutOfDateDef : 1;
-
- /// Has the full definition of this type been required by a use somewhere in
- /// the TU.
- unsigned IsCompleteDefinitionRequired : 1;
-
-private:
SourceRange BraceRange;
// A struct representing syntactic qualifier info,
@@ -3097,16 +3049,7 @@ private:
protected:
TagDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC,
SourceLocation L, IdentifierInfo *Id, TagDecl *PrevDecl,
- SourceLocation StartL)
- : TypeDecl(DK, DC, L, Id, StartL), DeclContext(DK), redeclarable_base(C),
- TagDeclKind(TK), IsCompleteDefinition(false), IsBeingDefined(false),
- IsEmbeddedInDeclarator(false), IsFreeStanding(false),
- IsCompleteDefinitionRequired(false),
- TypedefNameDeclOrQualifier((TypedefNameDecl *)nullptr) {
- assert((DK != Enum || TK == TTK_Enum) &&
- "EnumDecl not matched with TTK_Enum");
- setPreviousDecl(PrevDecl);
- }
+ SourceLocation StartL);
using redeclarable_base = Redeclarable<TagDecl>;
@@ -3127,6 +3070,17 @@ protected:
/// This is a helper function for derived classes.
void completeDefinition();
+ /// True if this decl is currently being defined.
+ void setBeingDefined(bool V = true) { TagDeclBits.IsBeingDefined = V; }
+
+ /// Indicates whether it is possible for declarations of this kind
+ /// to have an out-of-date definition.
+ ///
+ /// This option is only enabled when modules are enabled.
+ void setMayHaveOutOfDateDef(bool V = true) {
+ TagDeclBits.MayHaveOutOfDateDef = V;
+ }
+
public:
friend class ASTDeclReader;
friend class ASTDeclWriter;
@@ -3165,33 +3119,54 @@ public:
}
/// Return true if this decl has its body fully specified.
- bool isCompleteDefinition() const {
- return IsCompleteDefinition;
+ bool isCompleteDefinition() const { return TagDeclBits.IsCompleteDefinition; }
+
+ /// True if this decl has its body fully specified.
+ void setCompleteDefinition(bool V = true) {
+ TagDeclBits.IsCompleteDefinition = V;
}
/// Return true if this complete decl is
/// required to be complete for some existing use.
bool isCompleteDefinitionRequired() const {
- return IsCompleteDefinitionRequired;
+ return TagDeclBits.IsCompleteDefinitionRequired;
}
- /// Return true if this decl is currently being defined.
- bool isBeingDefined() const {
- return IsBeingDefined;
+ /// True if this complete decl is
+ /// required to be complete for some existing use.
+ void setCompleteDefinitionRequired(bool V = true) {
+ TagDeclBits.IsCompleteDefinitionRequired = V;
}
+ /// Return true if this decl is currently being defined.
+ bool isBeingDefined() const { return TagDeclBits.IsBeingDefined; }
+
+ /// True if this tag declaration is "embedded" (i.e., defined or declared
+ /// for the very first time) in the syntax of a declarator.
bool isEmbeddedInDeclarator() const {
- return IsEmbeddedInDeclarator;
+ return TagDeclBits.IsEmbeddedInDeclarator;
}
+
+ /// True if this tag declaration is "embedded" (i.e., defined or declared
+ /// for the very first time) in the syntax of a declarator.
void setEmbeddedInDeclarator(bool isInDeclarator) {
- IsEmbeddedInDeclarator = isInDeclarator;
+ TagDeclBits.IsEmbeddedInDeclarator = isInDeclarator;
}
- bool isFreeStanding() const { return IsFreeStanding; }
+ /// True if this tag is free standing, e.g. "struct foo;".
+ bool isFreeStanding() const { return TagDeclBits.IsFreeStanding; }
+
+ /// True if this tag is free standing, e.g. "struct foo;".
void setFreeStanding(bool isFreeStanding = true) {
- IsFreeStanding = isFreeStanding;
+ TagDeclBits.IsFreeStanding = isFreeStanding;
}
+ /// Indicates whether it is possible for declarations of this kind
+ /// to have an out-of-date definition.
+ ///
+ /// This option is only enabled when modules are enabled.
+ bool mayHaveOutOfDateDef() const { return TagDeclBits.MayHaveOutOfDateDef; }
+
/// Whether this declaration declares a type that is
/// dependent, i.e., a type that somehow depends on template
/// parameters.
@@ -3214,21 +3189,15 @@ public:
/// the struct/union/class/enum.
TagDecl *getDefinition() const;
- void setCompleteDefinition(bool V) { IsCompleteDefinition = V; }
-
- void setCompleteDefinitionRequired(bool V = true) {
- IsCompleteDefinitionRequired = V;
- }
-
StringRef getKindName() const {
return TypeWithKeyword::getTagTypeKindName(getTagKind());
}
TagKind getTagKind() const {
- return TagKind(TagDeclKind);
+ return static_cast<TagKind>(TagDeclBits.TagDeclKind);
}
- void setTagKind(TagKind TK) { TagDeclKind = TK; }
+ void setTagKind(TagKind TK) { TagDeclBits.TagDeclKind = TK; }
bool isStruct() const { return getTagKind() == TTK_Struct; }
bool isInterface() const { return getTagKind() == TTK_Interface; }
@@ -3308,6 +3277,9 @@ public:
/// with a fixed underlying type, and in C we allow them to be forward-declared
/// with no underlying type as an extension.
class EnumDecl : public TagDecl {
+ // This class stores some data in DeclContext::EnumDeclBits
+ // to save some space. Use the provided accessors to access it.
+
/// This represent the integer type that the enum corresponds
/// to for code generation purposes. Note that the enumerator constants may
/// have a different type than this does.
@@ -3336,28 +3308,50 @@ class EnumDecl : public TagDecl {
MemberSpecializationInfo *SpecializationInfo = nullptr;
/// Store the ODRHash after first calculation.
- unsigned HasODRHash : 1;
+ /// The corresponding flag HasODRHash is in EnumDeclBits
+ /// and can be accessed with the provided accessors.
unsigned ODRHash;
EnumDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id, EnumDecl *PrevDecl,
- bool Scoped, bool ScopedUsingClassTag, bool Fixed)
- : TagDecl(Enum, TTK_Enum, C, DC, IdLoc, Id, PrevDecl, StartLoc) {
- assert(Scoped || !ScopedUsingClassTag);
- IntegerType = (const Type *)nullptr;
- NumNegativeBits = 0;
- NumPositiveBits = 0;
- IsScoped = Scoped;
- IsScopedUsingClassTag = ScopedUsingClassTag;
- IsFixed = Fixed;
- HasODRHash = false;
- ODRHash = 0;
- }
+ bool Scoped, bool ScopedUsingClassTag, bool Fixed);
void anchor() override;
void setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED,
TemplateSpecializationKind TSK);
+
+ /// Sets the width in bits required to store all the
+ /// non-negative enumerators of this enum.
+ void setNumPositiveBits(unsigned Num) {
+ EnumDeclBits.NumPositiveBits = Num;
+ assert(EnumDeclBits.NumPositiveBits == Num && "can't store this bitcount");
+ }
+
+ /// Returns the width in bits required to store all the
+ /// negative enumerators of this enum. (see getNumNegativeBits)
+ void setNumNegativeBits(unsigned Num) { EnumDeclBits.NumNegativeBits = Num; }
+
+ /// True if this tag declaration is a scoped enumeration. Only
+ /// possible in C++11 mode.
+ void setScoped(bool Scoped = true) { EnumDeclBits.IsScoped = Scoped; }
+
+ /// If this tag declaration is a scoped enum,
+ /// then this is true if the scoped enum was declared using the class
+ /// tag, false if it was declared with the struct tag. No meaning is
+ /// associated if this tag declaration is not a scoped enum.
+ void setScopedUsingClassTag(bool ScopedUCT = true) {
+ EnumDeclBits.IsScopedUsingClassTag = ScopedUCT;
+ }
+
+ /// True if this is an Objective-C, C++11, or
+ /// Microsoft-style enumeration with a fixed underlying type.
+ void setFixed(bool Fixed = true) { EnumDeclBits.IsFixed = Fixed; }
+
+ /// True if a valid hash is stored in ODRHash.
+ bool hasODRHash() const { return EnumDeclBits.HasODRHash; }
+ void setHasODRHash(bool Hash = true) { EnumDeclBits.HasODRHash = Hash; }
+
public:
friend class ASTDeclReader;
@@ -3462,13 +3456,7 @@ public:
/// Returns the width in bits required to store all the
/// non-negative enumerators of this enum.
- unsigned getNumPositiveBits() const {
- return NumPositiveBits;
- }
- void setNumPositiveBits(unsigned Num) {
- NumPositiveBits = Num;
- assert(NumPositiveBits == Num && "can't store this bitcount");
- }
+ unsigned getNumPositiveBits() const { return EnumDeclBits.NumPositiveBits; }
/// Returns the width in bits required to store all the
/// negative enumerators of this enum. These widths include
@@ -3479,28 +3467,19 @@ public:
/// -1 1111111 1
/// -10 1110110 5
/// -101 1001011 8
- unsigned getNumNegativeBits() const {
- return NumNegativeBits;
- }
- void setNumNegativeBits(unsigned Num) {
- NumNegativeBits = Num;
- }
+ unsigned getNumNegativeBits() const { return EnumDeclBits.NumNegativeBits; }
/// Returns true if this is a C++11 scoped enumeration.
- bool isScoped() const {
- return IsScoped;
- }
+ bool isScoped() const { return EnumDeclBits.IsScoped; }
/// Returns true if this is a C++11 scoped enumeration.
bool isScopedUsingClassTag() const {
- return IsScopedUsingClassTag;
+ return EnumDeclBits.IsScopedUsingClassTag;
}
/// Returns true if this is an Objective-C, C++11, or
/// Microsoft-style enumeration with a fixed underlying type.
- bool isFixed() const {
- return IsFixed;
- }
+ bool isFixed() const { return EnumDeclBits.IsFixed; }
unsigned getODRHash();
@@ -3565,7 +3544,10 @@ public:
/// union Y { int A, B; }; // Has body with members A and B (FieldDecls).
/// This decl will be marked invalid if *any* members are invalid.
class RecordDecl : public TagDecl {
+ // This class stores some data in DeclContext::RecordDeclBits
+ // to save some space. Use the provided accessors to access it.
public:
+ friend class DeclContext;
/// Enum that represents the different ways arguments are passed to and
/// returned from function calls. This takes into account the target-specific
/// and version-specific rules along with the rules determined by the
@@ -3589,46 +3571,6 @@ public:
APK_CanNeverPassInRegs
};
-private:
- friend class DeclContext;
-
- // FIXME: This can be packed into the bitfields in Decl.
- /// This is true if this struct ends with a flexible
- /// array member (e.g. int X[]) or if this union contains a struct that does.
- /// If so, this cannot be contained in arrays or other structs as a member.
- unsigned HasFlexibleArrayMember : 1;
-
- /// Whether this is the type of an anonymous struct or union.
- unsigned AnonymousStructOrUnion : 1;
-
- /// This is true if this struct has at least one member
- /// containing an Objective-C object pointer type.
- unsigned HasObjectMember : 1;
-
- /// This is true if struct has at least one member of
- /// 'volatile' type.
- unsigned HasVolatileMember : 1;
-
- /// Whether the field declarations of this record have been loaded
- /// from external storage. To avoid unnecessary deserialization of
- /// methods/nested types we allow deserialization of just the fields
- /// when needed.
- mutable unsigned LoadedFieldsFromExternalStorage : 1;
-
- /// Basic properties of non-trivial C structs.
- unsigned NonTrivialToPrimitiveDefaultInitialize : 1;
- unsigned NonTrivialToPrimitiveCopy : 1;
- unsigned NonTrivialToPrimitiveDestroy : 1;
-
- /// Indicates whether this struct is destroyed in the callee.
- ///
- /// Please note that MSVC won't merge adjacent bitfields if they don't have
- /// the same type.
- unsigned ParamDestroyedInCallee : 1;
-
- /// Represents the way this type is passed to a function.
- unsigned ArgPassingRestrictions : 2;
-
protected:
RecordDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC,
SourceLocation StartLoc, SourceLocation IdLoc,
@@ -3655,8 +3597,13 @@ public:
return const_cast<RecordDecl*>(this)->getMostRecentDecl();
}
- bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; }
- void setHasFlexibleArrayMember(bool V) { HasFlexibleArrayMember = V; }
+ bool hasFlexibleArrayMember() const {
+ return RecordDeclBits.HasFlexibleArrayMember;
+ }
+
+ void setHasFlexibleArrayMember(bool V) {
+ RecordDeclBits.HasFlexibleArrayMember = V;
+ }
/// Whether this is an anonymous struct or union. To be an anonymous
/// struct or union, it must have been declared without a name and
@@ -3669,47 +3616,54 @@ public:
/// union X { int i; float f; };
/// union { int i; float f; } obj;
/// @endcode
- bool isAnonymousStructOrUnion() const { return AnonymousStructOrUnion; }
+ bool isAnonymousStructOrUnion() const {
+ return RecordDeclBits.AnonymousStructOrUnion;
+ }
+
void setAnonymousStructOrUnion(bool Anon) {
- AnonymousStructOrUnion = Anon;
+ RecordDeclBits.AnonymousStructOrUnion = Anon;
}
- bool hasObjectMember() const { return HasObjectMember; }
- void setHasObjectMember (bool val) { HasObjectMember = val; }
+ bool hasObjectMember() const { return RecordDeclBits.HasObjectMember; }
+ void setHasObjectMember(bool val) { RecordDeclBits.HasObjectMember = val; }
- bool hasVolatileMember() const { return HasVolatileMember; }
- void setHasVolatileMember (bool val) { HasVolatileMember = val; }
+ bool hasVolatileMember() const { return RecordDeclBits.HasVolatileMember; }
+
+ void setHasVolatileMember(bool val) {
+ RecordDeclBits.HasVolatileMember = val;
+ }
bool hasLoadedFieldsFromExternalStorage() const {
- return LoadedFieldsFromExternalStorage;
+ return RecordDeclBits.LoadedFieldsFromExternalStorage;
}
- void setHasLoadedFieldsFromExternalStorage(bool val) {
- LoadedFieldsFromExternalStorage = val;
+
+ void setHasLoadedFieldsFromExternalStorage(bool val) const {
+ RecordDeclBits.LoadedFieldsFromExternalStorage = val;
}
/// Functions to query basic properties of non-trivial C structs.
bool isNonTrivialToPrimitiveDefaultInitialize() const {
- return NonTrivialToPrimitiveDefaultInitialize;
+ return RecordDeclBits.NonTrivialToPrimitiveDefaultInitialize;
}
void setNonTrivialToPrimitiveDefaultInitialize(bool V) {
- NonTrivialToPrimitiveDefaultInitialize = V;
+ RecordDeclBits.NonTrivialToPrimitiveDefaultInitialize = V;
}
bool isNonTrivialToPrimitiveCopy() const {
- return NonTrivialToPrimitiveCopy;
+ return RecordDeclBits.NonTrivialToPrimitiveCopy;
}
void setNonTrivialToPrimitiveCopy(bool V) {
- NonTrivialToPrimitiveCopy = V;
+ RecordDeclBits.NonTrivialToPrimitiveCopy = V;
}
bool isNonTrivialToPrimitiveDestroy() const {
- return NonTrivialToPrimitiveDestroy;
+ return RecordDeclBits.NonTrivialToPrimitiveDestroy;
}
void setNonTrivialToPrimitiveDestroy(bool V) {
- NonTrivialToPrimitiveDestroy = V;
+ RecordDeclBits.NonTrivialToPrimitiveDestroy = V;
}
/// Determine whether this class can be passed in registers. In C++ mode,
@@ -3720,19 +3674,19 @@ public:
}
ArgPassingKind getArgPassingRestrictions() const {
- return static_cast<ArgPassingKind>(ArgPassingRestrictions);
+ return static_cast<ArgPassingKind>(RecordDeclBits.ArgPassingRestrictions);
}
void setArgPassingRestrictions(ArgPassingKind Kind) {
- ArgPassingRestrictions = static_cast<uint8_t>(Kind);
+ RecordDeclBits.ArgPassingRestrictions = Kind;
}
bool isParamDestroyedInCallee() const {
- return ParamDestroyedInCallee;
+ return RecordDeclBits.ParamDestroyedInCallee;
}
void setParamDestroyedInCallee(bool V) {
- ParamDestroyedInCallee = V;
+ RecordDeclBits.ParamDestroyedInCallee = V;
}
/// Determines whether this declaration represents the
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h
index d6b89d971d..3816da4222 100644
--- a/include/clang/AST/DeclBase.h
+++ b/include/clang/AST/DeclBase.h
@@ -1260,37 +1260,407 @@ public:
/// BlockDecl
/// OMPDeclareReductionDecl
class DeclContext {
- /// DeclKind - This indicates which class this is.
- unsigned DeclKind : 8;
+ // We use uint64_t in the bit-fields below since some bit-fields
+ // cross the unsigned boundary and this breaks the packing.
+
+ /// Stores the bits used by DeclContext.
+ /// If modified NumDeclContextBit, the ctor of DeclContext and the accessor
+ /// methods in DeclContext should be updated appropriately.
+ class DeclContextBitfields {
+ friend class DeclContext;
+ /// DeclKind - This indicates which class this is.
+ uint64_t DeclKind : 7;
+
+ /// Whether this declaration context also has some external
+ /// storage that contains additional declarations that are lexically
+ /// part of this context.
+ mutable uint64_t ExternalLexicalStorage : 1;
+
+ /// Whether this declaration context also has some external
+ /// storage that contains additional declarations that are visible
+ /// in this context.
+ mutable uint64_t ExternalVisibleStorage : 1;
+
+ /// Whether this declaration context has had externally visible
+ /// storage added since the last lookup. In this case, \c LookupPtr's
+ /// invariant may not hold and needs to be fixed before we perform
+ /// another lookup.
+ mutable uint64_t NeedToReconcileExternalVisibleStorage : 1;
+
+ /// If \c true, this context may have local lexical declarations
+ /// that are missing from the lookup table.
+ mutable uint64_t HasLazyLocalLexicalLookups : 1;
+
+ /// If \c true, the external source may have lexical declarations
+ /// that are missing from the lookup table.
+ mutable uint64_t HasLazyExternalLexicalLookups : 1;
+
+ /// If \c true, lookups should only return identifier from
+ /// DeclContext scope (for example TranslationUnit). Used in
+ /// LookupQualifiedName()
+ mutable uint64_t UseQualifiedLookup : 1;
+ };
- /// Whether this declaration context also has some external
- /// storage that contains additional declarations that are lexically
- /// part of this context.
- mutable bool ExternalLexicalStorage : 1;
+ /// Number of bits in DeclContextBitfields.
+ enum { NumDeclContextBits = 13 };
- /// Whether this declaration context also has some external
- /// storage that contains additional declarations that are visible
- /// in this context.
- mutable bool ExternalVisibleStorage : 1;
+ /// Stores the bits used by TagDecl.
+ /// If modified NumTagDeclBits and the accessor
+ /// methods in TagDecl should be updated appropriately.
+ class TagDeclBitfields {
+ friend class TagDecl;
+ /// For the bits in DeclContextBitfields
+ uint64_t : NumDeclContextBits;
- /// Whether this declaration context has had external visible
- /// storage added since the last lookup. In this case, \c LookupPtr's
- /// invariant may not hold and needs to be fixed before we perform
- /// another lookup.
- mutable bool NeedToReconcileExternalVisibleStorage : 1;
+ /// The TagKind enum.
+ uint64_t TagDeclKind : 3;
- /// If \c true, this context may have local lexical declarations
- /// that are missing from the lookup table.
- mutable bool HasLazyLocalLexicalLookups : 1;
+ /// True if this is a definition ("struct foo {};"), false if it is a
+ /// declaration ("struct foo;"). It is not considered a definition
+ /// until the definition has been fully processed.
+ uint64_t IsCompleteDefinition : 1;
- /// If \c true, the external source may have lexical declarations
- /// that are missing from the lookup table.
- mutable bool HasLazyExternalLexicalLookups : 1;
+ /// True if this is currently being defined.
+ uint64_t IsBeingDefined : 1;
+
+ /// True if this tag declaration is "embedded" (i.e., defined or declared
+ /// for the very first time) in the syntax of a declarator.
+ uint64_t IsEmbeddedInDeclarator : 1;
+
+ /// True if this tag is free standing, e.g. "struct foo;".
+ uint64_t IsFreeStanding : 1;
+
+ /// Indicates whether it is possible for declarations of this kind
+ /// to have an out-of-date definition.
+ ///
+ /// This option is only enabled when modules are enabled.
+ uint64_t MayHaveOutOfDateDef : 1;
+
+ /// Has the full definition of this type been required by a use somewhere in
+ /// the TU.
+ uint64_t IsCompleteDefinitionRequired : 1;
+ };
+
+ /// Number of non-inherited bits in TagDeclBitfields.
+ enum { NumTagDeclBits = 9 };
+
+ /// Stores the bits used by EnumDecl.
+ /// If modified NumEnumDeclBit and the accessor
+ /// methods in EnumDecl should be updated appropriately.
+ class EnumDeclBitfields {
+ friend class EnumDecl;
+ /// For the bits in DeclContextBitfields.
+ uint64_t : NumDeclContextBits;
+ /// For the bits in TagDeclBitfields.
+ uint64_t : NumTagDeclBits;
+
+ /// Width in bits required to store all the non-negative
+ /// enumerators of this enum.
+ uint64_t NumPositiveBits : 8;
+
+ /// Width in bits required to store all the negative
+ /// enumerators of this enum.
+ uint64_t NumNegativeBits : 8;
+
+ /// True if this tag declaration is a scoped enumeration. Only
+ /// possible in C++11 mode.
+ uint64_t IsScoped : 1;
+
+ /// If this tag declaration is a scoped enum,
+ /// then this is true if the scoped enum was declared using the class
+ /// tag, false if it was declared with the struct tag. No meaning is
+ /// associated if this tag declaration is not a scoped enum.
+ uint64_t IsScopedUsingClassTag : 1;
+
+ /// True if this is an enumeration with fixed underlying type. Only
+ /// possible in C++11, Microsoft extensions, or Objective C mode.
+ uint64_t IsFixed : 1;
+
+ /// True if a valid hash is stored in ODRHash.
+ uint64_t HasODRHash : 1;
+ };
+
+ /// Number of non-inherited bits in EnumDeclBitfields.
+ enum { NumEnumDeclBits = 20 };
+
+ /// Stores the bits used by RecordDecl.
+ /// If modified NumRecordDeclBits and the accessor
+ /// methods in RecordDecl should be updated appropriately.
+ class RecordDeclBitfields {
+ friend class RecordDecl;
+ /// For the bits in DeclContextBitfields.
+ uint64_t : NumDeclContextBits;
+ /// For the bits in TagDeclBitfields.
+ uint64_t : NumTagDeclBits;
+
+ /// This is true if this struct ends with a flexible
+ /// array member (e.g. int X[]) or if this union contains a struct that does.
+ /// If so, this cannot be contained in arrays or other structs as a member.
+ uint64_t HasFlexibleArrayMember : 1;
+
+ /// Whether this is the type of an anonymous struct or union.
+ uint64_t AnonymousStructOrUnion : 1;
+
+ /// This is true if this struct has at least one member
+ /// containing an Objective-C object pointer type.
+ uint64_t HasObjectMember : 1;
+
+ /// This is true if struct has at least one member of
+ /// 'volatile' type.
+ uint64_t HasVolatileMember : 1;
+
+ /// Whether the field declarations of this record have been loaded
+ /// from external storage. To avoid unnecessary deserialization of
+ /// methods/nested types we allow deserialization of just the fields
+ /// when needed.
+ mutable uint64_t LoadedFieldsFromExternalStorage : 1;
+
+ /// Basic properties of non-trivial C structs.
+ uint64_t NonTrivialToPrimitiveDefaultInitialize : 1;
+ uint64_t NonTrivialToPrimitiveCopy : 1;
+ uint64_t NonTrivialToPrimitiveDestroy : 1;
+
+ /// Indicates whether this struct is destroyed in the callee.
+ uint64_t ParamDestroyedInCallee : 1;
+
+ /// Represents the way this type is passed to a function.
+ uint64_t ArgPassingRestrictions : 2;
+ };
+
+ /// Number of non-inherited bits in RecordDeclBitfields.
+ enum { NumRecordDeclBits = 11 };
+
+ /// Stores the bits used by OMPDeclareReductionDecl.
+ /// If modified NumOMPDeclareReductionDeclBits and the accessor
+ /// methods in OMPDeclareReductionDecl should be updated appropriately.
+ class OMPDeclareReductionDeclBitfields {
+ friend class OMPDeclareReductionDecl;
+ /// For the bits in DeclContextBitfields
+ uint64_t : NumDeclContextBits;
+
+ /// Kind of initializer,
+ /// function call or omp_priv<init_expr> initializtion.
+ uint64_t InitializerKind : 2;
+ };
+
+ /// Number of non-inherited bits in OMPDeclareReductionDeclBitfields.
+ enum { NumOMPDeclareReductionDeclBits = 2 };
+
+ /// Stores the bits used by FunctionDecl.
+ /// If modified NumFunctionDeclBits and the accessor
+ /// methods in FunctionDecl and CXXDeductionGuideDecl
+ /// (for IsCopyDeductionCandidate) should be updated appropriately.
+ class FunctionDeclBitfields {
+ friend class FunctionDecl;
+ /// For IsCopyDeductionCandidate
+ friend class CXXDeductionGuideDecl;
+ /// For the bits in DeclContextBitfields.
+ uint64_t : NumDeclContextBits;
+
+ uint64_t SClass : 3;
+ uint64_t IsInline : 1;
+ uint64_t IsInlineSpecified : 1;
+
+ /// This is shared by CXXConstructorDecl,
+ /// CXXConversionDecl, and CXXDeductionGuideDecl.
+ uint64_t IsExplicitSpecified : 1;
+
+ uint64_t IsVirtualAsWritten : 1;
+ uint64_t IsPure : 1;
+ uint64_t HasInheritedPrototype : 1;
+ uint64_t HasWrittenPrototype : 1;
+ uint64_t IsDeleted : 1;
+ /// Used by CXXMethodDecl
+ uint64_t IsTrivial : 1;
+
+ /// This flag indicates whether this function is trivial for the purpose of
+ /// calls. This is meaningful only when this function is a copy/move
+ /// constructor or a destructor.
+ uint64_t IsTrivialForCall : 1;
+
+ /// Used by CXXMethodDecl
+ uint64_t IsDefaulted : 1;
+ /// Used by CXXMethodDecl
+ uint64_t IsExplicitlyDefaulted : 1;
+ uint64_t HasImplicitReturnZero : 1;
+ uint64_t IsLateTemplateParsed : 1;
+ uint64_t IsConstexpr : 1;
+ uint64_t InstantiationIsPending : 1;
+
+ /// Indicates if the function uses __try.
+ uint64_t UsesSEHTry : 1;
+
+ /// Indicates if the function was a definition
+ /// but its body was skipped.
+ uint64_t HasSkippedBody : 1;
+
+ /// Indicates if the function declaration will
+ /// have a body, once we're done parsing it.
+ uint64_t WillHaveBody : 1;
+
+ /// Indicates that this function is a multiversioned
+ /// function using attribute 'target'.
+ uint64_t IsMultiVersion : 1;
+
+ /// [C++17] Only used by CXXDeductionGuideDecl. Indicates that
+ /// the Deduction Guide is the implicitly generated 'copy
+ /// deduction candidate' (is used during overload resolution).
+ uint64_t IsCopyDeductionCandidate : 1;
+
+ /// Store the ODRHash after first calculation.
+ uint64_t HasODRHash : 1;
+ };
+
+ /// Number of non-inherited bits in FunctionDeclBitfields.
+ enum { NumFunctionDeclBits = 25 };
+
+ /// Stores the bits used by CXXConstructorDecl. If modified
+ /// NumCXXConstructorDeclBits and the accessor
+ /// methods in CXXConstructorDecl should be updated appropriately.
+ class CXXConstructorDeclBitfields {
+ friend class CXXConstructorDecl;
+ /// For the bits in DeclContextBitfields.
+ uint64_t : NumDeclContextBits;
+ /// For the bits in FunctionDeclBitfields.
+ uint64_t : NumFunctionDeclBits;
+
+ /// 25 bits to fit in the remaining availible space.
+ /// Note that this makes CXXConstructorDeclBitfields take
+ /// exactly 64 bits and thus the width of NumCtorInitializers
+ /// will need to be shrunk if some bit is added to NumDeclContextBitfields,
+ /// NumFunctionDeclBitfields or CXXConstructorDeclBitfields.
+ uint64_t NumCtorInitializers : 25;
+ uint64_t IsInheritingConstructor : 1;
+ };
+
+ /// Number of non-inherited bits in CXXConstructorDeclBitfields.
+ enum { NumCXXConstructorDeclBits = 26 };
+
+ /// Stores the bits used by ObjCMethodDecl.
+ /// If modified NumObjCMethodDeclBits and the accessor
+ /// methods in ObjCMethodDecl should be updated appropriately.
+ class ObjCMethodDeclBitfields {
+ friend class ObjCMethodDecl;
+ /// For the bits in DeclContextBitfields.
+ uint64_t : NumDeclContextBits;
+
+ /// This is needed for the bitwidth of Family below but
+ /// is defined in Basic/IdentifierTable.h which we do not include.
+ /// To avoid mismatches between the two definitions we have
+ /// a static_assert in the ctor of ObjCMethodDecl which checks
+ /// that these two ObjCMethodFamilyBitWidth are equal.
+ enum { ObjCMethodFamilyBitWidth = 4 };
+
+ /// The conventional meaning of this method; an ObjCMethodFamily.
+ /// This is not serialized; instead, it is computed on demand and
+ /// cached.
+ mutable uint64_t Family : ObjCMethodFamilyBitWidth;
+
+ /// instance (true) or class (false) method.
+ uint64_t IsInstance : 1;
+ uint64_t IsVariadic : 1;
+
+ /// True if this method is the getter or setter for an explicit property.
+ uint64_t IsPropertyAccessor : 1;
+
+ /// Method has a definition.
+ uint64_t IsDefined : 1;
+
+ /// Method redeclaration in the same interface.
+ uint64_t IsRedeclaration : 1;
+
+ /// Is redeclared in the same interface.
+ mutable uint64_t HasRedeclaration : 1;
+
+ /// \@required/\@optional
+ uint64_t DeclImplementation : 2;
+
+ /// in, inout, etc.
+ uint64_t objcDeclQualifier : 7;
+
+ /// Indicates whether this method has a related result type.
+ uint64_t RelatedResultType : 1;
+
+ /// Whether the locations of the selector identifiers are in a
+ /// "standard" position, a enum SelectorLocationsKind.
+ uint64_t SelLocsKind : 2;
+
+ /// 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.
+ uint64_t IsOverriding : 1;
+
+ /// Indicates if the method was a definition but its body was skipped.
+ uint64_t HasSkippedBody : 1;
+ };
+
+ /// Number of non-inherited bits in ObjCMethodDeclBitfields.
+ enum { NumObjCMethodDeclBits = 24 };
+
+ /// Stores the bits used by ObjCContainerDecl.
+ /// If modified NumObjCContainerDeclBits and the accessor
+ /// methods in ObjCContainerDecl should be updated appropriately.
+ class ObjCContainerDeclBitfields {
+ friend class ObjCContainerDecl;
+ /// For the bits in DeclContextBitfields
+ uint32_t : NumDeclContextBits;
+
+ // Not a bitfield but this saves space.
+ // Note that ObjCContainerDeclBitfields is full.
+ SourceLocation AtStart;
+ };
+
+ /// Number of non-inherited bits in ObjCContainerDeclBitfields.
+ /// Note that here we rely on the fact that SourceLocation is 32 bits
+ /// wide. We check this with the static_assert in the ctor of DeclContext.
+ enum { NumObjCContainerDeclBits = 64 - NumDeclContextBits };
+
+ /// Stores the bits used by LinkageSpecDecl.
+ /// If modified NumLinkageSpecDeclBits and the accessor
+ /// methods in LinkageSpecDecl should be updated appropriately.
+ class LinkageSpecDeclBitfields {
+ friend class LinkageSpecDecl;
+ /// For the bits in DeclContextBitfields.
+ uint64_t : NumDeclContextBits;
+
+ /// The language for this linkage specification with values
+ /// in the enum LinkageSpecDecl::LanguageIDs.
+ uint64_t Language : 3;
+
+ /// True if this linkage spec has braces.
+ /// This is needed so that hasBraces() returns the correct result while the
+ /// linkage spec body is being parsed. Once RBraceLoc has been set this is
+ /// not used, so it doesn't need to be serialized.
+ uint64_t HasBraces : 1;
+ };
+
+ /// Number of non-inherited bits in LinkageSpecDeclBitfields.
+ enum { NumLinkageSpecDeclBits = 4 };
+
+ /// Stores the bits used by BlockDecl.
+ /// If modified NumBlockDeclBits and the accessor
+ /// methods in BlockDecl should be updated appropriately.
+ class BlockDeclBitfields {
+ friend class BlockDecl;
+ /// For the bits in DeclContextBitfields.
+ uint64_t : NumDeclContextBits;
+
+ uint64_t IsVariadic : 1;
+ uint64_t CapturesCXXThis : 1;
+ uint64_t BlockMissingReturnType : 1;
+ uint64_t IsConversionFromLambda : 1;
+
+ /// A bit that indicates this block is passed directly to a function as a
+ /// non-escaping parameter.
+ uint64_t DoesNotEscape : 1;
+ };
- /// If \c true, lookups should only return identifier from
- /// DeclContext scope (for example TranslationUnit). Used in
- /// LookupQualifiedName()
- mutable bool UseQualifiedLookup : 1;
+ /// Number of non-inherited bits in BlockDeclBitfields.
+ enum { NumBlockDeclBits = 5 };
/// Pointer to the data structure used to lookup declarations
/// within this context (or a DependentStoredDeclsMap if this is a
@@ -1301,6 +1671,51 @@ class DeclContext {
mutable StoredDeclsMap *LookupPtr = nullptr;
protected:
+ /// This anonymous union stores the bits belonging to DeclContext and classes
+ /// deriving from it. The goal is to use otherwise wasted
+ /// space in DeclContext to store data belonging to derived classes.
+ /// The space saved is especially significient when pointers are aligned
+ /// to 8 bytes. In this case due to alignment requirements we have a
+ /// little less than 8 bytes free in DeclContext which we can use.
+ /// We check that none of the classes in this union is larger than
+ /// 8 bytes with static_asserts in the ctor of DeclContext.
+ union {
+ DeclContextBitfields DeclContextBits;
+ TagDeclBitfields TagDeclBits;
+ EnumDeclBitfields EnumDeclBits;
+ RecordDeclBitfields RecordDeclBits;
+ OMPDeclareReductionDeclBitfields OMPDeclareReductionDeclBits;
+ FunctionDeclBitfields FunctionDeclBits;
+ CXXConstructorDeclBitfields CXXConstructorDeclBits;
+ ObjCMethodDeclBitfields ObjCMethodDeclBits;
+ ObjCContainerDeclBitfields ObjCContainerDeclBits;
+ LinkageSpecDeclBitfields LinkageSpecDeclBits;
+ BlockDeclBitfields BlockDeclBits;
+
+ static_assert(sizeof(DeclContextBitfields) <= 8,
+ "DeclContextBitfields is larger than 8 bytes!");
+ static_assert(sizeof(TagDeclBitfields) <= 8,
+ "TagDeclBitfields is larger than 8 bytes!");
+ static_assert(sizeof(EnumDeclBitfields) <= 8,
+ "EnumDeclBitfields is larger than 8 bytes!");
+ static_assert(sizeof(RecordDeclBitfields) <= 8,
+ "RecordDeclBitfields is larger than 8 bytes!");
+ static_assert(sizeof(OMPDeclareReductionDeclBitfields) <= 8,
+ "OMPDeclareReductionDeclBitfields is larger than 8 bytes!");
+ static_assert(sizeof(FunctionDeclBitfields) <= 8,
+ "FunctionDeclBitfields is larger than 8 bytes!");
+ static_assert(sizeof(CXXConstructorDeclBitfields) <= 8,
+ "CXXConstructorDeclBitfields is larger than 8 bytes!");
+ static_assert(sizeof(ObjCMethodDeclBitfields) <= 8,
+ "ObjCMethodDeclBitfields is larger than 8 bytes!");
+ static_assert(sizeof(ObjCContainerDeclBitfields) <= 8,
+ "ObjCContainerDeclBitfields is larger than 8 bytes!");
+ static_assert(sizeof(LinkageSpecDeclBitfields) <= 8,
+ "LinkageSpecDeclBitfields is larger than 8 bytes!");
+ static_assert(sizeof(BlockDeclBitfields) <= 8,
+ "BlockDeclBitfields is larger than 8 bytes!");
+ };
+
friend class ASTDeclReader;
friend class ASTWriter;
friend class ExternalASTSource;
@@ -1321,18 +1736,13 @@ protected:
static std::pair<Decl *, Decl *>
BuildDeclChain(ArrayRef<Decl*> Decls, bool FieldsAlreadyLoaded);
- DeclContext(Decl::Kind K)
- : DeclKind(K), ExternalLexicalStorage(false),
- ExternalVisibleStorage(false),
- NeedToReconcileExternalVisibleStorage(false),
- HasLazyLocalLexicalLookups(false), HasLazyExternalLexicalLookups(false),
- UseQualifiedLookup(false) {}
+ DeclContext(Decl::Kind K);
public:
~DeclContext();
Decl::Kind getDeclKind() const {
- return static_cast<Decl::Kind>(DeclKind);
+ return static_cast<Decl::Kind>(DeclContextBits.DeclKind);
}
const char *getDeclKindName() const;
@@ -1371,54 +1781,54 @@ public:
return cast<Decl>(this)->getASTContext();
}
- bool isClosure() const {
- return DeclKind == Decl::Block;
- }
+ bool isClosure() const { return getDeclKind() == Decl::Block; }
bool isObjCContainer() const {
- switch (DeclKind) {
- case Decl::ObjCCategory:
- case Decl::ObjCCategoryImpl:
- case Decl::ObjCImplementation:
- case Decl::ObjCInterface:
- case Decl::ObjCProtocol:
- return true;
+ switch (getDeclKind()) {
+ case Decl::ObjCCategory:
+ case Decl::ObjCCategoryImpl:
+ case Decl::ObjCImplementation:
+ case Decl::ObjCInterface:
+ case Decl::ObjCProtocol:
+ return true;
+ default:
+ return false;
}
- return false;
}
bool isFunctionOrMethod() const {
- switch (DeclKind) {
+ switch (getDeclKind()) {
case Decl::Block:
case Decl::Captured:
case Decl::ObjCMethod:
return true;
default:
- return DeclKind >= Decl::firstFunction && DeclKind <= Decl::lastFunction;
+ return getDeclKind() >= Decl::firstFunction &&
+ getDeclKind() <= Decl::lastFunction;
}
}
/// Test whether the context supports looking up names.
bool isLookupContext() const {
- return !isFunctionOrMethod() && DeclKind != Decl::LinkageSpec &&
- DeclKind != Decl::Export;
+ return !isFunctionOrMethod() && getDeclKind() != Decl::LinkageSpec &&
+ getDeclKind() != Decl::Export;
}
bool isFileContext() const {
- return DeclKind == Decl::TranslationUnit || DeclKind == Decl::Namespace;
+ return getDeclKind() == Decl::TranslationUnit ||
+ getDeclKind() == Decl::Namespace;
}
bool isTranslationUnit() const {
- return DeclKind == Decl::TranslationUnit;
+ return getDeclKind() == Decl::TranslationUnit;
}
bool isRecord() const {
- return DeclKind >= Decl::firstRecord && DeclKind <= Decl::lastRecord;
+ return getDeclKind() >= Decl::firstRecord &&
+ getDeclKind() <= Decl::lastRecord;
}
- bool isNamespace() const {
- return DeclKind == Decl::Namespace;
- }
+ bool isNamespace() const { return getDeclKind() == Decl::Namespace; }
bool isStdNamespace() const;
@@ -1886,7 +2296,7 @@ public:
void setMustBuildLookupTable() {
assert(this == getPrimaryContext() &&
"should only be called on primary context");
- HasLazyExternalLexicalLookups = true;
+ DeclContextBits.HasLazyExternalLexicalLookups = true;
}
/// Retrieve the internal representation of the lookup structure.
@@ -1898,24 +2308,28 @@ public:
/// Whether this DeclContext has external storage containing
/// additional declarations that are lexically in this context.
- bool hasExternalLexicalStorage() const { return ExternalLexicalStorage; }
+ bool hasExternalLexicalStorage() const {
+ return DeclContextBits.ExternalLexicalStorage;
+ }
/// State whether this DeclContext has external storage for
/// declarations lexically in this context.
- void setHasExternalLexicalStorage(bool ES = true) {
- ExternalLexicalStorage = ES;
+ void setHasExternalLexicalStorage(bool ES = true) const {
+ DeclContextBits.ExternalLexicalStorage = ES;
}
/// Whether this DeclContext has external storage containing
/// additional declarations that are visible in this context.
- bool hasExternalVisibleStorage() const { return ExternalVisibleStorage; }
+ bool hasExternalVisibleStorage() const {
+ return DeclContextBits.ExternalVisibleStorage;
+ }
/// State whether this DeclContext has external storage for
/// declarations visible in this context.
- void setHasExternalVisibleStorage(bool ES = true) {
- ExternalVisibleStorage = ES;
+ void setHasExternalVisibleStorage(bool ES = true) const {
+ DeclContextBits.ExternalVisibleStorage = ES;
if (ES && LookupPtr)
- NeedToReconcileExternalVisibleStorage = true;
+ DeclContextBits.NeedToReconcileExternalVisibleStorage = true;
}
/// Determine whether the given declaration is stored in the list of
@@ -1925,14 +2339,14 @@ public:
D == LastDecl);
}
- bool setUseQualifiedLookup(bool use = true) {
- bool old_value = UseQualifiedLookup;
- UseQualifiedLookup = use;
+ bool setUseQualifiedLookup(bool use = true) const {
+ bool old_value = DeclContextBits.UseQualifiedLookup;
+ DeclContextBits.UseQualifiedLookup = use;
return old_value;
}
bool shouldUseQualifiedLookup() const {
- return UseQualifiedLookup;
+ return DeclContextBits.UseQualifiedLookup;
}
static bool classof(const Decl *D);
@@ -1944,6 +2358,46 @@ public:
bool Deserialize = false) const;
private:
+ /// Whether this declaration context has had externally visible
+ /// storage added since the last lookup. In this case, \c LookupPtr's
+ /// invariant may not hold and needs to be fixed before we perform
+ /// another lookup.
+ bool hasNeedToReconcileExternalVisibleStorage() const {
+ return DeclContextBits.NeedToReconcileExternalVisibleStorage;
+ }
+
+ /// State that this declaration context has had externally visible
+ /// storage added since the last lookup. In this case, \c LookupPtr's
+ /// invariant may not hold and needs to be fixed before we perform
+ /// another lookup.
+ void setNeedToReconcileExternalVisibleStorage(bool Need = true) const {
+ DeclContextBits.NeedToReconcileExternalVisibleStorage = Need;
+ }
+
+ /// If \c true, this context may have local lexical declarations
+ /// that are missing from the lookup table.
+ bool hasLazyLocalLexicalLookups() const {
+ return DeclContextBits.HasLazyLocalLexicalLookups;
+ }
+
+ /// If \c true, this context may have local lexical declarations
+ /// that are missing from the lookup table.
+ void setHasLazyLocalLexicalLookups(bool HasLLLL = true) const {
+ DeclContextBits.HasLazyLocalLexicalLookups = HasLLLL;
+ }
+
+ /// If \c true, the external source may have lexical declarations
+ /// that are missing from the lookup table.
+ bool hasLazyExternalLexicalLookups() const {
+ return DeclContextBits.HasLazyExternalLexicalLookups;
+ }
+
+ /// If \c true, the external source may have lexical declarations
+ /// that are missing from the lookup table.
+ void setHasLazyExternalLexicalLookups(bool HasLELL = true) const {
+ DeclContextBits.HasLazyExternalLexicalLookups = HasLELL;
+ }
+
friend class DependentDiagnostic;
void reconcileExternalVisibleStorage() const;