Consumed analysis: replace the consumes attribute with a set_typestate
attribute. Patch by chris.wailes@gmail.com; reviewed and edited by delesley.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@192515 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index a07d6ca..70ae9fd 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -1026,20 +1026,6 @@
return true;
}
-static void handleConsumesAttr(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)
- ConsumesAttr(Attr.getRange(), S.Context,
- Attr.getAttributeSpellingListIndex()));
-}
static void handleCallableWhenAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
@@ -1080,44 +1066,6 @@
}
-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;
- return;
- }
-
- 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)
- TestsTypestateAttr(Attr.getRange(), S.Context, TestState,
- Attr.getAttributeSpellingListIndex()));
-}
-
static void handleReturnTypestateAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
ReturnTypestateAttr::ConsumedState ReturnState;
@@ -1168,6 +1116,84 @@
Attr.getAttributeSpellingListIndex()));
}
+
+static void handleSetTypestateAttr(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;
+ return;
+ }
+
+ if (!checkForConsumableClass(S, cast<CXXMethodDecl>(D), Attr))
+ return;
+
+ SetTypestateAttr::ConsumedState NewState;
+
+ if (Attr.isArgIdent(0)) {
+ StringRef Param = Attr.getArgAsIdent(0)->Ident->getName();
+
+ if (Param == "unknown") {
+ NewState = SetTypestateAttr::Unknown;
+ } else if (Param == "consumed") {
+ NewState = SetTypestateAttr::Consumed;
+ } else if (Param == "unconsumed") {
+ NewState = SetTypestateAttr::Unconsumed;
+ } else {
+ S.Diag(Attr.getLoc(), diag::warn_unknown_consumed_state) << Param;
+ return;
+ }
+
+ } else {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) <<
+ Attr.getName() << AANT_ArgumentIdentifier;
+ return;
+ }
+
+ D->addAttr(::new (S.Context)
+ SetTypestateAttr(Attr.getRange(), S.Context, NewState,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+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;
+ return;
+ }
+
+ 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_unknown_consumed_state) << Param;
+ return;
+ }
+
+ } else {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) <<
+ Attr.getName() << AANT_ArgumentIdentifier;
+ return;
+ }
+
+ D->addAttr(::new (S.Context)
+ TestsTypestateAttr(Attr.getRange(), S.Context, TestState,
+ Attr.getAttributeSpellingListIndex()));
+}
+
static void handleExtVectorTypeAttr(Sema &S, Scope *scope, Decl *D,
const AttributeList &Attr) {
TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D);
@@ -4793,18 +4819,18 @@
case AttributeList::AT_Consumable:
handleConsumableAttr(S, D, Attr);
break;
- case AttributeList::AT_Consumes:
- handleConsumesAttr(S, D, Attr);
- break;
case AttributeList::AT_CallableWhen:
handleCallableWhenAttr(S, D, Attr);
break;
- case AttributeList::AT_TestsTypestate:
- handleTestsTypestateAttr(S, D, Attr);
- break;
case AttributeList::AT_ReturnTypestate:
handleReturnTypestateAttr(S, D, Attr);
break;
+ case AttributeList::AT_SetTypestate:
+ handleSetTypestateAttr(S, D, Attr);
+ break;
+ case AttributeList::AT_TestsTypestate:
+ handleTestsTypestateAttr(S, D, Attr);
+ break;
// Type safety attributes.
case AttributeList::AT_ArgumentWithTypeTag: