Skip to content

[Clang][AST] Move NamespaceDecl bits to DeclContext #98567

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ static bool haveSameNamespaceOrTranslationUnit(const CXXRecordDecl *Decl1,
"ParentDecl2 declaration must be a namespace");
auto *Ns1 = NamespaceDecl::castFromDeclContext(ParentDecl1);
auto *Ns2 = NamespaceDecl::castFromDeclContext(ParentDecl2);
return Ns1->getOriginalNamespace() == Ns2->getOriginalNamespace();
return Ns1->getFirstDecl() == Ns2->getFirstDecl();
}

static std::string getNameOfNamespace(const CXXRecordDecl *Decl) {
Expand Down
67 changes: 14 additions & 53 deletions clang/include/clang/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -542,25 +542,18 @@ class LabelDecl : public NamedDecl {
};

/// Represent a C++ namespace.
class NamespaceDecl : public NamedDecl, public DeclContext,
public Redeclarable<NamespaceDecl>
{

enum Flags : unsigned { F_Inline = 1 << 0, F_Nested = 1 << 1 };

class NamespaceDecl : public NamedDecl,
public DeclContext,
public Redeclarable<NamespaceDecl> {
/// The starting location of the source range, pointing
/// to either the namespace or the inline keyword.
SourceLocation LocStart;

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

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

NamespaceDecl(ASTContext &C, DeclContext *DC, bool Inline,
SourceLocation StartLoc, SourceLocation IdLoc,
Expand Down Expand Up @@ -607,35 +600,19 @@ class NamespaceDecl : public NamedDecl, public DeclContext,
}

/// Returns true if this is an inline namespace declaration.
bool isInline() const {
return AnonOrFirstNamespaceAndFlags.getInt() & F_Inline;
}
bool isInline() const { return NamespaceDeclBits.IsInline; }

/// Set whether this is an inline namespace declaration.
void setInline(bool Inline) {
unsigned F = AnonOrFirstNamespaceAndFlags.getInt();
if (Inline)
AnonOrFirstNamespaceAndFlags.setInt(F | F_Inline);
else
AnonOrFirstNamespaceAndFlags.setInt(F & ~F_Inline);
}
void setInline(bool Inline) { NamespaceDeclBits.IsInline = Inline; }

/// Returns true if this is a nested namespace declaration.
/// \code
/// namespace outer::nested { }
/// \endcode
bool isNested() const {
return AnonOrFirstNamespaceAndFlags.getInt() & F_Nested;
}
bool isNested() const { return NamespaceDeclBits.IsNested; }

/// Set whether this is a nested namespace declaration.
void setNested(bool Nested) {
unsigned F = AnonOrFirstNamespaceAndFlags.getInt();
if (Nested)
AnonOrFirstNamespaceAndFlags.setInt(F | F_Nested);
else
AnonOrFirstNamespaceAndFlags.setInt(F & ~F_Nested);
}
void setNested(bool Nested) { NamespaceDeclBits.IsNested = Nested; }

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

/// Get the original (first) namespace declaration.
NamespaceDecl *getOriginalNamespace();

/// Get the original (first) namespace declaration.
const NamespaceDecl *getOriginalNamespace() const;

/// Return true if this declaration is an original (first) declaration
/// of the namespace. This is false for non-original (subsequent) namespace
/// declarations and anonymous namespaces.
bool isOriginalNamespace() const;

/// Retrieve the anonymous namespace nested inside this namespace,
/// if any.
/// Retrieve the anonymous namespace that inhabits this namespace, if any.
NamespaceDecl *getAnonymousNamespace() const {
return getOriginalNamespace()->AnonOrFirstNamespaceAndFlags.getPointer();
return getFirstDecl()->AnonymousNamespace;
}

void setAnonymousNamespace(NamespaceDecl *D) {
getOriginalNamespace()->AnonOrFirstNamespaceAndFlags.setPointer(D);
getFirstDecl()->AnonymousNamespace = D;
}

/// Retrieves the canonical declaration of this namespace.
NamespaceDecl *getCanonicalDecl() override {
return getOriginalNamespace();
}
const NamespaceDecl *getCanonicalDecl() const {
return getOriginalNamespace();
}
NamespaceDecl *getCanonicalDecl() override { return getFirstDecl(); }
const NamespaceDecl *getCanonicalDecl() const { return getFirstDecl(); }

SourceRange getSourceRange() const override LLVM_READONLY {
return SourceRange(LocStart, RBraceLoc);
Expand Down
24 changes: 24 additions & 0 deletions clang/include/clang/AST/DeclBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -1484,6 +1484,27 @@ class DeclContext {
/// Number of bits in DeclContextBitfields.
enum { NumDeclContextBits = 13 };

/// Stores the bits used by NamespaceDecl.
/// If modified NumNamespaceDeclBits and the accessor
/// methods in NamespaceDecl should be updated appropriately.
class NamespaceDeclBitfields {
friend class NamespaceDecl;
/// For the bits in DeclContextBitfields
LLVM_PREFERRED_TYPE(DeclContextBitfields)
uint64_t : NumDeclContextBits;

/// True if this is an inline namespace.
LLVM_PREFERRED_TYPE(bool)
uint64_t IsInline : 1;

/// True if this is a nested-namespace-definition.
LLVM_PREFERRED_TYPE(bool)
uint64_t IsNested : 1;
};

/// Number of inherited and non-inherited bits in NamespaceDeclBitfields.
enum { NumNamespaceDeclBits = NumDeclContextBits + 2 };

/// Stores the bits used by TagDecl.
/// If modified NumTagDeclBits and the accessor
/// methods in TagDecl should be updated appropriately.
Expand Down Expand Up @@ -1982,6 +2003,7 @@ class DeclContext {
/// 8 bytes with static_asserts in the ctor of DeclContext.
union {
DeclContextBitfields DeclContextBits;
NamespaceDeclBitfields NamespaceDeclBits;
TagDeclBitfields TagDeclBits;
EnumDeclBitfields EnumDeclBits;
RecordDeclBitfields RecordDeclBits;
Expand All @@ -1995,6 +2017,8 @@ class DeclContext {

static_assert(sizeof(DeclContextBitfields) <= 8,
"DeclContextBitfields is larger than 8 bytes!");
static_assert(sizeof(NamespaceDeclBitfields) <= 8,
"NamespaceDeclBitfields is larger than 8 bytes!");
static_assert(sizeof(TagDeclBitfields) <= 8,
"TagDeclBitfields is larger than 8 bytes!");
static_assert(sizeof(EnumDeclBitfields) <= 8,
Expand Down
8 changes: 4 additions & 4 deletions clang/lib/AST/ASTContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7250,14 +7250,14 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const {
// A namespace is canonical; build a nested-name-specifier with
// this namespace and no prefix.
return NestedNameSpecifier::Create(*this, nullptr,
NNS->getAsNamespace()->getOriginalNamespace());
NNS->getAsNamespace()->getFirstDecl());

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

// The difference between TypeSpec and TypeSpecWithTemplate is that the
// latter will have the 'template' keyword when printed.
Expand Down
3 changes: 1 addition & 2 deletions clang/lib/AST/DeclBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1418,8 +1418,7 @@ DeclContext *DeclContext::getPrimaryContext() {
case Decl::TranslationUnit:
return static_cast<TranslationUnitDecl *>(this)->getFirstDecl();
case Decl::Namespace:
// The original namespace is our primary context.
return static_cast<NamespaceDecl *>(this)->getOriginalNamespace();
return static_cast<NamespaceDecl *>(this)->getFirstDecl();

case Decl::ObjCMethod:
return this;
Expand Down
31 changes: 4 additions & 27 deletions clang/lib/AST/DeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2941,7 +2941,7 @@ UsingDirectiveDecl *UsingDirectiveDecl::Create(ASTContext &C, DeclContext *DC,
NamedDecl *Used,
DeclContext *CommonAncestor) {
if (auto *NS = dyn_cast_or_null<NamespaceDecl>(Used))
Used = NS->getOriginalNamespace();
Used = NS->getFirstDecl();
return new (C, DC) UsingDirectiveDecl(DC, L, NamespaceLoc, QualifierLoc,
IdentLoc, Used, CommonAncestor);
}
Expand All @@ -2966,16 +2966,9 @@ NamespaceDecl::NamespaceDecl(ASTContext &C, DeclContext *DC, bool Inline,
bool Nested)
: NamedDecl(Namespace, DC, IdLoc, Id), DeclContext(Namespace),
redeclarable_base(C), LocStart(StartLoc) {
unsigned Flags = 0;
if (Inline)
Flags |= F_Inline;
if (Nested)
Flags |= F_Nested;
AnonOrFirstNamespaceAndFlags = {nullptr, Flags};
setInline(Inline);
setNested(Nested);
setPreviousDecl(PrevDecl);

if (PrevDecl)
AnonOrFirstNamespaceAndFlags.setPointer(PrevDecl->getOriginalNamespace());
}

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

NamespaceDecl *NamespaceDecl::getOriginalNamespace() {
if (isFirstDecl())
return this;

return AnonOrFirstNamespaceAndFlags.getPointer();
}

const NamespaceDecl *NamespaceDecl::getOriginalNamespace() const {
if (isFirstDecl())
return this;

return AnonOrFirstNamespaceAndFlags.getPointer();
}

bool NamespaceDecl::isOriginalNamespace() const { return isFirstDecl(); }

NamespaceDecl *NamespaceDecl::getNextRedeclarationImpl() {
return getNextRedeclaration();
}
Expand Down Expand Up @@ -3043,7 +3020,7 @@ NamespaceAliasDecl *NamespaceAliasDecl::Create(ASTContext &C, DeclContext *DC,
NamedDecl *Namespace) {
// FIXME: Preserve the aliased namespace as written.
if (auto *NS = dyn_cast_or_null<NamespaceDecl>(Namespace))
Namespace = NS->getOriginalNamespace();
Namespace = NS->getFirstDecl();
return new (C, DC) NamespaceAliasDecl(C, DC, UsingLoc, AliasLoc, Alias,
QualifierLoc, IdentLoc, Namespace);
}
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -960,7 +960,7 @@ bool CXXNameMangler::isStd(const NamespaceDecl *NS) {
if (!Context.getEffectiveParentContext(NS)->isTranslationUnit())
return false;

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

Expand Down
5 changes: 2 additions & 3 deletions clang/lib/AST/JSONNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -883,9 +883,8 @@ void JSONNodeDumper::VisitNamespaceDecl(const NamespaceDecl *ND) {
VisitNamedDecl(ND);
attributeOnlyIfTrue("isInline", ND->isInline());
attributeOnlyIfTrue("isNested", ND->isNested());
if (!ND->isOriginalNamespace())
JOS.attribute("originalNamespace",
createBareDeclRef(ND->getOriginalNamespace()));
if (!ND->isFirstDecl())
JOS.attribute("originalNamespace", createBareDeclRef(ND->getFirstDecl()));
}

void JSONNodeDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *UDD) {
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/TextNodeDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2386,8 +2386,8 @@ void TextNodeDumper::VisitNamespaceDecl(const NamespaceDecl *D) {
OS << " inline";
if (D->isNested())
OS << " nested";
if (!D->isOriginalNamespace())
dumpDeclRef(D->getOriginalNamespace(), "original");
if (!D->isFirstDecl())
dumpDeclRef(D->getFirstDecl(), "original");
}

void TextNodeDumper::VisitUsingDirectiveDecl(const UsingDirectiveDecl *D) {
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaCodeComplete.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6864,7 +6864,7 @@ void SemaCodeCompletion::CodeCompleteNamespaceDecl(Scope *S) {
NS(Ctx->decls_begin()),
NSEnd(Ctx->decls_end());
NS != NSEnd; ++NS)
OrigToLatest[NS->getOriginalNamespace()] = *NS;
OrigToLatest[NS->getFirstDecl()] = *NS;

// Add the most recent definition (or extended definition) of each
// namespace to the list of results.
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Sema/SemaLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2325,7 +2325,7 @@ static bool LookupQualifiedNameInUsingDirectives(Sema &S, LookupResult &R,
// We have already looked into the initial namespace; seed the queue
// with its using-children.
for (auto *I : StartDC->using_directives()) {
NamespaceDecl *ND = I->getNominatedNamespace()->getOriginalNamespace();
NamespaceDecl *ND = I->getNominatedNamespace()->getFirstDecl();
if (S.isVisible(I) && Visited.insert(ND).second)
Queue.push_back(ND);
}
Expand Down
16 changes: 2 additions & 14 deletions clang/lib/Serialization/ASTReaderDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1847,13 +1847,8 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) {
// same namespace, and we have an invariant that older declarations
// get merged before newer ones try to merge.
GlobalDeclID AnonNamespace;
if (Redecl.getFirstID() == ThisDeclID) {
if (Redecl.getFirstID() == ThisDeclID)
AnonNamespace = readDeclID();
} else {
// Link this namespace back to the first declaration, which has already
// been deserialized.
D->AnonOrFirstNamespaceAndFlags.setPointer(D->getFirstDecl());
}

mergeRedeclarable(D, Redecl);

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

// When we merge a namespace, update its pointer to the first namespace.
// We cannot have loaded any redeclarations of this declaration yet, so
// there's nothing else that needs to be updated.
if (auto *Namespace = dyn_cast<NamespaceDecl>(D))
Namespace->AnonOrFirstNamespaceAndFlags.setPointer(
assert_cast<NamespaceDecl *>(ExistingCanon));

// When we merge a template, merge its pattern.
if (auto *DTemplate = dyn_cast<RedeclarableTemplateDecl>(D))
mergeTemplatePattern(
Expand Down Expand Up @@ -3293,7 +3281,7 @@ ASTDeclReader::getOrFakePrimaryClassDefinition(ASTReader &Reader,
DeclContext *ASTDeclReader::getPrimaryContextForMerging(ASTReader &Reader,
DeclContext *DC) {
if (auto *ND = dyn_cast<NamespaceDecl>(DC))
return ND->getOriginalNamespace();
return ND->getFirstDecl();

if (auto *RD = dyn_cast<CXXRecordDecl>(DC))
return getOrFakePrimaryClassDefinition(Reader, RD);
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Serialization/ASTWriterDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1383,7 +1383,7 @@ void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) {
Record.AddSourceLocation(D->getBeginLoc());
Record.AddSourceLocation(D->getRBraceLoc());

if (D->isOriginalNamespace())
if (D->isFirstDecl())
Record.AddDeclRef(D->getAnonymousNamespace());
Code = serialization::DECL_NAMESPACE;

Expand Down
2 changes: 1 addition & 1 deletion clang/tools/libclang/CXIndexDataConsumer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,7 @@ bool CXIndexDataConsumer::handleObjCProperty(const ObjCPropertyDecl *D) {
}

bool CXIndexDataConsumer::handleNamespace(const NamespaceDecl *D) {
DeclInfo DInfo(/*isRedeclaration=*/!D->isOriginalNamespace(),
DeclInfo DInfo(/*isRedeclaration=*/!D->isFirstDecl(),
/*isDefinition=*/true,
/*isContainer=*/true);
return handleDecl(D, D->getLocation(), getCursor(D), DInfo);
Expand Down
Loading