Consumed Analysis:  Change callable_when so that it can take a list of states
that a function can be called in.  This reduced the total number of annotations
needed and makes writing more complicated behaviour less burdensome.
Patch by chriswails@gmail.com.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@191983 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index c6337a5..41cc3fd 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -1041,8 +1041,11 @@
                           Attr.getAttributeSpellingListIndex()));
 }
 
-static void handleCallableWhenUnconsumedAttr(Sema &S, Decl *D,
-                                             const AttributeList &Attr) {
+static void handleCallableWhenAttr(Sema &S, Decl *D,
+                                   const AttributeList &Attr) {
+  
+  if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) return;
+
   if (!isa<CXXMethodDecl>(D)) {
     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) <<
       Attr.getName() << ExpectedMethod;
@@ -1052,9 +1055,34 @@
   if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr))
     return;
   
+  SmallVector<CallableWhenAttr::ConsumedState, 3> States;
+  for (unsigned ArgIndex = 0; ArgIndex < Attr.getNumArgs(); ++ArgIndex) {
+    CallableWhenAttr::ConsumedState CallableState;
+    
+    if (Attr.isArgExpr(ArgIndex) &&
+        isa<StringLiteral>(Attr.getArgAsExpr(ArgIndex))) {
+      
+      Expr *Arg = Attr.getArgAsExpr(ArgIndex);
+      StringRef StateString = cast<StringLiteral>(Arg)->getString();
+      
+      if (!CallableWhenAttr::ConvertStrToConsumedState(StateString,
+                                                       CallableState)) {
+        S.Diag(Arg->getExprLoc(), diag::warn_attribute_type_not_supported)
+          << Attr.getName() << StateString;
+        return;
+      }
+      
+      States.push_back(CallableState);
+    } else {
+      S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) << Attr.getName()
+        << AANT_ArgumentString;
+      return;
+    }
+  }
+  
   D->addAttr(::new (S.Context)
-             CallableWhenUnconsumedAttr(Attr.getRange(), S.Context,
-                                        Attr.getAttributeSpellingListIndex()));
+             CallableWhenAttr(Attr.getRange(), S.Context, States.data(),
+               States.size(), Attr.getAttributeSpellingListIndex()));
 }
 
 static void handleTestsConsumedAttr(Sema &S, Decl *D,
@@ -4767,8 +4795,8 @@
   case AttributeList::AT_Consumes:
     handleConsumesAttr(S, D, Attr);
     break;
-  case AttributeList::AT_CallableWhenUnconsumed:
-    handleCallableWhenUnconsumedAttr(S, D, Attr);
+  case AttributeList::AT_CallableWhen:
+    handleCallableWhenAttr(S, D, Attr);
     break;
   case AttributeList::AT_TestsConsumed:
     handleTestsConsumedAttr(S, D, Attr);