Index: cfe/trunk/lib/Analysis/Consumed.cpp =================================================================== --- cfe/trunk/lib/Analysis/Consumed.cpp +++ cfe/trunk/lib/Analysis/Consumed.cpp @@ -644,10 +644,10 @@ continue; // Adjust state on the caller side. - if (isRValueRef(ParamType)) - setStateForVarOrTmp(StateMap, PInfo, consumed::CS_Consumed); - else if (ReturnTypestateAttr *RT = Param->getAttr()) + if (ReturnTypestateAttr *RT = Param->getAttr()) setStateForVarOrTmp(StateMap, PInfo, mapReturnTypestateAttrState(RT)); + else if (isRValueRef(ParamType) || isConsumableType(ParamType)) + setStateForVarOrTmp(StateMap, PInfo, consumed::CS_Consumed); else if (isPointerOrRef(ParamType) && (!ParamType->getPointeeType().isConstQualified() || isSetOnReadPtrType(ParamType))) Index: cfe/trunk/test/SemaCXX/warn-consumed-analysis.cpp =================================================================== --- cfe/trunk/test/SemaCXX/warn-consumed-analysis.cpp +++ cfe/trunk/test/SemaCXX/warn-consumed-analysis.cpp @@ -53,12 +53,18 @@ public: DestructorTester(); DestructorTester(int); + DestructorTester(nullptr_t) RETURN_TYPESTATE(unconsumed); + DestructorTester(DestructorTester &&); void operator*() CALLABLE_WHEN("unconsumed"); ~DestructorTester() CALLABLE_WHEN("consumed"); + }; +void dtByVal(DestructorTester); +void dtByValMarkUnconsumed(DestructorTester RETURN_TYPESTATE(unconsumed)); + void baf0(const ConsumableClass var); void baf1(const ConsumableClass &var); void baf2(const ConsumableClass *var); @@ -120,6 +126,19 @@ expected-warning {{invalid invocation of method '~DestructorTester' on object 'D1' while it is in the 'unconsumed' state}} } +void testDestructionByVal() { + { + // both the var and the temporary are consumed: + DestructorTester D0(nullptr); + dtByVal((DestructorTester &&)D0); + } + { + // the var is consumed but the temporary isn't: + DestructorTester D1(nullptr); + dtByValMarkUnconsumed((DestructorTester &&)D1); // expected-warning {{invalid invocation of method '~DestructorTester' on a temporary object while it is in the 'unconsumed' state}} + } +} + void testTempValue() { *ConsumableClass(); // expected-warning {{invalid invocation of method 'operator*' on a temporary object while it is in the 'consumed' state}} } @@ -413,10 +432,15 @@ Param.consume(); } +void testRvalueRefParamReturnTypestateCallee(ConsumableClass &&Param RETURN_TYPESTATE(unconsumed)) { + Param.unconsume(); +} + void testParamReturnTypestateCaller() { ConsumableClass var; testParamReturnTypestateCallee(true, var); + testRvalueRefParamReturnTypestateCallee((ConsumableClass &&)var); *var; } @@ -480,6 +504,9 @@ baf2(&var); *var; + + baf3(var); + *var; baf4(var); *var; // expected-warning {{invalid invocation of method 'operator*' on object 'var' while it is in the 'unknown' state}}