forked from OSchip/llvm-project
Extend hack to work around bad exception specifications for 'swap' members to
also cover libstdc++'s std::__debug::array and std::__profile::array. llvm-svn: 284669
This commit is contained in:
parent
210030ba95
commit
628954652f
|
@ -43,23 +43,36 @@ bool Sema::isLibstdcxxEagerExceptionSpecHack(const Declarator &D) {
|
|||
auto *RD = dyn_cast<CXXRecordDecl>(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<NamespaceDecl>(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<bool>(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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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<typename A, typename B> 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<X, X>;
|
||||
using PI = std::CLASS<int, int>;
|
||||
using PX = STD_CLASS<X, X>;
|
||||
using PI = STD_CLASS<int, int>;
|
||||
void swap(X &, X &) noexcept;
|
||||
PX px;
|
||||
PI pi;
|
||||
|
|
Loading…
Reference in New Issue