Add a convenience method for modifying parameter
attributes.  While there, I noticed that not all
attribute methods returned a pointer-to-constant,
so I fixed that.

llvm-svn: 44457
diff --git a/llvm/lib/VMCore/Function.cpp b/llvm/lib/VMCore/Function.cpp
index 92853e3..16728f6 100644
--- a/llvm/lib/VMCore/Function.cpp
+++ b/llvm/lib/VMCore/Function.cpp
@@ -167,7 +167,7 @@
 
 static ManagedStatic<FoldingSet<ParamAttrsList> > ParamAttrsLists;
 
-ParamAttrsList *
+const ParamAttrsList *
 ParamAttrsList::get(const ParamAttrsVector &attrVec) {
   // If there are no attributes then return a null ParamAttrsList pointer.
   if (attrVec.empty())
@@ -200,6 +200,64 @@
   return PAL;
 }
 
+const ParamAttrsList *
+ParamAttrsList::getModified(const ParamAttrsList *PAL,
+                            const ParamAttrsVector &modVec) {
+  if (modVec.empty())
+    return PAL;
+
+#ifndef NDEBUG
+  for (unsigned i = 0, e = modVec.size(); i < e; ++i)
+    assert((!i || modVec[i-1].index < modVec[i].index)
+           && "Misordered ParamAttrsList!");
+#endif
+
+  if (!PAL) {
+    // Strip any instances of ParamAttr::None from modVec before calling 'get'.
+    ParamAttrsVector newVec;
+    for (unsigned i = 0, e = modVec.size(); i < e; ++i)
+      if (modVec[i].attrs != ParamAttr::None)
+        newVec.push_back(modVec[i]);
+    return get(newVec);
+  }
+
+  const ParamAttrsVector &oldVec = PAL->attrs;
+
+  ParamAttrsVector newVec;
+  unsigned oldI = 0;
+  unsigned modI = 0;
+  unsigned oldE = oldVec.size();
+  unsigned modE = modVec.size();
+
+  while (oldI < oldE && modI < modE) {
+    uint16_t oldIndex = oldVec[oldI].index;
+    uint16_t modIndex = modVec[modI].index;
+
+    if (oldIndex < modIndex) {
+      newVec.push_back(oldVec[oldI]);
+      ++oldI;
+    } else if (modIndex < oldIndex) {
+      if (modVec[modI].attrs != ParamAttr::None)
+        newVec.push_back(modVec[modI]);
+      ++modI;
+    } else {
+      // Same index - overwrite or delete existing attributes.
+      if (modVec[modI].attrs != ParamAttr::None)
+        newVec.push_back(modVec[modI]);
+      ++oldI;
+      ++modI;
+    }
+  }
+
+  for (; oldI < oldE; ++oldI)
+    newVec.push_back(oldVec[oldI]);
+  for (; modI < modE; ++modI)
+    if (modVec[modI].attrs != ParamAttr::None)
+      newVec.push_back(modVec[modI]);
+
+  return get(newVec);
+}
+
 ParamAttrsList::~ParamAttrsList() {
   ParamAttrsLists->RemoveNode(this);
 }