[clang] 48f73ee - Fix assertion when generating diagnostic for inline namespaces
Aaron Ballman via cfe-commits
cfe-commits at lists.llvm.org
Fri Aug 20 06:50:56 PDT 2021
Author: Aaron Ballman
Date: 2021-08-20T09:50:24-04:00
New Revision: 48f73ee666a264d23716ff6bb671cad836b65ccf
URL: https://github.com/llvm/llvm-project/commit/48f73ee666a264d23716ff6bb671cad836b65ccf
DIFF: https://github.com/llvm/llvm-project/commit/48f73ee666a264d23716ff6bb671cad836b65ccf.diff
LOG: Fix assertion when generating diagnostic for inline namespaces
When calculating the name to display for inline namespaces, we have
custom logic to try to hide redundant inline namespaces from the
diagnostic. Calculating these redundancies requires performing a lookup
in the parent declaration context, but that lookup should not try to
look through transparent declaration contexts, like linkage
specifications. Instead, loop up the declaration context chain until we
find a non-transparent context and use that instead.
This fixes PR49954.
Added:
Modified:
clang/include/clang/AST/Decl.h
clang/include/clang/AST/DeclBase.h
clang/lib/AST/DeclBase.cpp
clang/test/Misc/diag-inline-namespace.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h
index 30923a4fa05c..d124ed282bb1 100644
--- a/clang/include/clang/AST/Decl.h
+++ b/clang/include/clang/AST/Decl.h
@@ -614,7 +614,9 @@ class NamespaceDecl : public NamedDecl, public DeclContext,
if (!isInline())
return false;
auto X = lookup(Name);
- auto Y = getParent()->lookup(Name);
+ // We should not perform a lookup within a transparent context, so find a
+ // non-transparent parent context.
+ auto Y = getParent()->getNonTransparentContext()->lookup(Name);
return std::distance(X.begin(), X.end()) ==
std::distance(Y.begin(), Y.end());
}
diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h
index 482d2889a25a..18468c8ca1c4 100644
--- a/clang/include/clang/AST/DeclBase.h
+++ b/clang/include/clang/AST/DeclBase.h
@@ -1997,6 +1997,12 @@ class DeclContext {
return const_cast<DeclContext*>(this)->getNonClosureAncestor();
}
+ // Retrieve the nearest context that is not a transparent context.
+ DeclContext *getNonTransparentContext();
+ const DeclContext *getNonTransparentContext() const {
+ return const_cast<DeclContext *>(this)->getNonTransparentContext();
+ }
+
/// getPrimaryContext - There may be many
diff erent
/// declarations of the same entity (including forward declarations
/// of classes, multiple definitions of namespaces, etc.), each with
diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp
index 3467da2b549e..53dd2ae3cbd3 100644
--- a/clang/lib/AST/DeclBase.cpp
+++ b/clang/lib/AST/DeclBase.cpp
@@ -1217,6 +1217,13 @@ bool DeclContext::Encloses(const DeclContext *DC) const {
return false;
}
+DeclContext *DeclContext::getNonTransparentContext() {
+ DeclContext *DC = this;
+ while (DC && DC->isTransparentContext())
+ DC = DC->getParent();
+ return DC;
+}
+
DeclContext *DeclContext::getPrimaryContext() {
switch (getDeclKind()) {
case Decl::ExternCContext:
diff --git a/clang/test/Misc/diag-inline-namespace.cpp b/clang/test/Misc/diag-inline-namespace.cpp
index 74bdeed68d21..34d549bc1cc0 100644
--- a/clang/test/Misc/diag-inline-namespace.cpp
+++ b/clang/test/Misc/diag-inline-namespace.cpp
@@ -48,3 +48,14 @@ namespace N {
T<struct A::B::C::i> t4; // expected-error {{implicit instantiation of undefined template 'N::T<N::A::i>'}}
T<struct A::B::C::j> t5; // expected-error {{implicit instantiation of undefined template 'N::T<N::B::C::j>'}}
}
+
+namespace dont_crash {
+// A malformed lookup involving inline namespaces in a linkage specification
+// would previous cause an assertion due to the way diagnostics are emitted.
+extern "C++" inline namespace {
+namespace a {
+ a : b // expected-error {{unexpected ':' in nested name specifier; did you mean '::'?}} \
+ // expected-error {{no type named 'b' in namespace 'dont_crash::a'}}
+} // expected-error {{expected unqualified-id}}
+} // inline namespace
+} // dont_crash
More information about the cfe-commits
mailing list