[PATCH] D27116: Fix crash when using __has_nothrow_copy with inherited constructors

Philippe Daouadi via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 25 12:56:17 PST 2016


blastrock updated this revision to Diff 79319.
blastrock added a comment.

I got what "shadows" means, this patch can handle a UsingDecl with multiple shadows.


https://reviews.llvm.org/D27116

Files:
  lib/Sema/SemaExprCXX.cpp
  test/CXX/special/class.copy/p34-cxx11.cpp


Index: test/CXX/special/class.copy/p34-cxx11.cpp
===================================================================
--- /dev/null
+++ test/CXX/special/class.copy/p34-cxx11.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+// expected-no-diagnostics
+
+struct A {
+  A(A const &) noexcept(false) {}
+  A(A&&) noexcept(true) {}
+};
+
+struct B : public A {
+  using A::A;
+};
+
+static_assert(!__has_nothrow_copy(B), "has_nothrow_copy fails");
Index: lib/Sema/SemaExprCXX.cpp
===================================================================
--- lib/Sema/SemaExprCXX.cpp
+++ lib/Sema/SemaExprCXX.cpp
@@ -4418,19 +4418,34 @@
         // resolution point.
         if (isa<FunctionTemplateDecl>(ND))
           continue;
-        const CXXConstructorDecl *Constructor = cast<CXXConstructorDecl>(ND);
-        if (Constructor->isCopyConstructor(FoundTQs)) {
-          FoundConstructor = true;
-          const FunctionProtoType *CPT
-              = Constructor->getType()->getAs<FunctionProtoType>();
-          CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
-          if (!CPT)
-            return false;
-          // TODO: check whether evaluating default arguments can throw.
-          // For now, we'll be conservative and assume that they can throw.
-          if (!CPT->isNothrow(C) || CPT->getNumParams() > 1)
-            return false;
-        }
+
+        auto const HandleConstructor =
+            [&](const CXXConstructorDecl *Constructor) {
+              if (Constructor->isCopyConstructor(FoundTQs)) {
+                FoundConstructor = true;
+                const FunctionProtoType *CPT =
+                    Constructor->getType()->getAs<FunctionProtoType>();
+                CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
+                if (!CPT)
+                  return false;
+                // TODO: check whether evaluating default arguments can throw.
+                // For now, we'll be conservative and assume that they can
+                // throw.
+                if (!CPT->isNothrow(C) || CPT->getNumParams() > 1)
+                  return false;
+              }
+              return true;
+            };
+
+        // handle inherited constructors
+        if (isa<UsingDecl>(ND)) {
+          const auto *UD = cast<UsingDecl>(ND);
+          for (const auto &C : UD->shadows())
+            if (!HandleConstructor(
+                    cast<CXXConstructorDecl>(C->getTargetDecl())))
+              return false;
+        } else if (!HandleConstructor(cast<CXXConstructorDecl>(ND)))
+          return false;
       }
 
       return FoundConstructor;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D27116.79319.patch
Type: text/x-patch
Size: 2626 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20161125/ae7a30c3/attachment.bin>


More information about the llvm-commits mailing list