r284669 - Extend hack to work around bad exception specifications for 'swap' members to

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Wed Oct 19 16:47:37 PDT 2016


Author: rsmith
Date: Wed Oct 19 18:47:37 2016
New Revision: 284669

URL: http://llvm.org/viewvc/llvm-project?rev=284669&view=rev
Log:
Extend hack to work around bad exception specifications for 'swap' members to
also cover libstdc++'s std::__debug::array and std::__profile::array.

Modified:
    cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
    cfe/trunk/test/SemaCXX/libstdcxx_pair_swap_hack.cpp

Modified: cfe/trunk/lib/Sema/SemaExceptionSpec.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExceptionSpec.cpp?rev=284669&r1=284668&r2=284669&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExceptionSpec.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExceptionSpec.cpp Wed Oct 19 18:47:37 2016
@@ -43,23 +43,36 @@ bool Sema::isLibstdcxxEagerExceptionSpec
   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);
 }
 

Modified: cfe/trunk/test/SemaCXX/libstdcxx_pair_swap_hack.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/libstdcxx_pair_swap_hack.cpp?rev=284669&r1=284668&r2=284669&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/libstdcxx_pair_swap_hack.cpp (original)
+++ cfe/trunk/test/SemaCXX/libstdcxx_pair_swap_hack.cpp Wed Oct 19 18:47:37 2016
@@ -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;




More information about the cfe-commits mailing list