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

Reply via email to