https://llvm.org/bugs/show_bug.cgi?id=30936
Bug ID: 30936 Summary: Static analyzer doesn't model copy elision Product: clang Version: trunk Hardware: PC OS: All Status: NEW Severity: normal Priority: P Component: Static Analyzer Assignee: dcough...@apple.com Reporter: ale...@google.com CC: llvm-bugs@lists.llvm.org, sbe...@google.com Classification: Unclassified Static Analyzer looses track of a field of an object when it doesn't see its copy constructor, even if the copy should be elided according to the standard ([class.copy]p32). In the case below, this part of the paragraph applies: " When certain criteria are met, an implementation is allowed to omit the copy/move construction of a class object, even if the constructor selected for the copy/move operation and/or the destructor for the object have side effects. In such cases, the implementation treats the source and target of the omitted copy/move operation as simply two different ways of referring to the same object, and the destruction of that object occurs at the later of the times when the two objects would have been destroyed without the optimization. This elision of copy/move operations, called copy elision, is permitted in the following circumstances (which may be combined to eliminate multiple copies): ... — when a temporary class object that has not been bound to a reference (12.2) would be copied/moved to a class object with the same cv-unqualified type, the copy/move operation can be omitted by constructing the temporary object directly into the target of the omitted copy/move" Here's a repro: $ clang-tidy -checks=-*,clang-analyzer*,-clang-analyzer-alpha* q.cc -- -std=c++11 1 warning generated. q.cc:51:20: warning: Dereference of null pointer (loaded from variable 'p') [clang-analyzer-core.NullDereference] EXPECT_TRUE(1 == *p); ^ ... If you remove the semicolon and the comment after `AssertionResult(const AssertionResult& other)`, the false positive goes away. Here's the code: =========== q.cc ============= class Message {}; class AssertHelper { public: AssertHelper(const char* file, int line, const char* message); ~AssertHelper(); void operator=(const Message& message) const; }; #define GTEST_MESSAGE_AT_(file, line, message) \ AssertHelper(file, line, message) = Message() #define GTEST_MESSAGE_(message) GTEST_MESSAGE_AT_(__FILE__, __LINE__, message) #define GTEST_FATAL_FAILURE_(message) return GTEST_MESSAGE_(message) #define GTEST_NONFATAL_FAILURE_(message) GTEST_MESSAGE_(message) class AssertionResult { public: AssertionResult(const AssertionResult& other); // : success_(other.success_) {} explicit AssertionResult(bool success) : success_(success) {} operator bool() const { return success_; } private: bool success_; }; #define GTEST_AMBIGUOUS_ELSE_BLOCKER_ switch (0) case 0: default: #define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \ GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ if (const AssertionResult gtest_ar_ = AssertionResult(expression)) \ ; \ else \ fail("") #define ASSERT_TRUE(condition) \ GTEST_TEST_BOOLEAN_(condition, #condition, false, true, GTEST_FATAL_FAILURE_) #define EXPECT_TRUE(condition) \ GTEST_TEST_BOOLEAN_(condition, #condition, false, true, \ GTEST_NONFATAL_FAILURE_) extern int *q(); void f() { int *p = q(); ASSERT_TRUE(p != nullptr); EXPECT_TRUE(1 == *p); } ======================== This issue accounts for a significant number of false positives in our codebase. -- You are receiving this mail because: You are on the CC list for the bug.
_______________________________________________ llvm-bugs mailing list llvm-bugs@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-bugs