clang API Documentation
00001 //===--- TransARCAssign.cpp - Tranformations to ARC mode ------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // makeAssignARCSafe: 00011 // 00012 // Add '__strong' where appropriate. 00013 // 00014 // for (id x in collection) { 00015 // x = 0; 00016 // } 00017 // ----> 00018 // for (__strong id x in collection) { 00019 // x = 0; 00020 // } 00021 // 00022 //===----------------------------------------------------------------------===// 00023 00024 #include "Transforms.h" 00025 #include "Internals.h" 00026 #include "clang/Sema/SemaDiagnostic.h" 00027 00028 using namespace clang; 00029 using namespace arcmt; 00030 using namespace trans; 00031 00032 namespace { 00033 00034 class ARCAssignChecker : public RecursiveASTVisitor<ARCAssignChecker> { 00035 MigrationPass &Pass; 00036 llvm::DenseSet<VarDecl *> ModifiedVars; 00037 00038 public: 00039 ARCAssignChecker(MigrationPass &pass) : Pass(pass) { } 00040 00041 bool VisitBinaryOperator(BinaryOperator *Exp) { 00042 if (Exp->getType()->isDependentType()) 00043 return true; 00044 00045 Expr *E = Exp->getLHS(); 00046 SourceLocation OrigLoc = E->getExprLoc(); 00047 SourceLocation Loc = OrigLoc; 00048 DeclRefExpr *declRef = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()); 00049 if (declRef && isa<VarDecl>(declRef->getDecl())) { 00050 ASTContext &Ctx = Pass.Ctx; 00051 Expr::isModifiableLvalueResult IsLV = E->isModifiableLvalue(Ctx, &Loc); 00052 if (IsLV != Expr::MLV_ConstQualified) 00053 return true; 00054 VarDecl *var = cast<VarDecl>(declRef->getDecl()); 00055 if (var->isARCPseudoStrong()) { 00056 Transaction Trans(Pass.TA); 00057 if (Pass.TA.clearDiagnostic(diag::err_typecheck_arr_assign_enumeration, 00058 Exp->getOperatorLoc())) { 00059 if (!ModifiedVars.count(var)) { 00060 TypeLoc TLoc = var->getTypeSourceInfo()->getTypeLoc(); 00061 Pass.TA.insert(TLoc.getBeginLoc(), "__strong "); 00062 ModifiedVars.insert(var); 00063 } 00064 } 00065 } 00066 } 00067 00068 return true; 00069 } 00070 }; 00071 00072 } // anonymous namespace 00073 00074 void trans::makeAssignARCSafe(MigrationPass &pass) { 00075 ARCAssignChecker assignCheck(pass); 00076 assignCheck.TraverseDecl(pass.Ctx.getTranslationUnitDecl()); 00077 }