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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits