r369408 - [LifetimeAnalysis] Add support for free functions

Gabor Horvath via cfe-commits cfe-commits at lists.llvm.org
Tue Aug 20 09:45:06 PDT 2019


Author: xazax
Date: Tue Aug 20 09:45:06 2019
New Revision: 369408

URL: http://llvm.org/viewvc/llvm-project?rev=369408&view=rev
Log:
[LifetimeAnalysis] Add support for free functions

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

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=369408&r1=369407&r2=369408&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Tue Aug 20 09:45:06 2019
@@ -6616,6 +6616,30 @@ static bool shouldTrackImplicitObjectArg
   return false;
 }
 
+static bool shouldTrackFirstArgument(const FunctionDecl *FD) {
+  if (!FD->getIdentifier() || FD->getNumParams() != 1)
+    return false;
+  const auto *RD = FD->getParamDecl(0)->getType()->getPointeeCXXRecordDecl();
+  if (!FD->isInStdNamespace() || !RD || !RD->isInStdNamespace())
+    return false;
+  if (!isRecordWithAttr<PointerAttr>(QualType(RD->getTypeForDecl(), 0)) &&
+      !isRecordWithAttr<OwnerAttr>(QualType(RD->getTypeForDecl(), 0)))
+    return false;
+  if (FD->getReturnType()->isPointerType() ||
+      isRecordWithAttr<PointerAttr>(FD->getReturnType())) {
+    return llvm::StringSwitch<bool>(FD->getName())
+        .Cases("begin", "rbegin", "cbegin", "crbegin", true)
+        .Cases("end", "rend", "cend", "crend", true)
+        .Case("data", true)
+        .Default(false);
+  } else if (FD->getReturnType()->isReferenceType()) {
+    return llvm::StringSwitch<bool>(FD->getName())
+        .Cases("get", "any_cast", true)
+        .Default(false);
+  }
+  return false;
+}
+
 static void handleGslAnnotatedTypes(IndirectLocalPath &Path, Expr *Call,
                                     LocalVisitor Visit) {
   auto VisitPointerArg = [&](const Decl *D, Expr *Arg) {
@@ -6639,6 +6663,11 @@ static void handleGslAnnotatedTypes(Indi
         shouldTrackImplicitObjectArg(cast<CXXMethodDecl>(Callee)))
       VisitPointerArg(Callee, OCE->getArg(0));
     return;
+  } else if (auto *CE = dyn_cast<CallExpr>(Call)) {
+    FunctionDecl *Callee = CE->getDirectCallee();
+    if (Callee && shouldTrackFirstArgument(Callee))
+      VisitPointerArg(Callee, CE->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=369408&r1=369407&r2=369408&view=diff
==============================================================================
--- cfe/trunk/test/Sema/warn-lifetime-analysis-nocfg.cpp (original)
+++ cfe/trunk/test/Sema/warn-lifetime-analysis-nocfg.cpp Tue Aug 20 09:45:06 2019
@@ -131,13 +131,16 @@ bool operator!=(basic_iterator<T>, basic
 }
 
 namespace std {
-template<class T> struct remove_reference       { typedef T type; };
-template<class T> struct remove_reference<T &>  { typedef T type; };
-template<class T> struct remove_reference<T &&> { typedef T type; };
+template<typename T> struct remove_reference       { typedef T type; };
+template<typename T> struct remove_reference<T &>  { typedef T type; };
+template<typename T> struct remove_reference<T &&> { typedef T type; };
 
-template<class T>
+template<typename T>
 typename remove_reference<T>::type &&move(T &&t) noexcept;
 
+template <typename C>
+auto data(const C &c) -> decltype(c.data());
+
 template <typename T>
 struct vector {
   typedef __gnu_cxx::basic_iterator<T> iterator;
@@ -180,6 +183,11 @@ template<typename T>
 struct stack {
   T &top();
 };
+
+struct any {};
+
+template<typename T>
+T any_cast(const any& operand);
 }
 
 void modelIterators() {
@@ -191,6 +199,22 @@ std::vector<int>::iterator modelIterator
   return std::vector<int>().begin(); // expected-warning {{returning address of local temporary object}}
 }
 
+const int *modelFreeFunctions() {
+  return std::data(std::vector<int>()); // expected-warning {{returning address of local temporary object}}
+}
+
+int &modelAnyCast() {
+  return std::any_cast<int&>(std::any{}); // expected-warning {{returning reference to local temporary object}}
+}
+
+int modelAnyCast2() {
+  return std::any_cast<int>(std::any{}); // ok
+}
+
+int modelAnyCast3() {
+  return std::any_cast<int&>(std::any{}); // ok
+}
+
 const char *danglingRawPtrFromLocal() {
   std::basic_string<char> s;
   return s.c_str(); // expected-warning {{address of stack memory associated with local variable 's' returned}}




More information about the cfe-commits mailing list