njames93 created this revision.
njames93 added a reviewer: rsmith.
Herald added subscribers: cfe-commits, martong.
Herald added a reviewer: shafik.
Herald added a project: clang.
njames93 requested review of this revision.
Adds support for NamespaceDecl to inform if its part of a nested namespace.
This flag only corresponds to the outer namespaces in a nested namespace
declaration.
In this example:
namespace <X>::<Y>::<Z> {}
Only <X> and <Y> will be classified as nested.
This flag isn't meant for assisting in building the AST, more for static
analysis and refactorings.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D90568
Files:
clang/include/clang/AST/Decl.h
clang/include/clang/Sema/Sema.h
clang/lib/AST/ASTContext.cpp
clang/lib/AST/ASTImporter.cpp
clang/lib/AST/DeclCXX.cpp
clang/lib/AST/TextNodeDumper.cpp
clang/lib/Parse/ParseDeclCXX.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/lib/Serialization/ASTReaderDecl.cpp
clang/lib/Serialization/ASTWriterDecl.cpp
clang/test/AST/ast-dump-decl.cpp
clang/unittests/Sema/ExternalSemaSourceTest.cpp
Index: clang/unittests/Sema/ExternalSemaSourceTest.cpp
===================================================================
--- clang/unittests/Sema/ExternalSemaSourceTest.cpp
+++ clang/unittests/Sema/ExternalSemaSourceTest.cpp
@@ -121,7 +121,7 @@
CurrentSema->getPreprocessor().getIdentifierInfo(CorrectTo);
NamespaceDecl *NewNamespace =
NamespaceDecl::Create(Context, DestContext, false, Typo.getBeginLoc(),
- Typo.getLoc(), ToIdent, nullptr);
+ Typo.getLoc(), ToIdent, nullptr, false);
DestContext->addDecl(NewNamespace);
TypoCorrection Correction(ToIdent);
Correction.addCorrectionDecl(NewNamespace);
Index: clang/test/AST/ast-dump-decl.cpp
===================================================================
--- clang/test/AST/ast-dump-decl.cpp
+++ clang/test/AST/ast-dump-decl.cpp
@@ -53,6 +53,23 @@
}
// CHECK: NamespaceDecl{{.*}} TestNamespaceDeclInline inline
+namespace TestNestedNameSpace::Nested {
+}
+// CHECK: NamespaceDecl{{.*}} TestNestedNameSpace nested
+// CHECK: NamespaceDecl{{.*}} Nested{{\s*$}}
+
+namespace TestMultipleNested::SecondLevelNested::Nested {
+}
+// CHECK: NamespaceDecl{{.*}} TestMultipleNested nested
+// CHECK: NamespaceDecl{{.*}} SecondLevelNested nested
+// CHECK: NamespaceDecl{{.*}} Nested{{\s*$}}
+
+namespace TestInlineNested::inline SecondLevel::inline Nested{
+}
+// CHECK: NamespaceDecl{{.*}} TestInlineNested nested
+// CHECK: NamespaceDecl{{.*}} SecondLevel inline nested
+// CHECK: NamespaceDecl{{.*}} Nested inline{{\s*$}}
+
namespace testUsingDirectiveDecl {
namespace A {
}
Index: clang/lib/Serialization/ASTWriterDecl.cpp
===================================================================
--- clang/lib/Serialization/ASTWriterDecl.cpp
+++ clang/lib/Serialization/ASTWriterDecl.cpp
@@ -1234,6 +1234,7 @@
VisitRedeclarable(D);
VisitNamedDecl(D);
Record.push_back(D->isInline());
+ Record.push_back(D->isNested());
Record.AddSourceLocation(D->getBeginLoc());
Record.AddSourceLocation(D->getRBraceLoc());
Index: clang/lib/Serialization/ASTReaderDecl.cpp
===================================================================
--- clang/lib/Serialization/ASTReaderDecl.cpp
+++ clang/lib/Serialization/ASTReaderDecl.cpp
@@ -1594,6 +1594,7 @@
RedeclarableResult Redecl = VisitRedeclarable(D);
VisitNamedDecl(D);
D->setInline(Record.readInt());
+ D->setNested(Record.readInt());
D->LocStart = readSourceLocation();
D->RBraceLoc = readSourceLocation();
@@ -1607,7 +1608,7 @@
} else {
// Link this namespace back to the first declaration, which has already
// been deserialized.
- D->AnonOrFirstNamespaceAndInline.setPointer(D->getFirstDecl());
+ D->AnonOrFirstNamespaceAndFlags.setPointer(D->getFirstDecl());
}
mergeRedeclarable(D, Redecl);
@@ -2594,8 +2595,8 @@
// 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->AnonOrFirstNamespaceAndInline.setPointer(
- assert_cast<NamespaceDecl*>(ExistingCanon));
+ Namespace->AnonOrFirstNamespaceAndFlags.setPointer(
+ assert_cast<NamespaceDecl *>(ExistingCanon));
// When we merge a template, merge its pattern.
if (auto *DTemplate = dyn_cast<RedeclarableTemplateDecl>(D))
Index: clang/lib/Sema/SemaDeclCXX.cpp
===================================================================
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -10824,10 +10824,13 @@
/// ActOnStartNamespaceDef - This is called at the start of a namespace
/// definition.
-Decl *Sema::ActOnStartNamespaceDef(
- Scope *NamespcScope, SourceLocation InlineLoc, SourceLocation NamespaceLoc,
- SourceLocation IdentLoc, IdentifierInfo *II, SourceLocation LBrace,
- const ParsedAttributesView &AttrList, UsingDirectiveDecl *&UD) {
+Decl *Sema::ActOnStartNamespaceDef(Scope *NamespcScope,
+ SourceLocation InlineLoc,
+ SourceLocation NamespaceLoc,
+ SourceLocation IdentLoc, IdentifierInfo *II,
+ SourceLocation LBrace,
+ const ParsedAttributesView &AttrList,
+ UsingDirectiveDecl *&UD, bool IsNested) {
SourceLocation StartLoc = InlineLoc.isValid() ? InlineLoc : NamespaceLoc;
// For anonymous namespace, take the location of the left brace.
SourceLocation Loc = II ? IdentLoc : LBrace;
@@ -10897,8 +10900,8 @@
&IsInline, PrevNS);
}
- NamespaceDecl *Namespc = NamespaceDecl::Create(Context, CurContext, IsInline,
- StartLoc, Loc, II, PrevNS);
+ NamespaceDecl *Namespc = NamespaceDecl::Create(
+ Context, CurContext, IsInline, StartLoc, Loc, II, PrevNS, IsNested);
if (IsInvalid)
Namespc->setInvalidDecl();
@@ -11159,12 +11162,11 @@
NamespaceDecl *Sema::getOrCreateStdNamespace() {
if (!StdNamespace) {
// The "std" namespace has not yet been defined, so build one implicitly.
- StdNamespace = NamespaceDecl::Create(Context,
- Context.getTranslationUnitDecl(),
- /*Inline=*/false,
- SourceLocation(), SourceLocation(),
- &PP.getIdentifierTable().get("std"),
- /*PrevDecl=*/nullptr);
+ StdNamespace = NamespaceDecl::Create(
+ Context, Context.getTranslationUnitDecl(),
+ /*Inline=*/false, SourceLocation(), SourceLocation(),
+ &PP.getIdentifierTable().get("std"),
+ /*PrevDecl=*/nullptr, false);
getStdNamespace()->setImplicit(true);
}
Index: clang/lib/Parse/ParseDeclCXX.cpp
===================================================================
--- clang/lib/Parse/ParseDeclCXX.cpp
+++ clang/lib/Parse/ParseDeclCXX.cpp
@@ -214,7 +214,8 @@
UsingDirectiveDecl *ImplicitUsingDirectiveDecl = nullptr;
Decl *NamespcDecl = Actions.ActOnStartNamespaceDef(
getCurScope(), InlineLoc, NamespaceLoc, IdentLoc, Ident,
- T.getOpenLocation(), attrs, ImplicitUsingDirectiveDecl);
+ T.getOpenLocation(), attrs, ImplicitUsingDirectiveDecl,
+ !ExtraNSs.empty());
PrettyDeclStackTraceEntry CrashInfo(Actions.Context, NamespcDecl,
NamespaceLoc, "parsing namespace");
@@ -261,7 +262,8 @@
Decl *NamespcDecl = Actions.ActOnStartNamespaceDef(
getCurScope(), InnerNSs[index].InlineLoc, InnerNSs[index].NamespaceLoc,
InnerNSs[index].IdentLoc, InnerNSs[index].Ident,
- Tracker.getOpenLocation(), attrs, ImplicitUsingDirectiveDecl);
+ Tracker.getOpenLocation(), attrs, ImplicitUsingDirectiveDecl,
+ index < InnerNSs.size() - 1);
assert(!ImplicitUsingDirectiveDecl &&
"nested namespace definition cannot define anonymous namespace");
Index: clang/lib/AST/TextNodeDumper.cpp
===================================================================
--- clang/lib/AST/TextNodeDumper.cpp
+++ clang/lib/AST/TextNodeDumper.cpp
@@ -1824,6 +1824,8 @@
dumpName(D);
if (D->isInline())
OS << " inline";
+ if (D->isNested())
+ OS << " nested";
if (!D->isOriginalNamespace())
dumpDeclRef(D->getOriginalNamespace(), "original");
}
Index: clang/lib/AST/DeclCXX.cpp
===================================================================
--- clang/lib/AST/DeclCXX.cpp
+++ clang/lib/AST/DeclCXX.cpp
@@ -2844,41 +2844,43 @@
NamespaceDecl::NamespaceDecl(ASTContext &C, DeclContext *DC, bool Inline,
SourceLocation StartLoc, SourceLocation IdLoc,
- IdentifierInfo *Id, NamespaceDecl *PrevDecl)
+ IdentifierInfo *Id, NamespaceDecl *PrevDecl,
+ bool Nested)
: NamedDecl(Namespace, DC, IdLoc, Id), DeclContext(Namespace),
redeclarable_base(C), LocStart(StartLoc),
- AnonOrFirstNamespaceAndInline(nullptr, Inline) {
+ AnonOrFirstNamespaceAndFlags(nullptr,
+ F_Inline * Inline | F_Nested * Nested) {
setPreviousDecl(PrevDecl);
if (PrevDecl)
- AnonOrFirstNamespaceAndInline.setPointer(PrevDecl->getOriginalNamespace());
+ AnonOrFirstNamespaceAndFlags.setPointer(PrevDecl->getOriginalNamespace());
}
NamespaceDecl *NamespaceDecl::Create(ASTContext &C, DeclContext *DC,
bool Inline, SourceLocation StartLoc,
SourceLocation IdLoc, IdentifierInfo *Id,
- NamespaceDecl *PrevDecl) {
- return new (C, DC) NamespaceDecl(C, DC, Inline, StartLoc, IdLoc, Id,
- PrevDecl);
+ NamespaceDecl *PrevDecl, bool Nested) {
+ return new (C, DC)
+ NamespaceDecl(C, DC, Inline, StartLoc, IdLoc, Id, PrevDecl, Nested);
}
NamespaceDecl *NamespaceDecl::CreateDeserialized(ASTContext &C, unsigned ID) {
return new (C, ID) NamespaceDecl(C, nullptr, false, SourceLocation(),
- SourceLocation(), nullptr, nullptr);
+ SourceLocation(), nullptr, nullptr, false);
}
NamespaceDecl *NamespaceDecl::getOriginalNamespace() {
if (isFirstDecl())
return this;
- return AnonOrFirstNamespaceAndInline.getPointer();
+ return AnonOrFirstNamespaceAndFlags.getPointer();
}
const NamespaceDecl *NamespaceDecl::getOriginalNamespace() const {
if (isFirstDecl())
return this;
- return AnonOrFirstNamespaceAndInline.getPointer();
+ return AnonOrFirstNamespaceAndFlags.getPointer();
}
bool NamespaceDecl::isOriginalNamespace() const { return isFirstDecl(); }
Index: clang/lib/AST/ASTImporter.cpp
===================================================================
--- clang/lib/AST/ASTImporter.cpp
+++ clang/lib/AST/ASTImporter.cpp
@@ -2346,10 +2346,10 @@
// Create the "to" namespace, if needed.
NamespaceDecl *ToNamespace = MergeWithNamespace;
if (!ToNamespace) {
- if (GetImportedOrCreateDecl(
- ToNamespace, D, Importer.getToContext(), DC, D->isInline(),
- *BeginLocOrErr, Loc, Name.getAsIdentifierInfo(),
- /*PrevDecl=*/nullptr))
+ if (GetImportedOrCreateDecl(ToNamespace, D, Importer.getToContext(), DC,
+ D->isInline(), *BeginLocOrErr, Loc,
+ Name.getAsIdentifierInfo(),
+ /*PrevDecl=*/nullptr, D->isNested()))
return ToNamespace;
ToNamespace->setRBraceLoc(*RBraceLocOrErr);
ToNamespace->setLexicalDeclContext(LexicalDC);
Index: clang/lib/AST/ASTContext.cpp
===================================================================
--- clang/lib/AST/ASTContext.cpp
+++ clang/lib/AST/ASTContext.cpp
@@ -7863,7 +7863,7 @@
Context->getTranslationUnitDecl(),
/*Inline*/ false, SourceLocation(),
SourceLocation(), &Context->Idents.get("std"),
- /*PrevDecl*/ nullptr);
+ /*PrevDecl*/ nullptr, false);
NS->setImplicit();
VaListTagDecl->setDeclContext(NS);
}
@@ -8050,9 +8050,9 @@
NamespaceDecl *NS;
NS = NamespaceDecl::Create(const_cast<ASTContext &>(*Context),
Context->getTranslationUnitDecl(),
- /*Inline*/false, SourceLocation(),
+ /*Inline*/ false, SourceLocation(),
SourceLocation(), &Context->Idents.get("std"),
- /*PrevDecl*/ nullptr);
+ /*PrevDecl*/ nullptr, false);
NS->setImplicit();
VaListDecl->setDeclContext(NS);
}
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -5466,7 +5466,7 @@
SourceLocation IdentLoc, IdentifierInfo *Ident,
SourceLocation LBrace,
const ParsedAttributesView &AttrList,
- UsingDirectiveDecl *&UsingDecl);
+ UsingDirectiveDecl *&UsingDecl, bool IsNested);
void ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace);
NamespaceDecl *getStdNamespace() const;
Index: clang/include/clang/AST/Decl.h
===================================================================
--- clang/include/clang/AST/Decl.h
+++ clang/include/clang/AST/Decl.h
@@ -512,6 +512,9 @@
class NamespaceDecl : public NamedDecl, public DeclContext,
public Redeclarable<NamespaceDecl>
{
+
+ enum Flags : unsigned { F_Inline = 1 << 0, F_Nested = 1 << 1 };
+
/// The starting location of the source range, pointing
/// to either the namespace or the inline keyword.
SourceLocation LocStart;
@@ -523,11 +526,12 @@
/// 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 *, 1, bool> AnonOrFirstNamespaceAndInline;
+ llvm::PointerIntPair<NamespaceDecl *, 2, unsigned>
+ AnonOrFirstNamespaceAndFlags;
NamespaceDecl(ASTContext &C, DeclContext *DC, bool Inline,
SourceLocation StartLoc, SourceLocation IdLoc,
- IdentifierInfo *Id, NamespaceDecl *PrevDecl);
+ IdentifierInfo *Id, NamespaceDecl *PrevDecl, bool Nested);
using redeclarable_base = Redeclarable<NamespaceDecl>;
@@ -539,10 +543,10 @@
friend class ASTDeclReader;
friend class ASTDeclWriter;
- static NamespaceDecl *Create(ASTContext &C, DeclContext *DC,
- bool Inline, SourceLocation StartLoc,
- SourceLocation IdLoc, IdentifierInfo *Id,
- NamespaceDecl *PrevDecl);
+ static NamespaceDecl *Create(ASTContext &C, DeclContext *DC, bool Inline,
+ SourceLocation StartLoc, SourceLocation IdLoc,
+ IdentifierInfo *Id, NamespaceDecl *PrevDecl,
+ bool Nested);
static NamespaceDecl *CreateDeserialized(ASTContext &C, unsigned ID);
@@ -571,12 +575,28 @@
/// Returns true if this is an inline namespace declaration.
bool isInline() const {
- return AnonOrFirstNamespaceAndInline.getInt();
+ return AnonOrFirstNamespaceAndFlags.getInt() & F_Inline;
}
/// Set whether this is an inline namespace declaration.
void setInline(bool Inline) {
- AnonOrFirstNamespaceAndInline.setInt(Inline);
+ unsigned F = AnonOrFirstNamespaceAndFlags.getInt();
+ if (Inline)
+ AnonOrFirstNamespaceAndFlags.setInt(F | F_Inline);
+ else
+ AnonOrFirstNamespaceAndFlags.setInt(F & ~F_Inline);
+ }
+
+ bool isNested() const {
+ return AnonOrFirstNamespaceAndFlags.getInt() & F_Nested;
+ }
+
+ void setNested(bool Nested) {
+ unsigned F = AnonOrFirstNamespaceAndFlags.getInt();
+ if (Nested)
+ AnonOrFirstNamespaceAndFlags.setInt(F | F_Nested);
+ else
+ AnonOrFirstNamespaceAndFlags.setInt(F & ~F_Nested);
}
/// Get the original (first) namespace declaration.
@@ -593,11 +613,11 @@
/// Retrieve the anonymous namespace nested inside this namespace,
/// if any.
NamespaceDecl *getAnonymousNamespace() const {
- return getOriginalNamespace()->AnonOrFirstNamespaceAndInline.getPointer();
+ return getOriginalNamespace()->AnonOrFirstNamespaceAndFlags.getPointer();
}
void setAnonymousNamespace(NamespaceDecl *D) {
- getOriginalNamespace()->AnonOrFirstNamespaceAndInline.setPointer(D);
+ getOriginalNamespace()->AnonOrFirstNamespaceAndFlags.setPointer(D);
}
/// Retrieves the canonical declaration of this namespace.
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits