clang API Documentation

TransARCAssign.cpp
Go to the documentation of this file.
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 }