Consumed analysis: Add param_typestate attribute, which specifies that
function parameters must be in a particular state. Patch by
chris.wailes@gmail.com. Reviewed by delesley@google.com.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@192934 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index c3e6bc4..3eabf87 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -1051,7 +1051,7 @@
return;
if (!CallableWhenAttr::ConvertStrToConsumedState(StateString,
- CallableState)) {
+ CallableState)) {
S.Diag(Loc, diag::warn_attribute_type_not_supported)
<< Attr.getName() << StateString;
return;
@@ -1066,6 +1066,52 @@
}
+static void handleParamTypestateAttr(Sema &S, Decl *D,
+ const AttributeList &Attr) {
+ if (!checkAttributeNumArgs(S, Attr, 1)) return;
+
+ if (!isa<ParmVarDecl>(D)) {
+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type) <<
+ Attr.getName() << ExpectedParameter;
+ return;
+ }
+
+ ParamTypestateAttr::ConsumedState ParamState;
+
+ if (Attr.isArgIdent(0)) {
+ IdentifierLoc *Ident = Attr.getArgAsIdent(0);
+ StringRef StateString = Ident->Ident->getName();
+
+ if (!ParamTypestateAttr::ConvertStrToConsumedState(StateString,
+ ParamState)) {
+ S.Diag(Ident->Loc, diag::warn_attribute_type_not_supported)
+ << Attr.getName() << StateString;
+ return;
+ }
+ } else {
+ S.Diag(Attr.getLoc(), diag::err_attribute_argument_type) <<
+ Attr.getName() << AANT_ArgumentIdentifier;
+ return;
+ }
+
+ // FIXME: This check is currently being done in the analysis. It can be
+ // enabled here only after the parser propagates attributes at
+ // template specialization definition, not declaration.
+ //QualType ReturnType = cast<ParmVarDecl>(D)->getType();
+ //const CXXRecordDecl *RD = ReturnType->getAsCXXRecordDecl();
+ //
+ //if (!RD || !RD->hasAttr<ConsumableAttr>()) {
+ // S.Diag(Attr.getLoc(), diag::warn_return_state_for_unconsumable_type) <<
+ // ReturnType.getAsString();
+ // return;
+ //}
+
+ D->addAttr(::new (S.Context)
+ ParamTypestateAttr(Attr.getRange(), S.Context, ParamState,
+ Attr.getAttributeSpellingListIndex()));
+}
+
+
static void handleReturnTypestateAttr(Sema &S, Decl *D,
const AttributeList &Attr) {
if (!checkAttributeNumArgs(S, Attr, 1)) return;
@@ -4818,6 +4864,9 @@
case AttributeList::AT_CallableWhen:
handleCallableWhenAttr(S, D, Attr);
break;
+ case AttributeList::AT_ParamTypestate:
+ handleParamTypestateAttr(S, D, Attr);
+ break;
case AttributeList::AT_ReturnTypestate:
handleReturnTypestateAttr(S, D, Attr);
break;