llvm::PointerIntPair<const InitializedEntity *, 3, LifetimeKind>;
72 return{Entity, LK_Extended};
97 return{Entity, LK_Extended};
104 return{
nullptr, LK_FullExpression};
109 return{
nullptr, LK_FullExpression};
115 return{
nullptr, LK_Return};
120 return{
nullptr, LK_StmtExprResult};
126 return{
nullptr, LK_New};
134 return{
nullptr, LK_FullExpression};
144 return{InitField, LK_MemInitializer};
151 return{InitField, LK_MemInitializer};
158 return{
nullptr, LK_FullExpression};
162 return{
nullptr, LK_FullExpression};
169 return{
nullptr, LK_FullExpression};
172llvm_unreachable(
"unknown entity kind");
181RK_StdInitializerList,
194structIndirectLocalPathEntry {
206GslPointerAssignment,
212 constDecl *
D=
nullptr;
215IndirectLocalPathEntry() {}
216IndirectLocalPathEntry(EntryKind K, Expr *E) :
Kind(K),
E(
E) {}
217IndirectLocalPathEntry(EntryKind K, Expr *E,
constDecl *
D)
219IndirectLocalPathEntry(EntryKind K, Expr *E,
constLambdaCapture *Capture)
225structRevertToOldSizeRAII {
228RevertToOldSizeRAII(IndirectLocalPath &Path) :
Path(
Path) {}
229~RevertToOldSizeRAII() {
Path.resize(OldSize); }
232usingLocalVisitor = llvm::function_ref<
bool(IndirectLocalPath &
Path, Local L,
237 for(
auto E:
Path)
238 if(
E.Kind == IndirectLocalPathEntry::VarInit &&
E.D == VD)
244 returnllvm::any_of(
Path, [=](IndirectLocalPathEntry
E) {
245 return E.Kind == IndirectLocalPathEntry::DefaultInit ||
246 E.Kind == IndirectLocalPathEntry::VarInit;
252 boolRevisitSubinits);
277 bool Result= RD->hasAttr<
T>();
279 if(
auto*CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RD))
280 Result|= CTSD->getSpecializedTemplate()->getTemplatedDecl()->hasAttr<
T>();
299 if(
const auto*ND = dyn_cast<NamespaceDecl>(DC))
301StringRef Name = II->getName();
302 if(Name.size() >= 2 && Name.front() ==
'_'&&
313 if(
const auto*CTSD =
314dyn_cast_if_present<ClassTemplateSpecializationDecl>(Container)) {
315 if(!CTSD->hasAttr<OwnerAttr>())
317 const auto&TAs = CTSD->getTemplateArgs();
325dyn_cast_if_present<ClassTemplateSpecializationDecl>(Container);
328 if(!CTSD->hasAttr<OwnerAttr>())
330 const auto&TAs = CTSD->getTemplateArgs();
332isRecordWithAttr<OwnerAttr>(TAs[0].getAsType());
337 if(
const auto*CTSD =
338dyn_cast_if_present<ClassTemplateSpecializationDecl>(RD)) {
339 const auto&TAs = CTSD->getTemplateArgs();
341RD->
getName() ==
"initializer_list"&& TAs.size() > 0 &&
349 if(
auto*Conv = dyn_cast_or_null<CXXConversionDecl>(Callee))
350 if(isRecordWithAttr<PointerAttr>(Conv->getConversionType()) &&
351Callee->getParent()->hasAttr<OwnerAttr>())
355 if(!isRecordWithAttr<PointerAttr>(
356Callee->getFunctionObjectParameterType()) &&
357!isRecordWithAttr<OwnerAttr>(Callee->getFunctionObjectParameterType()))
360 if(!Callee->getIdentifier())
362 returnllvm::StringSwitch<bool>(Callee->getName())
363.Cases(
"begin",
"rbegin",
"cbegin",
"crbegin",
true)
364.Cases(
"end",
"rend",
"cend",
"crend",
true)
365.Cases(
"c_str",
"data",
"get",
true)
367.Cases(
"find",
"equal_range",
"lower_bound",
"upper_bound",
true)
370 if(Callee->getReturnType()->isReferenceType()) {
371 if(!Callee->getIdentifier()) {
372 autoOO = Callee->getOverloadedOperator();
373 if(!Callee->getParent()->hasAttr<OwnerAttr>())
375 returnOO == OverloadedOperatorKind::OO_Subscript ||
376OO == OverloadedOperatorKind::OO_Star;
378 returnllvm::StringSwitch<bool>(Callee->getName())
379.Cases(
"front",
"back",
"at",
"top",
"value",
true)
391 if(!RD->hasAttr<PointerAttr>() && !RD->hasAttr<OwnerAttr>())
395 returnllvm::StringSwitch<bool>(FD->
getName())
396.Cases(
"begin",
"rbegin",
"cbegin",
"crbegin",
true)
397.Cases(
"end",
"rend",
"cend",
"crend",
true)
398.Case(
"data",
true)
402 returnllvm::StringSwitch<bool>(FD->
getName())
403.Cases(
"get",
"any_cast",
true)
414 const auto*ParamRefType =
420 if(
const auto*TST =
422 returnTST->getTemplateName()
437 if(LHSRecordDecl->hasAttr<PointerAttr>())
466 if(!isRecordWithAttr<OwnerAttr>(RHSArgType))
494 if(
const auto*PrimaryCtorTemplate =
496PrimaryCtorTemplate &&
498PrimaryCtorTemplate->getTemplatedDecl()))) {
517 auto*MD = dyn_cast<CXXMethodDecl>(FD);
518 if(MD && MD->isCXXInstanceMember())
519LHST = Ctx.getLValueReferenceType(MD->getFunctionObjectParameterType());
522 if(Ctx.hasSameType(RetT, LHST))
537 returncast_if_present<CXXMethodDecl>(
553 if(ATL.
getAttrAs<LifetimeBoundAttr>())
562LocalVisitor Visit) {
566 if(
auto*CE = dyn_cast<CallExpr>(
Call)) {
567Callee = CE->getDirectCallee();
570 auto*CCE = cast<CXXConstructExpr>(
Call);
571Callee = CCE->getConstructor();
577 boolEnableGSLAnalysis = !Callee->getASTContext().getDiagnostics().isIgnored(
579 Expr*ObjectArg =
nullptr;
580 if(isa<CXXOperatorCallExpr>(
Call) && Callee->isCXXInstanceMember()) {
582Args = Args.slice(1);
583}
else if(
auto*MCE = dyn_cast<CXXMemberCallExpr>(
Call)) {
584ObjectArg = MCE->getImplicitObjectArgument();
587 autoVisitLifetimeBoundArg = [&](
const Decl*
D,
Expr*Arg) {
588 Path.push_back({IndirectLocalPathEntry::LifetimeBoundCall, Arg,
D});
589 if(Arg->isGLValue())
597 autoReturnType = Callee->getReturnType();
601 if(ReturnType->isReferenceType() &&
602!isRecordWithAttr<OwnerAttr>(ReturnType->getPointeeType())) {
603 for(
constIndirectLocalPathEntry &PE : llvm::reverse(
Path)) {
604 if(PE.Kind == IndirectLocalPathEntry::GslReferenceInit ||
605PE.Kind == IndirectLocalPathEntry::LifetimeBoundCall)
607 if(PE.Kind == IndirectLocalPathEntry::GslPointerInit ||
608PE.Kind == IndirectLocalPathEntry::GslPointerAssignment)
613 Path.push_back({ReturnType->isReferenceType()
614? IndirectLocalPathEntry::GslReferenceInit
615: IndirectLocalPathEntry::GslPointerInit,
617 if(Arg->isGLValue())
625 boolCheckCoroCall =
false;
626 if(
const auto*RD = Callee->getReturnType()->getAsRecordDecl()) {
627CheckCoroCall = RD->hasAttr<CoroLifetimeBoundAttr>() &&
628RD->hasAttr<CoroReturnTypeAttr>() &&
629!Callee->hasAttr<CoroDisableLifetimeBoundAttr>();
633 boolCheckCoroObjArg = CheckCoroCall;
635 if(
auto*LE = dyn_cast<LambdaExpr>(ObjectArg->
IgnoreImplicit());
636LE && LE->captures().empty())
637CheckCoroObjArg =
false;
641CheckCoroObjArg =
false;
643VisitLifetimeBoundArg(Callee, ObjectArg);
644 else if(EnableGSLAnalysis) {
645 if(
auto*CME = dyn_cast<CXXMethodDecl>(Callee);
647VisitGSLPointerArg(Callee, ObjectArg);
652 unsignedNP = std::min(Callee->getNumParams(), CanonCallee->
getNumParams());
653 for(
unsignedI = 0, N = std::min<unsigned>(NP, Args.size()); I != N; ++I) {
655RevertToOldSizeRAII RAII(
Path);
656 if(
auto*DAE = dyn_cast<CXXDefaultArgExpr>(Arg)) {
658{IndirectLocalPathEntry::DefaultArg, DAE, DAE->getParam()});
659Arg = DAE->getExpr();
663VisitLifetimeBoundArg(CanonCallee->
getParamDecl(I), Arg);
664 else if(
const auto*CaptureAttr =
666CaptureAttr && isa<CXXConstructorDecl>(CanonCallee) &&
667llvm::any_of(CaptureAttr->params(), [](
intArgIdx) {
668return ArgIdx == LifetimeCaptureByAttr::THIS;
683VisitLifetimeBoundArg(CanonCallee->
getParamDecl(I), Arg);
684 else if(EnableGSLAnalysis && I == 0) {
687VisitGSLPointerArg(CanonCallee, Arg);
688}
else if(
auto*Ctor = dyn_cast<CXXConstructExpr>(
Call);
690VisitGSLPointerArg(Ctor->getConstructor(), Arg);
700LocalVisitor Visit) {
701RevertToOldSizeRAII RAII(
Path);
708 if(
auto*FE = dyn_cast<FullExpr>(
Init))
709 Init= FE->getSubExpr();
713 if(ILE->isTransparent())
714 Init= ILE->getInit(0);
717 if(
MemberExpr*ME = dyn_cast<MemberExpr>(
Init->IgnoreImpCasts()))
719{IndirectLocalPathEntry::MemberExpr, ME, ME->getMemberDecl()});
722 Init=
const_cast<Expr*
>(
Init->skipRValueSubobjectAdjustments());
727 if(CE->getSubExpr()->isGLValue())
728 Init= CE->getSubExpr();
732 if(
auto*ASE = dyn_cast<ArraySubscriptExpr>(
Init)) {
733 Init= ASE->getBase();
734 auto*ICE = dyn_cast<ImplicitCastExpr>(
Init);
735 if(ICE && ICE->getCastKind() == CK_ArrayToPointerDecay)
736 Init= ICE->getSubExpr();
745 if(
auto*DIE = dyn_cast<CXXDefaultInitExpr>(
Init)) {
747{IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
748 Init= DIE->getExpr();
750}
while(
Init!= Old);
752 if(
auto*MTE = dyn_cast<MaterializeTemporaryExpr>(
Init)) {
753 if(Visit(
Path, Local(MTE), RK))
757 if(
auto*M = dyn_cast<MemberExpr>(
Init)) {
759 if(
auto*F = dyn_cast<FieldDecl>(M->getMemberDecl());
760F && !F->getType()->isReferenceType())
764 if(isa<CallExpr>(
Init))
767 switch(
Init->getStmtClass()) {
768 caseStmt::DeclRefExprClass: {
771 auto*DRE = cast<DeclRefExpr>(
Init);
772 auto*VD = dyn_cast<VarDecl>(DRE->getDecl());
773 if(VD && VD->hasLocalStorage() &&
774!DRE->refersToEnclosingVariableOrCapture()) {
775 if(!VD->getType()->isReferenceType()) {
776Visit(
Path, Local(DRE), RK);
777}
else if(isa<ParmVarDecl>(DRE->getDecl())) {
782 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
784RK_ReferenceBinding, Visit);
790 caseStmt::UnaryOperatorClass: {
795 if(
U->getOpcode() == UO_Deref)
800 caseStmt::ArraySectionExprClass: {
802 Path, cast<ArraySectionExpr>(
Init)->getBase(), Visit,
true);
806 caseStmt::ConditionalOperatorClass:
807 caseStmt::BinaryConditionalOperatorClass: {
808 auto*
C= cast<AbstractConditionalOperator>(
Init);
809 if(!
C->getTrueExpr()->getType()->isVoidType())
811 if(!
C->getFalseExpr()->getType()->isVoidType())
816 caseStmt::CompoundLiteralExprClass: {
817 if(
auto*CLE = dyn_cast<CompoundLiteralExpr>(
Init)) {
818 if(!CLE->isFileScope())
819Visit(
Path, Local(CLE), RK);
835 boolRevisitSubinits) {
836RevertToOldSizeRAII RAII(
Path);
844 if(
auto*DIE = dyn_cast<CXXDefaultInitExpr>(
Init)) {
846{IndirectLocalPathEntry::DefaultInit, DIE, DIE->getField()});
847 Init= DIE->getExpr();
850 if(
auto*FE = dyn_cast<FullExpr>(
Init))
851 Init= FE->getSubExpr();
854 Init=
const_cast<Expr*
>(
Init->skipRValueSubobjectAdjustments());
857 Init= BTE->getSubExpr();
862 if(
auto*CE = dyn_cast<CastExpr>(
Init)) {
863 switch(CE->getCastKind()) {
864 caseCK_LValueToRValue:
867 Path.push_back({IndirectLocalPathEntry::LValToRVal, CE});
870[&](IndirectLocalPath &
Path, Local L, ReferenceKind RK) ->
bool{
871 if(
auto*DRE = dyn_cast<DeclRefExpr>(L)) {
872 auto*VD = dyn_cast<VarDecl>(DRE->getDecl());
873 if(VD && VD->getType().isConstQualified() && VD->getInit() &&
875 Path.push_back({IndirectLocalPathEntry::VarInit, DRE, VD});
879}
else if(
auto*MTE = dyn_cast<MaterializeTemporaryExpr>(L)) {
880 if(MTE->getType().isConstQualified())
893 caseCK_BaseToDerived:
894 caseCK_DerivedToBase:
895 caseCK_UncheckedDerivedToBase:
898 caseCK_UserDefinedConversion:
899 caseCK_ConstructorConversion:
900 caseCK_IntegralToPointer:
901 caseCK_PointerToIntegral:
903 caseCK_IntegralCast:
904 caseCK_CPointerToObjCPointerCast:
905 caseCK_BlockPointerToObjCPointerCast:
906 caseCK_AnyPointerToBlockPointerCast:
907 caseCK_AddressSpaceConversion:
910 caseCK_ArrayToPointerDecay:
913 Path.push_back({IndirectLocalPathEntry::AddressOf, CE});
915 Path, CE->getSubExpr(), RK_ReferenceBinding, Visit);
921 Init= CE->getSubExpr();
923}
while(Old !=
Init);
928 if(
auto*ILE = dyn_cast<CXXStdInitializerListExpr>(
Init))
930RK_StdInitializerList, Visit);
936 if(!RevisitSubinits)
939 if(ILE->isTransparent())
943 if(ILE->getType()->isArrayType()) {
944 for(
unsignedI = 0, N = ILE->getNumInits(); I != N; ++I)
950 if(
CXXRecordDecl*RD = ILE->getType()->getAsCXXRecordDecl()) {
951assert(RD->isAggregate() &&
"aggregate init on non-aggregate");
956 if(RD->isUnion() && ILE->getInitializedFieldInUnion() &&
957ILE->getInitializedFieldInUnion()->getType()->isReferenceType())
959RK_ReferenceBinding, Visit);
962 for(; Index < RD->getNumBases() && Index < ILE->getNumInits(); ++Index)
965 for(
const auto*I : RD->fields()) {
966 if(Index >= ILE->getNumInits())
968 if(I->isUnnamedBitField())
970 Expr*SubInit = ILE->getInit(Index);
971 if(I->getType()->isReferenceType())
973RK_ReferenceBinding, Visit);
989 if(
auto*LE = dyn_cast<LambdaExpr>(
Init)) {
991 for(
Expr*
E: LE->capture_inits()) {
992assert(CapI != LE->capture_end());
997 Path.push_back({IndirectLocalPathEntry::LambdaCaptureInit,
E, &Cap});
998 if(
E->isGLValue())
1010 if(
auto*CCE = dyn_cast<CXXConstructExpr>(
Init)) {
1011 if(CCE->getConstructor()->isCopyOrMoveConstructor()) {
1012 if(
auto*MTE = dyn_cast<MaterializeTemporaryExpr>(CCE->getArg(0))) {
1013 Expr*Arg = MTE->getSubExpr();
1014 Path.push_back({IndirectLocalPathEntry::TemporaryCopy, Arg,
1015CCE->getConstructor()});
1022 if(isa<CallExpr>(
Init) || isa<CXXConstructExpr>(
Init))
1025 if(
auto*CPE = dyn_cast<CXXParenListInitExpr>(
Init)) {
1026RevertToOldSizeRAII RAII(
Path);
1027 Path.push_back({IndirectLocalPathEntry::ParenAggInit, CPE});
1028 for(
auto*I : CPE->getInitExprs()) {
1036 switch(
Init->getStmtClass()) {
1037 caseStmt::UnaryOperatorClass: {
1038 auto*UO = cast<UnaryOperator>(
Init);
1041 if(UO->getOpcode() == UO_AddrOf) {
1045 if(isa<MaterializeTemporaryExpr>(UO->getSubExpr()))
1048 Path.push_back({IndirectLocalPathEntry::AddressOf, UO});
1050RK_ReferenceBinding, Visit);
1055 caseStmt::BinaryOperatorClass: {
1057 auto*BO = cast<BinaryOperator>(
Init);
1059 if(!BO->getType()->isPointerType() || (BOK != BO_Add && BOK != BO_Sub))
1062 if(BO->getLHS()->getType()->isPointerType())
1064 else if(BO->getRHS()->getType()->isPointerType())
1069 caseStmt::ConditionalOperatorClass:
1070 caseStmt::BinaryConditionalOperatorClass: {
1071 auto*
C= cast<AbstractConditionalOperator>(
Init);
1074 if(!
C->getTrueExpr()->getType()->isVoidType())
1076 if(!
C->getFalseExpr()->getType()->isVoidType())
1081 caseStmt::BlockExprClass:
1082 if(cast<BlockExpr>(
Init)->getBlockDecl()->hasCaptures()) {
1084Visit(
Path, Local(cast<BlockExpr>(
Init)), RK_ReferenceBinding);
1088 caseStmt::AddrLabelExprClass:
1090Visit(
Path, Local(cast<AddrLabelExpr>(
Init)), RK_ReferenceBinding);
1110 for(
autoElem :
Path) {
1111 if(Elem.Kind == IndirectLocalPathEntry::MemberExpr ||
1112Elem.Kind == IndirectLocalPathEntry::LambdaCaptureInit)
1114 returnElem.Kind == IndirectLocalPathEntry::DefaultInit
1124 for(
unsignedN =
Path.size(); I != N; ++I) {
1126 caseIndirectLocalPathEntry::AddressOf:
1127 caseIndirectLocalPathEntry::LValToRVal:
1128 caseIndirectLocalPathEntry::LifetimeBoundCall:
1129 caseIndirectLocalPathEntry::TemporaryCopy:
1130 caseIndirectLocalPathEntry::GslReferenceInit:
1131 caseIndirectLocalPathEntry::GslPointerInit:
1132 caseIndirectLocalPathEntry::GslPointerAssignment:
1133 caseIndirectLocalPathEntry::ParenAggInit:
1134 caseIndirectLocalPathEntry::MemberExpr:
1139 caseIndirectLocalPathEntry::VarInit:
1140 if(cast<VarDecl>(
Path[I].
D)->isImplicit())
1143 caseIndirectLocalPathEntry::DefaultInit:
1144 return Path[I].E->getSourceRange();
1146 caseIndirectLocalPathEntry::LambdaCaptureInit:
1149 return Path[I].E->getSourceRange();
1151 caseIndirectLocalPathEntry::DefaultArg:
1152 returncast<CXXDefaultArgExpr>(
Path[I].
E)->getUsedLocation();
1155 return E->getSourceRange();
1159 for(
const auto&It : llvm::reverse(
Path)) {
1161 caseIndirectLocalPathEntry::VarInit:
1162 caseIndirectLocalPathEntry::AddressOf:
1163 caseIndirectLocalPathEntry::LifetimeBoundCall:
1164 caseIndirectLocalPathEntry::MemberExpr:
1166 caseIndirectLocalPathEntry::GslPointerInit:
1167 caseIndirectLocalPathEntry::GslReferenceInit:
1168 caseIndirectLocalPathEntry::GslPointerAssignment:
1191Local L, LifetimeKind LK) {
1199 for(
const auto&
E:
Path) {
1200 if(
E.Kind == IndirectLocalPathEntry::MemberExpr) {
1209 if(
const auto*FD = llvm::dyn_cast_or_null<FieldDecl>(
E.D);
1210FD && !FD->getType()->isReferenceType() &&
1211isRecordWithAttr<OwnerAttr>(FD->getType()) &&
1212LK != LK_MemInitializer) {
1226 if(
Path.back().Kind == IndirectLocalPathEntry::LifetimeBoundCall) {
1229llvm::dyn_cast_or_null<FunctionDecl>(
Path.back().D);
1231 if(
const auto*PD = llvm::dyn_cast<ParmVarDecl>(
Path.back().D))
1232FD = llvm::dyn_cast<FunctionDecl>(PD->getDeclContext());
1234 if(isa_and_present<CXXConstructorDecl>(FD)) {
1252 if(isa<DeclRefExpr>(L)) {
1264 auto*MTE = dyn_cast<MaterializeTemporaryExpr>(L);
1266 boolIsGslPtrValueFromGslTempOwner =
1267MTE && !MTE->getExtendingDecl() &&
1268isRecordWithAttr<OwnerAttr>(MTE->getType());
1273 if(!IsGslPtrValueFromGslTempOwner)
1287diag::warn_dangling_lifetime_pointer_assignment,
SourceLocation());
1288 return(EnableGSLAssignmentWarnings &&
1289(isRecordWithAttr<PointerAttr>(Entity.
LHS->
getType()) ||
1298assert(!AEntity || LK == LK_Assignment);
1299assert(!CapEntity || LK == LK_LifetimeCapture);
1300assert(!InitEntity || (LK != LK_Assignment && LK != LK_LifetimeCapture));
1303 if(LK == LK_FullExpression)
1308 autoTemporaryVisitor = [&](
constIndirectLocalPath &
Path, Local L,
1309ReferenceKind RK) ->
bool{
1313 auto*MTE = dyn_cast<MaterializeTemporaryExpr>(L);
1315 boolIsGslPtrValueFromGslTempOwner =
true;
1322IsGslPtrValueFromGslTempOwner =
false;
1329 caseLK_FullExpression:
1330llvm_unreachable(
"already handled this");
1342 if(IsGslPtrValueFromGslTempOwner && DiagLoc.
isValid()) {
1343SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1352MTE->setExtendingDecl(ExtendingEntity->
getDecl(),
1364SemaRef.
Diag(DiagLoc, diag::warn_dangling_variable)
1367<< ExtendingEntity->
getDecl() <<
Init->isGLValue() << DiagRange;
1373 caseLK_LifetimeCapture: {
1379SemaRef.
Diag(DiagLoc, diag::warn_dangling_reference_captured)
1380<< CapEntity->
Entity<< DiagRange;
1382SemaRef.
Diag(DiagLoc, diag::warn_dangling_reference_captured_by_unknown)
1387 caseLK_Assignment: {
1390 if(IsGslPtrValueFromGslTempOwner)
1391SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_assignment)
1392<< AEntity->
LHS<< DiagRange;
1394SemaRef.
Diag(DiagLoc, diag::warn_dangling_pointer_assignment)
1399 caseLK_MemInitializer: {
1404 if(
auto*ExtendingDecl =
1405ExtendingEntity ? ExtendingEntity->
getDecl() :
nullptr) {
1406 if(IsGslPtrValueFromGslTempOwner) {
1407SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer_member)
1408<< ExtendingDecl << DiagRange;
1409SemaRef.
Diag(ExtendingDecl->getLocation(),
1410diag::note_ref_or_ptr_member_declared_here)
1414 boolIsSubobjectMember = ExtendingEntity != InitEntity;
1417? diag::err_dangling_member
1418: diag::warn_dangling_member)
1419<< ExtendingDecl << IsSubobjectMember << RK << DiagRange;
1423 if(
Path.empty() ||
1424 Path.back().Kind != IndirectLocalPathEntry::DefaultInit) {
1425SemaRef.
Diag(ExtendingDecl->getLocation(),
1426diag::note_lifetime_extending_member_declared_here)
1427<< RK << IsSubobjectMember;
1445 auto*DRE = dyn_cast<DeclRefExpr>(L);
1449 if(DRE && isRecordWithAttr<OwnerAttr>(DRE->getType()))
1452 auto*VD = DRE ? dyn_cast<VarDecl>(DRE->getDecl()) :
nullptr;
1460ExtendingEntity ? ExtendingEntity->
getDecl() :
nullptr) {
1461 boolIsPointer = !
Member->getType()->isReferenceType();
1462SemaRef.
Diag(DiagLoc,
1463IsPointer ? diag::warn_init_ptr_member_to_parameter_addr
1464: diag::warn_bind_ref_member_to_parameter)
1465<< Member << VD << isa<ParmVarDecl>(VD) << DiagRange;
1467diag::note_ref_or_ptr_member_declared_here)
1475 if(isa<MaterializeTemporaryExpr>(L)) {
1476 if(IsGslPtrValueFromGslTempOwner)
1477SemaRef.
Diag(DiagLoc, diag::warn_dangling_lifetime_pointer)
1480SemaRef.
Diag(DiagLoc, RK == RK_ReferenceBinding
1481? diag::warn_new_dangling_reference
1482: diag::warn_new_dangling_initializer_list)
1483<< !InitEntity->
getParent() << DiagRange;
1492 caseLK_StmtExprResult:
1493 if(
auto*DRE = dyn_cast<DeclRefExpr>(L)) {
1496 if(LK == LK_StmtExprResult)
1498SemaRef.
Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1500<< isa<ParmVarDecl>(DRE->getDecl()) << (LK == LK_MustTail)
1502}
else if(isa<BlockExpr>(L)) {
1503SemaRef.
Diag(DiagLoc, diag::err_ret_local_block) << DiagRange;
1504}
else if(isa<AddrLabelExpr>(L)) {
1507 if(LK == LK_StmtExprResult)
1509SemaRef.
Diag(DiagLoc, diag::warn_ret_addr_label) << DiagRange;
1510}
else if(
auto*CLE = dyn_cast<CompoundLiteralExpr>(L)) {
1511SemaRef.
Diag(DiagLoc, diag::warn_ret_stack_addr_ref)
1513<< 2 << (LK == LK_MustTail) << DiagRange;
1522SemaRef.
Diag(DiagLoc, diag::err_ret_local_temp_ref)
1524 else if(LK == LK_MustTail)
1525SemaRef.
Diag(DiagLoc, diag::warn_musttail_local_temp_addr_ref)
1528SemaRef.
Diag(DiagLoc, diag::warn_ret_local_temp_addr_ref)
1534 for(
unsignedI = 0; I !=
Path.size(); ++I) {
1535 autoElem =
Path[I];
1537 switch(Elem.Kind) {
1538 caseIndirectLocalPathEntry::AddressOf:
1539 caseIndirectLocalPathEntry::LValToRVal:
1540 caseIndirectLocalPathEntry::ParenAggInit:
1545 caseIndirectLocalPathEntry::LifetimeBoundCall:
1546 caseIndirectLocalPathEntry::TemporaryCopy:
1547 caseIndirectLocalPathEntry::MemberExpr:
1548 caseIndirectLocalPathEntry::GslPointerInit:
1549 caseIndirectLocalPathEntry::GslReferenceInit:
1550 caseIndirectLocalPathEntry::GslPointerAssignment:
1554 caseIndirectLocalPathEntry::DefaultInit: {
1555 auto*FD = cast<FieldDecl>(Elem.D);
1556SemaRef.
Diag(FD->getLocation(),
1557diag::note_init_with_default_member_initializer)
1562 caseIndirectLocalPathEntry::VarInit: {
1563 const VarDecl*VD = cast<VarDecl>(Elem.D);
1570 caseIndirectLocalPathEntry::LambdaCaptureInit: {
1571 if(!Elem.Capture->capturesVariable())
1575 const ValueDecl*VD = Elem.Capture->getCapturedVar();
1576SemaRef.
Diag(Elem.Capture->getLocation(),
1577diag::note_lambda_capture_initializer)
1578<< VD << VD->
isInitCapture() << Elem.Capture->isExplicit()
1579<< (Elem.Capture->getCaptureKind() ==
LCK_ByRef) << VD
1584 caseIndirectLocalPathEntry::DefaultArg: {
1585 const auto*DAE = cast<CXXDefaultArgExpr>(Elem.E);
1588diag::note_init_with_default_argument)
1602 caseLK_Assignment: {
1606? IndirectLocalPathEntry::LifetimeBoundCall
1607: IndirectLocalPathEntry::GslPointerAssignment,
1611 caseLK_LifetimeCapture: {
1613 Path.push_back({IndirectLocalPathEntry::GslPointerInit,
Init});
1620 if(
Init->isGLValue())
1633LifetimeKind LK = LTResult.getInt();
1636 nullptr,
nullptr, Init);
1642 nullptr,
nullptr, Init);
1649 boolRunAnalysis = (EnableDanglingPointerAssignment &&
1657 nullptr, LK_Assignment, &Entity,
1666diag::warn_dangling_reference_captured_by_unknown,
SourceLocation()))
1669 nullptr, LK_LifetimeCapture,
enum clang::sema::@1704::IndirectLocalPathEntry::EntryKind Kind
const LambdaCapture * Capture
C Language Family Type Representation.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Type source information for an attributed type.
TypeLoc getModifiedLoc() const
The modified type, which is generally canonically different from the attribute type.
Represents binding an expression to a temporary.
Represents a call to a C++ constructor.
Expr * getArg(unsigned Arg)
Return the specified argument.
CXXConstructorDecl * getConstructor() const
Get the constructor that this expression will (ultimately) call.
Represents a C++ constructor within a class.
Represents a static or instance method of a struct/union/class.
const CXXRecordDecl * getParent() const
Return the parent of this method declaration, which is the class in which this method is defined.
Represents a C++ struct/union/class.
CastExpr - Base class for type casts, including both implicit casts (ImplicitCastExpr) and explicit c...
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
bool isStdNamespace() const
Decl - This represents one declaration (or definition), e.g.
bool isInStdNamespace() const
ASTContext & getASTContext() const LLVM_READONLY
bool isImplicit() const
isImplicit - Indicates whether the declaration was implicitly generated by the implementation.
SourceLocation getLocation() const
OverloadedOperatorKind getCXXOverloadedOperator() const
If this name is the name of an overloadable operator in C++ (e.g., operator+), retrieve the kind of o...
TypeSourceInfo * getTypeSourceInfo() const
bool isIgnored(unsigned DiagID, SourceLocation Loc) const
Determine whether the diagnostic is known to be ignored.
This represents one expression.
Expr * IgnoreImplicit() LLVM_READONLY
Skip past any implicit AST nodes which might surround this expression until reaching a fixed point.
Represents a function declaration or definition.
const ParmVarDecl * getParamDecl(unsigned i) const
QualType getReturnType() const
FunctionTemplateDecl * getPrimaryTemplate() const
Retrieve the primary template that this function template specialization either specializes or was in...
unsigned getNumParams() const
Return the number of parameters this function must have based on its FunctionType.
size_t param_size() const
One of these records is kept for each identifier that is lexed.
Describes an C or C++ initializer list.
Describes an entity that is being initialized.
EntityKind getKind() const
Determine the kind of initialization.
unsigned allocateManglingNumber() const
QualType getType() const
Retrieve type being initialized.
ValueDecl * getDecl() const
Retrieve the variable, parameter, or field being initialized.
const InitializedEntity * getParent() const
Retrieve the parent of the entity being initialized, when the initialization itself is occurring with...
@ EK_Variable
The entity being initialized is a variable.
@ EK_Temporary
The entity being initialized is a temporary object.
@ EK_Binding
The entity being initialized is a structured binding of a decomposition declaration.
@ EK_BlockElement
The entity being initialized is a field of block descriptor for the copied-in c++ object.
@ EK_Parameter_CF_Audited
The entity being initialized is a function parameter; function is member of group of audited CF APIs.
@ EK_LambdaToBlockConversionBlockElement
The entity being initialized is a field of block descriptor for the copied-in lambda object that's us...
@ EK_Member
The entity being initialized is a non-static data member subobject.
@ EK_Base
The entity being initialized is a base member subobject.
@ EK_Result
The entity being initialized is the result of a function call.
@ EK_TemplateParameter
The entity being initialized is a non-type template parameter.
@ EK_StmtExprResult
The entity being initialized is the result of a statement expression.
@ EK_ParenAggInitMember
The entity being initialized is a non-static data member subobject of an object initialized via paren...
@ EK_VectorElement
The entity being initialized is an element of a vector.
@ EK_New
The entity being initialized is an object (or array of objects) allocated via new.
@ EK_CompoundLiteralInit
The entity being initialized is the initializer for a compound literal.
@ EK_Parameter
The entity being initialized is a function parameter.
@ EK_Delegating
The initialization is being done by a delegating constructor.
@ EK_ComplexElement
The entity being initialized is the real or imaginary part of a complex number.
@ EK_ArrayElement
The entity being initialized is an element of an array.
@ EK_LambdaCapture
The entity being initialized is the field that captures a variable in a lambda.
@ EK_Exception
The entity being initialized is an exception object that is being thrown.
@ EK_RelatedResult
The entity being implicitly initialized back to the formal result type.
bool isDefaultMemberInitializer() const
Is this the default member initializer of a member (specified inside the class definition)?
Describes the capture of a variable or of this, or of a C++1y init-capture.
bool capturesVariable() const
Determine whether this capture handles a variable.
MemberExpr - [C99 6.5.2.3] Structure and Union Members.
IdentifierInfo * getIdentifier() const
Get the identifier that names this declaration, if there is one.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Represents a parameter to a function.
SourceRange getDefaultArgRange() const
Retrieve the source range that covers the entire default argument.
A (possibly-)qualified type.
Represents a struct/union/class.
decl_type * getMostRecentDecl()
Returns the most recent (re)declaration of this declaration.
Base for LValueReferenceType and RValueReferenceType.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Sema - This implements semantic analysis and AST building for C.
DiagnosticsEngine & getDiagnostics() const
const LangOptions & getLangOpts() const
static bool CanBeGetReturnObject(const FunctionDecl *FD)
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
@ Type
The template argument is a type.
Represents a type template specialization; the template must be a class template, a type alias templa...
Base wrapper for a particular "section" of type source info.
T getAsAdjusted() const
Convert to the specified TypeLoc type, returning a null TypeLoc if this TypeLoc is not of the desired...
A container of type source information.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
The base class of the type hierarchy.
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
bool hasAttr(attr::Kind AK) const
Determine whether this type had the specified attribute applied to it (looking through top-level type...
bool isPointerType() const
bool isReferenceType() const
const CXXRecordDecl * getPointeeCXXRecordDecl() const
If this is a pointer or reference to a RecordType, return the CXXRecordDecl that the type refers to.
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isLValueReferenceType() const
const T * getAs() const
Member-template getAs<specific type>'.
bool isNullPtrType() const
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
UnaryOperator - This represents the unary-expression's (except sizeof and alignof),...
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
bool isInitCapture() const
Whether this variable is the implicit variable for a lambda init-capture.
Represents a variable declaration or definition.
static bool isStdInitializerListOfPointer(const RecordDecl *RD)
bool implicitObjectParamIsLifetimeBound(const FunctionDecl *FD)
static void checkExprLifetimeImpl(Sema &SemaRef, const InitializedEntity *InitEntity, const InitializedEntity *ExtendingEntity, LifetimeKind LK, const AssignedEntity *AEntity, const CapturingEntity *CapEntity, Expr *Init)
static bool shouldRunGSLAssignmentAnalysis(const Sema &SemaRef, const AssignedEntity &Entity)
static void visitLocalsRetainedByReferenceBinding(IndirectLocalPath &Path, Expr *Init, ReferenceKind RK, LocalVisitor Visit)
Visit the locals that would be reachable through a reference bound to the glvalue expression Init.
void checkExprLifetimeMustTailArg(Sema &SemaRef, const InitializedEntity &Entity, Expr *Init)
Check that the lifetime of the given expr (and its subobjects) is sufficient, assuming that it is pas...
static bool pathOnlyHandlesGslPointer(const IndirectLocalPath &Path)
static void visitLocalsRetainedByInitializer(IndirectLocalPath &Path, Expr *Init, LocalVisitor Visit, bool RevisitSubinits)
Visit the locals that would be reachable through an object initialized by the prvalue expression Init...
static bool isNormalAssignmentOperator(const FunctionDecl *FD)
static AnalysisResult analyzePathForGSLPointer(const IndirectLocalPath &Path, Local L, LifetimeKind LK)
static bool isInStlNamespace(const Decl *D)
static bool isRecordWithAttr(QualType Type)
bool isGLSPointerType(QualType QT)
static bool shouldTrackFirstArgument(const FunctionDecl *FD)
static bool isContainerOfOwner(const RecordDecl *Container)
static SourceRange nextPathEntryRange(const IndirectLocalPath &Path, unsigned I, Expr *E)
Find the range for the first interesting entry in the path at or after I.
static LifetimeResult getEntityLifetime(const InitializedEntity *Entity, const InitializedEntity *InitField=nullptr)
Determine the declaration which an initialized entity ultimately refers to, for the purpose of lifeti...
static const FunctionDecl * getDeclWithMergedLifetimeBoundAttrs(const FunctionDecl *FD)
static bool isContainerOfPointer(const RecordDecl *Container)
void checkInitLifetime(Sema &SemaRef, const InitializedEntity &Entity, Expr *Init)
Check that the lifetime of the given expr (and its subobjects) is sufficient for initializing the ent...
static bool isCopyLikeConstructor(const CXXConstructorDecl *Ctor)
void checkAssignmentLifetime(Sema &SemaRef, const AssignedEntity &Entity, Expr *Init)
Check that the lifetime of the given expr (and its subobjects) is sufficient for assigning to the ent...
static bool shouldTrackFirstArgumentForConstructor(const CXXConstructExpr *Ctor)
PathLifetimeKind
Whether a path to an object supports lifetime extension.
@ NoExtend
Do not lifetime extend along this path.
@ Extend
Lifetime-extend along this path.
static bool isVarOnPath(const IndirectLocalPath &Path, VarDecl *VD)
static bool pathContainsInit(const IndirectLocalPath &Path)
static bool isPointerLikeType(QualType QT)
static void visitFunctionCallArguments(IndirectLocalPath &Path, Expr *Call, LocalVisitor Visit)
void checkCaptureByLifetime(Sema &SemaRef, const CapturingEntity &Entity, Expr *Init)
static bool shouldTrackImplicitObjectArg(const CXXMethodDecl *Callee)
static bool isAssignmentOperatorLifetimeBound(const CXXMethodDecl *CMD)
static PathLifetimeKind shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path)
Determine whether this is an indirect path to a temporary that we are supposed to lifetime-extend alo...
OverloadedOperatorKind
Enumeration specifying the different kinds of C++ overloaded operators.
bool isCompoundAssignmentOperator(OverloadedOperatorKind Kind)
Determine if this is a compound assignment operator.
LLVM_READONLY bool isUppercase(unsigned char c)
Return true if this character is an uppercase ASCII letter: [A-Z].
@ LCK_ByRef
Capturing by reference.
@ Result
The result type of a method or function.
const FunctionProtoType * T
Describes an entity that is being assigned.
CXXMethodDecl * AssignmentOperator
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4