brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.9 KiB · 54e343f Raw
105 lines · cpp
1//===- LifetimeAnnotations.cpp -  -*--------------- C++------------------*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8#include "clang/Analysis/Analyses/LifetimeSafety/LifetimeAnnotations.h"9#include "clang/AST/ASTContext.h"10#include "clang/AST/Attr.h"11#include "clang/AST/Decl.h"12#include "clang/AST/DeclCXX.h"13#include "clang/AST/DeclTemplate.h"14#include "clang/AST/Type.h"15#include "clang/AST/TypeLoc.h"16 17namespace clang::lifetimes {18 19const FunctionDecl *20getDeclWithMergedLifetimeBoundAttrs(const FunctionDecl *FD) {21  return FD != nullptr ? FD->getMostRecentDecl() : nullptr;22}23 24const CXXMethodDecl *25getDeclWithMergedLifetimeBoundAttrs(const CXXMethodDecl *CMD) {26  const FunctionDecl *FD = CMD;27  return cast_if_present<CXXMethodDecl>(28      getDeclWithMergedLifetimeBoundAttrs(FD));29}30 31bool isNormalAssignmentOperator(const FunctionDecl *FD) {32  OverloadedOperatorKind OO = FD->getDeclName().getCXXOverloadedOperator();33  bool IsAssignment = OO == OO_Equal || isCompoundAssignmentOperator(OO);34  if (!IsAssignment)35    return false;36  QualType RetT = FD->getReturnType();37  if (!RetT->isLValueReferenceType())38    return false;39  ASTContext &Ctx = FD->getASTContext();40  QualType LHST;41  auto *MD = dyn_cast<CXXMethodDecl>(FD);42  if (MD && MD->isCXXInstanceMember())43    LHST = Ctx.getLValueReferenceType(MD->getFunctionObjectParameterType());44  else45    LHST = FD->getParamDecl(0)->getType();46  return Ctx.hasSameType(RetT, LHST);47}48 49bool isAssignmentOperatorLifetimeBound(const CXXMethodDecl *CMD) {50  CMD = getDeclWithMergedLifetimeBoundAttrs(CMD);51  return CMD && isNormalAssignmentOperator(CMD) && CMD->param_size() == 1 &&52         CMD->getParamDecl(0)->hasAttr<clang::LifetimeBoundAttr>();53}54 55bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD) {56  FD = getDeclWithMergedLifetimeBoundAttrs(FD);57  const TypeSourceInfo *TSI = FD->getTypeSourceInfo();58  if (!TSI)59    return false;60  // Don't declare this variable in the second operand of the for-statement;61  // GCC miscompiles that by ending its lifetime before evaluating the62  // third operand. See gcc.gnu.org/PR86769.63  AttributedTypeLoc ATL;64  for (TypeLoc TL = TSI->getTypeLoc();65       (ATL = TL.getAsAdjusted<AttributedTypeLoc>());66       TL = ATL.getModifiedLoc()) {67    if (ATL.getAttrAs<clang::LifetimeBoundAttr>())68      return true;69  }70 71  return isNormalAssignmentOperator(FD);72}73 74template <typename T> static bool isRecordWithAttr(QualType Type) {75  auto *RD = Type->getAsCXXRecordDecl();76  if (!RD)77    return false;78  // Generally, if a primary template class declaration is annotated with an79  // attribute, all its specializations generated from template instantiations80  // should inherit the attribute.81  //82  // However, since lifetime analysis occurs during parsing, we may encounter83  // cases where a full definition of the specialization is not required. In84  // such cases, the specialization declaration remains incomplete and lacks the85  // attribute. Therefore, we fall back to checking the primary template class.86  //87  // Note: it is possible for a specialization declaration to have an attribute88  // even if the primary template does not.89  //90  // FIXME: What if the primary template and explicit specialization91  // declarations have conflicting attributes? We should consider diagnosing92  // this scenario.93  bool Result = RD->hasAttr<T>();94 95  if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))96    Result |= CTSD->getSpecializedTemplate()->getTemplatedDecl()->hasAttr<T>();97 98  return Result;99}100 101bool isGslPointerType(QualType QT) { return isRecordWithAttr<PointerAttr>(QT); }102bool isGslOwnerType(QualType QT) { return isRecordWithAttr<OwnerAttr>(QT); }103 104} // namespace clang::lifetimes105