forked from OSchip/llvm-project
[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 llvm-svn: 338630
This commit is contained in:
parent
7f33094486
commit
f92f31c6a8
|
@ -3014,63 +3014,15 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Represents the declaration of a struct/union/class/enum.
|
/// Represents the declaration of a struct/union/class/enum.
|
||||||
class TagDecl
|
class TagDecl : public TypeDecl,
|
||||||
: public TypeDecl, public DeclContext, public Redeclarable<TagDecl> {
|
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:
|
public:
|
||||||
// This is really ugly.
|
// This is really ugly.
|
||||||
using TagKind = TagTypeKind;
|
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:
|
private:
|
||||||
SourceRange BraceRange;
|
SourceRange BraceRange;
|
||||||
|
|
||||||
|
@ -3097,16 +3049,7 @@ private:
|
||||||
protected:
|
protected:
|
||||||
TagDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC,
|
TagDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC,
|
||||||
SourceLocation L, IdentifierInfo *Id, TagDecl *PrevDecl,
|
SourceLocation L, IdentifierInfo *Id, TagDecl *PrevDecl,
|
||||||
SourceLocation StartL)
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
using redeclarable_base = Redeclarable<TagDecl>;
|
using redeclarable_base = Redeclarable<TagDecl>;
|
||||||
|
|
||||||
|
@ -3127,6 +3070,17 @@ protected:
|
||||||
/// This is a helper function for derived classes.
|
/// This is a helper function for derived classes.
|
||||||
void completeDefinition();
|
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:
|
public:
|
||||||
friend class ASTDeclReader;
|
friend class ASTDeclReader;
|
||||||
friend class ASTDeclWriter;
|
friend class ASTDeclWriter;
|
||||||
|
@ -3165,33 +3119,54 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true if this decl has its body fully specified.
|
/// Return true if this decl has its body fully specified.
|
||||||
bool isCompleteDefinition() const {
|
bool isCompleteDefinition() const { return TagDeclBits.IsCompleteDefinition; }
|
||||||
return 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
|
/// Return true if this complete decl is
|
||||||
/// required to be complete for some existing use.
|
/// required to be complete for some existing use.
|
||||||
bool isCompleteDefinitionRequired() const {
|
bool isCompleteDefinitionRequired() const {
|
||||||
return IsCompleteDefinitionRequired;
|
return TagDeclBits.IsCompleteDefinitionRequired;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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.
|
/// Return true if this decl is currently being defined.
|
||||||
bool isBeingDefined() const {
|
bool isBeingDefined() const { return TagDeclBits.IsBeingDefined; }
|
||||||
return 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 {
|
bool isEmbeddedInDeclarator() const {
|
||||||
return IsEmbeddedInDeclarator;
|
return TagDeclBits.IsEmbeddedInDeclarator;
|
||||||
}
|
|
||||||
void setEmbeddedInDeclarator(bool isInDeclarator) {
|
|
||||||
IsEmbeddedInDeclarator = isInDeclarator;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isFreeStanding() const { return IsFreeStanding; }
|
/// True if this tag declaration is "embedded" (i.e., defined or declared
|
||||||
void setFreeStanding(bool isFreeStanding = true) {
|
/// for the very first time) in the syntax of a declarator.
|
||||||
IsFreeStanding = isFreeStanding;
|
void setEmbeddedInDeclarator(bool isInDeclarator) {
|
||||||
|
TagDeclBits.IsEmbeddedInDeclarator = isInDeclarator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 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) {
|
||||||
|
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
|
/// Whether this declaration declares a type that is
|
||||||
/// dependent, i.e., a type that somehow depends on template
|
/// dependent, i.e., a type that somehow depends on template
|
||||||
/// parameters.
|
/// parameters.
|
||||||
|
@ -3214,21 +3189,15 @@ public:
|
||||||
/// the struct/union/class/enum.
|
/// the struct/union/class/enum.
|
||||||
TagDecl *getDefinition() const;
|
TagDecl *getDefinition() const;
|
||||||
|
|
||||||
void setCompleteDefinition(bool V) { IsCompleteDefinition = V; }
|
|
||||||
|
|
||||||
void setCompleteDefinitionRequired(bool V = true) {
|
|
||||||
IsCompleteDefinitionRequired = V;
|
|
||||||
}
|
|
||||||
|
|
||||||
StringRef getKindName() const {
|
StringRef getKindName() const {
|
||||||
return TypeWithKeyword::getTagTypeKindName(getTagKind());
|
return TypeWithKeyword::getTagTypeKindName(getTagKind());
|
||||||
}
|
}
|
||||||
|
|
||||||
TagKind getTagKind() const {
|
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 isStruct() const { return getTagKind() == TTK_Struct; }
|
||||||
bool isInterface() const { return getTagKind() == TTK_Interface; }
|
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 a fixed underlying type, and in C we allow them to be forward-declared
|
||||||
/// with no underlying type as an extension.
|
/// with no underlying type as an extension.
|
||||||
class EnumDecl : public TagDecl {
|
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
|
/// This represent the integer type that the enum corresponds
|
||||||
/// to for code generation purposes. Note that the enumerator constants may
|
/// to for code generation purposes. Note that the enumerator constants may
|
||||||
/// have a different type than this does.
|
/// have a different type than this does.
|
||||||
|
@ -3336,28 +3308,50 @@ class EnumDecl : public TagDecl {
|
||||||
MemberSpecializationInfo *SpecializationInfo = nullptr;
|
MemberSpecializationInfo *SpecializationInfo = nullptr;
|
||||||
|
|
||||||
/// Store the ODRHash after first calculation.
|
/// 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;
|
unsigned ODRHash;
|
||||||
|
|
||||||
EnumDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
|
EnumDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc,
|
||||||
SourceLocation IdLoc, IdentifierInfo *Id, EnumDecl *PrevDecl,
|
SourceLocation IdLoc, IdentifierInfo *Id, EnumDecl *PrevDecl,
|
||||||
bool Scoped, bool ScopedUsingClassTag, bool Fixed)
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
void anchor() override;
|
void anchor() override;
|
||||||
|
|
||||||
void setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED,
|
void setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED,
|
||||||
TemplateSpecializationKind TSK);
|
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:
|
public:
|
||||||
friend class ASTDeclReader;
|
friend class ASTDeclReader;
|
||||||
|
|
||||||
|
@ -3462,13 +3456,7 @@ public:
|
||||||
|
|
||||||
/// Returns the width in bits required to store all the
|
/// Returns the width in bits required to store all the
|
||||||
/// non-negative enumerators of this enum.
|
/// non-negative enumerators of this enum.
|
||||||
unsigned getNumPositiveBits() const {
|
unsigned getNumPositiveBits() const { return EnumDeclBits.NumPositiveBits; }
|
||||||
return NumPositiveBits;
|
|
||||||
}
|
|
||||||
void setNumPositiveBits(unsigned Num) {
|
|
||||||
NumPositiveBits = Num;
|
|
||||||
assert(NumPositiveBits == Num && "can't store this bitcount");
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the width in bits required to store all the
|
/// Returns the width in bits required to store all the
|
||||||
/// negative enumerators of this enum. These widths include
|
/// negative enumerators of this enum. These widths include
|
||||||
|
@ -3479,28 +3467,19 @@ public:
|
||||||
/// -1 1111111 1
|
/// -1 1111111 1
|
||||||
/// -10 1110110 5
|
/// -10 1110110 5
|
||||||
/// -101 1001011 8
|
/// -101 1001011 8
|
||||||
unsigned getNumNegativeBits() const {
|
unsigned getNumNegativeBits() const { return EnumDeclBits.NumNegativeBits; }
|
||||||
return NumNegativeBits;
|
|
||||||
}
|
|
||||||
void setNumNegativeBits(unsigned Num) {
|
|
||||||
NumNegativeBits = Num;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if this is a C++11 scoped enumeration.
|
/// Returns true if this is a C++11 scoped enumeration.
|
||||||
bool isScoped() const {
|
bool isScoped() const { return EnumDeclBits.IsScoped; }
|
||||||
return IsScoped;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns true if this is a C++11 scoped enumeration.
|
/// Returns true if this is a C++11 scoped enumeration.
|
||||||
bool isScopedUsingClassTag() const {
|
bool isScopedUsingClassTag() const {
|
||||||
return IsScopedUsingClassTag;
|
return EnumDeclBits.IsScopedUsingClassTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this is an Objective-C, C++11, or
|
/// Returns true if this is an Objective-C, C++11, or
|
||||||
/// Microsoft-style enumeration with a fixed underlying type.
|
/// Microsoft-style enumeration with a fixed underlying type.
|
||||||
bool isFixed() const {
|
bool isFixed() const { return EnumDeclBits.IsFixed; }
|
||||||
return IsFixed;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned getODRHash();
|
unsigned getODRHash();
|
||||||
|
|
||||||
|
@ -3565,7 +3544,10 @@ public:
|
||||||
/// union Y { int A, B; }; // Has body with members A and B (FieldDecls).
|
/// union Y { int A, B; }; // Has body with members A and B (FieldDecls).
|
||||||
/// This decl will be marked invalid if *any* members are invalid.
|
/// This decl will be marked invalid if *any* members are invalid.
|
||||||
class RecordDecl : public TagDecl {
|
class RecordDecl : public TagDecl {
|
||||||
|
// This class stores some data in DeclContext::RecordDeclBits
|
||||||
|
// to save some space. Use the provided accessors to access it.
|
||||||
public:
|
public:
|
||||||
|
friend class DeclContext;
|
||||||
/// Enum that represents the different ways arguments are passed to and
|
/// Enum that represents the different ways arguments are passed to and
|
||||||
/// returned from function calls. This takes into account the target-specific
|
/// returned from function calls. This takes into account the target-specific
|
||||||
/// and version-specific rules along with the rules determined by the
|
/// and version-specific rules along with the rules determined by the
|
||||||
|
@ -3589,46 +3571,6 @@ public:
|
||||||
APK_CanNeverPassInRegs
|
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:
|
protected:
|
||||||
RecordDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC,
|
RecordDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC,
|
||||||
SourceLocation StartLoc, SourceLocation IdLoc,
|
SourceLocation StartLoc, SourceLocation IdLoc,
|
||||||
|
@ -3655,8 +3597,13 @@ public:
|
||||||
return const_cast<RecordDecl*>(this)->getMostRecentDecl();
|
return const_cast<RecordDecl*>(this)->getMostRecentDecl();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; }
|
bool hasFlexibleArrayMember() const {
|
||||||
void setHasFlexibleArrayMember(bool V) { HasFlexibleArrayMember = V; }
|
return RecordDeclBits.HasFlexibleArrayMember;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setHasFlexibleArrayMember(bool V) {
|
||||||
|
RecordDeclBits.HasFlexibleArrayMember = V;
|
||||||
|
}
|
||||||
|
|
||||||
/// Whether this is an anonymous struct or union. To be an anonymous
|
/// Whether this is an anonymous struct or union. To be an anonymous
|
||||||
/// struct or union, it must have been declared without a name and
|
/// struct or union, it must have been declared without a name and
|
||||||
|
@ -3669,47 +3616,54 @@ public:
|
||||||
/// union X { int i; float f; };
|
/// union X { int i; float f; };
|
||||||
/// union { int i; float f; } obj;
|
/// union { int i; float f; } obj;
|
||||||
/// @endcode
|
/// @endcode
|
||||||
bool isAnonymousStructOrUnion() const { return AnonymousStructOrUnion; }
|
bool isAnonymousStructOrUnion() const {
|
||||||
void setAnonymousStructOrUnion(bool Anon) {
|
return RecordDeclBits.AnonymousStructOrUnion;
|
||||||
AnonymousStructOrUnion = Anon;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasObjectMember() const { return HasObjectMember; }
|
void setAnonymousStructOrUnion(bool Anon) {
|
||||||
void setHasObjectMember (bool val) { HasObjectMember = val; }
|
RecordDeclBits.AnonymousStructOrUnion = Anon;
|
||||||
|
}
|
||||||
|
|
||||||
bool hasVolatileMember() const { return HasVolatileMember; }
|
bool hasObjectMember() const { return RecordDeclBits.HasObjectMember; }
|
||||||
void setHasVolatileMember (bool val) { HasVolatileMember = val; }
|
void setHasObjectMember(bool val) { RecordDeclBits.HasObjectMember = val; }
|
||||||
|
|
||||||
|
bool hasVolatileMember() const { return RecordDeclBits.HasVolatileMember; }
|
||||||
|
|
||||||
|
void setHasVolatileMember(bool val) {
|
||||||
|
RecordDeclBits.HasVolatileMember = val;
|
||||||
|
}
|
||||||
|
|
||||||
bool hasLoadedFieldsFromExternalStorage() const {
|
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.
|
/// Functions to query basic properties of non-trivial C structs.
|
||||||
bool isNonTrivialToPrimitiveDefaultInitialize() const {
|
bool isNonTrivialToPrimitiveDefaultInitialize() const {
|
||||||
return NonTrivialToPrimitiveDefaultInitialize;
|
return RecordDeclBits.NonTrivialToPrimitiveDefaultInitialize;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setNonTrivialToPrimitiveDefaultInitialize(bool V) {
|
void setNonTrivialToPrimitiveDefaultInitialize(bool V) {
|
||||||
NonTrivialToPrimitiveDefaultInitialize = V;
|
RecordDeclBits.NonTrivialToPrimitiveDefaultInitialize = V;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNonTrivialToPrimitiveCopy() const {
|
bool isNonTrivialToPrimitiveCopy() const {
|
||||||
return NonTrivialToPrimitiveCopy;
|
return RecordDeclBits.NonTrivialToPrimitiveCopy;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setNonTrivialToPrimitiveCopy(bool V) {
|
void setNonTrivialToPrimitiveCopy(bool V) {
|
||||||
NonTrivialToPrimitiveCopy = V;
|
RecordDeclBits.NonTrivialToPrimitiveCopy = V;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNonTrivialToPrimitiveDestroy() const {
|
bool isNonTrivialToPrimitiveDestroy() const {
|
||||||
return NonTrivialToPrimitiveDestroy;
|
return RecordDeclBits.NonTrivialToPrimitiveDestroy;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setNonTrivialToPrimitiveDestroy(bool V) {
|
void setNonTrivialToPrimitiveDestroy(bool V) {
|
||||||
NonTrivialToPrimitiveDestroy = V;
|
RecordDeclBits.NonTrivialToPrimitiveDestroy = V;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determine whether this class can be passed in registers. In C++ mode,
|
/// Determine whether this class can be passed in registers. In C++ mode,
|
||||||
|
@ -3720,19 +3674,19 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
ArgPassingKind getArgPassingRestrictions() const {
|
ArgPassingKind getArgPassingRestrictions() const {
|
||||||
return static_cast<ArgPassingKind>(ArgPassingRestrictions);
|
return static_cast<ArgPassingKind>(RecordDeclBits.ArgPassingRestrictions);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setArgPassingRestrictions(ArgPassingKind Kind) {
|
void setArgPassingRestrictions(ArgPassingKind Kind) {
|
||||||
ArgPassingRestrictions = static_cast<uint8_t>(Kind);
|
RecordDeclBits.ArgPassingRestrictions = Kind;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isParamDestroyedInCallee() const {
|
bool isParamDestroyedInCallee() const {
|
||||||
return ParamDestroyedInCallee;
|
return RecordDeclBits.ParamDestroyedInCallee;
|
||||||
}
|
}
|
||||||
|
|
||||||
void setParamDestroyedInCallee(bool V) {
|
void setParamDestroyedInCallee(bool V) {
|
||||||
ParamDestroyedInCallee = V;
|
RecordDeclBits.ParamDestroyedInCallee = V;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determines whether this declaration represents the
|
/// Determines whether this declaration represents the
|
||||||
|
|
|
@ -1260,37 +1260,407 @@ public:
|
||||||
/// BlockDecl
|
/// BlockDecl
|
||||||
/// OMPDeclareReductionDecl
|
/// OMPDeclareReductionDecl
|
||||||
class DeclContext {
|
class DeclContext {
|
||||||
/// DeclKind - This indicates which class this is.
|
// We use uint64_t in the bit-fields below since some bit-fields
|
||||||
unsigned DeclKind : 8;
|
// cross the unsigned boundary and this breaks the packing.
|
||||||
|
|
||||||
/// Whether this declaration context also has some external
|
/// Stores the bits used by DeclContext.
|
||||||
/// storage that contains additional declarations that are lexically
|
/// If modified NumDeclContextBit, the ctor of DeclContext and the accessor
|
||||||
/// part of this context.
|
/// methods in DeclContext should be updated appropriately.
|
||||||
mutable bool ExternalLexicalStorage : 1;
|
class DeclContextBitfields {
|
||||||
|
friend class DeclContext;
|
||||||
|
/// DeclKind - This indicates which class this is.
|
||||||
|
uint64_t DeclKind : 7;
|
||||||
|
|
||||||
/// Whether this declaration context also has some external
|
/// Whether this declaration context also has some external
|
||||||
/// storage that contains additional declarations that are visible
|
/// storage that contains additional declarations that are lexically
|
||||||
/// in this context.
|
/// part of this context.
|
||||||
mutable bool ExternalVisibleStorage : 1;
|
mutable uint64_t ExternalLexicalStorage : 1;
|
||||||
|
|
||||||
/// Whether this declaration context has had external visible
|
/// Whether this declaration context also has some external
|
||||||
/// storage added since the last lookup. In this case, \c LookupPtr's
|
/// storage that contains additional declarations that are visible
|
||||||
/// invariant may not hold and needs to be fixed before we perform
|
/// in this context.
|
||||||
/// another lookup.
|
mutable uint64_t ExternalVisibleStorage : 1;
|
||||||
mutable bool NeedToReconcileExternalVisibleStorage : 1;
|
|
||||||
|
|
||||||
/// If \c true, this context may have local lexical declarations
|
/// Whether this declaration context has had externally visible
|
||||||
/// that are missing from the lookup table.
|
/// storage added since the last lookup. In this case, \c LookupPtr's
|
||||||
mutable bool HasLazyLocalLexicalLookups : 1;
|
/// invariant may not hold and needs to be fixed before we perform
|
||||||
|
/// another lookup.
|
||||||
|
mutable uint64_t NeedToReconcileExternalVisibleStorage : 1;
|
||||||
|
|
||||||
/// If \c true, the external source may have lexical declarations
|
/// If \c true, this context may have local lexical declarations
|
||||||
/// that are missing from the lookup table.
|
/// that are missing from the lookup table.
|
||||||
mutable bool HasLazyExternalLexicalLookups : 1;
|
mutable uint64_t HasLazyLocalLexicalLookups : 1;
|
||||||
|
|
||||||
/// If \c true, lookups should only return identifier from
|
/// If \c true, the external source may have lexical declarations
|
||||||
/// DeclContext scope (for example TranslationUnit). Used in
|
/// that are missing from the lookup table.
|
||||||
/// LookupQualifiedName()
|
mutable uint64_t HasLazyExternalLexicalLookups : 1;
|
||||||
mutable bool UseQualifiedLookup : 1;
|
|
||||||
|
/// If \c true, lookups should only return identifier from
|
||||||
|
/// DeclContext scope (for example TranslationUnit). Used in
|
||||||
|
/// LookupQualifiedName()
|
||||||
|
mutable uint64_t UseQualifiedLookup : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Number of bits in DeclContextBitfields.
|
||||||
|
enum { NumDeclContextBits = 13 };
|
||||||
|
|
||||||
|
/// 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;
|
||||||
|
|
||||||
|
/// The TagKind enum.
|
||||||
|
uint64_t 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.
|
||||||
|
uint64_t IsCompleteDefinition : 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Number of non-inherited bits in BlockDeclBitfields.
|
||||||
|
enum { NumBlockDeclBits = 5 };
|
||||||
|
|
||||||
/// Pointer to the data structure used to lookup declarations
|
/// Pointer to the data structure used to lookup declarations
|
||||||
/// within this context (or a DependentStoredDeclsMap if this is a
|
/// within this context (or a DependentStoredDeclsMap if this is a
|
||||||
|
@ -1301,6 +1671,51 @@ class DeclContext {
|
||||||
mutable StoredDeclsMap *LookupPtr = nullptr;
|
mutable StoredDeclsMap *LookupPtr = nullptr;
|
||||||
|
|
||||||
protected:
|
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 ASTDeclReader;
|
||||||
friend class ASTWriter;
|
friend class ASTWriter;
|
||||||
friend class ExternalASTSource;
|
friend class ExternalASTSource;
|
||||||
|
@ -1321,18 +1736,13 @@ protected:
|
||||||
static std::pair<Decl *, Decl *>
|
static std::pair<Decl *, Decl *>
|
||||||
BuildDeclChain(ArrayRef<Decl*> Decls, bool FieldsAlreadyLoaded);
|
BuildDeclChain(ArrayRef<Decl*> Decls, bool FieldsAlreadyLoaded);
|
||||||
|
|
||||||
DeclContext(Decl::Kind K)
|
DeclContext(Decl::Kind K);
|
||||||
: DeclKind(K), ExternalLexicalStorage(false),
|
|
||||||
ExternalVisibleStorage(false),
|
|
||||||
NeedToReconcileExternalVisibleStorage(false),
|
|
||||||
HasLazyLocalLexicalLookups(false), HasLazyExternalLexicalLookups(false),
|
|
||||||
UseQualifiedLookup(false) {}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
~DeclContext();
|
~DeclContext();
|
||||||
|
|
||||||
Decl::Kind getDeclKind() const {
|
Decl::Kind getDeclKind() const {
|
||||||
return static_cast<Decl::Kind>(DeclKind);
|
return static_cast<Decl::Kind>(DeclContextBits.DeclKind);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *getDeclKindName() const;
|
const char *getDeclKindName() const;
|
||||||
|
@ -1371,54 +1781,54 @@ public:
|
||||||
return cast<Decl>(this)->getASTContext();
|
return cast<Decl>(this)->getASTContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isClosure() const {
|
bool isClosure() const { return getDeclKind() == Decl::Block; }
|
||||||
return DeclKind == Decl::Block;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isObjCContainer() const {
|
bool isObjCContainer() const {
|
||||||
switch (DeclKind) {
|
switch (getDeclKind()) {
|
||||||
case Decl::ObjCCategory:
|
case Decl::ObjCCategory:
|
||||||
case Decl::ObjCCategoryImpl:
|
case Decl::ObjCCategoryImpl:
|
||||||
case Decl::ObjCImplementation:
|
case Decl::ObjCImplementation:
|
||||||
case Decl::ObjCInterface:
|
case Decl::ObjCInterface:
|
||||||
case Decl::ObjCProtocol:
|
case Decl::ObjCProtocol:
|
||||||
return true;
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isFunctionOrMethod() const {
|
bool isFunctionOrMethod() const {
|
||||||
switch (DeclKind) {
|
switch (getDeclKind()) {
|
||||||
case Decl::Block:
|
case Decl::Block:
|
||||||
case Decl::Captured:
|
case Decl::Captured:
|
||||||
case Decl::ObjCMethod:
|
case Decl::ObjCMethod:
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return DeclKind >= Decl::firstFunction && DeclKind <= Decl::lastFunction;
|
return getDeclKind() >= Decl::firstFunction &&
|
||||||
|
getDeclKind() <= Decl::lastFunction;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test whether the context supports looking up names.
|
/// Test whether the context supports looking up names.
|
||||||
bool isLookupContext() const {
|
bool isLookupContext() const {
|
||||||
return !isFunctionOrMethod() && DeclKind != Decl::LinkageSpec &&
|
return !isFunctionOrMethod() && getDeclKind() != Decl::LinkageSpec &&
|
||||||
DeclKind != Decl::Export;
|
getDeclKind() != Decl::Export;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isFileContext() const {
|
bool isFileContext() const {
|
||||||
return DeclKind == Decl::TranslationUnit || DeclKind == Decl::Namespace;
|
return getDeclKind() == Decl::TranslationUnit ||
|
||||||
|
getDeclKind() == Decl::Namespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isTranslationUnit() const {
|
bool isTranslationUnit() const {
|
||||||
return DeclKind == Decl::TranslationUnit;
|
return getDeclKind() == Decl::TranslationUnit;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isRecord() const {
|
bool isRecord() const {
|
||||||
return DeclKind >= Decl::firstRecord && DeclKind <= Decl::lastRecord;
|
return getDeclKind() >= Decl::firstRecord &&
|
||||||
|
getDeclKind() <= Decl::lastRecord;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNamespace() const {
|
bool isNamespace() const { return getDeclKind() == Decl::Namespace; }
|
||||||
return DeclKind == Decl::Namespace;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool isStdNamespace() const;
|
bool isStdNamespace() const;
|
||||||
|
|
||||||
|
@ -1886,7 +2296,7 @@ public:
|
||||||
void setMustBuildLookupTable() {
|
void setMustBuildLookupTable() {
|
||||||
assert(this == getPrimaryContext() &&
|
assert(this == getPrimaryContext() &&
|
||||||
"should only be called on primary context");
|
"should only be called on primary context");
|
||||||
HasLazyExternalLexicalLookups = true;
|
DeclContextBits.HasLazyExternalLexicalLookups = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieve the internal representation of the lookup structure.
|
/// Retrieve the internal representation of the lookup structure.
|
||||||
|
@ -1898,24 +2308,28 @@ public:
|
||||||
|
|
||||||
/// Whether this DeclContext has external storage containing
|
/// Whether this DeclContext has external storage containing
|
||||||
/// additional declarations that are lexically in this context.
|
/// 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
|
/// State whether this DeclContext has external storage for
|
||||||
/// declarations lexically in this context.
|
/// declarations lexically in this context.
|
||||||
void setHasExternalLexicalStorage(bool ES = true) {
|
void setHasExternalLexicalStorage(bool ES = true) const {
|
||||||
ExternalLexicalStorage = ES;
|
DeclContextBits.ExternalLexicalStorage = ES;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether this DeclContext has external storage containing
|
/// Whether this DeclContext has external storage containing
|
||||||
/// additional declarations that are visible in this context.
|
/// 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
|
/// State whether this DeclContext has external storage for
|
||||||
/// declarations visible in this context.
|
/// declarations visible in this context.
|
||||||
void setHasExternalVisibleStorage(bool ES = true) {
|
void setHasExternalVisibleStorage(bool ES = true) const {
|
||||||
ExternalVisibleStorage = ES;
|
DeclContextBits.ExternalVisibleStorage = ES;
|
||||||
if (ES && LookupPtr)
|
if (ES && LookupPtr)
|
||||||
NeedToReconcileExternalVisibleStorage = true;
|
DeclContextBits.NeedToReconcileExternalVisibleStorage = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Determine whether the given declaration is stored in the list of
|
/// Determine whether the given declaration is stored in the list of
|
||||||
|
@ -1925,14 +2339,14 @@ public:
|
||||||
D == LastDecl);
|
D == LastDecl);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool setUseQualifiedLookup(bool use = true) {
|
bool setUseQualifiedLookup(bool use = true) const {
|
||||||
bool old_value = UseQualifiedLookup;
|
bool old_value = DeclContextBits.UseQualifiedLookup;
|
||||||
UseQualifiedLookup = use;
|
DeclContextBits.UseQualifiedLookup = use;
|
||||||
return old_value;
|
return old_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool shouldUseQualifiedLookup() const {
|
bool shouldUseQualifiedLookup() const {
|
||||||
return UseQualifiedLookup;
|
return DeclContextBits.UseQualifiedLookup;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool classof(const Decl *D);
|
static bool classof(const Decl *D);
|
||||||
|
@ -1944,6 +2358,46 @@ public:
|
||||||
bool Deserialize = false) const;
|
bool Deserialize = false) const;
|
||||||
|
|
||||||
private:
|
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;
|
friend class DependentDiagnostic;
|
||||||
|
|
||||||
void reconcileExternalVisibleStorage() const;
|
void reconcileExternalVisibleStorage() const;
|
||||||
|
|
|
@ -3767,6 +3767,22 @@ void FieldDecl::setCapturedVLAType(const VariableArrayType *VLAType) {
|
||||||
// TagDecl Implementation
|
// TagDecl Implementation
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
TagDecl::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),
|
||||||
|
TypedefNameDeclOrQualifier((TypedefNameDecl *)nullptr) {
|
||||||
|
assert((DK != Enum || TK == TTK_Enum) &&
|
||||||
|
"EnumDecl not matched with TTK_Enum");
|
||||||
|
setPreviousDecl(PrevDecl);
|
||||||
|
setTagKind(TK);
|
||||||
|
setCompleteDefinition(false);
|
||||||
|
setBeingDefined(false);
|
||||||
|
setEmbeddedInDeclarator(false);
|
||||||
|
setFreeStanding(false);
|
||||||
|
setCompleteDefinitionRequired(false);
|
||||||
|
}
|
||||||
|
|
||||||
SourceLocation TagDecl::getOuterLocStart() const {
|
SourceLocation TagDecl::getOuterLocStart() const {
|
||||||
return getTemplateOrInnerLocStart(this);
|
return getTemplateOrInnerLocStart(this);
|
||||||
}
|
}
|
||||||
|
@ -3789,7 +3805,7 @@ void TagDecl::setTypedefNameForAnonDecl(TypedefNameDecl *TDD) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TagDecl::startDefinition() {
|
void TagDecl::startDefinition() {
|
||||||
IsBeingDefined = true;
|
setBeingDefined(true);
|
||||||
|
|
||||||
if (auto *D = dyn_cast<CXXRecordDecl>(this)) {
|
if (auto *D = dyn_cast<CXXRecordDecl>(this)) {
|
||||||
struct CXXRecordDecl::DefinitionData *Data =
|
struct CXXRecordDecl::DefinitionData *Data =
|
||||||
|
@ -3804,8 +3820,8 @@ void TagDecl::completeDefinition() {
|
||||||
cast<CXXRecordDecl>(this)->hasDefinition()) &&
|
cast<CXXRecordDecl>(this)->hasDefinition()) &&
|
||||||
"definition completed but not started");
|
"definition completed but not started");
|
||||||
|
|
||||||
IsCompleteDefinition = true;
|
setCompleteDefinition(true);
|
||||||
IsBeingDefined = false;
|
setBeingDefined(false);
|
||||||
|
|
||||||
if (ASTMutationListener *L = getASTMutationListener())
|
if (ASTMutationListener *L = getASTMutationListener())
|
||||||
L->CompletedTagDefinition(this);
|
L->CompletedTagDefinition(this);
|
||||||
|
@ -3816,7 +3832,7 @@ TagDecl *TagDecl::getDefinition() const {
|
||||||
return const_cast<TagDecl *>(this);
|
return const_cast<TagDecl *>(this);
|
||||||
|
|
||||||
// If it's possible for us to have an out-of-date definition, check now.
|
// If it's possible for us to have an out-of-date definition, check now.
|
||||||
if (MayHaveOutOfDateDef) {
|
if (mayHaveOutOfDateDef()) {
|
||||||
if (IdentifierInfo *II = getIdentifier()) {
|
if (IdentifierInfo *II = getIdentifier()) {
|
||||||
if (II->isOutOfDate()) {
|
if (II->isOutOfDate()) {
|
||||||
updateOutOfDate(*II);
|
updateOutOfDate(*II);
|
||||||
|
@ -3869,6 +3885,21 @@ void TagDecl::setTemplateParameterListsInfo(
|
||||||
// EnumDecl Implementation
|
// EnumDecl Implementation
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
EnumDecl::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 = nullptr;
|
||||||
|
setNumPositiveBits(0);
|
||||||
|
setNumNegativeBits(0);
|
||||||
|
setScoped(Scoped);
|
||||||
|
setScopedUsingClassTag(ScopedUsingClassTag);
|
||||||
|
setFixed(Fixed);
|
||||||
|
setHasODRHash(false);
|
||||||
|
ODRHash = 0;
|
||||||
|
}
|
||||||
|
|
||||||
void EnumDecl::anchor() {}
|
void EnumDecl::anchor() {}
|
||||||
|
|
||||||
EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC,
|
EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC,
|
||||||
|
@ -3878,7 +3909,7 @@ EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC,
|
||||||
bool IsScopedUsingClassTag, bool IsFixed) {
|
bool IsScopedUsingClassTag, bool IsFixed) {
|
||||||
auto *Enum = new (C, DC) EnumDecl(C, DC, StartLoc, IdLoc, Id, PrevDecl,
|
auto *Enum = new (C, DC) EnumDecl(C, DC, StartLoc, IdLoc, Id, PrevDecl,
|
||||||
IsScoped, IsScopedUsingClassTag, IsFixed);
|
IsScoped, IsScopedUsingClassTag, IsFixed);
|
||||||
Enum->MayHaveOutOfDateDef = C.getLangOpts().Modules;
|
Enum->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
|
||||||
C.getTypeDeclType(Enum, PrevDecl);
|
C.getTypeDeclType(Enum, PrevDecl);
|
||||||
return Enum;
|
return Enum;
|
||||||
}
|
}
|
||||||
|
@ -3887,7 +3918,7 @@ EnumDecl *EnumDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
|
||||||
EnumDecl *Enum =
|
EnumDecl *Enum =
|
||||||
new (C, ID) EnumDecl(C, nullptr, SourceLocation(), SourceLocation(),
|
new (C, ID) EnumDecl(C, nullptr, SourceLocation(), SourceLocation(),
|
||||||
nullptr, nullptr, false, false, false);
|
nullptr, nullptr, false, false, false);
|
||||||
Enum->MayHaveOutOfDateDef = C.getLangOpts().Modules;
|
Enum->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
|
||||||
return Enum;
|
return Enum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3971,12 +4002,12 @@ void EnumDecl::setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED,
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned EnumDecl::getODRHash() {
|
unsigned EnumDecl::getODRHash() {
|
||||||
if (HasODRHash)
|
if (hasODRHash())
|
||||||
return ODRHash;
|
return ODRHash;
|
||||||
|
|
||||||
class ODRHash Hash;
|
class ODRHash Hash;
|
||||||
Hash.AddEnumDecl(this);
|
Hash.AddEnumDecl(this);
|
||||||
HasODRHash = true;
|
setHasODRHash(true);
|
||||||
ODRHash = Hash.CalculateHash();
|
ODRHash = Hash.CalculateHash();
|
||||||
return ODRHash;
|
return ODRHash;
|
||||||
}
|
}
|
||||||
|
@ -3989,14 +4020,18 @@ RecordDecl::RecordDecl(Kind DK, TagKind TK, const ASTContext &C,
|
||||||
DeclContext *DC, SourceLocation StartLoc,
|
DeclContext *DC, SourceLocation StartLoc,
|
||||||
SourceLocation IdLoc, IdentifierInfo *Id,
|
SourceLocation IdLoc, IdentifierInfo *Id,
|
||||||
RecordDecl *PrevDecl)
|
RecordDecl *PrevDecl)
|
||||||
: TagDecl(DK, TK, C, DC, IdLoc, Id, PrevDecl, StartLoc),
|
: TagDecl(DK, TK, C, DC, IdLoc, Id, PrevDecl, StartLoc) {
|
||||||
HasFlexibleArrayMember(false), AnonymousStructOrUnion(false),
|
assert(classof(static_cast<Decl *>(this)) && "Invalid Kind!");
|
||||||
HasObjectMember(false), HasVolatileMember(false),
|
setHasFlexibleArrayMember(false);
|
||||||
LoadedFieldsFromExternalStorage(false),
|
setAnonymousStructOrUnion(false);
|
||||||
NonTrivialToPrimitiveDefaultInitialize(false),
|
setHasObjectMember(false);
|
||||||
NonTrivialToPrimitiveCopy(false), NonTrivialToPrimitiveDestroy(false),
|
setHasVolatileMember(false);
|
||||||
ParamDestroyedInCallee(false), ArgPassingRestrictions(APK_CanPassInRegs) {
|
setHasLoadedFieldsFromExternalStorage(false);
|
||||||
assert(classof(static_cast<Decl*>(this)) && "Invalid Kind!");
|
setNonTrivialToPrimitiveDefaultInitialize(false);
|
||||||
|
setNonTrivialToPrimitiveCopy(false);
|
||||||
|
setNonTrivialToPrimitiveDestroy(false);
|
||||||
|
setParamDestroyedInCallee(false);
|
||||||
|
setArgPassingRestrictions(APK_CanPassInRegs);
|
||||||
}
|
}
|
||||||
|
|
||||||
RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC,
|
RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC,
|
||||||
|
@ -4004,7 +4039,7 @@ RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC,
|
||||||
IdentifierInfo *Id, RecordDecl* PrevDecl) {
|
IdentifierInfo *Id, RecordDecl* PrevDecl) {
|
||||||
RecordDecl *R = new (C, DC) RecordDecl(Record, TK, C, DC,
|
RecordDecl *R = new (C, DC) RecordDecl(Record, TK, C, DC,
|
||||||
StartLoc, IdLoc, Id, PrevDecl);
|
StartLoc, IdLoc, Id, PrevDecl);
|
||||||
R->MayHaveOutOfDateDef = C.getLangOpts().Modules;
|
R->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
|
||||||
|
|
||||||
C.getTypeDeclType(R, PrevDecl);
|
C.getTypeDeclType(R, PrevDecl);
|
||||||
return R;
|
return R;
|
||||||
|
@ -4014,7 +4049,7 @@ RecordDecl *RecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {
|
||||||
RecordDecl *R =
|
RecordDecl *R =
|
||||||
new (C, ID) RecordDecl(Record, TTK_Struct, C, nullptr, SourceLocation(),
|
new (C, ID) RecordDecl(Record, TTK_Struct, C, nullptr, SourceLocation(),
|
||||||
SourceLocation(), nullptr, nullptr);
|
SourceLocation(), nullptr, nullptr);
|
||||||
R->MayHaveOutOfDateDef = C.getLangOpts().Modules;
|
R->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
|
||||||
return R;
|
return R;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4038,7 +4073,7 @@ void RecordDecl::setCapturedRecord() {
|
||||||
}
|
}
|
||||||
|
|
||||||
RecordDecl::field_iterator RecordDecl::field_begin() const {
|
RecordDecl::field_iterator RecordDecl::field_begin() const {
|
||||||
if (hasExternalLexicalStorage() && !LoadedFieldsFromExternalStorage)
|
if (hasExternalLexicalStorage() && !hasLoadedFieldsFromExternalStorage())
|
||||||
LoadFieldsFromExternalStorage();
|
LoadFieldsFromExternalStorage();
|
||||||
|
|
||||||
return field_iterator(decl_iterator(FirstDecl));
|
return field_iterator(decl_iterator(FirstDecl));
|
||||||
|
@ -4066,7 +4101,7 @@ void RecordDecl::LoadFieldsFromExternalStorage() const {
|
||||||
ExternalASTSource::Deserializing TheFields(Source);
|
ExternalASTSource::Deserializing TheFields(Source);
|
||||||
|
|
||||||
SmallVector<Decl*, 64> Decls;
|
SmallVector<Decl*, 64> Decls;
|
||||||
LoadedFieldsFromExternalStorage = true;
|
setHasLoadedFieldsFromExternalStorage(true);
|
||||||
Source->FindExternalLexicalDecls(this, [](Decl::Kind K) {
|
Source->FindExternalLexicalDecls(this, [](Decl::Kind K) {
|
||||||
return FieldDecl::classofKind(K) || IndirectFieldDecl::classofKind(K);
|
return FieldDecl::classofKind(K) || IndirectFieldDecl::classofKind(K);
|
||||||
}, Decls);
|
}, Decls);
|
||||||
|
|
|
@ -153,7 +153,7 @@ void Decl::setInvalidDecl(bool Invalid) {
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *DeclContext::getDeclKindName() const {
|
const char *DeclContext::getDeclKindName() const {
|
||||||
switch (DeclKind) {
|
switch (getDeclKind()) {
|
||||||
default: llvm_unreachable("Declaration context not in DeclNodes.inc!");
|
default: llvm_unreachable("Declaration context not in DeclNodes.inc!");
|
||||||
#define DECL(DERIVED, BASE) case Decl::DERIVED: return #DERIVED;
|
#define DECL(DERIVED, BASE) case Decl::DERIVED: return #DERIVED;
|
||||||
#define ABSTRACT_DECL(DECL)
|
#define ABSTRACT_DECL(DECL)
|
||||||
|
@ -980,6 +980,16 @@ Decl *DeclContext::getNonClosureAncestor() {
|
||||||
// DeclContext Implementation
|
// DeclContext Implementation
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
DeclContext::DeclContext(Decl::Kind K) {
|
||||||
|
DeclContextBits.DeclKind = K;
|
||||||
|
setHasExternalLexicalStorage(false);
|
||||||
|
setHasExternalVisibleStorage(false);
|
||||||
|
setNeedToReconcileExternalVisibleStorage(false);
|
||||||
|
setHasLazyLocalLexicalLookups(false);
|
||||||
|
setHasLazyExternalLexicalLookups(false);
|
||||||
|
setUseQualifiedLookup(false);
|
||||||
|
}
|
||||||
|
|
||||||
bool DeclContext::classof(const Decl *D) {
|
bool DeclContext::classof(const Decl *D) {
|
||||||
switch (D->getKind()) {
|
switch (D->getKind()) {
|
||||||
#define DECL(NAME, BASE)
|
#define DECL(NAME, BASE)
|
||||||
|
@ -1070,9 +1080,9 @@ bool DeclContext::isDependentContext() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DeclContext::isTransparentContext() const {
|
bool DeclContext::isTransparentContext() const {
|
||||||
if (DeclKind == Decl::Enum)
|
if (getDeclKind() == Decl::Enum)
|
||||||
return !cast<EnumDecl>(this)->isScoped();
|
return !cast<EnumDecl>(this)->isScoped();
|
||||||
else if (DeclKind == Decl::LinkageSpec || DeclKind == Decl::Export)
|
else if (getDeclKind() == Decl::LinkageSpec || getDeclKind() == Decl::Export)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -1118,7 +1128,7 @@ bool DeclContext::Encloses(const DeclContext *DC) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
DeclContext *DeclContext::getPrimaryContext() {
|
DeclContext *DeclContext::getPrimaryContext() {
|
||||||
switch (DeclKind) {
|
switch (getDeclKind()) {
|
||||||
case Decl::TranslationUnit:
|
case Decl::TranslationUnit:
|
||||||
case Decl::ExternCContext:
|
case Decl::ExternCContext:
|
||||||
case Decl::LinkageSpec:
|
case Decl::LinkageSpec:
|
||||||
|
@ -1154,7 +1164,7 @@ DeclContext *DeclContext::getPrimaryContext() {
|
||||||
return this;
|
return this;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (DeclKind >= Decl::firstTag && DeclKind <= Decl::lastTag) {
|
if (getDeclKind() >= Decl::firstTag && getDeclKind() <= Decl::lastTag) {
|
||||||
// If this is a tag type that has a definition or is currently
|
// If this is a tag type that has a definition or is currently
|
||||||
// being defined, that definition is our primary context.
|
// being defined, that definition is our primary context.
|
||||||
auto *Tag = cast<TagDecl>(this);
|
auto *Tag = cast<TagDecl>(this);
|
||||||
|
@ -1174,7 +1184,8 @@ DeclContext *DeclContext::getPrimaryContext() {
|
||||||
return Tag;
|
return Tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(DeclKind >= Decl::firstFunction && DeclKind <= Decl::lastFunction &&
|
assert(getDeclKind() >= Decl::firstFunction &&
|
||||||
|
getDeclKind() <= Decl::lastFunction &&
|
||||||
"Unknown DeclContext kind");
|
"Unknown DeclContext kind");
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -1184,7 +1195,7 @@ void
|
||||||
DeclContext::collectAllContexts(SmallVectorImpl<DeclContext *> &Contexts){
|
DeclContext::collectAllContexts(SmallVectorImpl<DeclContext *> &Contexts){
|
||||||
Contexts.clear();
|
Contexts.clear();
|
||||||
|
|
||||||
if (DeclKind != Decl::Namespace) {
|
if (getDeclKind() != Decl::Namespace) {
|
||||||
Contexts.push_back(this);
|
Contexts.push_back(this);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1222,8 +1233,8 @@ DeclContext::BuildDeclChain(ArrayRef<Decl *> Decls,
|
||||||
/// built a lookup map. For every name in the map, pull in the new names from
|
/// built a lookup map. For every name in the map, pull in the new names from
|
||||||
/// the external storage.
|
/// the external storage.
|
||||||
void DeclContext::reconcileExternalVisibleStorage() const {
|
void DeclContext::reconcileExternalVisibleStorage() const {
|
||||||
assert(NeedToReconcileExternalVisibleStorage && LookupPtr);
|
assert(hasNeedToReconcileExternalVisibleStorage() && LookupPtr);
|
||||||
NeedToReconcileExternalVisibleStorage = false;
|
setNeedToReconcileExternalVisibleStorage(false);
|
||||||
|
|
||||||
for (auto &Lookup : *LookupPtr)
|
for (auto &Lookup : *LookupPtr)
|
||||||
Lookup.second.setHasExternalDecls();
|
Lookup.second.setHasExternalDecls();
|
||||||
|
@ -1242,7 +1253,7 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const {
|
||||||
|
|
||||||
// Load the external declarations, if any.
|
// Load the external declarations, if any.
|
||||||
SmallVector<Decl*, 64> Decls;
|
SmallVector<Decl*, 64> Decls;
|
||||||
ExternalLexicalStorage = false;
|
setHasExternalLexicalStorage(false);
|
||||||
Source->FindExternalLexicalDecls(this, Decls);
|
Source->FindExternalLexicalDecls(this, Decls);
|
||||||
|
|
||||||
if (Decls.empty())
|
if (Decls.empty())
|
||||||
|
@ -1252,7 +1263,7 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const {
|
||||||
// we need to ignore them.
|
// we need to ignore them.
|
||||||
bool FieldsAlreadyLoaded = false;
|
bool FieldsAlreadyLoaded = false;
|
||||||
if (const auto *RD = dyn_cast<RecordDecl>(this))
|
if (const auto *RD = dyn_cast<RecordDecl>(this))
|
||||||
FieldsAlreadyLoaded = RD->LoadedFieldsFromExternalStorage;
|
FieldsAlreadyLoaded = RD->hasLoadedFieldsFromExternalStorage();
|
||||||
|
|
||||||
// Splice the newly-read declarations into the beginning of the list
|
// Splice the newly-read declarations into the beginning of the list
|
||||||
// of declarations.
|
// of declarations.
|
||||||
|
@ -1273,7 +1284,7 @@ ExternalASTSource::SetNoExternalVisibleDeclsForName(const DeclContext *DC,
|
||||||
StoredDeclsMap *Map;
|
StoredDeclsMap *Map;
|
||||||
if (!(Map = DC->LookupPtr))
|
if (!(Map = DC->LookupPtr))
|
||||||
Map = DC->CreateStoredDeclsMap(Context);
|
Map = DC->CreateStoredDeclsMap(Context);
|
||||||
if (DC->NeedToReconcileExternalVisibleStorage)
|
if (DC->hasNeedToReconcileExternalVisibleStorage())
|
||||||
DC->reconcileExternalVisibleStorage();
|
DC->reconcileExternalVisibleStorage();
|
||||||
|
|
||||||
(*Map)[Name].removeExternalDecls();
|
(*Map)[Name].removeExternalDecls();
|
||||||
|
@ -1289,7 +1300,7 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC,
|
||||||
StoredDeclsMap *Map;
|
StoredDeclsMap *Map;
|
||||||
if (!(Map = DC->LookupPtr))
|
if (!(Map = DC->LookupPtr))
|
||||||
Map = DC->CreateStoredDeclsMap(Context);
|
Map = DC->CreateStoredDeclsMap(Context);
|
||||||
if (DC->NeedToReconcileExternalVisibleStorage)
|
if (DC->hasNeedToReconcileExternalVisibleStorage())
|
||||||
DC->reconcileExternalVisibleStorage();
|
DC->reconcileExternalVisibleStorage();
|
||||||
|
|
||||||
StoredDeclsList &List = (*Map)[Name];
|
StoredDeclsList &List = (*Map)[Name];
|
||||||
|
@ -1483,21 +1494,24 @@ void DeclContext::addDeclInternal(Decl *D) {
|
||||||
StoredDeclsMap *DeclContext::buildLookup() {
|
StoredDeclsMap *DeclContext::buildLookup() {
|
||||||
assert(this == getPrimaryContext() && "buildLookup called on non-primary DC");
|
assert(this == getPrimaryContext() && "buildLookup called on non-primary DC");
|
||||||
|
|
||||||
if (!HasLazyLocalLexicalLookups && !HasLazyExternalLexicalLookups)
|
if (!hasLazyLocalLexicalLookups() &&
|
||||||
|
!hasLazyExternalLexicalLookups())
|
||||||
return LookupPtr;
|
return LookupPtr;
|
||||||
|
|
||||||
SmallVector<DeclContext *, 2> Contexts;
|
SmallVector<DeclContext *, 2> Contexts;
|
||||||
collectAllContexts(Contexts);
|
collectAllContexts(Contexts);
|
||||||
|
|
||||||
if (HasLazyExternalLexicalLookups) {
|
if (hasLazyExternalLexicalLookups()) {
|
||||||
HasLazyExternalLexicalLookups = false;
|
setHasLazyExternalLexicalLookups(false);
|
||||||
for (auto *DC : Contexts) {
|
for (auto *DC : Contexts) {
|
||||||
if (DC->hasExternalLexicalStorage())
|
if (DC->hasExternalLexicalStorage()) {
|
||||||
HasLazyLocalLexicalLookups |=
|
bool LoadedDecls = DC->LoadLexicalDeclsFromExternalStorage();
|
||||||
DC->LoadLexicalDeclsFromExternalStorage();
|
setHasLazyLocalLexicalLookups(
|
||||||
|
hasLazyLocalLexicalLookups() | LoadedDecls );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!HasLazyLocalLexicalLookups)
|
if (!hasLazyLocalLexicalLookups())
|
||||||
return LookupPtr;
|
return LookupPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1505,7 +1519,7 @@ StoredDeclsMap *DeclContext::buildLookup() {
|
||||||
buildLookupImpl(DC, hasExternalVisibleStorage());
|
buildLookupImpl(DC, hasExternalVisibleStorage());
|
||||||
|
|
||||||
// We no longer have any lazy decls.
|
// We no longer have any lazy decls.
|
||||||
HasLazyLocalLexicalLookups = false;
|
setHasLazyLocalLexicalLookups(false);
|
||||||
return LookupPtr;
|
return LookupPtr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1543,7 +1557,8 @@ NamedDecl *const DeclContextLookupResult::SingleElementDummyList = nullptr;
|
||||||
|
|
||||||
DeclContext::lookup_result
|
DeclContext::lookup_result
|
||||||
DeclContext::lookup(DeclarationName Name) const {
|
DeclContext::lookup(DeclarationName Name) const {
|
||||||
assert(DeclKind != Decl::LinkageSpec && DeclKind != Decl::Export &&
|
assert(getDeclKind() != Decl::LinkageSpec &&
|
||||||
|
getDeclKind() != Decl::Export &&
|
||||||
"should not perform lookups into transparent contexts");
|
"should not perform lookups into transparent contexts");
|
||||||
|
|
||||||
const DeclContext *PrimaryContext = getPrimaryContext();
|
const DeclContext *PrimaryContext = getPrimaryContext();
|
||||||
|
@ -1560,12 +1575,13 @@ DeclContext::lookup(DeclarationName Name) const {
|
||||||
if (hasExternalVisibleStorage()) {
|
if (hasExternalVisibleStorage()) {
|
||||||
assert(Source && "external visible storage but no external source?");
|
assert(Source && "external visible storage but no external source?");
|
||||||
|
|
||||||
if (NeedToReconcileExternalVisibleStorage)
|
if (hasNeedToReconcileExternalVisibleStorage())
|
||||||
reconcileExternalVisibleStorage();
|
reconcileExternalVisibleStorage();
|
||||||
|
|
||||||
StoredDeclsMap *Map = LookupPtr;
|
StoredDeclsMap *Map = LookupPtr;
|
||||||
|
|
||||||
if (HasLazyLocalLexicalLookups || HasLazyExternalLexicalLookups)
|
if (hasLazyLocalLexicalLookups() ||
|
||||||
|
hasLazyExternalLexicalLookups())
|
||||||
// FIXME: Make buildLookup const?
|
// FIXME: Make buildLookup const?
|
||||||
Map = const_cast<DeclContext*>(this)->buildLookup();
|
Map = const_cast<DeclContext*>(this)->buildLookup();
|
||||||
|
|
||||||
|
@ -1590,7 +1606,8 @@ DeclContext::lookup(DeclarationName Name) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
StoredDeclsMap *Map = LookupPtr;
|
StoredDeclsMap *Map = LookupPtr;
|
||||||
if (HasLazyLocalLexicalLookups || HasLazyExternalLexicalLookups)
|
if (hasLazyLocalLexicalLookups() ||
|
||||||
|
hasLazyExternalLexicalLookups())
|
||||||
Map = const_cast<DeclContext*>(this)->buildLookup();
|
Map = const_cast<DeclContext*>(this)->buildLookup();
|
||||||
|
|
||||||
if (!Map)
|
if (!Map)
|
||||||
|
@ -1605,7 +1622,8 @@ DeclContext::lookup(DeclarationName Name) const {
|
||||||
|
|
||||||
DeclContext::lookup_result
|
DeclContext::lookup_result
|
||||||
DeclContext::noload_lookup(DeclarationName Name) {
|
DeclContext::noload_lookup(DeclarationName Name) {
|
||||||
assert(DeclKind != Decl::LinkageSpec && DeclKind != Decl::Export &&
|
assert(getDeclKind() != Decl::LinkageSpec &&
|
||||||
|
getDeclKind() != Decl::Export &&
|
||||||
"should not perform lookups into transparent contexts");
|
"should not perform lookups into transparent contexts");
|
||||||
|
|
||||||
DeclContext *PrimaryContext = getPrimaryContext();
|
DeclContext *PrimaryContext = getPrimaryContext();
|
||||||
|
@ -1626,12 +1644,12 @@ DeclContext::noload_lookup(DeclarationName Name) {
|
||||||
// now. Don't import any external declarations, not even if we know we have
|
// now. Don't import any external declarations, not even if we know we have
|
||||||
// some missing from the external visible lookups.
|
// some missing from the external visible lookups.
|
||||||
void DeclContext::loadLazyLocalLexicalLookups() {
|
void DeclContext::loadLazyLocalLexicalLookups() {
|
||||||
if (HasLazyLocalLexicalLookups) {
|
if (hasLazyLocalLexicalLookups()) {
|
||||||
SmallVector<DeclContext *, 2> Contexts;
|
SmallVector<DeclContext *, 2> Contexts;
|
||||||
collectAllContexts(Contexts);
|
collectAllContexts(Contexts);
|
||||||
for (auto *Context : Contexts)
|
for (auto *Context : Contexts)
|
||||||
buildLookupImpl(Context, hasExternalVisibleStorage());
|
buildLookupImpl(Context, hasExternalVisibleStorage());
|
||||||
HasLazyLocalLexicalLookups = false;
|
setHasLazyLocalLexicalLookups(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1649,7 +1667,8 @@ void DeclContext::localUncachedLookup(DeclarationName Name,
|
||||||
|
|
||||||
// If we have a lookup table, check there first. Maybe we'll get lucky.
|
// If we have a lookup table, check there first. Maybe we'll get lucky.
|
||||||
// FIXME: Should we be checking these flags on the primary context?
|
// FIXME: Should we be checking these flags on the primary context?
|
||||||
if (Name && !HasLazyLocalLexicalLookups && !HasLazyExternalLexicalLookups) {
|
if (Name && !hasLazyLocalLexicalLookups() &&
|
||||||
|
!hasLazyExternalLexicalLookups()) {
|
||||||
if (StoredDeclsMap *Map = LookupPtr) {
|
if (StoredDeclsMap *Map = LookupPtr) {
|
||||||
StoredDeclsMap::iterator Pos = Map->find(Name);
|
StoredDeclsMap::iterator Pos = Map->find(Name);
|
||||||
if (Pos != Map->end()) {
|
if (Pos != Map->end()) {
|
||||||
|
@ -1758,7 +1777,7 @@ void DeclContext::makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal,
|
||||||
buildLookup();
|
buildLookup();
|
||||||
makeDeclVisibleInContextImpl(D, Internal);
|
makeDeclVisibleInContextImpl(D, Internal);
|
||||||
} else {
|
} else {
|
||||||
HasLazyLocalLexicalLookups = true;
|
setHasLazyLocalLexicalLookups(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we are a transparent context or inline namespace, insert into our
|
// If we are a transparent context or inline namespace, insert into our
|
||||||
|
|
|
@ -128,7 +128,7 @@ CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK,
|
||||||
bool DelayTypeCreation) {
|
bool DelayTypeCreation) {
|
||||||
auto *R = new (C, DC) CXXRecordDecl(CXXRecord, TK, C, DC, StartLoc, IdLoc, Id,
|
auto *R = new (C, DC) CXXRecordDecl(CXXRecord, TK, C, DC, StartLoc, IdLoc, Id,
|
||||||
PrevDecl);
|
PrevDecl);
|
||||||
R->MayHaveOutOfDateDef = C.getLangOpts().Modules;
|
R->setMayHaveOutOfDateDef(C.getLangOpts().Modules);
|
||||||
|
|
||||||
// FIXME: DelayTypeCreation seems like such a hack
|
// FIXME: DelayTypeCreation seems like such a hack
|
||||||
if (!DelayTypeCreation)
|
if (!DelayTypeCreation)
|
||||||
|
@ -143,11 +143,11 @@ CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC,
|
||||||
LambdaCaptureDefault CaptureDefault) {
|
LambdaCaptureDefault CaptureDefault) {
|
||||||
auto *R = new (C, DC) CXXRecordDecl(CXXRecord, TTK_Class, C, DC, Loc, Loc,
|
auto *R = new (C, DC) CXXRecordDecl(CXXRecord, TTK_Class, C, DC, Loc, Loc,
|
||||||
nullptr, nullptr);
|
nullptr, nullptr);
|
||||||
R->IsBeingDefined = true;
|
R->setBeingDefined(true);
|
||||||
R->DefinitionData =
|
R->DefinitionData =
|
||||||
new (C) struct LambdaDefinitionData(R, Info, Dependent, IsGeneric,
|
new (C) struct LambdaDefinitionData(R, Info, Dependent, IsGeneric,
|
||||||
CaptureDefault);
|
CaptureDefault);
|
||||||
R->MayHaveOutOfDateDef = false;
|
R->setMayHaveOutOfDateDef(false);
|
||||||
R->setImplicit(true);
|
R->setImplicit(true);
|
||||||
C.getTypeDeclType(R, /*PrevDecl=*/nullptr);
|
C.getTypeDeclType(R, /*PrevDecl=*/nullptr);
|
||||||
return R;
|
return R;
|
||||||
|
@ -158,7 +158,7 @@ CXXRecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) {
|
||||||
auto *R = new (C, ID) CXXRecordDecl(
|
auto *R = new (C, ID) CXXRecordDecl(
|
||||||
CXXRecord, TTK_Struct, C, nullptr, SourceLocation(), SourceLocation(),
|
CXXRecord, TTK_Struct, C, nullptr, SourceLocation(), SourceLocation(),
|
||||||
nullptr, nullptr);
|
nullptr, nullptr);
|
||||||
R->MayHaveOutOfDateDef = false;
|
R->setMayHaveOutOfDateDef(false);
|
||||||
return R;
|
return R;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -712,7 +712,7 @@ ClassTemplateSpecializationDecl::Create(ASTContext &Context, TagKind TK,
|
||||||
new (Context, DC) ClassTemplateSpecializationDecl(
|
new (Context, DC) ClassTemplateSpecializationDecl(
|
||||||
Context, ClassTemplateSpecialization, TK, DC, StartLoc, IdLoc,
|
Context, ClassTemplateSpecialization, TK, DC, StartLoc, IdLoc,
|
||||||
SpecializedTemplate, Args, PrevDecl);
|
SpecializedTemplate, Args, PrevDecl);
|
||||||
Result->MayHaveOutOfDateDef = false;
|
Result->setMayHaveOutOfDateDef(false);
|
||||||
|
|
||||||
Context.getTypeDeclType(Result, PrevDecl);
|
Context.getTypeDeclType(Result, PrevDecl);
|
||||||
return Result;
|
return Result;
|
||||||
|
@ -723,7 +723,7 @@ ClassTemplateSpecializationDecl::CreateDeserialized(ASTContext &C,
|
||||||
unsigned ID) {
|
unsigned ID) {
|
||||||
auto *Result =
|
auto *Result =
|
||||||
new (C, ID) ClassTemplateSpecializationDecl(C, ClassTemplateSpecialization);
|
new (C, ID) ClassTemplateSpecializationDecl(C, ClassTemplateSpecialization);
|
||||||
Result->MayHaveOutOfDateDef = false;
|
Result->setMayHaveOutOfDateDef(false);
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -830,7 +830,7 @@ Create(ASTContext &Context, TagKind TK,DeclContext *DC,
|
||||||
Params, SpecializedTemplate, Args,
|
Params, SpecializedTemplate, Args,
|
||||||
ASTArgInfos, PrevDecl);
|
ASTArgInfos, PrevDecl);
|
||||||
Result->setSpecializationKind(TSK_ExplicitSpecialization);
|
Result->setSpecializationKind(TSK_ExplicitSpecialization);
|
||||||
Result->MayHaveOutOfDateDef = false;
|
Result->setMayHaveOutOfDateDef(false);
|
||||||
|
|
||||||
Context.getInjectedClassNameType(Result, CanonInjectedType);
|
Context.getInjectedClassNameType(Result, CanonInjectedType);
|
||||||
return Result;
|
return Result;
|
||||||
|
@ -840,7 +840,7 @@ ClassTemplatePartialSpecializationDecl *
|
||||||
ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
|
ClassTemplatePartialSpecializationDecl::CreateDeserialized(ASTContext &C,
|
||||||
unsigned ID) {
|
unsigned ID) {
|
||||||
auto *Result = new (C, ID) ClassTemplatePartialSpecializationDecl(C);
|
auto *Result = new (C, ID) ClassTemplatePartialSpecializationDecl(C);
|
||||||
Result->MayHaveOutOfDateDef = false;
|
Result->setMayHaveOutOfDateDef(false);
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -742,16 +742,16 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
|
||||||
ED->setPromotionType(Record.readType());
|
ED->setPromotionType(Record.readType());
|
||||||
ED->setNumPositiveBits(Record.readInt());
|
ED->setNumPositiveBits(Record.readInt());
|
||||||
ED->setNumNegativeBits(Record.readInt());
|
ED->setNumNegativeBits(Record.readInt());
|
||||||
ED->IsScoped = Record.readInt();
|
ED->setScoped(Record.readInt());
|
||||||
ED->IsScopedUsingClassTag = Record.readInt();
|
ED->setScopedUsingClassTag(Record.readInt());
|
||||||
ED->IsFixed = Record.readInt();
|
ED->setFixed(Record.readInt());
|
||||||
|
|
||||||
ED->HasODRHash = true;
|
ED->setHasODRHash(true);
|
||||||
ED->ODRHash = Record.readInt();
|
ED->ODRHash = Record.readInt();
|
||||||
|
|
||||||
// If this is a definition subject to the ODR, and we already have a
|
// If this is a definition subject to the ODR, and we already have a
|
||||||
// definition, merge this one into it.
|
// definition, merge this one into it.
|
||||||
if (ED->IsCompleteDefinition &&
|
if (ED->isCompleteDefinition() &&
|
||||||
Reader.getContext().getLangOpts().Modules &&
|
Reader.getContext().getLangOpts().Modules &&
|
||||||
Reader.getContext().getLangOpts().CPlusPlus) {
|
Reader.getContext().getLangOpts().CPlusPlus) {
|
||||||
EnumDecl *&OldDef = Reader.EnumDefinitions[ED->getCanonicalDecl()];
|
EnumDecl *&OldDef = Reader.EnumDefinitions[ED->getCanonicalDecl()];
|
||||||
|
@ -767,7 +767,7 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
|
||||||
}
|
}
|
||||||
if (OldDef) {
|
if (OldDef) {
|
||||||
Reader.MergedDeclContexts.insert(std::make_pair(ED, OldDef));
|
Reader.MergedDeclContexts.insert(std::make_pair(ED, OldDef));
|
||||||
ED->IsCompleteDefinition = false;
|
ED->setCompleteDefinition(false);
|
||||||
Reader.mergeDefinitionVisibility(OldDef, ED);
|
Reader.mergeDefinitionVisibility(OldDef, ED);
|
||||||
if (OldDef->getODRHash() != ED->getODRHash())
|
if (OldDef->getODRHash() != ED->getODRHash())
|
||||||
Reader.PendingEnumOdrMergeFailures[OldDef].push_back(ED);
|
Reader.PendingEnumOdrMergeFailures[OldDef].push_back(ED);
|
||||||
|
@ -1744,7 +1744,7 @@ void ASTDeclReader::MergeDefinitionData(
|
||||||
Reader.MergedDeclContexts.insert(std::make_pair(MergeDD.Definition,
|
Reader.MergedDeclContexts.insert(std::make_pair(MergeDD.Definition,
|
||||||
DD.Definition));
|
DD.Definition));
|
||||||
Reader.PendingDefinitions.erase(MergeDD.Definition);
|
Reader.PendingDefinitions.erase(MergeDD.Definition);
|
||||||
MergeDD.Definition->IsCompleteDefinition = false;
|
MergeDD.Definition->setCompleteDefinition(false);
|
||||||
Reader.mergeDefinitionVisibility(DD.Definition, MergeDD.Definition);
|
Reader.mergeDefinitionVisibility(DD.Definition, MergeDD.Definition);
|
||||||
assert(Reader.Lookups.find(MergeDD.Definition) == Reader.Lookups.end() &&
|
assert(Reader.Lookups.find(MergeDD.Definition) == Reader.Lookups.end() &&
|
||||||
"already loaded pending lookups for merged definition");
|
"already loaded pending lookups for merged definition");
|
||||||
|
@ -1884,7 +1884,7 @@ void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mark this declaration as being a definition.
|
// Mark this declaration as being a definition.
|
||||||
D->IsCompleteDefinition = true;
|
D->setCompleteDefinition(true);
|
||||||
|
|
||||||
// If this is not the first declaration or is an update record, we can have
|
// If this is not the first declaration or is an update record, we can have
|
||||||
// other redeclarations already. Make a note that we need to propagate the
|
// other redeclarations already. Make a note that we need to propagate the
|
||||||
|
@ -1946,7 +1946,7 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) {
|
||||||
// compute it.
|
// compute it.
|
||||||
if (WasDefinition) {
|
if (WasDefinition) {
|
||||||
DeclID KeyFn = ReadDeclID();
|
DeclID KeyFn = ReadDeclID();
|
||||||
if (KeyFn && D->IsCompleteDefinition)
|
if (KeyFn && D->isCompleteDefinition())
|
||||||
// FIXME: This is wrong for the ARM ABI, where some other module may have
|
// FIXME: This is wrong for the ARM ABI, where some other module may have
|
||||||
// made this function no longer be a key function. We need an update
|
// made this function no longer be a key function. We need an update
|
||||||
// record or similar for that case.
|
// record or similar for that case.
|
||||||
|
@ -3076,7 +3076,7 @@ DeclContext *ASTDeclReader::getPrimaryContextForMerging(ASTReader &Reader,
|
||||||
// we load the update record.
|
// we load the update record.
|
||||||
if (!DD) {
|
if (!DD) {
|
||||||
DD = new (Reader.getContext()) struct CXXRecordDecl::DefinitionData(RD);
|
DD = new (Reader.getContext()) struct CXXRecordDecl::DefinitionData(RD);
|
||||||
RD->IsCompleteDefinition = true;
|
RD->setCompleteDefinition(true);
|
||||||
RD->DefinitionData = DD;
|
RD->DefinitionData = DD;
|
||||||
RD->getCanonicalDecl()->DefinitionData = DD;
|
RD->getCanonicalDecl()->DefinitionData = DD;
|
||||||
|
|
||||||
|
|
|
@ -3960,7 +3960,8 @@ public:
|
||||||
|
|
||||||
bool ASTWriter::isLookupResultExternal(StoredDeclsList &Result,
|
bool ASTWriter::isLookupResultExternal(StoredDeclsList &Result,
|
||||||
DeclContext *DC) {
|
DeclContext *DC) {
|
||||||
return Result.hasExternalDecls() && DC->NeedToReconcileExternalVisibleStorage;
|
return Result.hasExternalDecls() &&
|
||||||
|
DC->hasNeedToReconcileExternalVisibleStorage();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ASTWriter::isLookupResultEntirelyExternal(StoredDeclsList &Result,
|
bool ASTWriter::isLookupResultEntirelyExternal(StoredDeclsList &Result,
|
||||||
|
@ -3975,8 +3976,8 @@ bool ASTWriter::isLookupResultEntirelyExternal(StoredDeclsList &Result,
|
||||||
void
|
void
|
||||||
ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC,
|
ASTWriter::GenerateNameLookupTable(const DeclContext *ConstDC,
|
||||||
llvm::SmallVectorImpl<char> &LookupTable) {
|
llvm::SmallVectorImpl<char> &LookupTable) {
|
||||||
assert(!ConstDC->HasLazyLocalLexicalLookups &&
|
assert(!ConstDC->hasLazyLocalLexicalLookups() &&
|
||||||
!ConstDC->HasLazyExternalLexicalLookups &&
|
!ConstDC->hasLazyExternalLexicalLookups() &&
|
||||||
"must call buildLookups first");
|
"must call buildLookups first");
|
||||||
|
|
||||||
// FIXME: We need to build the lookups table, which is logically const.
|
// FIXME: We need to build the lookups table, which is logically const.
|
||||||
|
|
|
@ -1275,7 +1275,7 @@ void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) {
|
||||||
|
|
||||||
// Store (what we currently believe to be) the key function to avoid
|
// Store (what we currently believe to be) the key function to avoid
|
||||||
// deserializing every method so we can compute it.
|
// deserializing every method so we can compute it.
|
||||||
if (D->IsCompleteDefinition)
|
if (D->isCompleteDefinition())
|
||||||
Record.AddDeclRef(Context.getCurrentKeyFunction(D));
|
Record.AddDeclRef(Context.getCurrentKeyFunction(D));
|
||||||
|
|
||||||
Code = serialization::DECL_CXX_RECORD;
|
Code = serialization::DECL_CXX_RECORD;
|
||||||
|
|
Loading…
Reference in New Issue