clang API Documentation

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