r348229 - [analyzer] MoveChecker: Improve warning and note messages.
Artem Dergachev via cfe-commits
cfe-commits at lists.llvm.org
Mon Dec 3 18:00:30 PST 2018
Author: dergachev
Date: Mon Dec 3 18:00:29 2018
New Revision: 348229
URL: http://llvm.org/viewvc/llvm-project?rev=348229&view=rev
Log:
[analyzer] MoveChecker: Improve warning and note messages.
The warning piece traditionally describes the bug itself, i.e.
"The bug is a _____", eg. "Attempt to delete released memory",
"Resource leak", "Method call on a moved-from object".
Event pieces produced by the visitor are usually in a present tense, i.e.
"At this moment _____": "Memory is released", "File is closed",
"Object is moved".
Additionally, type information is added into the event pieces for STL objects
(in order to highlight that it is in fact an STL object), and the respective
event piece now mentions that the object is left in an unspecified state
after it was moved, which is a vital piece of information to understand the bug.
Differential Revision: https://reviews.llvm.org/D54560
Modified:
cfe/trunk/lib/StaticAnalyzer/Checkers/MoveChecker.cpp
cfe/trunk/test/Analysis/use-after-move.cpp
Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/MoveChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/MoveChecker.cpp?rev=348229&r1=348228&r2=348229&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/MoveChecker.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/MoveChecker.cpp Mon Dec 3 18:00:29 2018
@@ -67,17 +67,29 @@ private:
bool STL : 1; // Is this an object of a standard type?
};
+ // Obtains ObjectKind of an object. Because class declaration cannot always
+ // be easily obtained from the memory region, it is supplied separately.
static ObjectKind classifyObject(const MemRegion *MR,
const CXXRecordDecl *RD);
+ // Classifies the object and dumps a user-friendly description string to
+ // the stream. Return value is equivalent to classifyObject.
+ static ObjectKind explainObject(llvm::raw_ostream &OS,
+ const MemRegion *MR, const CXXRecordDecl *RD);
+
class MovedBugVisitor : public BugReporterVisitor {
public:
- MovedBugVisitor(const MemRegion *R) : Region(R), Found(false) {}
+ MovedBugVisitor(const MemRegion *R, const CXXRecordDecl *RD)
+ : Region(R), RD(RD), Found(false) {}
void Profile(llvm::FoldingSetNodeID &ID) const override {
static int X = 0;
ID.AddPointer(&X);
ID.AddPointer(Region);
+ // Don't add RD because it's, in theory, uniquely determined by
+ // the region. In practice though, it's not always possible to obtain
+ // the declaration directly from the region, that's why we store it
+ // in the first place.
}
std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N,
@@ -87,6 +99,8 @@ private:
private:
// The tracked region.
const MemRegion *Region;
+ // The class of the tracked object.
+ const CXXRecordDecl *RD;
bool Found;
};
@@ -164,23 +178,21 @@ MoveChecker::MovedBugVisitor::VisitNode(
return nullptr;
Found = true;
- std::string ObjectName;
- if (const auto DecReg =
- unwrapRValueReferenceIndirection(Region)->getAs<DeclRegion>()) {
- const auto *RegionDecl = dyn_cast<NamedDecl>(DecReg->getDecl());
- ObjectName = RegionDecl->getNameAsString();
- }
- std::string InfoText;
- if (ObjectName != "")
- InfoText = "'" + ObjectName + "' became 'moved-from' here";
+ SmallString<128> Str;
+ llvm::raw_svector_ostream OS(Str);
+
+ OS << "Object";
+ ObjectKind OK = explainObject(OS, Region, RD);
+ if (OK.STL)
+ OS << " is left in a valid but unspecified state after move";
else
- InfoText = "Became 'moved-from' here";
+ OS << " is moved";
// Generate the extra diagnostic.
PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
N->getLocationContext());
- return std::make_shared<PathDiagnosticEventPiece>(Pos, InfoText, true);
-}
+ return std::make_shared<PathDiagnosticEventPiece>(Pos, OS.str(), true);
+ }
const ExplodedNode *MoveChecker::getMoveLocation(const ExplodedNode *N,
const MemRegion *Region,
@@ -205,7 +217,7 @@ ExplodedNode *MoveChecker::reportBug(con
MisuseKind MK) const {
if (ExplodedNode *N = C.generateNonFatalErrorNode()) {
if (!BT)
- BT.reset(new BugType(this, "Usage of a 'moved-from' object",
+ BT.reset(new BugType(this, "Use-after-move",
"C++ move semantics"));
// Uniqueing report to the same object.
@@ -217,27 +229,29 @@ ExplodedNode *MoveChecker::reportBug(con
MoveStmt, C.getSourceManager(), MoveNode->getLocationContext());
// Creating the error message.
- std::string ErrorMessage;
+ llvm::SmallString<128> Str;
+ llvm::raw_svector_ostream OS(Str);
switch(MK) {
case MK_FunCall:
- ErrorMessage = "Method call on a 'moved-from' object";
+ OS << "Method called on moved-from object";
+ explainObject(OS, Region, RD);
break;
case MK_Copy:
- ErrorMessage = "Copying a 'moved-from' object";
+ OS << "Moved-from object";
+ explainObject(OS, Region, RD);
+ OS << " is copied";
break;
case MK_Move:
- ErrorMessage = "Moving a 'moved-from' object";
+ OS << "Moved-from object";
+ explainObject(OS, Region, RD);
+ OS << " is moved";
break;
}
- if (const auto DecReg = Region->getAs<DeclRegion>()) {
- const auto *RegionDecl = dyn_cast<NamedDecl>(DecReg->getDecl());
- ErrorMessage += " '" + RegionDecl->getNameAsString() + "'";
- }
auto R =
- llvm::make_unique<BugReport>(*BT, ErrorMessage, N, LocUsedForUniqueing,
+ llvm::make_unique<BugReport>(*BT, OS.str(), N, LocUsedForUniqueing,
MoveNode->getLocationContext()->getDecl());
- R->addVisitor(llvm::make_unique<MovedBugVisitor>(Region));
+ R->addVisitor(llvm::make_unique<MovedBugVisitor>(Region, RD));
C.emitReport(std::move(R));
return N;
}
@@ -364,6 +378,23 @@ MoveChecker::ObjectKind MoveChecker::cla
};
}
+MoveChecker::ObjectKind MoveChecker::explainObject(llvm::raw_ostream &OS,
+ const MemRegion *MR,
+ const CXXRecordDecl *RD) {
+ // We may need a leading space every time we actually explain anything,
+ // and we never know if we are to explain anything until we try.
+ if (const auto DR =
+ dyn_cast_or_null<DeclRegion>(unwrapRValueReferenceIndirection(MR))) {
+ const auto *RegionDecl = cast<NamedDecl>(DR->getDecl());
+ OS << " '" << RegionDecl->getNameAsString() << "'";
+ }
+ ObjectKind OK = classifyObject(MR, RD);
+ if (OK.STL) {
+ OS << " of type '" << RD->getQualifiedNameAsString() << "'";
+ }
+ return OK;
+}
+
void MoveChecker::checkPreCall(const CallEvent &Call, CheckerContext &C) const {
ProgramStateRef State = C.getState();
const LocationContext *LC = C.getLocationContext();
Modified: cfe/trunk/test/Analysis/use-after-move.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/use-after-move.cpp?rev=348229&r1=348228&r2=348229&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/use-after-move.cpp (original)
+++ cfe/trunk/test/Analysis/use-after-move.cpp Mon Dec 3 18:00:29 2018
@@ -88,7 +88,7 @@ public:
A(const A &other) : i(other.i), d(other.d), b(other.b) {}
A(A &&other) : i(other.i), d(other.d), b(std::move(other.b)) {
#ifdef AGGRESSIVE
- // expected-note at -2{{'b' became 'moved-from' here}}
+ // expected-note at -2{{Object 'b' is moved}}
#endif
}
A(A &&other, char *k) {
@@ -137,18 +137,18 @@ void copyOrMoveCall(A a) {
void simpleMoveCtorTest() {
{
A a;
- A b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
- a.foo(); // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
+ A b = std::move(a); // expected-note {{Object 'a' is moved}}
+ a.foo(); // expected-warning {{Method called on moved-from object 'a'}} expected-note {{Method called on moved-from object 'a'}}
}
{
A a;
- A b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
- b = a; // expected-warning {{Copying a 'moved-from' object 'a'}} expected-note {{Copying a 'moved-from' object 'a'}}
+ A b = std::move(a); // expected-note {{Object 'a' is moved}}
+ b = a; // expected-warning {{Moved-from object 'a' is copied}} expected-note {{Moved-from object 'a' is copied}}
}
{
A a;
- A b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
- b = std::move(a); // expected-warning {{Moving a 'moved-from' object 'a'}} expected-note {{Moving a 'moved-from' object 'a'}}
+ A b = std::move(a); // expected-note {{Object 'a' is moved}}
+ b = std::move(a); // expected-warning {{Moved-from object 'a' is moved}} expected-note {{Moved-from object 'a' is moved}}
}
}
@@ -156,20 +156,20 @@ void simpleMoveAssignementTest() {
{
A a;
A b;
- b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
- a.foo(); // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
+ b = std::move(a); // expected-note {{Object 'a' is moved}}
+ a.foo(); // expected-warning {{Method called on moved-from object 'a'}} expected-note {{Method called on moved-from object 'a'}}
}
{
A a;
A b;
- b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
- A c(a); // expected-warning {{Copying a 'moved-from' object 'a'}} expected-note {{Copying a 'moved-from' object 'a'}}
+ b = std::move(a); // expected-note {{Object 'a' is moved}}
+ A c(a); // expected-warning {{Moved-from object 'a' is copied}} expected-note {{Moved-from object 'a' is copied}}
}
{
A a;
A b;
- b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
- A c(std::move(a)); // expected-warning {{Moving a 'moved-from' object 'a'}} expected-note {{Moving a 'moved-from' object 'a'}}
+ b = std::move(a); // expected-note {{Object 'a' is moved}}
+ A c(std::move(a)); // expected-warning {{Moved-from object 'a' is moved}} expected-note {{Moved-from object 'a' is moved}}
}
}
@@ -178,8 +178,8 @@ void moveInInitListTest() {
A a;
};
A a;
- S s{std::move(a)}; // expected-note {{'a' became 'moved-from' here}}
- a.foo(); // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
+ S s{std::move(a)}; // expected-note {{Object 'a' is moved}}
+ a.foo(); // expected-warning {{Method called on moved-from object 'a'}} expected-note {{Method called on moved-from object 'a'}}
}
// Don't report a bug if the variable was assigned to in the meantime.
@@ -227,19 +227,19 @@ void reinitializationTest(int i) {
A b;
b = std::move(a);
a = A();
- b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
- a.foo(); // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
+ b = std::move(a); // expected-note {{Object 'a' is moved}}
+ a.foo(); // expected-warning {{Method called on moved-from object 'a'}} expected-note {{Method called on moved-from object 'a'}}
}
// If a path exist where we not reinitialize the variable we report a bug.
{
A a;
A b;
- b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
+ b = std::move(a); // expected-note {{Object 'a' is moved}}
if (i < 10) { // expected-note {{Assuming 'i' is >= 10}} expected-note {{Taking false branch}}
a = A();
}
if (i > 5) { // expected-note {{Taking true branch}}
- a.foo(); // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
+ a.foo(); // expected-warning {{Method called on moved-from object 'a'}} expected-note {{Method called on moved-from object 'a'}}
}
}
}
@@ -325,8 +325,8 @@ void loopTest() {
{
A a;
for (int i = 0; i < bignum(); i++) { // expected-note {{Loop condition is true. Entering loop body}} expected-note {{Loop condition is true. Entering loop body}}
- constCopyOrMoveCall(std::move(a)); // expected-warning {{Moving a 'moved-from' object 'a'}} expected-note {{Moving a 'moved-from' object 'a'}}
- // expected-note at -1 {{'a' became 'moved-from' here}}
+ constCopyOrMoveCall(std::move(a)); // expected-warning {{Moved-from object 'a' is moved}} expected-note {{Moved-from object 'a' is moved}}
+ // expected-note at -1 {{Object 'a' is moved}}
}
}
@@ -348,10 +348,10 @@ void loopTest() {
void uniqueTest(bool cond) {
A a(42, 42.0);
A b;
- b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
+ b = std::move(a); // expected-note {{Object 'a' is moved}}
if (cond) { // expected-note {{Assuming 'cond' is not equal to 0}} expected-note {{Taking true branch}}
- a.foo(); // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
+ a.foo(); // expected-warning {{Method called on moved-from object 'a'}} expected-note {{Method called on moved-from object 'a'}}
}
if (cond) {
a.bar(); // no-warning
@@ -362,8 +362,8 @@ void uniqueTest(bool cond) {
void uniqueTest2() {
A a;
- A a1 = std::move(a); // expected-note {{'a' became 'moved-from' here}}
- a.foo(); // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
+ A a1 = std::move(a); // expected-note {{Object 'a' is moved}}
+ a.foo(); // expected-warning {{Method called on moved-from object 'a'}} expected-note {{Method called on moved-from object 'a'}}
A a2 = std::move(a); // no-warning
a.foo(); // no-warning
@@ -373,12 +373,12 @@ void uniqueTest2() {
//even on moved-from objects.
void moveSafeFunctionsTest() {
A a;
- A b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
+ A b = std::move(a); // expected-note {{Object 'a' is moved}}
a.empty(); // no-warning
a.isEmpty(); // no-warning
(void)a; // no-warning
(bool)a; // expected-warning {{expression result unused}}
- a.foo(); // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
+ a.foo(); // expected-warning {{Method called on moved-from object 'a'}} expected-note {{Method called on moved-from object 'a'}}
}
void moveStateResetFunctionsTest() {
@@ -445,17 +445,17 @@ class memberVariablesTest {
b = std::move(a);
a.foo();
#ifdef AGGRESSIVE
- // expected-note at -3{{'a' became 'moved-from' here}}
- // expected-warning at -3 {{Method call on a 'moved-from' object 'a'}}
- // expected-note at -4{{Method call on a 'moved-from' object 'a'}}
+ // expected-note at -3{{Object 'a' is moved}}
+ // expected-warning at -3 {{Method called on moved-from object 'a'}}
+ // expected-note at -4{{Method called on moved-from object 'a'}}
#endif
b = std::move(static_a);
static_a.foo();
#ifdef AGGRESSIVE
- // expected-note at -3{{'static_a' became 'moved-from' here}}
- // expected-warning at -3{{Method call on a 'moved-from' object 'static_a'}}
- // expected-note at -4{{Method call on a 'moved-from' object 'static_a'}}
+ // expected-note at -3{{Object 'static_a' is moved}}
+ // expected-warning at -3{{Method called on moved-from object 'static_a'}}
+ // expected-note at -4{{Method called on moved-from object 'static_a'}}
#endif
}
};
@@ -466,26 +466,26 @@ void PtrAndArrayTest() {
Arr[2] = std::move(*Ptr);
(*Ptr).foo();
#ifdef AGGRESSIVE
- // expected-note at -3{{Became 'moved-from' here}}
- // expected-warning at -3{{Method call on a 'moved-from' object}}
- // expected-note at -4{{Method call on a 'moved-from' object}}
+ // expected-note at -3{{Object is moved}}
+ // expected-warning at -3{{Method called on moved-from object}}
+ // expected-note at -4{{Method called on moved-from object}}
#endif
Ptr = &Arr[1];
Arr[3] = std::move(Arr[1]);
Ptr->foo();
#ifdef AGGRESSIVE
- // expected-note at -3{{Became 'moved-from' here}}
- // expected-warning at -3{{Method call on a 'moved-from' object}}
- // expected-note at -4{{Method call on a 'moved-from' object}}
+ // expected-note at -3{{Object is moved}}
+ // expected-warning at -3{{Method called on moved-from object}}
+ // expected-note at -4{{Method called on moved-from object}}
#endif
Arr[3] = std::move(Arr[2]);
Arr[2].foo();
#ifdef AGGRESSIVE
- // expected-note at -3{{Became 'moved-from' here}}
- // expected-warning at -3{{Method call on a 'moved-from' object}}
- // expected-note at -4{{Method call on a 'moved-from' object}}
+ // expected-note at -3{{Object is moved}}
+ // expected-warning at -3{{Method called on moved-from object}}
+ // expected-note at -4{{Method called on moved-from object}}
#endif
Arr[2] = std::move(Arr[3]); // reinitialization
@@ -545,9 +545,9 @@ void differentBranchesTest(int i) {
A a, b;
switch (i) { // expected-note {{Control jumps to 'case 1:'}}
case 1:
- b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
+ b = std::move(a); // expected-note {{Object 'a' is moved}}
case 2:
- a.foo(); // expected-warning {{Method call on a 'moved-from' object}} expected-note {{Method call on a 'moved-from' object 'a'}}
+ a.foo(); // expected-warning {{Method called on moved-from object}} expected-note {{Method called on moved-from object 'a'}}
break;
}
}
@@ -562,13 +562,13 @@ void tempTest() {
}
void interFunTest1(A &a) {
- a.bar(); // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
+ a.bar(); // expected-warning {{Method called on moved-from object 'a'}} expected-note {{Method called on moved-from object 'a'}}
}
void interFunTest2() {
A a;
A b;
- b = std::move(a); // expected-note {{'a' became 'moved-from' here}}
+ b = std::move(a); // expected-note {{Object 'a' is moved}}
interFunTest1(a); // expected-note {{Calling 'interFunTest1'}}
}
@@ -577,8 +577,8 @@ void foobar(int i, A a);
void paramEvaluateOrderTest() {
A a;
- foobar(std::move(a), a.getI()); // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
- // expected-note at -1 {{'a' became 'moved-from' here}}
+ foobar(std::move(a), a.getI()); // expected-warning {{Method called on moved-from object 'a'}} expected-note {{Method called on moved-from object 'a'}}
+ // expected-note at -1 {{Object 'a' is moved}}
//FALSE NEGATIVE since parameters evaluate order is undefined
foobar(a.getI(), std::move(a)); //no-warning
@@ -613,8 +613,8 @@ void declarationSequenceTest() {
}
{
A a;
- A a1 = std::move(a), a2 = a; // expected-warning {{Copying a 'moved-from' object 'a'}} expected-note {{Copying a 'moved-from' object 'a'}}
- // expected-note at -1 {{'a' became 'moved-from' here}}
+ A a1 = std::move(a), a2 = a; // expected-warning {{Moved-from object 'a' is copied}} expected-note {{Moved-from object 'a' is copied}}
+ // expected-note at -1 {{Object 'a' is moved}}
}
}
@@ -640,8 +640,8 @@ void logicalOperatorsSequenceTest() {
}
{
A a;
- if (A(std::move(a)).foo() > 0 && a.foo() > 0) { // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
- // expected-note at -1 {{'a' became 'moved-from' here}} expected-note at -1 {{Assuming the condition is true}} expected-note at -1 {{Assuming the condition is false}}
+ if (A(std::move(a)).foo() > 0 && a.foo() > 0) { // expected-warning {{Method called on moved-from object 'a'}} expected-note {{Method called on moved-from object 'a'}}
+ // expected-note at -1 {{Object 'a' is moved}} expected-note at -1 {{Assuming the condition is true}} expected-note at -1 {{Assuming the condition is false}}
// expected-note at -2 {{Left side of '&&' is false}} expected-note at -2 {{Left side of '&&' is true}}
// expected-note at -3 {{Taking false branch}}
A().bar();
@@ -657,8 +657,8 @@ void logicalOperatorsSequenceTest() {
}
{
A a;
- if (A(std::move(a)).foo() > 0 || a.foo() > 0) { // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
- // expected-note at -1 {{'a' became 'moved-from' here}} expected-note at -1 {{Assuming the condition is false}} expected-note at -1 {{Left side of '||' is false}}
+ if (A(std::move(a)).foo() > 0 || a.foo() > 0) { // expected-warning {{Method called on moved-from object 'a'}} expected-note {{Method called on moved-from object 'a'}}
+ // expected-note at -1 {{Object 'a' is moved}} expected-note at -1 {{Assuming the condition is false}} expected-note at -1 {{Left side of '||' is false}}
A().bar();
}
}
@@ -695,9 +695,9 @@ void subRegionMoveTest() {
B b = std::move(a.b);
a.b.foo();
#ifdef AGGRESSIVE
- // expected-note at -3{{'b' became 'moved-from' here}}
- // expected-warning at -3{{Method call on a 'moved-from' object 'b'}}
- // expected-note at -4 {{Method call on a 'moved-from' object 'b'}}
+ // expected-note at -3{{Object 'b' is moved}}
+ // expected-warning at -3{{Method called on moved-from object 'b'}}
+ // expected-note at -4 {{Method called on moved-from object 'b'}}
#endif
}
{
@@ -707,21 +707,21 @@ void subRegionMoveTest() {
#ifdef AGGRESSIVE
// expected-note at -3{{Calling move constructor for 'A'}}
// expected-note at -4{{Returning from move constructor for 'A'}}
- // expected-warning at -4{{Method call on a 'moved-from' object 'b'}}
- // expected-note at -5{{Method call on a 'moved-from' object 'b'}}
+ // expected-warning at -4{{Method called on moved-from object 'b'}}
+ // expected-note at -5{{Method called on moved-from object 'b'}}
#endif
}
// Don't report a misuse if any SuperRegion is already reported.
{
A a;
- A a1 = std::move(a); // expected-note {{'a' became 'moved-from' here}}
- a.foo(); // expected-warning {{Method call on a 'moved-from' object 'a'}} expected-note {{Method call on a 'moved-from' object 'a'}}
+ A a1 = std::move(a); // expected-note {{Object 'a' is moved}}
+ a.foo(); // expected-warning {{Method called on moved-from object 'a'}} expected-note {{Method called on moved-from object 'a'}}
a.b.foo(); // no-warning
}
{
C c;
- C c1 = std::move(c); // expected-note {{'c' became 'moved-from' here}}
- c.foo(); // expected-warning {{Method call on a 'moved-from' object 'c'}} expected-note {{Method call on a 'moved-from' object 'c'}}
+ C c1 = std::move(c); // expected-note {{Object 'c' is moved}}
+ c.foo(); // expected-warning {{Method called on moved-from object 'c'}} expected-note {{Method called on moved-from object 'c'}}
c.b.foo(); // no-warning
}
}
@@ -742,8 +742,8 @@ void resetSuperClass2() {
void reportSuperClass() {
C c;
- C c1 = std::move(c); // expected-note {{'c' became 'moved-from' here}}
- c.foo(); // expected-warning {{Method call on a 'moved-from' object 'c'}} expected-note {{Method call on a 'moved-from' object 'c'}}
+ C c1 = std::move(c); // expected-note {{Object 'c' is moved}}
+ c.foo(); // expected-warning {{Method called on moved-from object 'c'}} expected-note {{Method called on moved-from object 'c'}}
C c2 = c; // no-warning
}
@@ -786,14 +786,14 @@ class HasSTLField {
void foo() {
// Warn even in non-aggressive mode when it comes to STL, because
// in STL the object is left in "valid but unspecified state" after move.
- std::vector<int> W = std::move(V); // expected-note{{'V' became 'moved-from' here}}
- V.push_back(123); // expected-warning{{Method call on a 'moved-from' object 'V'}}
- // expected-note at -1{{Method call on a 'moved-from' object 'V'}}
+ std::vector<int> W = std::move(V); // expected-note{{Object 'V' of type 'std::vector' is left in a valid but unspecified state after move}}
+ V.push_back(123); // expected-warning{{Method called on moved-from object 'V'}}
+ // expected-note at -1{{Method called on moved-from object 'V'}}
}
};
void localRValueMove(A &&a) {
- A b = std::move(a); // expected-note{{'a' became 'moved-from' here}}
- a.foo(); // expected-warning{{Method call on a 'moved-from' object}}
- // expected-note at -1{{Method call on a 'moved-from' object}}
+ A b = std::move(a); // expected-note{{Object 'a' is moved}}
+ a.foo(); // expected-warning{{Method called on moved-from object 'a'}}
+ // expected-note at -1{{Method called on moved-from object 'a'}}
}
More information about the cfe-commits
mailing list