From 3a71bb8341973a3d2478a92c0b3d42931631f0f5 Mon Sep 17 00:00:00 2001
From: Richard Smith <richard-llvm@metafoo.co.uk>
Date: Tue, 10 Mar 2015 02:00:53 +0000
Subject: [PATCH] PR21687: when adding a redeclaration of a function with an
 implicit exception specification, update all prior declarations if the new
 one has an explicit exception specification and the prior ones don't.

Patch by Vassil Vassilev! Some minor tweaking and test case by me.


git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@231738 91177308-0d34-0410-b5e6-96231b3b80d8
---
 lib/Serialization/ASTReaderDecl.cpp          | 21 ++++++++++++++------
 test/Modules/Inputs/PR21687/a.h              |  1 +
 test/Modules/Inputs/PR21687/b.h              |  2 ++
 test/Modules/Inputs/PR21687/c.h              |  4 ++++
 test/Modules/Inputs/PR21687/module.modulemap |  3 +++
 test/Modules/pr21687.cpp                     |  3 +++
 6 files changed, 28 insertions(+), 6 deletions(-)
 create mode 100644 test/Modules/Inputs/PR21687/a.h
 create mode 100644 test/Modules/Inputs/PR21687/b.h
 create mode 100644 test/Modules/Inputs/PR21687/c.h
 create mode 100644 test/Modules/Inputs/PR21687/module.modulemap
 create mode 100644 test/Modules/pr21687.cpp

diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 2a01d853c7c..9a382c1659d 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -2833,14 +2833,23 @@ void ASTDeclReader::attachPreviousDeclImpl(ASTReader &Reader,
 
   // If this declaration has an unresolved exception specification but the
   // previous declaration had a resolved one, resolve the exception
-  // specification now.
+  // specification now. If this declaration has a resolved exception
+  // specification but the previous declarations did not, apply our exception
+  // specification to all prior ones now.
   auto *FPT = FD->getType()->getAs<FunctionProtoType>();
   auto *PrevFPT = PrevFD->getType()->getAs<FunctionProtoType>();
-  if (FPT && PrevFPT &&
-      isUnresolvedExceptionSpec(FPT->getExceptionSpecType()) &&
-      !isUnresolvedExceptionSpec(PrevFPT->getExceptionSpecType())) {
-    Reader.Context.adjustExceptionSpec(
-        FD, PrevFPT->getExtProtoInfo().ExceptionSpec);
+  if (FPT && PrevFPT) {
+    bool WasUnresolved = isUnresolvedExceptionSpec(FPT->getExceptionSpecType());
+    bool IsUnresolved = isUnresolvedExceptionSpec(PrevFPT->getExceptionSpecType());
+    if (WasUnresolved && !IsUnresolved) {
+      Reader.Context.adjustExceptionSpec(
+          FD, PrevFPT->getExtProtoInfo().ExceptionSpec);
+    } else if (!WasUnresolved && IsUnresolved) {
+      FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo();
+      for (FunctionDecl *PrevFDToUpdate = PrevFD; PrevFDToUpdate;
+           PrevFDToUpdate = PrevFDToUpdate->getPreviousDecl())
+         Reader.Context.adjustExceptionSpec(PrevFDToUpdate, EPI.ExceptionSpec);
+    }
   }
 }
 }
diff --git a/test/Modules/Inputs/PR21687/a.h b/test/Modules/Inputs/PR21687/a.h
new file mode 100644
index 00000000000..023606eb35a
--- /dev/null
+++ b/test/Modules/Inputs/PR21687/a.h
@@ -0,0 +1 @@
+struct X { X(); virtual ~X(); };
diff --git a/test/Modules/Inputs/PR21687/b.h b/test/Modules/Inputs/PR21687/b.h
new file mode 100644
index 00000000000..7085b1f6739
--- /dev/null
+++ b/test/Modules/Inputs/PR21687/b.h
@@ -0,0 +1,2 @@
+#include "a.h"
+X *n = new X;
diff --git a/test/Modules/Inputs/PR21687/c.h b/test/Modules/Inputs/PR21687/c.h
new file mode 100644
index 00000000000..5c5d555a3f0
--- /dev/null
+++ b/test/Modules/Inputs/PR21687/c.h
@@ -0,0 +1,4 @@
+#include "a.h"
+inline void f() { X x, y(x); }
+#include "b.h"
+X x, y(x);
diff --git a/test/Modules/Inputs/PR21687/module.modulemap b/test/Modules/Inputs/PR21687/module.modulemap
new file mode 100644
index 00000000000..77e0a89e39a
--- /dev/null
+++ b/test/Modules/Inputs/PR21687/module.modulemap
@@ -0,0 +1,3 @@
+module a { header "a.h" export * }
+module b { header "b.h" export * }
+module c { header "c.h" export * }
diff --git a/test/Modules/pr21687.cpp b/test/Modules/pr21687.cpp
new file mode 100644
index 00000000000..ad67489541d
--- /dev/null
+++ b/test/Modules/pr21687.cpp
@@ -0,0 +1,3 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -I%S/Inputs/PR21687 -emit-llvm-only %s
+#include "c.h"
-- 
GitLab