From 9dc238026d06a3cc7ec502a0166f7773bf8b7ea4 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Wed, 19 Oct 2016 23:47:37 +0000 Subject: [PATCH] Extend hack to work around bad exception specifications for 'swap' members to also cover libstdc++'s std::__debug::array and std::__profile::array. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@284669 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaExceptionSpec.cpp | 29 ++++++++++++++++------- test/SemaCXX/libstdcxx_pair_swap_hack.cpp | 18 ++++++++++++-- 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/lib/Sema/SemaExceptionSpec.cpp b/lib/Sema/SemaExceptionSpec.cpp index a81ef51795..74c5b420c5 100644 --- a/lib/Sema/SemaExceptionSpec.cpp +++ b/lib/Sema/SemaExceptionSpec.cpp @@ -43,23 +43,36 @@ bool Sema::isLibstdcxxEagerExceptionSpecHack(const Declarator &D) { auto *RD = dyn_cast(CurContext); // All the problem cases are member functions named "swap" within class - // templates declared directly within namespace std. - if (!RD || !getStdNamespace() || - !RD->getEnclosingNamespaceContext()->Equals(getStdNamespace()) || - !RD->getIdentifier() || !RD->getDescribedClassTemplate() || + // templates declared directly within namespace std or std::__debug or + // std::__profile. + if (!RD || !RD->getIdentifier() || !RD->getDescribedClassTemplate() || !D.getIdentifier() || !D.getIdentifier()->isStr("swap")) return false; + auto *ND = dyn_cast(RD->getDeclContext()); + if (!ND) + return false; + + bool IsInStd = ND->isStdNamespace(); + if (!IsInStd) { + // This isn't a direct member of namespace std, but it might still be + // libstdc++'s std::__debug::array or std::__profile::array. + IdentifierInfo *II = ND->getIdentifier(); + if (!II || !(II->isStr("__debug") || II->isStr("__profile")) || + !ND->isInStdNamespace()) + return false; + } + // Only apply this hack within a system header. if (!Context.getSourceManager().isInSystemHeader(D.getLocStart())) return false; return llvm::StringSwitch(RD->getIdentifier()->getName()) .Case("array", true) - .Case("pair", true) - .Case("priority_queue", true) - .Case("stack", true) - .Case("queue", true) + .Case("pair", IsInStd) + .Case("priority_queue", IsInStd) + .Case("stack", IsInStd) + .Case("queue", IsInStd) .Default(false); } diff --git a/test/SemaCXX/libstdcxx_pair_swap_hack.cpp b/test/SemaCXX/libstdcxx_pair_swap_hack.cpp index 1a92bf9855..9f9c71a50c 100644 --- a/test/SemaCXX/libstdcxx_pair_swap_hack.cpp +++ b/test/SemaCXX/libstdcxx_pair_swap_hack.cpp @@ -13,6 +13,9 @@ // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=priority_queue // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=stack // RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=queue +// +// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array -DNAMESPACE=__debug +// RUN: %clang_cc1 -fsyntax-only %s -std=c++11 -verify -fexceptions -fcxx-exceptions -DCLASS=array -DNAMESPACE=__profile // MSVC's standard library uses a very similar pattern that relies on delayed // parsing of exception specifications. @@ -32,6 +35,13 @@ namespace std { swap(a, b); } +#ifdef NAMESPACE + namespace NAMESPACE { +#define STD_CLASS std::NAMESPACE::CLASS +#else +#define STD_CLASS std::CLASS +#endif + template struct CLASS { #ifdef MSVC void swap(CLASS &other) noexcept(noexcept(do_swap(member, other.member))); @@ -47,6 +57,10 @@ namespace std { // void swap(vector &other) noexcept(noexcept(do_swap(member, other.member))); // A member; // }; + +#ifdef NAMESPACE + } +#endif } #else @@ -55,8 +69,8 @@ namespace std { #include __FILE__ struct X {}; -using PX = std::CLASS; -using PI = std::CLASS; +using PX = STD_CLASS; +using PI = STD_CLASS; void swap(X &, X &) noexcept; PX px; PI pi; -- 2.40.0