diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 858450926455c..4bee18767dd11 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -268,17 +268,37 @@ class alignas(8) Decl { /// } /// void A::f(); // SemanticDC == namespace 'A' /// // LexicalDC == global namespace - llvm::PointerUnion DeclCtx; - bool isInSemaDC() const { return DeclCtx.is(); } - bool isOutOfSemaDC() const { return DeclCtx.is(); } + // Compress the InvalidDecl and HasAttrs bits into DeclCtx to keep Decl below + // 32 bytes in size + llvm::PointerIntPair< + llvm::PointerIntPair, 1, + bool>, + 1, bool> + DeclCtxWithInvalidDeclAndHasAttrs; + + bool isInSemaDC() const { + return DeclCtxWithInvalidDeclAndHasAttrs.getPointer() + .getPointer() + .is(); + } + + bool isOutOfSemaDC() const { + return DeclCtxWithInvalidDeclAndHasAttrs.getPointer() + .getPointer() + .is(); + } MultipleDC *getMultipleDC() const { - return DeclCtx.get(); + return DeclCtxWithInvalidDeclAndHasAttrs.getPointer() + .getPointer() + .get(); } DeclContext *getSemanticDC() const { - return DeclCtx.get(); + return DeclCtxWithInvalidDeclAndHasAttrs.getPointer() + .getPointer() + .get(); } /// Loc - The location of this decl. @@ -288,14 +308,6 @@ class alignas(8) Decl { LLVM_PREFERRED_TYPE(Kind) unsigned DeclKind : 7; - /// InvalidDecl - This indicates a semantic error occurred. - LLVM_PREFERRED_TYPE(bool) - unsigned InvalidDecl : 1; - - /// HasAttrs - This indicates whether the decl has attributes or not. - LLVM_PREFERRED_TYPE(bool) - unsigned HasAttrs : 1; - /// Implicit - Whether this declaration was implicitly generated by /// the implementation rather than explicitly written by the user. LLVM_PREFERRED_TYPE(bool) @@ -393,21 +405,22 @@ class alignas(8) Decl { protected: Decl(Kind DK, DeclContext *DC, SourceLocation L) : NextInContextAndBits(nullptr, getModuleOwnershipKindForChildOf(DC)), - DeclCtx(DC), Loc(L), DeclKind(DK), InvalidDecl(false), HasAttrs(false), - Implicit(false), Used(false), Referenced(false), + DeclCtxWithInvalidDeclAndHasAttrs({DC, false}, false), Loc(L), + DeclKind(DK), Implicit(false), Used(false), Referenced(false), TopLevelDeclInObjCContainer(false), Access(AS_none), FromASTFile(0), IdentifierNamespace(getIdentifierNamespaceForKind(DK)), CacheValidAndLinkage(llvm::to_underlying(Linkage::Invalid)) { - if (StatisticsEnabled) add(DK); + if (StatisticsEnabled) + add(DK); } Decl(Kind DK, EmptyShell Empty) - : DeclKind(DK), InvalidDecl(false), HasAttrs(false), Implicit(false), - Used(false), Referenced(false), TopLevelDeclInObjCContainer(false), - Access(AS_none), FromASTFile(0), + : DeclKind(DK), Implicit(false), Used(false), Referenced(false), + TopLevelDeclInObjCContainer(false), Access(AS_none), FromASTFile(0), IdentifierNamespace(getIdentifierNamespaceForKind(DK)), CacheValidAndLinkage(llvm::to_underlying(Linkage::Invalid)) { - if (StatisticsEnabled) add(DK); + if (StatisticsEnabled) + add(DK); } virtual ~Decl(); @@ -520,7 +533,9 @@ class alignas(8) Decl { return AccessSpecifier(Access); } - bool hasAttrs() const { return HasAttrs; } + bool hasAttrs() const { + return DeclCtxWithInvalidDeclAndHasAttrs.getPointer().getInt(); + } void setAttrs(const AttrVec& Attrs) { return setAttrsImpl(Attrs, getASTContext()); @@ -549,13 +564,17 @@ class alignas(8) Decl { } template void dropAttrs() { - if (!HasAttrs) return; + if (!hasAttrs()) + return; AttrVec &Vec = getAttrs(); llvm::erase_if(Vec, [](Attr *A) { return isa(A); }); - if (Vec.empty()) - HasAttrs = false; + if (Vec.empty()) { + auto InnerPtr = DeclCtxWithInvalidDeclAndHasAttrs.getPointer(); + InnerPtr.setInt(false); + DeclCtxWithInvalidDeclAndHasAttrs.setPointer(InnerPtr); + } } template void dropAttr() { dropAttrs(); } @@ -590,7 +609,10 @@ class alignas(8) Decl { /// setInvalidDecl - Indicates the Decl had a semantic error. This /// allows for graceful error recovery. void setInvalidDecl(bool Invalid = true); - bool isInvalidDecl() const { return (bool) InvalidDecl; } + + bool isInvalidDecl() const { + return DeclCtxWithInvalidDeclAndHasAttrs.getInt(); + } /// isImplicit - Indicates whether the declaration was implicitly /// generated by the implementation. If false, this declaration diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 66a727d9dd0c3..8c83c711d882d 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -52,6 +52,8 @@ using namespace clang; +static_assert(sizeof(Decl) <= 32, "Decl grew beyond 32 bytes!"); + //===----------------------------------------------------------------------===// // Statistics //===----------------------------------------------------------------------===// @@ -130,7 +132,7 @@ const char *Decl::getDeclKindName() const { } void Decl::setInvalidDecl(bool Invalid) { - InvalidDecl = Invalid; + DeclCtxWithInvalidDeclAndHasAttrs.setInt(Invalid); assert(!isa(this) || !cast(this)->isCompleteDefinition()); if (!Invalid) { return; @@ -334,7 +336,9 @@ void PrettyStackTraceDecl::print(raw_ostream &OS) const { Decl::~Decl() = default; void Decl::setDeclContext(DeclContext *DC) { - DeclCtx = DC; + auto InnerPtr = DeclCtxWithInvalidDeclAndHasAttrs.getPointer(); + InnerPtr.setPointer(DC); + DeclCtxWithInvalidDeclAndHasAttrs.setPointer(InnerPtr); } void Decl::setLexicalDeclContext(DeclContext *DC) { @@ -364,12 +368,16 @@ void Decl::setLexicalDeclContext(DeclContext *DC) { void Decl::setDeclContextsImpl(DeclContext *SemaDC, DeclContext *LexicalDC, ASTContext &Ctx) { if (SemaDC == LexicalDC) { - DeclCtx = SemaDC; + auto InnerPtr = DeclCtxWithInvalidDeclAndHasAttrs.getPointer(); + InnerPtr.setPointer(SemaDC); + DeclCtxWithInvalidDeclAndHasAttrs.setPointer(InnerPtr); } else { auto *MDC = new (Ctx) Decl::MultipleDC(); MDC->SemanticDC = SemaDC; MDC->LexicalDC = LexicalDC; - DeclCtx = MDC; + auto InnerPtr = DeclCtxWithInvalidDeclAndHasAttrs.getPointer(); + InnerPtr.setPointer(MDC); + DeclCtxWithInvalidDeclAndHasAttrs.setPointer(InnerPtr); } } @@ -956,19 +964,24 @@ unsigned Decl::getIdentifierNamespaceForKind(Kind DeclKind) { } void Decl::setAttrsImpl(const AttrVec &attrs, ASTContext &Ctx) { - assert(!HasAttrs && "Decl already contains attrs."); + assert(!hasAttrs() && "Decl already contains attrs."); AttrVec &AttrBlank = Ctx.getDeclAttrs(this); assert(AttrBlank.empty() && "HasAttrs was wrong?"); AttrBlank = attrs; - HasAttrs = true; + auto InnerPtr = DeclCtxWithInvalidDeclAndHasAttrs.getPointer(); + InnerPtr.setInt(true); + DeclCtxWithInvalidDeclAndHasAttrs.setPointer(InnerPtr); } void Decl::dropAttrs() { - if (!HasAttrs) return; + if (!hasAttrs()) + return; - HasAttrs = false; + auto InnerPtr = DeclCtxWithInvalidDeclAndHasAttrs.getPointer(); + InnerPtr.setInt(false); + DeclCtxWithInvalidDeclAndHasAttrs.setPointer(InnerPtr); getASTContext().eraseDeclAttrs(this); } @@ -996,7 +1009,7 @@ void Decl::addAttr(Attr *A) { } const AttrVec &Decl::getAttrs() const { - assert(HasAttrs && "No attrs to get!"); + assert(hasAttrs() && "No attrs to get!"); return getASTContext().getDeclAttrs(this); } diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp index ff72fc30c718f..c5dd89e1c8a4d 100644 --- a/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/clang/lib/Serialization/ASTReaderDecl.cpp @@ -588,7 +588,7 @@ void ASTDeclReader::VisitDecl(Decl *D) { bool HasStandaloneLexicalDC = DeclBits.getNextBit(); bool HasAttrs = DeclBits.getNextBit(); D->setTopLevelDeclInObjCContainer(DeclBits.getNextBit()); - D->InvalidDecl = DeclBits.getNextBit(); + D->DeclCtxWithInvalidDeclAndHasAttrs.setInt(DeclBits.getNextBit()); D->FromASTFile = true; if (D->isTemplateParameter() || D->isTemplateParameterPack() ||