r192515 - Consumed analysis: replace the consumes attribute with a set_typestate
Aaron Ballman
aaron at aaronballman.com
Mon Oct 14 16:26:32 PDT 2013
No worries about fixing them; I had some spare time tonight where I
could make the changes myself. :-) It's fixed up in r192639.
Thanks!
~Aaron
On Mon, Oct 14, 2013 at 10:57 AM, Delesley Hutchins <delesley at google.com> wrote:
> Thanks for the review, Aaron! Excellent points -- I'll fix those
> issues in a future patch. FYI, my goal right now is to get all of
> Chris's stuff working and upstream first; I'll go back and refine the
> code afterword. You had some good comments earlier regarding use of
> raw pointers that I want to address too. I appreciate the code
> review,
>
> -DeLesley
>
>
> On Sat, Oct 12, 2013 at 8:01 AM, Aaron Ballman <aaron at aaronballman.com> wrote:
>> A couple of points below:
>>
>> On Fri, Oct 11, 2013 at 7:03 PM, DeLesley Hutchins <delesley at google.com> wrote:
>>> Author: delesley
>>> Date: Fri Oct 11 18:03:26 2013
>>> New Revision: 192515
>>>
>>> URL: http://llvm.org/viewvc/llvm-project?rev=192515&view=rev
>>> Log:
>>> Consumed analysis: replace the consumes attribute with a set_typestate
>>> attribute. Patch by chris.wailes at gmail.com; reviewed and edited by delesley.
>>>
>>> Modified:
>>> cfe/trunk/include/clang/Basic/Attr.td
>>> cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>>> cfe/trunk/lib/Analysis/Consumed.cpp
>>> cfe/trunk/lib/Sema/SemaDeclAttr.cpp
>>> cfe/trunk/test/SemaCXX/warn-consumed-analysis.cpp
>>> cfe/trunk/test/SemaCXX/warn-consumed-parsing.cpp
>>>
>>> Modified: cfe/trunk/include/clang/Basic/Attr.td
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Attr.td?rev=192515&r1=192514&r2=192515&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/include/clang/Basic/Attr.td (original)
>>> +++ cfe/trunk/include/clang/Basic/Attr.td Fri Oct 11 18:03:26 2013
>>> @@ -967,19 +967,6 @@ def CallableWhen : InheritableAttr {
>>> ["Unknown", "Consumed", "Unconsumed"]>];
>>> }
>>>
>>> -def TestsTypestate : InheritableAttr {
>>> - let Spellings = [GNU<"tests_typestate">];
>>> - let Subjects = [CXXMethod];
>>> - let Args = [EnumArgument<"TestState", "ConsumedState",
>>> - ["consumed", "unconsumed"],
>>> - ["Consumed", "Unconsumed"]>];
>>> -}
>>> -
>>> -def Consumes : InheritableAttr {
>>> - let Spellings = [GNU<"consumes">];
>>> - let Subjects = [CXXMethod];
>>> -}
>>> -
>>> def ReturnTypestate : InheritableAttr {
>>> let Spellings = [GNU<"return_typestate">];
>>> let Subjects = [Function];
>>> @@ -988,6 +975,22 @@ def ReturnTypestate : InheritableAttr {
>>> ["Unknown", "Consumed", "Unconsumed"]>];
>>> }
>>>
>>> +def SetTypestate : InheritableAttr {
>>> + let Spellings = [GNU<"set_typestate">];
>>> + let Subjects = [CXXMethod];
>>> + let Args = [EnumArgument<"NewState", "ConsumedState",
>>> + ["unknown", "consumed", "unconsumed"],
>>> + ["Unknown", "Consumed", "Unconsumed"]>];
>>> +}
>>> +
>>> +def TestsTypestate : InheritableAttr {
>>> + let Spellings = [GNU<"tests_typestate">];
>>> + let Subjects = [CXXMethod];
>>> + let Args = [EnumArgument<"TestState", "ConsumedState",
>>> + ["consumed", "unconsumed"],
>>> + ["Consumed", "Unconsumed"]>];
>>> +}
>>> +
>>> // Type safety attributes for `void *' pointers and type tags.
>>>
>>> def ArgumentWithTypeTag : InheritableAttr {
>>>
>>> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=192515&r1=192514&r2=192515&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
>>> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Oct 11 18:03:26 2013
>>> @@ -2216,8 +2216,8 @@ def warn_attr_on_unconsumable_class : Wa
>>> def warn_return_typestate_for_unconsumable_type : Warning<
>>> "return state set for an unconsumable type '%0'">, InGroup<Consumed>,
>>> DefaultIgnore;
>>> -def warn_invalid_test_typestate : Warning<
>>> - "invalid test typestate '%0'">, InGroup<Consumed>, DefaultIgnore;
>>> +def warn_unknown_consumed_state : Warning<
>>> + "unknown consumed analysis state '%0'">, InGroup<Consumed>, DefaultIgnore;
>>
>> This is not needed (more info below).
>>
>>> def warn_return_typestate_mismatch : Warning<
>>> "return value not in expected state; expected '%0', observed '%1'">,
>>> InGroup<Consumed>, DefaultIgnore;
>>>
>>> Modified: cfe/trunk/lib/Analysis/Consumed.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/Consumed.cpp?rev=192515&r1=192514&r2=192515&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/lib/Analysis/Consumed.cpp (original)
>>> +++ cfe/trunk/lib/Analysis/Consumed.cpp Fri Oct 11 18:03:26 2013
>>> @@ -157,6 +157,18 @@ static ConsumedState mapConsumableAttrSt
>>> llvm_unreachable("invalid enum");
>>> }
>>>
>>> +static ConsumedState mapSetTypestateAttrState(const SetTypestateAttr *STAttr) {
>>> + switch (STAttr->getNewState()) {
>>> + case SetTypestateAttr::Unknown:
>>> + return CS_Unknown;
>>> + case SetTypestateAttr::Unconsumed:
>>> + return CS_Unconsumed;
>>> + case SetTypestateAttr::Consumed:
>>> + return CS_Consumed;
>>> + }
>>> + llvm_unreachable("invalid_enum");
>>> +}
>>> +
>>> static ConsumedState
>>> mapReturnTypestateAttrState(const ReturnTypestateAttr *RTSAttr) {
>>> switch (RTSAttr->getState()) {
>>> @@ -639,8 +651,9 @@ void ConsumedStmtVisitor::VisitCXXMember
>>> if (isTestingFunction(MethodDecl))
>>> PropagationMap.insert(PairType(Call,
>>> PropagationInfo(PInfo.getVar(), testsFor(MethodDecl))));
>>> - else if (MethodDecl->hasAttr<ConsumesAttr>())
>>> - StateMap->setState(PInfo.getVar(), consumed::CS_Consumed);
>>> + else if (MethodDecl->hasAttr<SetTypestateAttr>())
>>> + StateMap->setState(PInfo.getVar(),
>>> + mapSetTypestateAttrState(MethodDecl->getAttr<SetTypestateAttr>()));
>>> }
>>> }
>>> }
>>> @@ -728,8 +741,9 @@ void ConsumedStmtVisitor::VisitCXXOperat
>>> if (isTestingFunction(FunDecl))
>>> PropagationMap.insert(PairType(Call,
>>> PropagationInfo(PInfo.getVar(), testsFor(FunDecl))));
>>> - else if (FunDecl->hasAttr<ConsumesAttr>())
>>> - StateMap->setState(PInfo.getVar(), consumed::CS_Consumed);
>>> + else if (FunDecl->hasAttr<SetTypestateAttr>())
>>> + StateMap->setState(PInfo.getVar(),
>>> + mapSetTypestateAttrState(FunDecl->getAttr<SetTypestateAttr>()));
>>> }
>>> }
>>> }
>>>
>>> Modified: cfe/trunk/lib/Sema/SemaDeclAttr.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclAttr.cpp?rev=192515&r1=192514&r2=192515&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/lib/Sema/SemaDeclAttr.cpp (original)
>>> +++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp Fri Oct 11 18:03:26 2013
>>> @@ -1026,20 +1026,6 @@ static bool checkForConsumableClass(Sema
>>> 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
>>> }
>>>
>>>
>>> -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(Se
>>> 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;
>>> + }
>>
>> This whole block (from isArgIdent down) can be replaced with
>> ConvertStrToTypeSetState (or something akin to that) -- it's td
>> generated code for converting enumerations to their proper value,
>> including many diagnostics. As an example, here's visibility:
>>
>> VisibilityAttr::VisibilityType type;
>> if (!VisibilityAttr::ConvertStrToVisibilityType(TypeStr, type)) {
>> S.Diag(LiteralLoc, diag::warn_attribute_type_not_supported)
>> << Attr.getName() << TypeStr;
>> return;
>> }
>>
>> You should be using the warn_attribute_type_not_support diagnostic for
>> compatibility.
>>
>>> +
>>> + 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;
>>> + }
>>
>> Same comments apply here as above.
>>
>>> +
>>> + 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
>>> 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:
>>>
>>> Modified: cfe/trunk/test/SemaCXX/warn-consumed-analysis.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-consumed-analysis.cpp?rev=192515&r1=192514&r2=192515&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/test/SemaCXX/warn-consumed-analysis.cpp (original)
>>> +++ cfe/trunk/test/SemaCXX/warn-consumed-analysis.cpp Fri Oct 11 18:03:26 2013
>>> @@ -4,7 +4,7 @@
>>>
>>> #define CALLABLE_WHEN(...) __attribute__ ((callable_when(__VA_ARGS__)))
>>> #define CONSUMABLE(state) __attribute__ ((consumable(state)))
>>> -#define CONSUMES __attribute__ ((consumes))
>>> +#define SET_TYPESTATE(state) __attribute__ ((set_typestate(state)))
>>> #define RETURN_TYPESTATE(state) __attribute__ ((return_typestate(state)))
>>> #define TESTS_TYPESTATE(state) __attribute__ ((tests_typestate(state)))
>>>
>>> @@ -23,7 +23,7 @@ public:
>>>
>>> ConsumableClass<T>& operator=(ConsumableClass<T> &other);
>>> ConsumableClass<T>& operator=(ConsumableClass<T> &&other);
>>> - ConsumableClass<T>& operator=(nullptr_t) CONSUMES;
>>> + ConsumableClass<T>& operator=(nullptr_t) SET_TYPESTATE(consumed);
>>>
>>> template <typename U>
>>> ConsumableClass<T>& operator=(ConsumableClass<U> &other);
>>> @@ -31,7 +31,7 @@ public:
>>> template <typename U>
>>> ConsumableClass<T>& operator=(ConsumableClass<U> &&other);
>>>
>>> - void operator()(int a) CONSUMES;
>>> + void operator()(int a) SET_TYPESTATE(consumed);
>>> void operator*() const CALLABLE_WHEN("unconsumed");
>>> void unconsumedCall() const CALLABLE_WHEN("unconsumed");
>>> void callableWhenUnknown() const CALLABLE_WHEN("unconsumed", "unknown");
>>> @@ -44,7 +44,8 @@ public:
>>> void constCall() const;
>>> void nonconstCall();
>>>
>>> - void consume() CONSUMES;
>>> + void consume() SET_TYPESTATE(consumed);
>>> + void unconsume() SET_TYPESTATE(unconsumed);
>>> };
>>>
>>> class CONSUMABLE(unconsumed) DestructorTester {
>>> @@ -484,7 +485,7 @@ void testConditionalMerge() {
>>> *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
>>> }
>>>
>>> -void testConsumes0() {
>>> +void testSetTypestate() {
>>> ConsumableClass<int> var(42);
>>>
>>> *var;
>>> @@ -492,15 +493,19 @@ void testConsumes0() {
>>> var.consume();
>>>
>>> *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
>>> +
>>> + var.unconsume();
>>> +
>>> + *var;
>>> }
>>>
>>> -void testConsumes1() {
>>> +void testConsumes0() {
>>> ConsumableClass<int> var(nullptr);
>>>
>>> *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'consumed' state}}
>>> }
>>>
>>> -void testConsumes2() {
>>> +void testConsumes1() {
>>> ConsumableClass<int> var(42);
>>>
>>> var.unconsumedCall();
>>>
>>> Modified: cfe/trunk/test/SemaCXX/warn-consumed-parsing.cpp
>>> URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/warn-consumed-parsing.cpp?rev=192515&r1=192514&r2=192515&view=diff
>>> ==============================================================================
>>> --- cfe/trunk/test/SemaCXX/warn-consumed-parsing.cpp (original)
>>> +++ cfe/trunk/test/SemaCXX/warn-consumed-parsing.cpp Fri Oct 11 18:03:26 2013
>>> @@ -1,10 +1,10 @@
>>> // RUN: %clang_cc1 -fsyntax-only -verify -Wconsumed -std=c++11 %s
>>>
>>> #define CALLABLE_WHEN(...) __attribute__ ((callable_when(__VA_ARGS__)))
>>> -#define CONSUMABLE(state) __attribute__ ((consumable(state)))
>>> -#define CONSUMES __attribute__ ((consumes))
>>> -#define RETURN_TYPESTATE(state) __attribute__ ((return_typestate(state)))
>>> -#define TESTS_TYPESTATE(state) __attribute__ ((tests_typestate(state)))
>>> +#define CONSUMABLE(state) __attribute__ ((consumable(state)))
>>> +#define SET_TYPESTATE(state) __attribute__ ((set_typestate(state)))
>>> +#define RETURN_TYPESTATE(state) __attribute__ ((return_typestate(state)))
>>> +#define TESTS_TYPESTATE(state) __attribute__ ((tests_typestate(state)))
>>>
>>> // FIXME: This test is here because the warning is issued by the Consumed
>>> // analysis, not SemaDeclAttr. The analysis won't run after an error
>>> @@ -17,27 +17,27 @@ int returnTypestateForUnconsumable() {
>>> }
>>>
>>> class AttrTester0 {
>>> - void consumes() __attribute__ ((consumes(42))); // expected-error {{attribute takes no arguments}}
>>> + void consumes() __attribute__ ((set_typestate())); // expected-error {{attribute takes one argument}}
>>> bool testsUnconsumed() __attribute__ ((tests_typestate())); // expected-error {{attribute takes one argument}}
>>> void callableWhen() __attribute__ ((callable_when())); // expected-error {{attribute takes at least 1 argument}}
>>> };
>>>
>>> -int var0 CONSUMES; // expected-warning {{'consumes' attribute only applies to methods}}
>>> +int var0 SET_TYPESTATE(consumed); // expected-warning {{'set_typestate' attribute only applies to methods}}
>>> int var1 TESTS_TYPESTATE(consumed); // expected-warning {{'tests_typestate' attribute only applies to methods}}
>>> -int var2 CALLABLE_WHEN(42); // expected-warning {{'callable_when' attribute only applies to methods}}
>>> +int var2 CALLABLE_WHEN("consumed"); // expected-warning {{'callable_when' attribute only applies to methods}}
>>> int var3 CONSUMABLE(consumed); // expected-warning {{'consumable' attribute only applies to classes}}
>>> int var4 RETURN_TYPESTATE(consumed); // expected-warning {{'return_typestate' attribute only applies to functions}}
>>>
>>> -void function0() CONSUMES; // expected-warning {{'consumes' attribute only applies to methods}}
>>> +void function0() SET_TYPESTATE(consumed); // expected-warning {{'set_typestate' attribute only applies to methods}}
>>> void function1() TESTS_TYPESTATE(consumed); // expected-warning {{'tests_typestate' attribute only applies to methods}}
>>> -void function2() CALLABLE_WHEN(42); // expected-warning {{'callable_when' attribute only applies to methods}}
>>> +void function2() CALLABLE_WHEN("consumed"); // expected-warning {{'callable_when' attribute only applies to methods}}
>>> void function3() CONSUMABLE(consumed); // expected-warning {{'consumable' attribute only applies to classes}}
>>>
>>> class CONSUMABLE(unknown) AttrTester1 {
>>> void callableWhen0() CALLABLE_WHEN("unconsumed");
>>> void callableWhen1() CALLABLE_WHEN(42); // expected-error {{'callable_when' attribute requires a string}}
>>> void callableWhen2() CALLABLE_WHEN("foo"); // expected-warning {{'callable_when' attribute argument not supported: foo}}
>>> - void consumes() CONSUMES;
>>> + void consumes() SET_TYPESTATE(consumed);
>>> bool testsUnconsumed() TESTS_TYPESTATE(consumed);
>>> };
>>>
>>> @@ -46,7 +46,7 @@ AttrTester1 returnTypestateTester1() RET
>>>
>>> class AttrTester2 {
>>> void callableWhen() CALLABLE_WHEN("unconsumed"); // expected-warning {{consumed analysis attribute is attached to member of class 'AttrTester2' which isn't marked as consumable}}
>>> - void consumes() CONSUMES; // expected-warning {{consumed analysis attribute is attached to member of class 'AttrTester2' which isn't marked as consumable}}
>>> + void consumes() SET_TYPESTATE(consumed); // expected-warning {{consumed analysis attribute is attached to member of class 'AttrTester2' which isn't marked as consumable}}
>>> bool testsUnconsumed() TESTS_TYPESTATE(consumed); // expected-warning {{consumed analysis attribute is attached to member of class 'AttrTester2' which isn't marked as consumable}}
>>> };
>>>
>>>
>>>
>>> _______________________________________________
>>> cfe-commits mailing list
>>> cfe-commits at cs.uiuc.edu
>>> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
>>
>> ~Aaron
>
>
>
> --
> DeLesley Hutchins | Software Engineer | delesley at google.com | 505-206-0315
More information about the cfe-commits
mailing list