clang API Documentation
00001 //===--- TransARCAssign.cpp - Transformations 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/AST/ASTContext.h" 00027 #include "clang/Sema/SemaDiagnostic.h" 00028 00029 using namespace clang; 00030 using namespace arcmt; 00031 using namespace trans; 00032 00033 namespace { 00034 00035 class ARCAssignChecker : public RecursiveASTVisitor<ARCAssignChecker> { 00036 MigrationPass &Pass; 00037 llvm::DenseSet<VarDecl *> ModifiedVars; 00038 00039 public: 00040 ARCAssignChecker(MigrationPass &pass) : Pass(pass) { } 00041 00042 bool VisitBinaryOperator(BinaryOperator *Exp) { 00043 if (Exp->getType()->isDependentType()) 00044 return true; 00045 00046 Expr *E = Exp->getLHS(); 00047 SourceLocation OrigLoc = E->getExprLoc(); 00048 SourceLocation Loc = OrigLoc; 00049 DeclRefExpr *declRef = dyn_cast<DeclRefExpr>(E->IgnoreParenCasts()); 00050 if (declRef && isa<VarDecl>(declRef->getDecl())) { 00051 ASTContext &Ctx = Pass.Ctx; 00052 Expr::isModifiableLvalueResult IsLV = E->isModifiableLvalue(Ctx, &Loc); 00053 if (IsLV != Expr::MLV_ConstQualified) 00054 return true; 00055 VarDecl *var = cast<VarDecl>(declRef->getDecl()); 00056 if (var->isARCPseudoStrong()) { 00057 Transaction Trans(Pass.TA); 00058 if (Pass.TA.clearDiagnostic(diag::err_typecheck_arr_assign_enumeration, 00059 Exp->getOperatorLoc())) { 00060 if (!ModifiedVars.count(var)) { 00061 TypeLoc TLoc = var->getTypeSourceInfo()->getTypeLoc(); 00062 Pass.TA.insert(TLoc.getBeginLoc(), "__strong "); 00063 ModifiedVars.insert(var); 00064 } 00065 } 00066 } 00067 } 00068 00069 return true; 00070 } 00071 }; 00072 00073 } // anonymous namespace 00074 00075 void trans::makeAssignARCSafe(MigrationPass &pass) { 00076 ARCAssignChecker assignCheck(pass); 00077 assignCheck.TraverseDecl(pass.Ctx.getTranslationUnitDecl()); 00078 }