forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			241 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			241 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===--- ScopeInfo.cpp - Information about a semantic context -------------===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| //
 | |
| // This file implements FunctionScopeInfo and its subclasses, which contain
 | |
| // information about a single function, block, lambda, or method body.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #include "clang/Sema/ScopeInfo.h"
 | |
| #include "clang/AST/Decl.h"
 | |
| #include "clang/AST/DeclCXX.h"
 | |
| #include "clang/AST/DeclObjC.h"
 | |
| #include "clang/AST/Expr.h"
 | |
| #include "clang/AST/ExprCXX.h"
 | |
| #include "clang/AST/ExprObjC.h"
 | |
| 
 | |
| using namespace clang;
 | |
| using namespace sema;
 | |
| 
 | |
| void FunctionScopeInfo::Clear() {
 | |
|   HasBranchProtectedScope = false;
 | |
|   HasBranchIntoScope = false;
 | |
|   HasIndirectGoto = false;
 | |
|   HasDroppedStmt = false;
 | |
|   ObjCShouldCallSuper = false;
 | |
|   ObjCIsDesignatedInit = false;
 | |
|   ObjCWarnForNoDesignatedInitChain = false;
 | |
|   ObjCIsSecondaryInit = false;
 | |
|   ObjCWarnForNoInitDelegation = false;
 | |
|   FirstReturnLoc = SourceLocation();
 | |
|   FirstCXXTryLoc = SourceLocation();
 | |
|   FirstSEHTryLoc = SourceLocation();
 | |
| 
 | |
|   SwitchStack.clear();
 | |
|   Returns.clear();
 | |
|   CoroutinePromise = nullptr;
 | |
|   CoroutineStmts.clear();
 | |
|   ErrorTrap.reset();
 | |
|   PossiblyUnreachableDiags.clear();
 | |
|   WeakObjectUses.clear();
 | |
|   ModifiedNonNullParams.clear();
 | |
| }
 | |
| 
 | |
| static const NamedDecl *getBestPropertyDecl(const ObjCPropertyRefExpr *PropE) {
 | |
|   if (PropE->isExplicitProperty())
 | |
|     return PropE->getExplicitProperty();
 | |
| 
 | |
|   return PropE->getImplicitPropertyGetter();
 | |
| }
 | |
| 
 | |
| FunctionScopeInfo::WeakObjectProfileTy::BaseInfoTy
 | |
| FunctionScopeInfo::WeakObjectProfileTy::getBaseInfo(const Expr *E) {
 | |
|   E = E->IgnoreParenCasts();
 | |
| 
 | |
|   const NamedDecl *D = nullptr;
 | |
|   bool IsExact = false;
 | |
| 
 | |
|   switch (E->getStmtClass()) {
 | |
|   case Stmt::DeclRefExprClass:
 | |
|     D = cast<DeclRefExpr>(E)->getDecl();
 | |
|     IsExact = isa<VarDecl>(D);
 | |
|     break;
 | |
|   case Stmt::MemberExprClass: {
 | |
|     const MemberExpr *ME = cast<MemberExpr>(E);
 | |
|     D = ME->getMemberDecl();
 | |
|     IsExact = isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts());
 | |
|     break;
 | |
|   }
 | |
|   case Stmt::ObjCIvarRefExprClass: {
 | |
|     const ObjCIvarRefExpr *IE = cast<ObjCIvarRefExpr>(E);
 | |
|     D = IE->getDecl();
 | |
|     IsExact = IE->getBase()->isObjCSelfExpr();
 | |
|     break;
 | |
|   }
 | |
|   case Stmt::PseudoObjectExprClass: {
 | |
|     const PseudoObjectExpr *POE = cast<PseudoObjectExpr>(E);
 | |
|     const ObjCPropertyRefExpr *BaseProp =
 | |
|       dyn_cast<ObjCPropertyRefExpr>(POE->getSyntacticForm());
 | |
|     if (BaseProp) {
 | |
|       D = getBestPropertyDecl(BaseProp);
 | |
| 
 | |
|       const Expr *DoubleBase = BaseProp->getBase();
 | |
|       if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(DoubleBase))
 | |
|         DoubleBase = OVE->getSourceExpr();
 | |
| 
 | |
|       IsExact = DoubleBase->isObjCSelfExpr();
 | |
|     }
 | |
|     break;
 | |
|   }
 | |
|   default:
 | |
|     break;
 | |
|   }
 | |
| 
 | |
|   return BaseInfoTy(D, IsExact);
 | |
| }
 | |
| 
 | |
| bool CapturingScopeInfo::isVLATypeCaptured(const VariableArrayType *VAT) const {
 | |
|   RecordDecl *RD = nullptr;
 | |
|   if (auto *LSI = dyn_cast<LambdaScopeInfo>(this))
 | |
|     RD = LSI->Lambda;
 | |
|   else if (auto CRSI = dyn_cast<CapturedRegionScopeInfo>(this))
 | |
|     RD = CRSI->TheRecordDecl;
 | |
| 
 | |
|   if (RD)
 | |
|     for (auto *FD : RD->fields()) {
 | |
|       if (FD->hasCapturedVLAType() && FD->getCapturedVLAType() == VAT)
 | |
|         return true;
 | |
|     }
 | |
|   return false;
 | |
| }
 | |
| 
 | |
| FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
 | |
|                                           const ObjCPropertyRefExpr *PropE)
 | |
|     : Base(nullptr, true), Property(getBestPropertyDecl(PropE)) {
 | |
| 
 | |
|   if (PropE->isObjectReceiver()) {
 | |
|     const OpaqueValueExpr *OVE = cast<OpaqueValueExpr>(PropE->getBase());
 | |
|     const Expr *E = OVE->getSourceExpr();
 | |
|     Base = getBaseInfo(E);
 | |
|   } else if (PropE->isClassReceiver()) {
 | |
|     Base.setPointer(PropE->getClassReceiver());
 | |
|   } else {
 | |
|     assert(PropE->isSuperReceiver());
 | |
|   }
 | |
| }
 | |
| 
 | |
| FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(const Expr *BaseE,
 | |
|                                                 const ObjCPropertyDecl *Prop)
 | |
|     : Base(nullptr, true), Property(Prop) {
 | |
|   if (BaseE)
 | |
|     Base = getBaseInfo(BaseE);
 | |
|   // else, this is a message accessing a property on super.
 | |
| }
 | |
| 
 | |
| FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
 | |
|                                                       const DeclRefExpr *DRE)
 | |
|   : Base(nullptr, true), Property(DRE->getDecl()) {
 | |
|   assert(isa<VarDecl>(Property));
 | |
| }
 | |
| 
 | |
| FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy(
 | |
|                                                   const ObjCIvarRefExpr *IvarE)
 | |
|   : Base(getBaseInfo(IvarE->getBase())), Property(IvarE->getDecl()) {
 | |
| }
 | |
| 
 | |
| void FunctionScopeInfo::recordUseOfWeak(const ObjCMessageExpr *Msg,
 | |
|                                         const ObjCPropertyDecl *Prop) {
 | |
|   assert(Msg && Prop);
 | |
|   WeakUseVector &Uses =
 | |
|     WeakObjectUses[WeakObjectProfileTy(Msg->getInstanceReceiver(), Prop)];
 | |
|   Uses.push_back(WeakUseTy(Msg, Msg->getNumArgs() == 0));
 | |
| }
 | |
| 
 | |
| void FunctionScopeInfo::markSafeWeakUse(const Expr *E) {
 | |
|   E = E->IgnoreParenCasts();
 | |
| 
 | |
|   if (const PseudoObjectExpr *POE = dyn_cast<PseudoObjectExpr>(E)) {
 | |
|     markSafeWeakUse(POE->getSyntacticForm());
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   if (const ConditionalOperator *Cond = dyn_cast<ConditionalOperator>(E)) {
 | |
|     markSafeWeakUse(Cond->getTrueExpr());
 | |
|     markSafeWeakUse(Cond->getFalseExpr());
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   if (const BinaryConditionalOperator *Cond =
 | |
|         dyn_cast<BinaryConditionalOperator>(E)) {
 | |
|     markSafeWeakUse(Cond->getCommon());
 | |
|     markSafeWeakUse(Cond->getFalseExpr());
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   // Has this weak object been seen before?
 | |
|   FunctionScopeInfo::WeakObjectUseMap::iterator Uses;
 | |
|   if (const ObjCPropertyRefExpr *RefExpr = dyn_cast<ObjCPropertyRefExpr>(E)) {
 | |
|     if (!RefExpr->isObjectReceiver())
 | |
|       return;
 | |
|     if (isa<OpaqueValueExpr>(RefExpr->getBase()))
 | |
|      Uses = WeakObjectUses.find(WeakObjectProfileTy(RefExpr));
 | |
|     else {
 | |
|       markSafeWeakUse(RefExpr->getBase());
 | |
|       return;
 | |
|     }
 | |
|   }
 | |
|   else if (const ObjCIvarRefExpr *IvarE = dyn_cast<ObjCIvarRefExpr>(E))
 | |
|     Uses = WeakObjectUses.find(WeakObjectProfileTy(IvarE));
 | |
|   else if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
 | |
|     Uses = WeakObjectUses.find(WeakObjectProfileTy(DRE));
 | |
|   else if (const ObjCMessageExpr *MsgE = dyn_cast<ObjCMessageExpr>(E)) {
 | |
|     Uses = WeakObjectUses.end();
 | |
|     if (const ObjCMethodDecl *MD = MsgE->getMethodDecl()) {
 | |
|       if (const ObjCPropertyDecl *Prop = MD->findPropertyDecl()) {
 | |
|         Uses =
 | |
|           WeakObjectUses.find(WeakObjectProfileTy(MsgE->getInstanceReceiver(),
 | |
|                                                   Prop));
 | |
|       }
 | |
|     }
 | |
|   }
 | |
|   else
 | |
|     return;
 | |
| 
 | |
|   if (Uses == WeakObjectUses.end())
 | |
|     return;
 | |
| 
 | |
|   // Has there been a read from the object using this Expr?
 | |
|   FunctionScopeInfo::WeakUseVector::reverse_iterator ThisUse =
 | |
|     std::find(Uses->second.rbegin(), Uses->second.rend(), WeakUseTy(E, true));
 | |
|   if (ThisUse == Uses->second.rend())
 | |
|     return;
 | |
| 
 | |
|   ThisUse->markSafe();
 | |
| }
 | |
| 
 | |
| void LambdaScopeInfo::getPotentialVariableCapture(unsigned Idx, VarDecl *&VD,
 | |
|                                                   Expr *&E) const {
 | |
|   assert(Idx < getNumPotentialVariableCaptures() &&
 | |
|          "Index of potential capture must be within 0 to less than the "
 | |
|          "number of captures!");
 | |
|   E = PotentiallyCapturingExprs[Idx];
 | |
|   if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
 | |
|     VD = dyn_cast<VarDecl>(DRE->getFoundDecl());
 | |
|   else if (MemberExpr *ME = dyn_cast<MemberExpr>(E))
 | |
|     VD = dyn_cast<VarDecl>(ME->getMemberDecl());
 | |
|   else
 | |
|     llvm_unreachable("Only DeclRefExprs or MemberExprs should be added for "
 | |
|     "potential captures");
 | |
|   assert(VD);
 | |
| }
 | |
| 
 | |
| FunctionScopeInfo::~FunctionScopeInfo() { }
 | |
| BlockScopeInfo::~BlockScopeInfo() { }
 | |
| CapturedRegionScopeInfo::~CapturedRegionScopeInfo() { }
 |