aaron.ballman updated this revision to Diff 367765. aaron.ballman added a comment.
Updating based on review comments. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D108403/new/ https://reviews.llvm.org/D108403 Files: clang/include/clang/AST/Decl.h clang/include/clang/AST/DeclBase.h clang/lib/AST/DeclBase.cpp clang/test/Misc/diag-inline-namespace.cpp Index: clang/test/Misc/diag-inline-namespace.cpp =================================================================== --- clang/test/Misc/diag-inline-namespace.cpp +++ clang/test/Misc/diag-inline-namespace.cpp @@ -48,3 +48,14 @@ 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 Index: clang/lib/AST/DeclBase.cpp =================================================================== --- clang/lib/AST/DeclBase.cpp +++ clang/lib/AST/DeclBase.cpp @@ -1217,6 +1217,13 @@ 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: Index: clang/include/clang/AST/DeclBase.h =================================================================== --- clang/include/clang/AST/DeclBase.h +++ clang/include/clang/AST/DeclBase.h @@ -1997,6 +1997,12 @@ 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 different /// declarations of the same entity (including forward declarations /// of classes, multiple definitions of namespaces, etc.), each with Index: clang/include/clang/AST/Decl.h =================================================================== --- clang/include/clang/AST/Decl.h +++ clang/include/clang/AST/Decl.h @@ -614,7 +614,9 @@ 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()); }
Index: clang/test/Misc/diag-inline-namespace.cpp =================================================================== --- clang/test/Misc/diag-inline-namespace.cpp +++ clang/test/Misc/diag-inline-namespace.cpp @@ -48,3 +48,14 @@ 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 Index: clang/lib/AST/DeclBase.cpp =================================================================== --- clang/lib/AST/DeclBase.cpp +++ clang/lib/AST/DeclBase.cpp @@ -1217,6 +1217,13 @@ 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: Index: clang/include/clang/AST/DeclBase.h =================================================================== --- clang/include/clang/AST/DeclBase.h +++ clang/include/clang/AST/DeclBase.h @@ -1997,6 +1997,12 @@ 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 different /// declarations of the same entity (including forward declarations /// of classes, multiple definitions of namespaces, etc.), each with Index: clang/include/clang/AST/Decl.h =================================================================== --- clang/include/clang/AST/Decl.h +++ clang/include/clang/AST/Decl.h @@ -614,7 +614,9 @@ 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()); }
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits