[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