Even more warnings utilizing gsl::Owner/gsl::Pointer annotations

Differential Revision: https://reviews.llvm.org/D65127

llvm-svn: 368454
This commit is contained in:
Gabor Horvath 2019-08-09 17:11:32 +00:00
parent 8a21214174
commit 7c3c8ba8da
2 changed files with 79 additions and 10 deletions

View File

@ -6568,19 +6568,33 @@ static bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee) {
if (auto *Conv = dyn_cast_or_null<CXXConversionDecl>(Callee))
if (isRecordWithAttr<PointerAttr>(Conv->getConversionType()))
return true;
if (!Callee->getParent()->isInStdNamespace() || !Callee->getIdentifier())
if (!Callee->getParent()->isInStdNamespace())
return false;
if (!isRecordWithAttr<PointerAttr>(Callee->getThisObjectType()) &&
!isRecordWithAttr<OwnerAttr>(Callee->getThisObjectType()))
return false;
if (!isRecordWithAttr<PointerAttr>(Callee->getReturnType()) &&
!Callee->getReturnType()->isPointerType())
return false;
return llvm::StringSwitch<bool>(Callee->getName())
.Cases("begin", "rbegin", "cbegin", "crbegin", true)
.Cases("end", "rend", "cend", "crend", true)
.Cases("c_str", "data", "get", true)
.Default(false);
if (Callee->getReturnType()->isPointerType() ||
isRecordWithAttr<PointerAttr>(Callee->getReturnType())) {
if (!Callee->getIdentifier())
return false;
return llvm::StringSwitch<bool>(Callee->getName())
.Cases("begin", "rbegin", "cbegin", "crbegin", true)
.Cases("end", "rend", "cend", "crend", true)
.Cases("c_str", "data", "get", true)
// Map and set types.
.Cases("find", "equal_range", "lower_bound", "upper_bound", true)
.Default(false);
} else if (Callee->getReturnType()->isReferenceType()) {
if (!Callee->getIdentifier()) {
auto OO = Callee->getOverloadedOperator();
return OO == OverloadedOperatorKind::OO_Subscript ||
OO == OverloadedOperatorKind::OO_Star;
}
return llvm::StringSwitch<bool>(Callee->getName())
.Cases("front", "back", "at", true)
.Default(false);
}
return false;
}
static void handleGslAnnotatedTypes(IndirectLocalPath &Path, Expr *Call,
@ -6600,6 +6614,12 @@ static void handleGslAnnotatedTypes(IndirectLocalPath &Path, Expr *Call,
if (MD && shouldTrackImplicitObjectArg(MD))
VisitPointerArg(MD, MCE->getImplicitObjectArgument());
return;
} else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(Call)) {
FunctionDecl *Callee = OCE->getDirectCallee();
if (Callee->isCXXInstanceMember() &&
shouldTrackImplicitObjectArg(cast<CXXMethodDecl>(Callee)))
VisitPointerArg(Callee, OCE->getArg(0));
return;
}
if (auto *CCE = dyn_cast<CXXConstructExpr>(Call)) {

View File

@ -121,24 +121,47 @@ void initLocalGslPtrWithTempOwner() {
namespace std {
template <typename T>
struct basic_iterator {};
struct basic_iterator {
basic_iterator operator++();
T& operator*();
};
template<typename T>
bool operator!=(basic_iterator<T>, basic_iterator<T>);
template <typename T>
struct vector {
typedef basic_iterator<T> iterator;
iterator begin();
iterator end();
T *data();
T &at(int n);
};
template<typename T>
struct basic_string_view {
basic_string_view(const T *);
const T *begin() const;
};
template<typename T>
struct basic_string {
const T *c_str() const;
operator basic_string_view<T> () const;
};
template<typename T>
struct unique_ptr {
T *get() const;
};
template<typename T>
struct optional {
optional();
optional(const T&);
T &operator*();
};
}
void modelIterators() {
@ -168,3 +191,29 @@ int *danglingUniquePtrFromTemp() {
int *danglingUniquePtrFromTemp2() {
return std::unique_ptr<int>().get(); // expected-warning {{returning address of local temporary object}}
}
void danglingReferenceFromTempOwner() {
int &r = *std::optional<int>(); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
int &r2 = *std::optional<int>(5); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
int &r3 = std::vector<int>().at(3); // expected-warning {{object backing the pointer will be destroyed at the end of the full-expression}}
}
std::vector<int> getTempVec();
std::optional<std::vector<int>> getTempOptVec();
int &usedToBeFalsePositive(std::vector<int> &v) {
std::vector<int>::iterator it = v.begin();
int& value = *it;
return value; // ok
}
int &doNotFollowReferencesForLocalOwner() {
std::unique_ptr<int> localOwner;
int &p = *localOwner.get();
// In real world code localOwner is usually moved here.
return p; // ok
}
const char *trackThroughMultiplePointer() {
return std::basic_string_view<char>(std::basic_string<char>()).begin(); // expected-warning {{returning address of local temporary object}}
}