xref: /freebsd-src/contrib/llvm-project/clang/lib/Sema/ScopeInfo.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //===--- ScopeInfo.cpp - Information about a semantic context -------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements FunctionScopeInfo and its subclasses, which contain
100b57cec5SDimitry Andric // information about a single function, block, lambda, or method body.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "clang/Sema/ScopeInfo.h"
150b57cec5SDimitry Andric #include "clang/AST/Decl.h"
160b57cec5SDimitry Andric #include "clang/AST/DeclCXX.h"
170b57cec5SDimitry Andric #include "clang/AST/DeclObjC.h"
180b57cec5SDimitry Andric #include "clang/AST/Expr.h"
190b57cec5SDimitry Andric #include "clang/AST/ExprCXX.h"
200b57cec5SDimitry Andric #include "clang/AST/ExprObjC.h"
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric using namespace clang;
230b57cec5SDimitry Andric using namespace sema;
240b57cec5SDimitry Andric 
250b57cec5SDimitry Andric void FunctionScopeInfo::Clear() {
260b57cec5SDimitry Andric   HasBranchProtectedScope = false;
270b57cec5SDimitry Andric   HasBranchIntoScope = false;
280b57cec5SDimitry Andric   HasIndirectGoto = false;
290b57cec5SDimitry Andric   HasDroppedStmt = false;
300b57cec5SDimitry Andric   HasOMPDeclareReductionCombiner = false;
310b57cec5SDimitry Andric   HasFallthroughStmt = false;
32e8d8bef9SDimitry Andric   UsesFPIntrin = false;
330b57cec5SDimitry Andric   HasPotentialAvailabilityViolations = false;
340b57cec5SDimitry Andric   ObjCShouldCallSuper = false;
350b57cec5SDimitry Andric   ObjCIsDesignatedInit = false;
360b57cec5SDimitry Andric   ObjCWarnForNoDesignatedInitChain = false;
370b57cec5SDimitry Andric   ObjCIsSecondaryInit = false;
380b57cec5SDimitry Andric   ObjCWarnForNoInitDelegation = false;
390b57cec5SDimitry Andric   FirstReturnLoc = SourceLocation();
40349cc55cSDimitry Andric   FirstCXXOrObjCTryLoc = SourceLocation();
410b57cec5SDimitry Andric   FirstSEHTryLoc = SourceLocation();
42*0fca6ea1SDimitry Andric   FirstVLALoc = SourceLocation();
4306c3fb27SDimitry Andric   FoundImmediateEscalatingExpression = false;
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric   // Coroutine state
460b57cec5SDimitry Andric   FirstCoroutineStmtLoc = SourceLocation();
470b57cec5SDimitry Andric   CoroutinePromise = nullptr;
480b57cec5SDimitry Andric   CoroutineParameterMoves.clear();
490b57cec5SDimitry Andric   NeedsCoroutineSuspends = true;
500b57cec5SDimitry Andric   CoroutineSuspends.first = nullptr;
510b57cec5SDimitry Andric   CoroutineSuspends.second = nullptr;
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric   SwitchStack.clear();
540b57cec5SDimitry Andric   Returns.clear();
550b57cec5SDimitry Andric   ErrorTrap.reset();
560b57cec5SDimitry Andric   PossiblyUnreachableDiags.clear();
570b57cec5SDimitry Andric   WeakObjectUses.clear();
580b57cec5SDimitry Andric   ModifiedNonNullParams.clear();
590b57cec5SDimitry Andric   Blocks.clear();
600b57cec5SDimitry Andric   ByrefBlockVars.clear();
61bdd1243dSDimitry Andric   AddrLabels.clear();
620b57cec5SDimitry Andric }
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric static const NamedDecl *getBestPropertyDecl(const ObjCPropertyRefExpr *PropE) {
650b57cec5SDimitry Andric   if (PropE->isExplicitProperty())
660b57cec5SDimitry Andric     return PropE->getExplicitProperty();
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric   return PropE->getImplicitPropertyGetter();
690b57cec5SDimitry Andric }
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric FunctionScopeInfo::WeakObjectProfileTy::BaseInfoTy
720b57cec5SDimitry Andric FunctionScopeInfo::WeakObjectProfileTy::getBaseInfo(const Expr *E) {
730b57cec5SDimitry Andric   E = E->IgnoreParenCasts();
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric   const NamedDecl *D = nullptr;
760b57cec5SDimitry Andric   bool IsExact = false;
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric   switch (E->getStmtClass()) {
790b57cec5SDimitry Andric   case Stmt::DeclRefExprClass:
800b57cec5SDimitry Andric     D = cast<DeclRefExpr>(E)->getDecl();
810b57cec5SDimitry Andric     IsExact = isa<VarDecl>(D);
820b57cec5SDimitry Andric     break;
830b57cec5SDimitry Andric   case Stmt::MemberExprClass: {
840b57cec5SDimitry Andric     const MemberExpr *ME = cast<MemberExpr>(E);
850b57cec5SDimitry Andric     D = ME->getMemberDecl();
860b57cec5SDimitry Andric     IsExact = isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts());
870b57cec5SDimitry Andric     break;
880b57cec5SDimitry Andric   }
890b57cec5SDimitry Andric   case Stmt::ObjCIvarRefExprClass: {
900b57cec5SDimitry Andric     const ObjCIvarRefExpr *IE = cast<ObjCIvarRefExpr>(E);
910b57cec5SDimitry Andric     D = IE->getDecl();
920b57cec5SDimitry Andric     IsExact = IE->getBase()->isObjCSelfExpr();
930b57cec5SDimitry Andric     break;
940b57cec5SDimitry Andric   }
950b57cec5SDimitry Andric   case Stmt::PseudoObjectExprClass: {
960b57cec5SDimitry Andric     const PseudoObjectExpr *POE = cast<PseudoObjectExpr>(E);
970b57cec5SDimitry Andric     const ObjCPropertyRefExpr *BaseProp =
980b57cec5SDimitry Andric       dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm());
990b57cec5SDimitry Andric     if (BaseProp) {
1000b57cec5SDimitry Andric       D = getBestPropertyDecl(BaseProp);
1010b57cec5SDimitry Andric 
1020b57cec5SDimitry Andric       if (BaseProp->isObjectReceiver()) {
1030b57cec5SDimitry Andric         const Expr *DoubleBase = BaseProp->getBase();
1040b57cec5SDimitry Andric         if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(DoubleBase))
1050b57cec5SDimitry Andric           DoubleBase = OVE->getSourceExpr();
1060b57cec5SDimitry Andric 
1070b57cec5SDimitry Andric         IsExact = DoubleBase->isObjCSelfExpr();
1080b57cec5SDimitry Andric       }
1090b57cec5SDimitry Andric     }
1100b57cec5SDimitry Andric     break;
1110b57cec5SDimitry Andric   }
1120b57cec5SDimitry Andric   default:
1130b57cec5SDimitry Andric     break;
1140b57cec5SDimitry Andric   }
1150b57cec5SDimitry Andric 
1160b57cec5SDimitry Andric   return BaseInfoTy(D, IsExact);
1170b57cec5SDimitry Andric }
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
1200b57cec5SDimitry Andric                                           const ObjCPropertyRefExpr *PropE)
1210b57cec5SDimitry Andric     : Base(nullptr, true), Property(getBestPropertyDecl(PropE)) {
1220b57cec5SDimitry Andric 
1230b57cec5SDimitry Andric   if (PropE->isObjectReceiver()) {
1240b57cec5SDimitry Andric     const OpaqueValueExpr *OVE = cast<OpaqueValueExpr>(PropE->getBase());
1250b57cec5SDimitry Andric     const Expr *E = OVE->getSourceExpr();
1260b57cec5SDimitry Andric     Base = getBaseInfo(E);
1270b57cec5SDimitry Andric   } else if (PropE->isClassReceiver()) {
1280b57cec5SDimitry Andric     Base.setPointer(PropE->getClassReceiver());
1290b57cec5SDimitry Andric   } else {
1300b57cec5SDimitry Andric     assert(PropE->isSuperReceiver());
1310b57cec5SDimitry Andric   }
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(const Expr *BaseE,
1350b57cec5SDimitry Andric                                                 const ObjCPropertyDecl *Prop)
1360b57cec5SDimitry Andric     : Base(nullptr, true), Property(Prop) {
1370b57cec5SDimitry Andric   if (BaseE)
1380b57cec5SDimitry Andric     Base = getBaseInfo(BaseE);
1390b57cec5SDimitry Andric   // else, this is a message accessing a property on super.
1400b57cec5SDimitry Andric }
1410b57cec5SDimitry Andric 
1420b57cec5SDimitry Andric FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
1430b57cec5SDimitry Andric                                                       const DeclRefExpr *DRE)
1440b57cec5SDimitry Andric   : Base(nullptr, true), Property(DRE->getDecl()) {
1450b57cec5SDimitry Andric   assert(isa<VarDecl>(Property));
1460b57cec5SDimitry Andric }
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
1490b57cec5SDimitry Andric                                                   const ObjCIvarRefExpr *IvarE)
1500b57cec5SDimitry Andric   : Base(getBaseInfo(IvarE->getBase())), Property(IvarE->getDecl()) {
1510b57cec5SDimitry Andric }
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric void FunctionScopeInfo::recordUseOfWeak(const ObjCMessageExpr *Msg,
1540b57cec5SDimitry Andric                                         const ObjCPropertyDecl *Prop) {
1550b57cec5SDimitry Andric   assert(Msg && Prop);
1560b57cec5SDimitry Andric   WeakUseVector &Uses =
1570b57cec5SDimitry Andric     WeakObjectUses[WeakObjectProfileTy(Msg->getInstanceReceiver(), Prop)];
1580b57cec5SDimitry Andric   Uses.push_back(WeakUseTy(Msg, Msg->getNumArgs() == 0));
1590b57cec5SDimitry Andric }
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric void FunctionScopeInfo::markSafeWeakUse(const Expr *E) {
1620b57cec5SDimitry Andric   E = E->IgnoreParenCasts();
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric   if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) {
1650b57cec5SDimitry Andric     markSafeWeakUse(POE->getSyntacticForm());
1660b57cec5SDimitry Andric     return;
1670b57cec5SDimitry Andric   }
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric   if (const ConditionalOperator *Cond = dyn_cast<ConditionalOperator>(E)) {
1700b57cec5SDimitry Andric     markSafeWeakUse(Cond->getTrueExpr());
1710b57cec5SDimitry Andric     markSafeWeakUse(Cond->getFalseExpr());
1720b57cec5SDimitry Andric     return;
1730b57cec5SDimitry Andric   }
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric   if (const BinaryConditionalOperator *Cond =
1760b57cec5SDimitry Andric         dyn_cast<BinaryConditionalOperator>(E)) {
1770b57cec5SDimitry Andric     markSafeWeakUse(Cond->getCommon());
1780b57cec5SDimitry Andric     markSafeWeakUse(Cond->getFalseExpr());
1790b57cec5SDimitry Andric     return;
1800b57cec5SDimitry Andric   }
1810b57cec5SDimitry Andric 
1820b57cec5SDimitry Andric   // Has this weak object been seen before?
1830b57cec5SDimitry Andric   FunctionScopeInfo::WeakObjectUseMap::iterator Uses = WeakObjectUses.end();
1840b57cec5SDimitry Andric   if (const ObjCPropertyRefExpr *RefExpr = dyn_cast<ObjCPropertyRefExpr>(E)) {
1850b57cec5SDimitry Andric     if (!RefExpr->isObjectReceiver())
1860b57cec5SDimitry Andric       return;
1870b57cec5SDimitry Andric     if (isa<OpaqueValueExpr>(RefExpr->getBase()))
1880b57cec5SDimitry Andric      Uses = WeakObjectUses.find(WeakObjectProfileTy(RefExpr));
1890b57cec5SDimitry Andric     else {
1900b57cec5SDimitry Andric       markSafeWeakUse(RefExpr->getBase());
1910b57cec5SDimitry Andric       return;
1920b57cec5SDimitry Andric     }
1930b57cec5SDimitry Andric   }
1940b57cec5SDimitry Andric   else if (const ObjCIvarRefExpr *IvarE = dyn_cast<ObjCIvarRefExpr>(E))
1950b57cec5SDimitry Andric     Uses = WeakObjectUses.find(WeakObjectProfileTy(IvarE));
1960b57cec5SDimitry Andric   else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) {
1970b57cec5SDimitry Andric     if (isa<VarDecl>(DRE->getDecl()))
1980b57cec5SDimitry Andric       Uses = WeakObjectUses.find(WeakObjectProfileTy(DRE));
1990b57cec5SDimitry Andric   } else if (const ObjCMessageExpr *MsgE = dyn_cast<ObjCMessageExpr>(E)) {
2000b57cec5SDimitry Andric     if (const ObjCMethodDecl *MD = MsgE->getMethodDecl()) {
2010b57cec5SDimitry Andric       if (const ObjCPropertyDecl *Prop = MD->findPropertyDecl()) {
2020b57cec5SDimitry Andric         Uses =
2030b57cec5SDimitry Andric           WeakObjectUses.find(WeakObjectProfileTy(MsgE->getInstanceReceiver(),
2040b57cec5SDimitry Andric                                                   Prop));
2050b57cec5SDimitry Andric       }
2060b57cec5SDimitry Andric     }
2070b57cec5SDimitry Andric   }
2080b57cec5SDimitry Andric   else
2090b57cec5SDimitry Andric     return;
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric   if (Uses == WeakObjectUses.end())
2120b57cec5SDimitry Andric     return;
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric   // Has there been a read from the object using this Expr?
2150b57cec5SDimitry Andric   FunctionScopeInfo::WeakUseVector::reverse_iterator ThisUse =
2160b57cec5SDimitry Andric       llvm::find(llvm::reverse(Uses->second), WeakUseTy(E, true));
2170b57cec5SDimitry Andric   if (ThisUse == Uses->second.rend())
2180b57cec5SDimitry Andric     return;
2190b57cec5SDimitry Andric 
2200b57cec5SDimitry Andric   ThisUse->markSafe();
2210b57cec5SDimitry Andric }
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric bool Capture::isInitCapture() const {
2240b57cec5SDimitry Andric   // Note that a nested capture of an init-capture is not itself an
2250b57cec5SDimitry Andric   // init-capture.
2260b57cec5SDimitry Andric   return !isNested() && isVariableCapture() && getVariable()->isInitCapture();
2270b57cec5SDimitry Andric }
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric bool CapturingScopeInfo::isVLATypeCaptured(const VariableArrayType *VAT) const {
2300b57cec5SDimitry Andric   for (auto &Cap : Captures)
2310b57cec5SDimitry Andric     if (Cap.isVLATypeCapture() && Cap.getCapturedVLAType() == VAT)
2320b57cec5SDimitry Andric       return true;
2330b57cec5SDimitry Andric   return false;
2340b57cec5SDimitry Andric }
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric void LambdaScopeInfo::visitPotentialCaptures(
237bdd1243dSDimitry Andric     llvm::function_ref<void(ValueDecl *, Expr *)> Callback) const {
2380b57cec5SDimitry Andric   for (Expr *E : PotentiallyCapturingExprs) {
2390b57cec5SDimitry Andric     if (auto *DRE = dyn_cast<DeclRefExpr>(E)) {
240bdd1243dSDimitry Andric       Callback(cast<ValueDecl>(DRE->getFoundDecl()), E);
2410b57cec5SDimitry Andric     } else if (auto *ME = dyn_cast<MemberExpr>(E)) {
242bdd1243dSDimitry Andric       Callback(cast<ValueDecl>(ME->getMemberDecl()), E);
2430b57cec5SDimitry Andric     } else if (auto *FP = dyn_cast<FunctionParmPackExpr>(E)) {
244bdd1243dSDimitry Andric       for (ValueDecl *VD : *FP)
2450b57cec5SDimitry Andric         Callback(VD, E);
2460b57cec5SDimitry Andric     } else {
2470b57cec5SDimitry Andric       llvm_unreachable("unexpected expression in potential captures list");
2480b57cec5SDimitry Andric     }
2490b57cec5SDimitry Andric   }
2500b57cec5SDimitry Andric }
2510b57cec5SDimitry Andric 
2525f757f3fSDimitry Andric bool LambdaScopeInfo::lambdaCaptureShouldBeConst() const {
2535f757f3fSDimitry Andric   if (ExplicitObjectParameter)
2545f757f3fSDimitry Andric     return ExplicitObjectParameter->getType()
2555f757f3fSDimitry Andric         .getNonReferenceType()
2565f757f3fSDimitry Andric         .isConstQualified();
2575f757f3fSDimitry Andric   return !Mutable;
2585f757f3fSDimitry Andric }
2595f757f3fSDimitry Andric 
2600b57cec5SDimitry Andric FunctionScopeInfo::~FunctionScopeInfo() { }
2610b57cec5SDimitry Andric BlockScopeInfo::~BlockScopeInfo() { }
2620b57cec5SDimitry Andric CapturedRegionScopeInfo::~CapturedRegionScopeInfo() { }
263