Skip to content

Commit e6ec7c8

Browse files
authored
[Clang][AST] Move NamespaceDecl bits to DeclContext (#98567)
Currently, `NamespaceDecl` has a member `AnonOrFirstNamespaceAndFlags` which stores a few pieces of data: - a bit indicating whether the namespace was declared `inline`, and - a bit indicating whether the namespace was declared as a _nested-namespace-definition_, and - a pointer a `NamespaceDecl` that either stores: - a pointer to the first declaration of that namespace if the declaration is no the first declaration, or - a pointer to the unnamed namespace that inhabits the namespace otherwise. `Redeclarable` already stores a pointer to the first declaration of an entity, so it's unnecessary to store this in `NamespaceDecl`. `DeclContext` has 8 bytes in which various bitfields can be stored for a declaration, so it's not necessary to store these in `NamespaceDecl` either. We only need to store a pointer to the unnamed namespace that inhabits the first declaration of a namespace. This patch moves the two bits currently stored in `NamespaceDecl` to `DeclContext`, and only stores a pointer to the unnamed namespace that inhabits a namespace in the first declaration of that namespace. Since `getOriginalNamespace` always returns the same `NamespaceDecl` as `getFirstDecl`, this function is removed to avoid confusion.
1 parent 2905372 commit e6ec7c8

File tree

14 files changed

+59
-111
lines changed

14 files changed

+59
-111
lines changed

clang-tools-extra/clang-tidy/bugprone/ForwardDeclarationNamespaceCheck.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ static bool haveSameNamespaceOrTranslationUnit(const CXXRecordDecl *Decl1,
9595
"ParentDecl2 declaration must be a namespace");
9696
auto *Ns1 = NamespaceDecl::castFromDeclContext(ParentDecl1);
9797
auto *Ns2 = NamespaceDecl::castFromDeclContext(ParentDecl2);
98-
return Ns1->getOriginalNamespace() == Ns2->getOriginalNamespace();
98+
return Ns1->getFirstDecl() == Ns2->getFirstDecl();
9999
}
100100

101101
static std::string getNameOfNamespace(const CXXRecordDecl *Decl) {

clang/include/clang/AST/Decl.h

Lines changed: 14 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -542,25 +542,18 @@ class LabelDecl : public NamedDecl {
542542
};
543543

544544
/// Represent a C++ namespace.
545-
class NamespaceDecl : public NamedDecl, public DeclContext,
546-
public Redeclarable<NamespaceDecl>
547-
{
548-
549-
enum Flags : unsigned { F_Inline = 1 << 0, F_Nested = 1 << 1 };
550-
545+
class NamespaceDecl : public NamedDecl,
546+
public DeclContext,
547+
public Redeclarable<NamespaceDecl> {
551548
/// The starting location of the source range, pointing
552549
/// to either the namespace or the inline keyword.
553550
SourceLocation LocStart;
554551

555552
/// The ending location of the source range.
556553
SourceLocation RBraceLoc;
557554

558-
/// A pointer to either the anonymous namespace that lives just inside
559-
/// this namespace or to the first namespace in the chain (the latter case
560-
/// only when this is not the first in the chain), along with a
561-
/// boolean value indicating whether this is an inline namespace.
562-
llvm::PointerIntPair<NamespaceDecl *, 2, unsigned>
563-
AnonOrFirstNamespaceAndFlags;
555+
/// The unnamed namespace that inhabits this namespace, if any.
556+
NamespaceDecl *AnonymousNamespace = nullptr;
564557

565558
NamespaceDecl(ASTContext &C, DeclContext *DC, bool Inline,
566559
SourceLocation StartLoc, SourceLocation IdLoc,
@@ -607,35 +600,19 @@ class NamespaceDecl : public NamedDecl, public DeclContext,
607600
}
608601

609602
/// Returns true if this is an inline namespace declaration.
610-
bool isInline() const {
611-
return AnonOrFirstNamespaceAndFlags.getInt() & F_Inline;
612-
}
603+
bool isInline() const { return NamespaceDeclBits.IsInline; }
613604

614605
/// Set whether this is an inline namespace declaration.
615-
void setInline(bool Inline) {
616-
unsigned F = AnonOrFirstNamespaceAndFlags.getInt();
617-
if (Inline)
618-
AnonOrFirstNamespaceAndFlags.setInt(F | F_Inline);
619-
else
620-
AnonOrFirstNamespaceAndFlags.setInt(F & ~F_Inline);
621-
}
606+
void setInline(bool Inline) { NamespaceDeclBits.IsInline = Inline; }
622607

623608
/// Returns true if this is a nested namespace declaration.
624609
/// \code
625610
/// namespace outer::nested { }
626611
/// \endcode
627-
bool isNested() const {
628-
return AnonOrFirstNamespaceAndFlags.getInt() & F_Nested;
629-
}
612+
bool isNested() const { return NamespaceDeclBits.IsNested; }
630613

631614
/// Set whether this is a nested namespace declaration.
632-
void setNested(bool Nested) {
633-
unsigned F = AnonOrFirstNamespaceAndFlags.getInt();
634-
if (Nested)
635-
AnonOrFirstNamespaceAndFlags.setInt(F | F_Nested);
636-
else
637-
AnonOrFirstNamespaceAndFlags.setInt(F & ~F_Nested);
638-
}
615+
void setNested(bool Nested) { NamespaceDeclBits.IsNested = Nested; }
639616

640617
/// Returns true if the inline qualifier for \c Name is redundant.
641618
bool isRedundantInlineQualifierFor(DeclarationName Name) const {
@@ -649,34 +626,18 @@ class NamespaceDecl : public NamedDecl, public DeclContext,
649626
std::distance(Y.begin(), Y.end());
650627
}
651628

652-
/// Get the original (first) namespace declaration.
653-
NamespaceDecl *getOriginalNamespace();
654-
655-
/// Get the original (first) namespace declaration.
656-
const NamespaceDecl *getOriginalNamespace() const;
657-
658-
/// Return true if this declaration is an original (first) declaration
659-
/// of the namespace. This is false for non-original (subsequent) namespace
660-
/// declarations and anonymous namespaces.
661-
bool isOriginalNamespace() const;
662-
663-
/// Retrieve the anonymous namespace nested inside this namespace,
664-
/// if any.
629+
/// Retrieve the anonymous namespace that inhabits this namespace, if any.
665630
NamespaceDecl *getAnonymousNamespace() const {
666-
return getOriginalNamespace()->AnonOrFirstNamespaceAndFlags.getPointer();
631+
return getFirstDecl()->AnonymousNamespace;
667632
}
668633

669634
void setAnonymousNamespace(NamespaceDecl *D) {
670-
getOriginalNamespace()->AnonOrFirstNamespaceAndFlags.setPointer(D);
635+
getFirstDecl()->AnonymousNamespace = D;
671636
}
672637

673638
/// Retrieves the canonical declaration of this namespace.
674-
NamespaceDecl *getCanonicalDecl() override {
675-
return getOriginalNamespace();
676-
}
677-
const NamespaceDecl *getCanonicalDecl() const {
678-
return getOriginalNamespace();
679-
}
639+
NamespaceDecl *getCanonicalDecl() override { return getFirstDecl(); }
640+
const NamespaceDecl *getCanonicalDecl() const { return getFirstDecl(); }
680641

681642
SourceRange getSourceRange() const override LLVM_READONLY {
682643
return SourceRange(LocStart, RBraceLoc);

clang/include/clang/AST/DeclBase.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1487,6 +1487,27 @@ class DeclContext {
14871487
/// Number of bits in DeclContextBitfields.
14881488
enum { NumDeclContextBits = 13 };
14891489

1490+
/// Stores the bits used by NamespaceDecl.
1491+
/// If modified NumNamespaceDeclBits and the accessor
1492+
/// methods in NamespaceDecl should be updated appropriately.
1493+
class NamespaceDeclBitfields {
1494+
friend class NamespaceDecl;
1495+
/// For the bits in DeclContextBitfields
1496+
LLVM_PREFERRED_TYPE(DeclContextBitfields)
1497+
uint64_t : NumDeclContextBits;
1498+
1499+
/// True if this is an inline namespace.
1500+
LLVM_PREFERRED_TYPE(bool)
1501+
uint64_t IsInline : 1;
1502+
1503+
/// True if this is a nested-namespace-definition.
1504+
LLVM_PREFERRED_TYPE(bool)
1505+
uint64_t IsNested : 1;
1506+
};
1507+
1508+
/// Number of inherited and non-inherited bits in NamespaceDeclBitfields.
1509+
enum { NumNamespaceDeclBits = NumDeclContextBits + 2 };
1510+
14901511
/// Stores the bits used by TagDecl.
14911512
/// If modified NumTagDeclBits and the accessor
14921513
/// methods in TagDecl should be updated appropriately.
@@ -1985,6 +2006,7 @@ class DeclContext {
19852006
/// 8 bytes with static_asserts in the ctor of DeclContext.
19862007
union {
19872008
DeclContextBitfields DeclContextBits;
2009+
NamespaceDeclBitfields NamespaceDeclBits;
19882010
TagDeclBitfields TagDeclBits;
19892011
EnumDeclBitfields EnumDeclBits;
19902012
RecordDeclBitfields RecordDeclBits;
@@ -1998,6 +2020,8 @@ class DeclContext {
19982020

19992021
static_assert(sizeof(DeclContextBitfields) <= 8,
20002022
"DeclContextBitfields is larger than 8 bytes!");
2023+
static_assert(sizeof(NamespaceDeclBitfields) <= 8,
2024+
"NamespaceDeclBitfields is larger than 8 bytes!");
20012025
static_assert(sizeof(TagDeclBitfields) <= 8,
20022026
"TagDeclBitfields is larger than 8 bytes!");
20032027
static_assert(sizeof(EnumDeclBitfields) <= 8,

clang/lib/AST/ASTContext.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7250,14 +7250,14 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const {
72507250
// A namespace is canonical; build a nested-name-specifier with
72517251
// this namespace and no prefix.
72527252
return NestedNameSpecifier::Create(*this, nullptr,
7253-
NNS->getAsNamespace()->getOriginalNamespace());
7253+
NNS->getAsNamespace()->getFirstDecl());
72547254

72557255
case NestedNameSpecifier::NamespaceAlias:
72567256
// A namespace is canonical; build a nested-name-specifier with
72577257
// this namespace and no prefix.
7258-
return NestedNameSpecifier::Create(*this, nullptr,
7259-
NNS->getAsNamespaceAlias()->getNamespace()
7260-
->getOriginalNamespace());
7258+
return NestedNameSpecifier::Create(
7259+
*this, nullptr,
7260+
NNS->getAsNamespaceAlias()->getNamespace()->getFirstDecl());
72617261

72627262
// The difference between TypeSpec and TypeSpecWithTemplate is that the
72637263
// latter will have the 'template' keyword when printed.

clang/lib/AST/DeclBase.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1422,8 +1422,7 @@ DeclContext *DeclContext::getPrimaryContext() {
14221422
case Decl::TranslationUnit:
14231423
return static_cast<TranslationUnitDecl *>(this)->getFirstDecl();
14241424
case Decl::Namespace:
1425-
// The original namespace is our primary context.
1426-
return static_cast<NamespaceDecl *>(this)->getOriginalNamespace();
1425+
return static_cast<NamespaceDecl *>(this)->getFirstDecl();
14271426

14281427
case Decl::ObjCMethod:
14291428
return this;

clang/lib/AST/DeclCXX.cpp

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2941,7 +2941,7 @@ UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC,
29412941
NamedDecl *Used,
29422942
DeclContext *CommonAncestor) {
29432943
if (auto *NS = dyn_cast_or_null<NamespaceDecl>(Used))
2944-
Used = NS->getOriginalNamespace();
2944+
Used = NS->getFirstDecl();
29452945
return new (C, DC) UsingDirectiveDecl(DC, L, NamespaceLoc, QualifierLoc,
29462946
IdentLoc, Used, CommonAncestor);
29472947
}
@@ -2966,16 +2966,9 @@ NamespaceDecl::NamespaceDecl(ASTContext &C, DeclContext *DC, bool Inline,
29662966
bool Nested)
29672967
: NamedDecl(Namespace, DC, IdLoc, Id), DeclContext(Namespace),
29682968
redeclarable_base(C), LocStart(StartLoc) {
2969-
unsigned Flags = 0;
2970-
if (Inline)
2971-
Flags |= F_Inline;
2972-
if (Nested)
2973-
Flags |= F_Nested;
2974-
AnonOrFirstNamespaceAndFlags = {nullptr, Flags};
2969+
setInline(Inline);
2970+
setNested(Nested);
29752971
setPreviousDecl(PrevDecl);
2976-
2977-
if (PrevDecl)
2978-
AnonOrFirstNamespaceAndFlags.setPointer(PrevDecl->getOriginalNamespace());
29792972
}
29802973

29812974
NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC,
@@ -2992,22 +2985,6 @@ NamespaceDecl *NamespaceDecl::CreateDeserialized(ASTContext &C,
29922985
SourceLocation(), nullptr, nullptr, false);
29932986
}
29942987

2995-
NamespaceDecl *NamespaceDecl::getOriginalNamespace() {
2996-
if (isFirstDecl())
2997-
return this;
2998-
2999-
return AnonOrFirstNamespaceAndFlags.getPointer();
3000-
}
3001-
3002-
const NamespaceDecl *NamespaceDecl::getOriginalNamespace() const {
3003-
if (isFirstDecl())
3004-
return this;
3005-
3006-
return AnonOrFirstNamespaceAndFlags.getPointer();
3007-
}
3008-
3009-
bool NamespaceDecl::isOriginalNamespace() const { return isFirstDecl(); }
3010-
30112988
NamespaceDecl *NamespaceDecl::getNextRedeclarationImpl() {
30122989
return getNextRedeclaration();
30132990
}
@@ -3043,7 +3020,7 @@ NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
30433020
NamedDecl *Namespace) {
30443021
// FIXME: Preserve the aliased namespace as written.
30453022
if (auto *NS = dyn_cast_or_null<NamespaceDecl>(Namespace))
3046-
Namespace = NS->getOriginalNamespace();
3023+
Namespace = NS->getFirstDecl();
30473024
return new (C, DC) NamespaceAliasDecl(C, DC, UsingLoc, AliasLoc, Alias,
30483025
QualifierLoc, IdentLoc, Namespace);
30493026
}

clang/lib/AST/ItaniumMangle.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -961,7 +961,7 @@ bool CXXNameMangler::isStd(const NamespaceDecl *NS) {
961961
if (!Context.getEffectiveParentContext(NS)->isTranslationUnit())
962962
return false;
963963

964-
const IdentifierInfo *II = NS->getOriginalNamespace()->getIdentifier();
964+
const IdentifierInfo *II = NS->getFirstDecl()->getIdentifier();
965965
return II && II->isStr("std");
966966
}
967967

clang/lib/AST/JSONNodeDumper.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -883,9 +883,8 @@ void JSONNodeDumper::VisitNamespaceDecl(const NamespaceDecl *ND) {
883883
VisitNamedDecl(ND);
884884
attributeOnlyIfTrue("isInline", ND->isInline());
885885
attributeOnlyIfTrue("isNested", ND->isNested());
886-
if (!ND->isOriginalNamespace())
887-
JOS.attribute("originalNamespace",
888-
createBareDeclRef(ND->getOriginalNamespace()));
886+
if (!ND->isFirstDecl())
887+
JOS.attribute("originalNamespace", createBareDeclRef(ND->getFirstDecl()));
889888
}
890889

891890
void JSONNodeDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *UDD) {

clang/lib/AST/TextNodeDumper.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2386,8 +2386,8 @@ void TextNodeDumper::VisitNamespaceDecl(const NamespaceDecl *D) {
23862386
OS << " inline";
23872387
if (D->isNested())
23882388
OS << " nested";
2389-
if (!D->isOriginalNamespace())
2390-
dumpDeclRef(D->getOriginalNamespace(), "original");
2389+
if (!D->isFirstDecl())
2390+
dumpDeclRef(D->getFirstDecl(), "original");
23912391
}
23922392

23932393
void TextNodeDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {

clang/lib/Sema/SemaCodeComplete.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6864,7 +6864,7 @@ void SemaCodeCompletion::CodeCompleteNamespaceDecl(Scope *S) {
68646864
NS(Ctx->decls_begin()),
68656865
NSEnd(Ctx->decls_end());
68666866
NS != NSEnd; ++NS)
6867-
OrigToLatest[NS->getOriginalNamespace()] = *NS;
6867+
OrigToLatest[NS->getFirstDecl()] = *NS;
68686868

68696869
// Add the most recent definition (or extended definition) of each
68706870
// namespace to the list of results.

clang/lib/Sema/SemaLookup.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2325,7 +2325,7 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R,
23252325
// We have already looked into the initial namespace; seed the queue
23262326
// with its using-children.
23272327
for (auto *I : StartDC->using_directives()) {
2328-
NamespaceDecl *ND = I->getNominatedNamespace()->getOriginalNamespace();
2328+
NamespaceDecl *ND = I->getNominatedNamespace()->getFirstDecl();
23292329
if (S.isVisible(I) && Visited.insert(ND).second)
23302330
Queue.push_back(ND);
23312331
}

clang/lib/Serialization/ASTReaderDecl.cpp

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1847,13 +1847,8 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
18471847
// same namespace, and we have an invariant that older declarations
18481848
// get merged before newer ones try to merge.
18491849
GlobalDeclID AnonNamespace;
1850-
if (Redecl.getFirstID() == ThisDeclID) {
1850+
if (Redecl.getFirstID() == ThisDeclID)
18511851
AnonNamespace = readDeclID();
1852-
} else {
1853-
// Link this namespace back to the first declaration, which has already
1854-
// been deserialized.
1855-
D->AnonOrFirstNamespaceAndFlags.setPointer(D->getFirstDecl());
1856-
}
18571852

18581853
mergeRedeclarable(D, Redecl);
18591854

@@ -2974,13 +2969,6 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing,
29742969
ExistingCanon->Used |= D->Used;
29752970
D->Used = false;
29762971

2977-
// When we merge a namespace, update its pointer to the first namespace.
2978-
// We cannot have loaded any redeclarations of this declaration yet, so
2979-
// there's nothing else that needs to be updated.
2980-
if (auto *Namespace = dyn_cast<NamespaceDecl>(D))
2981-
Namespace->AnonOrFirstNamespaceAndFlags.setPointer(
2982-
assert_cast<NamespaceDecl *>(ExistingCanon));
2983-
29842972
// When we merge a template, merge its pattern.
29852973
if (auto *DTemplate = dyn_cast<RedeclarableTemplateDecl>(D))
29862974
mergeTemplatePattern(
@@ -3293,7 +3281,7 @@ ASTDeclReader::getOrFakePrimaryClassDefinition(ASTReader &Reader,
32933281
DeclContext *ASTDeclReader::getPrimaryContextForMerging(ASTReader &Reader,
32943282
DeclContext *DC) {
32953283
if (auto *ND = dyn_cast<NamespaceDecl>(DC))
3296-
return ND->getOriginalNamespace();
3284+
return ND->getFirstDecl();
32973285

32983286
if (auto *RD = dyn_cast<CXXRecordDecl>(DC))
32993287
return getOrFakePrimaryClassDefinition(Reader, RD);

clang/lib/Serialization/ASTWriterDecl.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1383,7 +1383,7 @@ void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) {
13831383
Record.AddSourceLocation(D->getBeginLoc());
13841384
Record.AddSourceLocation(D->getRBraceLoc());
13851385

1386-
if (D->isOriginalNamespace())
1386+
if (D->isFirstDecl())
13871387
Record.AddDeclRef(D->getAnonymousNamespace());
13881388
Code = serialization::DECL_NAMESPACE;
13891389

clang/tools/libclang/CXIndexDataConsumer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -861,7 +861,7 @@ bool CXIndexDataConsumer::handleObjCProperty(const ObjCPropertyDecl *D) {
861861
}
862862

863863
bool CXIndexDataConsumer::handleNamespace(const NamespaceDecl *D) {
864-
DeclInfo DInfo(/*isRedeclaration=*/!D->isOriginalNamespace(),
864+
DeclInfo DInfo(/*isRedeclaration=*/!D->isFirstDecl(),
865865
/*isDefinition=*/true,
866866
/*isContainer=*/true);
867867
return handleDecl(D, D->getLocation(), getCursor(D), DInfo);

0 commit comments

Comments
 (0)