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

Gabor Horvath via cfe-commits cfe-commits at lists.llvm.org
Fri Aug 9 10:11:33 PDT 2019


Author: xazax
Date: Fri Aug  9 10:11:32 2019
New Revision: 368454

URL: http://llvm.org/viewvc/llvm-project?rev=368454&view=rev
Log:
Even more warnings utilizing gsl::Owner/gsl::Pointer annotations

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

Modified:
    cfe/trunk/lib/Sema/SemaInit.cpp
    cfe/trunk/test/Sema/warn-lifetime-analysis-nocfg.cpp

Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=368454&r1=368453&r2=368454&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Fri Aug  9 10:11:32 2019
@@ -6568,19 +6568,33 @@ static bool shouldTrackImplicitObjectArg
   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(Indi
     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)) {

Modified: cfe/trunk/test/Sema/warn-lifetime-analysis-nocfg.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/warn-lifetime-analysis-nocfg.cpp?rev=368454&r1=368453&r2=368454&view=diff
==============================================================================
--- cfe/trunk/test/Sema/warn-lifetime-analysis-nocfg.cpp (original)
+++ cfe/trunk/test/Sema/warn-lifetime-analysis-nocfg.cpp Fri Aug  9 10:11:32 2019
@@ -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}}
+}




More information about the cfe-commits mailing list