This revision was automatically updated to reflect the committed changes.
Closed by commit rL368871: [LifetimeAnalysis] Fix false negatives of statement 
local lifetime analysis for… (authored by xazax, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D66152?vs=214872&id=215144#toc

Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D66152/new/

https://reviews.llvm.org/D66152

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

Index: cfe/trunk/lib/Sema/SemaInit.cpp
===================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp
+++ cfe/trunk/lib/Sema/SemaInit.cpp
@@ -16,6 +16,7 @@
 #include "clang/AST/ExprObjC.h"
 #include "clang/AST/ExprOpenMP.h"
 #include "clang/AST/TypeLoc.h"
+#include "clang/Basic/CharInfo.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Sema/Designator.h"
 #include "clang/Sema/Initialization.h"
@@ -6564,11 +6565,29 @@
   return false;
 }
 
+// Decl::isInStdNamespace will return false for iterators in some STL
+// implementations due to them being defined in a namespace outside of the std
+// namespace.
+static bool isInStlNamespace(const Decl *D) {
+  const DeclContext *DC = D->getDeclContext();
+  if (!DC)
+    return false;
+  if (const auto *ND = dyn_cast<NamespaceDecl>(DC))
+    if (const IdentifierInfo *II = ND->getIdentifier()) {
+      StringRef Name = II->getName();
+      if (Name.size() >= 2 && Name.front() == '_' &&
+          (Name[1] == '_' || isUppercase(Name[1])))
+        return true;
+    }
+
+  return DC->isStdNamespace();
+}
+
 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())
+  if (!isInStlNamespace(Callee->getParent()))
     return false;
   if (!isRecordWithAttr<PointerAttr>(Callee->getThisObjectType()) &&
       !isRecordWithAttr<OwnerAttr>(Callee->getThisObjectType()))
@@ -7107,25 +7126,29 @@
     SourceLocation DiagLoc = DiagRange.getBegin();
 
     auto *MTE = dyn_cast<MaterializeTemporaryExpr>(L);
-    bool IsTempGslOwner = MTE && !MTE->getExtendingDecl() &&
-                          isRecordWithAttr<OwnerAttr>(MTE->getType());
-    bool IsLocalGslOwner =
-        isa<DeclRefExpr>(L) && isRecordWithAttr<OwnerAttr>(L->getType());
-
-    // Skipping a chain of initializing gsl::Pointer annotated objects.
-    // We are looking only for the final source to find out if it was
-    // a local or temporary owner or the address of a local variable/param. We
-    // do not want to follow the references when returning a pointer originating
-    // from a local owner to avoid the following false positive:
-    //   int &p = *localUniquePtr;
-    //   someContainer.add(std::move(localUniquePtr));
-    //   return p;
-    if (!IsTempGslOwner && pathOnlyInitializesGslPointer(Path) &&
-        !(IsLocalGslOwner && !pathContainsInit(Path)))
-      return true;
 
-    bool IsGslPtrInitWithGslTempOwner =
-        IsTempGslOwner && pathOnlyInitializesGslPointer(Path);
+    bool IsGslPtrInitWithGslTempOwner = false;
+    bool IsLocalGslOwner = false;
+    if (pathOnlyInitializesGslPointer(Path)) {
+      if (isa<DeclRefExpr>(L)) {
+        // We do not want to follow the references when returning a pointer originating
+        // from a local owner to avoid the following false positive:
+        //   int &p = *localUniquePtr;
+        //   someContainer.add(std::move(localUniquePtr));
+        //   return p;
+        IsLocalGslOwner = isRecordWithAttr<OwnerAttr>(L->getType());
+        if (pathContainsInit(Path) || !IsLocalGslOwner)
+          return false;
+      } else {
+        IsGslPtrInitWithGslTempOwner = MTE && !MTE->getExtendingDecl() &&
+                            isRecordWithAttr<OwnerAttr>(MTE->getType());
+        // Skipping a chain of initializing gsl::Pointer annotated objects.
+        // We are looking only for the final source to find out if it was
+        // a local or temporary owner or the address of a local variable/param.
+        if (!IsGslPtrInitWithGslTempOwner)
+          return true;
+      }
+    }
 
     switch (LK) {
     case LK_FullExpression:
Index: cfe/trunk/test/Sema/warn-lifetime-analysis-nocfg.cpp
===================================================================
--- cfe/trunk/test/Sema/warn-lifetime-analysis-nocfg.cpp
+++ cfe/trunk/test/Sema/warn-lifetime-analysis-nocfg.cpp
@@ -119,14 +119,7 @@
   global2 = MyLongOwnerWithConversion{}; // TODO ?
 }
 
-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<class T>
-typename remove_reference<T>::type &&move(T &&t) noexcept;
-
+namespace __gnu_cxx {
 template <typename T>
 struct basic_iterator {
   basic_iterator operator++();
@@ -135,10 +128,19 @@
 
 template<typename T>
 bool operator!=(basic_iterator<T>, basic_iterator<T>);
+}
+
+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<class T>
+typename remove_reference<T>::type &&move(T &&t) noexcept;
 
 template <typename T>
 struct vector {
-  typedef basic_iterator<T> iterator;
+  typedef __gnu_cxx::basic_iterator<T> iterator;
   iterator begin();
   iterator end();
   const T *data() const;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to