diff options
Diffstat (limited to 'clang/lib/Analysis/LifetimeAnnotations.cpp')
-rw-r--r-- | clang/lib/Analysis/LifetimeAnnotations.cpp | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/clang/lib/Analysis/LifetimeAnnotations.cpp b/clang/lib/Analysis/LifetimeAnnotations.cpp new file mode 100644 index 0000000..e791224 --- /dev/null +++ b/clang/lib/Analysis/LifetimeAnnotations.cpp @@ -0,0 +1,75 @@ +//===- 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<CXXMethodDecl>( + 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<CXXMethodDecl>(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<clang::LifetimeBoundAttr>(); +} + +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<AttributedTypeLoc>()); + TL = ATL.getModifiedLoc()) { + if (ATL.getAttrAs<clang::LifetimeBoundAttr>()) + return true; + } + + return isNormalAssignmentOperator(FD); +} + +} // namespace lifetimes +} // namespace clang |