//===- LifetimeAnnotations.cpp - -*--------------- C++------------------*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "clang/Analysis/Analyses/LifetimeAnnotations.h" #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLoc.h" namespace clang { namespace lifetimes { const FunctionDecl * getDeclWithMergedLifetimeBoundAttrs(const FunctionDecl *FD) { return FD != nullptr ? FD->getMostRecentDecl() : nullptr; } const CXXMethodDecl * getDeclWithMergedLifetimeBoundAttrs(const CXXMethodDecl *CMD) { const FunctionDecl *FD = CMD; return cast_if_present( getDeclWithMergedLifetimeBoundAttrs(FD)); } bool isNormalAssignmentOperator(const FunctionDecl *FD) { OverloadedOperatorKind OO = FD->getDeclName().getCXXOverloadedOperator(); bool IsAssignment = OO == OO_Equal || isCompoundAssignmentOperator(OO); if (!IsAssignment) return false; QualType RetT = FD->getReturnType(); if (!RetT->isLValueReferenceType()) return false; ASTContext &Ctx = FD->getASTContext(); QualType LHST; auto *MD = dyn_cast(FD); if (MD && MD->isCXXInstanceMember()) LHST = Ctx.getLValueReferenceType(MD->getFunctionObjectParameterType()); else LHST = FD->getParamDecl(0)->getType(); return Ctx.hasSameType(RetT, LHST); } bool isAssignmentOperatorLifetimeBound(const CXXMethodDecl *CMD) { CMD = getDeclWithMergedLifetimeBoundAttrs(CMD); return CMD && isNormalAssignmentOperator(CMD) && CMD->param_size() == 1 && CMD->getParamDecl(0)->hasAttr(); } bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD) { FD = getDeclWithMergedLifetimeBoundAttrs(FD); const TypeSourceInfo *TSI = FD->getTypeSourceInfo(); if (!TSI) return false; // Don't declare this variable in the second operand of the for-statement; // GCC miscompiles that by ending its lifetime before evaluating the // third operand. See gcc.gnu.org/PR86769. AttributedTypeLoc ATL; for (TypeLoc TL = TSI->getTypeLoc(); (ATL = TL.getAsAdjusted()); TL = ATL.getModifiedLoc()) { if (ATL.getAttrAs()) return true; } return isNormalAssignmentOperator(FD); } } // namespace lifetimes } // namespace clang