003 File Manager
Current Path:
/usr/src/contrib/llvm-project/clang/lib/ARCMigrate
usr
/
src
/
contrib
/
llvm-project
/
clang
/
lib
/
ARCMigrate
/
📁
..
📄
ARCMT.cpp
(21.93 KB)
📄
ARCMTActions.cpp
(2.44 KB)
📄
FileRemapper.cpp
(8.26 KB)
📄
Internals.h
(5.47 KB)
📄
ObjCMT.cpp
(81.85 KB)
📄
PlistReporter.cpp
(3.64 KB)
📄
TransAPIUses.cpp
(3.49 KB)
📄
TransARCAssign.cpp
(2.25 KB)
📄
TransAutoreleasePool.cpp
(14.26 KB)
📄
TransBlockObjCVariable.cpp
(4.55 KB)
📄
TransEmptyStatementsAndDealloc.cpp
(7 KB)
📄
TransGCAttrs.cpp
(11.29 KB)
📄
TransGCCalls.cpp
(2.54 KB)
📄
TransProperties.cpp
(12.35 KB)
📄
TransProtectedScope.cpp
(6.02 KB)
📄
TransRetainReleaseDealloc.cpp
(13.65 KB)
📄
TransUnbridgedCasts.cpp
(15.85 KB)
📄
TransUnusedInitDelegate.cpp
(2.2 KB)
📄
TransZeroOutPropsInDealloc.cpp
(6.71 KB)
📄
TransformActions.cpp
(23.07 KB)
📄
Transforms.cpp
(17.72 KB)
📄
Transforms.h
(6.72 KB)
Editing: TransProtectedScope.cpp
//===--- TransProtectedScope.cpp - Transformations to ARC mode ------------===// // // 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 // //===----------------------------------------------------------------------===// // // Adds brackets in case statements that "contain" initialization of retaining // variable, thus emitting the "switch case is in protected scope" error. // //===----------------------------------------------------------------------===// #include "Internals.h" #include "Transforms.h" #include "clang/AST/ASTContext.h" #include "clang/Basic/SourceManager.h" #include "clang/Sema/SemaDiagnostic.h" using namespace clang; using namespace arcmt; using namespace trans; namespace { class LocalRefsCollector : public RecursiveASTVisitor<LocalRefsCollector> { SmallVectorImpl<DeclRefExpr *> &Refs; public: LocalRefsCollector(SmallVectorImpl<DeclRefExpr *> &refs) : Refs(refs) { } bool VisitDeclRefExpr(DeclRefExpr *E) { if (ValueDecl *D = E->getDecl()) if (D->getDeclContext()->getRedeclContext()->isFunctionOrMethod()) Refs.push_back(E); return true; } }; struct CaseInfo { SwitchCase *SC; SourceRange Range; enum { St_Unchecked, St_CannotFix, St_Fixed } State; CaseInfo() : SC(nullptr), State(St_Unchecked) {} CaseInfo(SwitchCase *S, SourceRange Range) : SC(S), Range(Range), State(St_Unchecked) {} }; class CaseCollector : public RecursiveASTVisitor<CaseCollector> { ParentMap &PMap; SmallVectorImpl<CaseInfo> &Cases; public: CaseCollector(ParentMap &PMap, SmallVectorImpl<CaseInfo> &Cases) : PMap(PMap), Cases(Cases) { } bool VisitSwitchStmt(SwitchStmt *S) { SwitchCase *Curr = S->getSwitchCaseList(); if (!Curr) return true; Stmt *Parent = getCaseParent(Curr); Curr = Curr->getNextSwitchCase(); // Make sure all case statements are in the same scope. while (Curr) { if (getCaseParent(Curr) != Parent) return true; Curr = Curr->getNextSwitchCase(); } SourceLocation NextLoc = S->getEndLoc(); Curr = S->getSwitchCaseList(); // We iterate over case statements in reverse source-order. while (Curr) { Cases.push_back( CaseInfo(Curr, SourceRange(Curr->getBeginLoc(), NextLoc))); NextLoc = Curr->getBeginLoc(); Curr = Curr->getNextSwitchCase(); } return true; } Stmt *getCaseParent(SwitchCase *S) { Stmt *Parent = PMap.getParent(S); while (Parent && (isa<SwitchCase>(Parent) || isa<LabelStmt>(Parent))) Parent = PMap.getParent(Parent); return Parent; } }; class ProtectedScopeFixer { MigrationPass &Pass; SourceManager &SM; SmallVector<CaseInfo, 16> Cases; SmallVector<DeclRefExpr *, 16> LocalRefs; public: ProtectedScopeFixer(BodyContext &BodyCtx) : Pass(BodyCtx.getMigrationContext().Pass), SM(Pass.Ctx.getSourceManager()) { CaseCollector(BodyCtx.getParentMap(), Cases) .TraverseStmt(BodyCtx.getTopStmt()); LocalRefsCollector(LocalRefs).TraverseStmt(BodyCtx.getTopStmt()); SourceRange BodyRange = BodyCtx.getTopStmt()->getSourceRange(); const CapturedDiagList &DiagList = Pass.getDiags(); // Copy the diagnostics so we don't have to worry about invaliding iterators // from the diagnostic list. SmallVector<StoredDiagnostic, 16> StoredDiags; StoredDiags.append(DiagList.begin(), DiagList.end()); SmallVectorImpl<StoredDiagnostic>::iterator I = StoredDiags.begin(), E = StoredDiags.end(); while (I != E) { if (I->getID() == diag::err_switch_into_protected_scope && isInRange(I->getLocation(), BodyRange)) { handleProtectedScopeError(I, E); continue; } ++I; } } void handleProtectedScopeError( SmallVectorImpl<StoredDiagnostic>::iterator &DiagI, SmallVectorImpl<StoredDiagnostic>::iterator DiagE){ Transaction Trans(Pass.TA); assert(DiagI->getID() == diag::err_switch_into_protected_scope); SourceLocation ErrLoc = DiagI->getLocation(); bool handledAllNotes = true; ++DiagI; for (; DiagI != DiagE && DiagI->getLevel() == DiagnosticsEngine::Note; ++DiagI) { if (!handleProtectedNote(*DiagI)) handledAllNotes = false; } if (handledAllNotes) Pass.TA.clearDiagnostic(diag::err_switch_into_protected_scope, ErrLoc); } bool handleProtectedNote(const StoredDiagnostic &Diag) { assert(Diag.getLevel() == DiagnosticsEngine::Note); for (unsigned i = 0; i != Cases.size(); i++) { CaseInfo &info = Cases[i]; if (isInRange(Diag.getLocation(), info.Range)) { if (info.State == CaseInfo::St_Unchecked) tryFixing(info); assert(info.State != CaseInfo::St_Unchecked); if (info.State == CaseInfo::St_Fixed) { Pass.TA.clearDiagnostic(Diag.getID(), Diag.getLocation()); return true; } return false; } } return false; } void tryFixing(CaseInfo &info) { assert(info.State == CaseInfo::St_Unchecked); if (hasVarReferencedOutside(info)) { info.State = CaseInfo::St_CannotFix; return; } Pass.TA.insertAfterToken(info.SC->getColonLoc(), " {"); Pass.TA.insert(info.Range.getEnd(), "}\n"); info.State = CaseInfo::St_Fixed; } bool hasVarReferencedOutside(CaseInfo &info) { for (unsigned i = 0, e = LocalRefs.size(); i != e; ++i) { DeclRefExpr *DRE = LocalRefs[i]; if (isInRange(DRE->getDecl()->getLocation(), info.Range) && !isInRange(DRE->getLocation(), info.Range)) return true; } return false; } bool isInRange(SourceLocation Loc, SourceRange R) { if (Loc.isInvalid()) return false; return !SM.isBeforeInTranslationUnit(Loc, R.getBegin()) && SM.isBeforeInTranslationUnit(Loc, R.getEnd()); } }; } // anonymous namespace void ProtectedScopeTraverser::traverseBody(BodyContext &BodyCtx) { ProtectedScopeFixer Fix(BodyCtx); }
Upload File
Create Folder