diff options
author | DeLesley Hutchins <delesley@google.com> | 2013-10-11 23:03:26 +0000 |
---|---|---|
committer | DeLesley Hutchins <delesley@google.com> | 2013-10-11 23:03:26 +0000 |
commit | 33a293433fd75d227bce03d85e8be37ca470330f (patch) | |
tree | c3e0a3118926c2156523bd562aba424824ac667d /clang/lib/Sema/SemaDeclAttr.cpp | |
parent | 6587bcfdbc98d845c54771225b5c653989282579 (diff) | |
download | bcm5719-llvm-33a293433fd75d227bce03d85e8be37ca470330f.tar.gz bcm5719-llvm-33a293433fd75d227bce03d85e8be37ca470330f.zip |
Consumed analysis: replace the consumes attribute with a set_typestate
attribute. Patch by chris.wailes@gmail.com; reviewed and edited by delesley.
llvm-svn: 192515
Diffstat (limited to 'clang/lib/Sema/SemaDeclAttr.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 142 |
1 files changed, 84 insertions, 58 deletions
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index a07d6ca79d3..70ae9fd9bc1 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -1026,20 +1026,6 @@ static bool checkForConsumableClass(Sema &S, const CXXMethodDecl *MD, 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 handleCallableWhenAttr(Sema &S, Decl *D, } -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 @@ static void handleReturnTypestateAttr(Sema &S, Decl *D, 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 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, 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: |