xazax.hun created this revision. xazax.hun added reviewers: gribozavr, mgehre. Herald added subscribers: Charusso, gamesh411, Szelethus, dkrupp, rnkovacs. Herald added a project: clang. xazax.hun marked an inline comment as done. xazax.hun added inline comments.
================ Comment at: clang/lib/Sema/SemaInit.cpp:7130 - bool IsGslPtrInitWithGslTempOwner = - IsTempGslOwner && pathOnlyInitializesGslPointer(Path); + bool IsGslPtrInitWithGslTempOwner = false; + bool IsLocalGslOwner = false; ---------------- This is the NFC part. Some STL implementations have some class definitions (e.g. iterators) in a namespace outside of `std`. This patch will extend the warnings from classes in `std` namespace to other implementation specified namespaces (that start with double underscored or underscore and a capital letter). This patch also contains some NFC changes that supposed to make the code cleaner. If desired, I can split up this patch to two parts. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D66152 Files: clang/lib/Sema/SemaInit.cpp clang/test/Sema/warn-lifetime-analysis-nocfg.cpp
Index: clang/test/Sema/warn-lifetime-analysis-nocfg.cpp =================================================================== --- clang/test/Sema/warn-lifetime-analysis-nocfg.cpp +++ clang/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; Index: clang/lib/Sema/SemaInit.cpp =================================================================== --- clang/lib/Sema/SemaInit.cpp +++ clang/lib/Sema/SemaInit.cpp @@ -6565,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] == '_' || llvm::toUpper(Name[1]) == 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())) @@ -7108,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:
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits