Consumed analysis: switch from tests_consumed/unconsumed to a general
tests_typestate attribute.  Patch by chris.wailes@gmail.com.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@192513 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/AnalysisBasedWarnings.cpp b/lib/Sema/AnalysisBasedWarnings.cpp
index 53e53b2..88b7dc4 100644
--- a/lib/Sema/AnalysisBasedWarnings.cpp
+++ b/lib/Sema/AnalysisBasedWarnings.cpp
@@ -1501,15 +1501,6 @@
     Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
   }
   
-  void warnUnnecessaryTest(StringRef VariableName, StringRef VariableState,
-                           SourceLocation Loc) {
-
-    PartialDiagnosticAt Warning(Loc, S.PDiag(diag::warn_unnecessary_test) <<
-                                 VariableName << VariableState);
-    
-    Warnings.push_back(DelayedDiag(Warning, OptionalNotes()));
-  }
-  
   void warnUseOfTempInInvalidState(StringRef MethodName, StringRef State,
                                    SourceLocation Loc) {
                                                     
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index 1985de4..a07d6ca 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -1079,24 +1079,11 @@
                States.size(), Attr.getAttributeSpellingListIndex()));
 }
 
-static void handleTestsConsumedAttr(Sema &S, Decl *D,
-                                    const AttributeList &Attr) {
-  if (!isa<CXXMethodDecl>(D)) {
-    S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) <<
-      Attr.getName() << ExpectedMethod;
-    return;
-  }
-  
-  if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr))
-    return;
-  
-  D->addAttr(::new (S.Context)
-             TestsConsumedAttr(Attr.getRange(), S.Context,
-                               Attr.getAttributeSpellingListIndex()));
-}
 
-static void handleTestsUnconsumedAttr(Sema &S, Decl *D,
-                                      const AttributeList &Attr) {
+static void handleTestsTypestateAttr(Sema &S, Decl *D,
+                                     const AttributeList &Attr) {
+  if (!checkAttributeNumArgs(S, Attr, 1)) return;
+  
   if (!isa<CXXMethodDecl>(D)) {
     S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) <<
       Attr.getName() << ExpectedMethod;
@@ -1106,9 +1093,29 @@
   if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr))
     return;
   
+  TestsTypestateAttr::ConsumedState TestState;
+  
+  if (Attr.isArgIdent(0)) {
+    StringRef Param = Attr.getArgAsIdent(0)->Ident->getName();
+    
+    if (Param == "consumed") {
+      TestState = TestsTypestateAttr::Consumed;
+    } else if (Param == "unconsumed") {
+      TestState = TestsTypestateAttr::Unconsumed;
+    } else {
+      S.Diag(Attr.getLoc(), diag::warn_invalid_test_typestate) << Param;
+      return;
+    }
+    
+  } else {
+    S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) <<
+      Attr.getName() << AANT_ArgumentIdentifier;
+    return;
+  }
+  
   D->addAttr(::new (S.Context)
-             TestsUnconsumedAttr(Attr.getRange(), S.Context,
-                                 Attr.getAttributeSpellingListIndex()));
+             TestsTypestateAttr(Attr.getRange(), S.Context, TestState,
+                                Attr.getAttributeSpellingListIndex()));
 }
 
 static void handleReturnTypestateAttr(Sema &S, Decl *D,
@@ -4782,7 +4789,7 @@
     handleAcquiredAfterAttr(S, D, Attr);
     break;
 
-  // Uniqueness analysis attributes.
+  // Consumed analysis attributes.
   case AttributeList::AT_Consumable:
     handleConsumableAttr(S, D, Attr);
     break;
@@ -4792,11 +4799,8 @@
   case AttributeList::AT_CallableWhen:
     handleCallableWhenAttr(S, D, Attr);
     break;
-  case AttributeList::AT_TestsConsumed:
-    handleTestsConsumedAttr(S, D, Attr);
-    break;
-  case AttributeList::AT_TestsUnconsumed:
-    handleTestsUnconsumedAttr(S, D, Attr);
+  case AttributeList::AT_TestsTypestate:
+    handleTestsTypestateAttr(S, D, Attr);
     break;
   case AttributeList::AT_ReturnTypestate:
     handleReturnTypestateAttr(S, D, Attr);