When inlining through an 'nounwind' call, mark inlined
calls 'nounwind'.  It is important for correct C++
exception handling that nounwind markings do not get
lost, so this transformation is actually needed for
correctness.

llvm-svn: 45218
diff --git a/llvm/lib/VMCore/Function.cpp b/llvm/lib/VMCore/Function.cpp
index f985899..37e25ad 100644
--- a/llvm/lib/VMCore/Function.cpp
+++ b/llvm/lib/VMCore/Function.cpp
@@ -261,6 +261,32 @@
   return get(newVec);
 }
 
+const ParamAttrsList *
+ParamAttrsList::includeAttrs(const ParamAttrsList *PAL,
+                             uint16_t idx, uint16_t attrs) {
+  uint16_t OldAttrs = PAL ? PAL->getParamAttrs(idx) : 0;
+  uint16_t NewAttrs = OldAttrs | attrs;
+  if (NewAttrs == OldAttrs)
+    return PAL;
+
+  ParamAttrsVector modVec;
+  modVec.push_back(ParamAttrsWithIndex::get(idx, NewAttrs));
+  return getModified(PAL, modVec);
+}
+
+const ParamAttrsList *
+ParamAttrsList::excludeAttrs(const ParamAttrsList *PAL,
+                             uint16_t idx, uint16_t attrs) {
+  uint16_t OldAttrs = PAL ? PAL->getParamAttrs(idx) : 0;
+  uint16_t NewAttrs = OldAttrs & ~attrs;
+  if (NewAttrs == OldAttrs)
+    return PAL;
+
+  ParamAttrsVector modVec;
+  modVec.push_back(ParamAttrsWithIndex::get(idx, NewAttrs));
+  return getModified(PAL, modVec);
+}
+
 ParamAttrsList::~ParamAttrsList() {
   ParamAttrsLists->RemoveNode(this);
 }
diff --git a/llvm/lib/VMCore/Instructions.cpp b/llvm/lib/VMCore/Instructions.cpp
index 3531bad..b76b11d 100644
--- a/llvm/lib/VMCore/Instructions.cpp
+++ b/llvm/lib/VMCore/Instructions.cpp
@@ -71,6 +71,12 @@
   else
     return cast<InvokeInst>(I)->doesNotThrow();
 }
+void CallSite::setDoesNotThrow(bool doesNotThrow) {
+  if (CallInst *CI = dyn_cast<CallInst>(I))
+    CI->setDoesNotThrow(doesNotThrow);
+  else
+    cast<InvokeInst>(I)->setDoesNotThrow(doesNotThrow);
+}
 
 //===----------------------------------------------------------------------===//
 //                            TerminatorInst Class
@@ -405,6 +411,15 @@
   return false;
 }
 
+void CallInst::setDoesNotThrow(bool doesNotThrow) {
+  const ParamAttrsList *PAL = getParamAttrs();
+  if (doesNotThrow)
+    PAL = ParamAttrsList::includeAttrs(PAL, 0, ParamAttr::NoUnwind);
+  else
+    PAL = ParamAttrsList::excludeAttrs(PAL, 0, ParamAttr::NoUnwind);
+  setParamAttrs(PAL);
+}
+
 
 //===----------------------------------------------------------------------===//
 //                        InvokeInst Implementation
@@ -483,6 +498,15 @@
   return false;
 }
 
+void InvokeInst::setDoesNotThrow(bool doesNotThrow) {
+  const ParamAttrsList *PAL = getParamAttrs();
+  if (doesNotThrow)
+    PAL = ParamAttrsList::includeAttrs(PAL, 0, ParamAttr::NoUnwind);
+  else
+    PAL = ParamAttrsList::excludeAttrs(PAL, 0, ParamAttr::NoUnwind);
+  setParamAttrs(PAL);
+}
+
 
 //===----------------------------------------------------------------------===//
 //                        ReturnInst Implementation