zcov: / lib/Frontend/RewriteObjC.cpp


Files: 1 Branches Taken: 67.0% 1062 / 1585
Generated: 2010-02-10 01:31 Branches Executed: 88.2% 1398 / 1585
Line Coverage: 88.7% 2463 / 2776


Programs: 1 Runs 2897


       1                 : //===--- RewriteObjC.cpp - Playground for the code rewriter ---------------===//
       2                 : //
       3                 : //                     The LLVM Compiler Infrastructure
       4                 : //
       5                 : // This file is distributed under the University of Illinois Open Source
       6                 : // License. See LICENSE.TXT for details.
       7                 : //
       8                 : //===----------------------------------------------------------------------===//
       9                 : //
      10                 : // Hacks and fun related to the code rewriter.
      11                 : //
      12                 : //===----------------------------------------------------------------------===//
      13                 : 
      14                 : #include "clang/Frontend/ASTConsumers.h"
      15                 : #include "clang/Rewrite/Rewriter.h"
      16                 : #include "clang/AST/AST.h"
      17                 : #include "clang/AST/ASTConsumer.h"
      18                 : #include "clang/AST/ParentMap.h"
      19                 : #include "clang/Basic/SourceManager.h"
      20                 : #include "clang/Basic/IdentifierTable.h"
      21                 : #include "clang/Basic/Diagnostic.h"
      22                 : #include "clang/Lex/Lexer.h"
      23                 : #include "llvm/Support/MemoryBuffer.h"
      24                 : #include "llvm/Support/raw_ostream.h"
      25                 : #include "llvm/ADT/StringExtras.h"
      26                 : #include "llvm/ADT/SmallPtrSet.h"
      27                 : #include "llvm/ADT/OwningPtr.h"
      28                 : #include "llvm/ADT/DenseSet.h"
      29                 : using namespace clang;
      30                 : using llvm::utostr;
      31                 : 
      32                 : namespace {
      33                 :   class RewriteObjC : public ASTConsumer {
      34                 :     enum {
      35                 :       BLOCK_FIELD_IS_OBJECT   =  3,  /* id, NSObject, __attribute__((NSObject)), 
      36                 :                                         block, ... */
      37                 :       BLOCK_FIELD_IS_BLOCK    =  7,  /* a block variable */
      38                 :       BLOCK_FIELD_IS_BYREF    =  8,  /* the on stack structure holding the 
      39                 :                                         __block variable */
      40                 :       BLOCK_FIELD_IS_WEAK     = 16,  /* declared __weak, only used in byref copy 
      41                 :                                         helpers */
      42                 :       BLOCK_BYREF_CALLER      = 128, /* called from __block (byref) copy/dispose 
      43                 :                                         support routines */
      44                 :       BLOCK_BYREF_CURRENT_MAX = 256
      45                 :     };
      46                 :     
      47                 :     enum {
      48                 :       BLOCK_NEEDS_FREE =        (1 << 24),
      49                 :       BLOCK_HAS_COPY_DISPOSE =  (1 << 25),
      50                 :       BLOCK_HAS_CXX_OBJ =       (1 << 26),
      51                 :       BLOCK_IS_GC =             (1 << 27),
      52                 :       BLOCK_IS_GLOBAL =         (1 << 28),
      53                 :       BLOCK_HAS_DESCRIPTOR =    (1 << 29)
      54                 :     };
      55                 :     
      56                 :     Rewriter Rewrite;
      57                 :     Diagnostic &Diags;
      58                 :     const LangOptions &LangOpts;
      59                 :     unsigned RewriteFailedDiag;
      60                 :     unsigned TryFinallyContainsReturnDiag;
      61                 : 
      62                 :     ASTContext *Context;
      63                 :     SourceManager *SM;
      64                 :     TranslationUnitDecl *TUDecl;
      65                 :     FileID MainFileID;
      66                 :     const char *MainFileStart, *MainFileEnd;
      67                 :     SourceLocation LastIncLoc;
      68                 : 
      69                 :     llvm::SmallVector<ObjCImplementationDecl *, 8> ClassImplementation;
      70                 :     llvm::SmallVector<ObjCCategoryImplDecl *, 8> CategoryImplementation;
      71                 :     llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCSynthesizedStructs;
      72                 :     llvm::SmallPtrSet<ObjCProtocolDecl*, 8> ObjCSynthesizedProtocols;
      73                 :     llvm::SmallPtrSet<ObjCInterfaceDecl*, 8> ObjCForwardDecls;
      74                 :     llvm::DenseMap<ObjCMethodDecl*, std::string> MethodInternalNames;
      75                 :     llvm::SmallVector<Stmt *, 32> Stmts;
      76                 :     llvm::SmallVector<int, 8> ObjCBcLabelNo;
      77                 :     // Remember all the @protocol(<expr>) expressions.
      78                 :     llvm::SmallPtrSet<ObjCProtocolDecl *, 32> ProtocolExprDecls;
      79                 :     
      80                 :     llvm::DenseSet<uint64_t> CopyDestroyCache;
      81                 :     
      82                 :     unsigned NumObjCStringLiterals;
      83                 : 
      84                 :     FunctionDecl *MsgSendFunctionDecl;
      85                 :     FunctionDecl *MsgSendSuperFunctionDecl;
      86                 :     FunctionDecl *MsgSendStretFunctionDecl;
      87                 :     FunctionDecl *MsgSendSuperStretFunctionDecl;
      88                 :     FunctionDecl *MsgSendFpretFunctionDecl;
      89                 :     FunctionDecl *GetClassFunctionDecl;
      90                 :     FunctionDecl *GetMetaClassFunctionDecl;
      91                 :     FunctionDecl *SelGetUidFunctionDecl;
      92                 :     FunctionDecl *CFStringFunctionDecl;
      93                 :     FunctionDecl *SuperContructorFunctionDecl;
      94                 : 
      95                 :     // ObjC string constant support.
      96                 :     VarDecl *ConstantStringClassReference;
      97                 :     RecordDecl *NSStringRecord;
      98                 : 
      99                 :     // ObjC foreach break/continue generation support.
     100                 :     int BcLabelCount;
     101                 : 
     102                 :     // Needed for super.
     103                 :     ObjCMethodDecl *CurMethodDef;
     104                 :     RecordDecl *SuperStructDecl;
     105                 :     RecordDecl *ConstantStringDecl;
     106                 : 
     107                 :     TypeDecl *ProtocolTypeDecl;
     108                 :     QualType getProtocolType();
     109                 : 
     110                 :     // Needed for header files being rewritten
     111                 :     bool IsHeader;
     112                 : 
     113                 :     std::string InFileName;
     114                 :     llvm::raw_ostream* OutFile;
     115                 : 
     116                 :     bool SilenceRewriteMacroWarning;
     117                 :     bool objc_impl_method;
     118                 : 
     119                 :     std::string Preamble;
     120                 : 
     121                 :     // Block expressions.
     122                 :     llvm::SmallVector<BlockExpr *, 32> Blocks;
     123                 :     llvm::SmallVector<BlockDeclRefExpr *, 32> BlockDeclRefs;
     124                 :     llvm::DenseMap<BlockDeclRefExpr *, CallExpr *> BlockCallExprs;
     125                 : 
     126                 :     // Block related declarations.
     127                 :     llvm::SmallPtrSet<ValueDecl *, 8> BlockByCopyDecls;
     128                 :     llvm::SmallPtrSet<ValueDecl *, 8> BlockByRefDecls;
     129                 :     llvm::DenseMap<ValueDecl *, unsigned> BlockByRefDeclNo;
     130                 :     llvm::SmallPtrSet<ValueDecl *, 8> ImportedBlockDecls;
     131                 : 
     132                 :     llvm::DenseMap<BlockExpr *, std::string> RewrittenBlockExprs;
     133                 : 
     134                 :     // This maps a property to it's assignment statement.
     135                 :     llvm::DenseMap<ObjCPropertyRefExpr *, BinaryOperator *> PropSetters;
     136                 :     // This maps a property to it's synthesied message expression.
     137                 :     // This allows us to rewrite chained getters (e.g. o.a.b.c).
     138                 :     llvm::DenseMap<ObjCPropertyRefExpr *, Stmt *> PropGetters;
     139                 : 
     140                 :     // This maps an original source AST to it's rewritten form. This allows
     141                 :     // us to avoid rewriting the same node twice (which is very uncommon).
     142                 :     // This is needed to support some of the exotic property rewriting.
     143                 :     llvm::DenseMap<Stmt *, Stmt *> ReplacedNodes;
     144                 : 
     145                 :     FunctionDecl *CurFunctionDef;
     146                 :     FunctionDecl *CurFunctionDeclToDeclareForBlock;
     147                 :     VarDecl *GlobalVarDecl;
     148                 : 
     149                 :     bool DisableReplaceStmt;
     150                 : 
     151                 :     static const int OBJC_ABI_VERSION =7 ;
     152                 :   public:
     153                 :     virtual void Initialize(ASTContext &context);
     154                 : 
     155                 :     // Top Level Driver code.
     156              320:     virtual void HandleTopLevelDecl(DeclGroupRef D) {
                      330: branch 2 taken
                      320: branch 3 taken
     157              650:       for (DeclGroupRef::iterator I = D.begin(), E = D.end(); I != E; ++I)
     158              330:         HandleTopLevelSingleDecl(*I);
     159              320:     }
     160                 :     void HandleTopLevelSingleDecl(Decl *D);
     161                 :     void HandleDeclInMainFile(Decl *D);
     162                 :     RewriteObjC(std::string inFile, llvm::raw_ostream *OS,
     163                 :                 Diagnostic &D, const LangOptions &LOpts,
     164                 :                 bool silenceMacroWarn);
     165                 : 
                       51: branch 25 taken
                        0: branch 26 not taken
                        0: branch 53 not taken
                        0: branch 54 not taken
     166               51:     ~RewriteObjC() {}
     167                 : 
     168                 :     virtual void HandleTranslationUnit(ASTContext &C);
     169                 : 
     170              138:     void ReplaceStmt(Stmt *Old, Stmt *New) {
     171              138:       Stmt *ReplacingStmt = ReplacedNodes[Old];
     172                 : 
                        0: branch 0 not taken
                      138: branch 1 taken
     173              138:       if (ReplacingStmt)
     174                0:         return; // We can't rewrite the same node twice.
     175                 : 
                        5: branch 0 taken
                      133: branch 1 taken
     176              138:       if (DisableReplaceStmt)
     177                5:         return; // Used when rewriting the assignment of a property setter.
     178                 : 
     179                 :       // If replacement succeeded or warning disabled return with no warning.
                      133: branch 1 taken
                        0: branch 2 not taken
     180              133:       if (!Rewrite.ReplaceStmt(Old, New)) {
     181              133:         ReplacedNodes[Old] = New;
     182              133:         return;
     183                 :       }
                        0: branch 0 not taken
                        0: branch 1 not taken
     184                0:       if (SilenceRewriteMacroWarning)
     185                0:         return;
     186                 :       Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
     187                0:                    << Old->getSourceRange();
     188                 :     }
     189                 : 
     190                7:     void ReplaceStmtWithRange(Stmt *Old, Stmt *New, SourceRange SrcRange) {
     191                 :       // Measaure the old text.
     192                7:       int Size = Rewrite.getRangeSize(SrcRange);
                        0: branch 0 not taken
                        7: branch 1 taken
     193                7:       if (Size == -1) {
     194                 :         Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
     195                0:                      << Old->getSourceRange();
     196                0:         return;
     197                 :       }
     198                 :       // Get the new text.
     199                7:       std::string SStr;
     200                7:       llvm::raw_string_ostream S(SStr);
     201                7:       New->printPretty(S, *Context, 0, PrintingPolicy(LangOpts));
     202                7:       const std::string &Str = S.str();
     203                 : 
     204                 :       // If replacement succeeded or warning disabled return with no warning.
                        7: branch 3 taken
                        0: branch 4 not taken
     205                7:       if (!Rewrite.ReplaceText(SrcRange.getBegin(), Size, Str)) {
     206                7:         ReplacedNodes[Old] = New;
     207                7:         return;
     208                 :       }
                        0: branch 0 not taken
                        0: branch 1 not taken
     209                0:       if (SilenceRewriteMacroWarning)
     210                 :         return;
     211                 :       Diags.Report(Context->getFullLoc(Old->getLocStart()), RewriteFailedDiag)
                        0: branch 7 not taken
                        7: branch 8 taken
                        0: branch 10 not taken
                        7: branch 11 taken
     212                0:                    << Old->getSourceRange();
     213                 :     }
     214                 : 
     215                 :     void InsertText(SourceLocation Loc, const char *StrData, unsigned StrLen,
     216              445:                     bool InsertAfter = true) {
     217                 :       // If insertion succeeded or warning disabled return with no warning.
                        0: branch 2 not taken
                      445: branch 3 taken
                      445: branch 4 taken
                      445: branch 5 taken
                      445: branch 6 taken
                        0: branch 7 not taken
     218              445:       if (!Rewrite.InsertText(Loc, llvm::StringRef(StrData, StrLen),
     219                 :                               InsertAfter) ||
     220                 :           SilenceRewriteMacroWarning)
     221              445:         return;
     222                 : 
     223                0:       Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);
     224                 :     }
     225                 : 
     226                 :     void RemoveText(SourceLocation Loc, unsigned StrLen) {
     227                 :       // If removal succeeded or warning disabled return with no warning.
     228                 :       if (!Rewrite.RemoveText(Loc, StrLen) || SilenceRewriteMacroWarning)
     229                 :         return;
     230                 : 
     231                 :       Diags.Report(Context->getFullLoc(Loc), RewriteFailedDiag);
     232                 :     }
     233                 : 
     234                 :     void ReplaceText(SourceLocation Start, unsigned OrigLength,
     235              349:                      const char *NewStr, unsigned NewLength) {
     236                 :       // If removal succeeded or warning disabled return with no warning.
                        0: branch 2 not taken
                      349: branch 3 taken
                      349: branch 4 taken
                      349: branch 5 taken
                      349: branch 6 taken
                        0: branch 7 not taken
     237              349:       if (!Rewrite.ReplaceText(Start, OrigLength,
     238                 :                                llvm::StringRef(NewStr, NewLength)) ||
     239                 :           SilenceRewriteMacroWarning)
     240              349:         return;
     241                 : 
     242                0:       Diags.Report(Context->getFullLoc(Start), RewriteFailedDiag);
     243                 :     }
     244                 : 
     245                 :     // Syntactic Rewriting.
     246                 :     void RewritePrologue(SourceLocation Loc);
     247                 :     void RewriteInclude();
     248                 :     void RewriteTabs();
     249                 :     void RewriteForwardClassDecl(ObjCClassDecl *Dcl);
     250                 :     void RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
     251                 :                                  ObjCImplementationDecl *IMD,
     252                 :                                  ObjCCategoryImplDecl *CID);
     253                 :     void RewriteInterfaceDecl(ObjCInterfaceDecl *Dcl);
     254                 :     void RewriteImplementationDecl(Decl *Dcl);
     255                 :     void RewriteObjCMethodDecl(ObjCMethodDecl *MDecl, std::string &ResultStr);
     256                 :     void RewriteByRefString(std::string &ResultStr, const std::string &Name,
     257                 :                             ValueDecl *VD);
     258                 :     void RewriteCategoryDecl(ObjCCategoryDecl *Dcl);
     259                 :     void RewriteProtocolDecl(ObjCProtocolDecl *Dcl);
     260                 :     void RewriteForwardProtocolDecl(ObjCForwardProtocolDecl *Dcl);
     261                 :     void RewriteMethodDeclaration(ObjCMethodDecl *Method);
     262                 :     void RewriteProperty(ObjCPropertyDecl *prop);
     263                 :     void RewriteFunctionDecl(FunctionDecl *FD);
     264                 :     void RewriteBlockLiteralFunctionDecl(FunctionDecl *FD);
     265                 :     void RewriteObjCQualifiedInterfaceTypes(Decl *Dcl);
     266                 :     void RewriteObjCQualifiedInterfaceTypes(Expr *E);
     267                 :     bool needToScanForQualifiers(QualType T);
     268                 :     ObjCInterfaceDecl *isSuperReceiver(Expr *recExpr);
     269                 :     QualType getSuperStructType();
     270                 :     QualType getConstantStringStructType();
     271                 :     bool BufferContainsPPDirectives(const char *startBuf, const char *endBuf);
     272                 : 
     273                 :     // Expression Rewriting.
     274                 :     Stmt *RewriteFunctionBodyOrGlobalInitializer(Stmt *S);
     275                 :     void CollectPropertySetters(Stmt *S);
     276                 : 
     277                 :     Stmt *CurrentBody;
     278                 :     ParentMap *PropParentMap; // created lazily.
     279                 : 
     280                 :     Stmt *RewriteAtEncode(ObjCEncodeExpr *Exp);
     281                 :     Stmt *RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV, SourceLocation OrigStart,
     282                 :                                  bool &replaced);
     283                 :     Stmt *RewriteObjCNestedIvarRefExpr(Stmt *S, bool &replaced);
     284                 :     Stmt *RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr);
     285                 :     Stmt *RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt,
     286                 :                                 SourceRange SrcRange);
     287                 :     Stmt *RewriteAtSelector(ObjCSelectorExpr *Exp);
     288                 :     Stmt *RewriteMessageExpr(ObjCMessageExpr *Exp);
     289                 :     Stmt *RewriteObjCStringLiteral(ObjCStringLiteral *Exp);
     290                 :     Stmt *RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp);
     291                 :     void WarnAboutReturnGotoStmts(Stmt *S);
     292                 :     void HasReturnStmts(Stmt *S, bool &hasReturns);
     293                 :     void RewriteTryReturnStmts(Stmt *S);
     294                 :     void RewriteSyncReturnStmts(Stmt *S, std::string buf);
     295                 :     Stmt *RewriteObjCTryStmt(ObjCAtTryStmt *S);
     296                 :     Stmt *RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S);
     297                 :     Stmt *RewriteObjCCatchStmt(ObjCAtCatchStmt *S);
     298                 :     Stmt *RewriteObjCFinallyStmt(ObjCAtFinallyStmt *S);
     299                 :     Stmt *RewriteObjCThrowStmt(ObjCAtThrowStmt *S);
     300                 :     Stmt *RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
     301                 :                                        SourceLocation OrigEnd);
     302                 :     CallExpr *SynthesizeCallToFunctionDecl(FunctionDecl *FD,
     303                 :                                            Expr **args, unsigned nargs);
     304                 :     Stmt *SynthMessageExpr(ObjCMessageExpr *Exp);
     305                 :     Stmt *RewriteBreakStmt(BreakStmt *S);
     306                 :     Stmt *RewriteContinueStmt(ContinueStmt *S);
     307                 :     void SynthCountByEnumWithState(std::string &buf);
     308                 : 
     309                 :     void SynthMsgSendFunctionDecl();
     310                 :     void SynthMsgSendSuperFunctionDecl();
     311                 :     void SynthMsgSendStretFunctionDecl();
     312                 :     void SynthMsgSendFpretFunctionDecl();
     313                 :     void SynthMsgSendSuperStretFunctionDecl();
     314                 :     void SynthGetClassFunctionDecl();
     315                 :     void SynthGetMetaClassFunctionDecl();
     316                 :     void SynthSelGetUidFunctionDecl();
     317                 :     void SynthSuperContructorFunctionDecl();
     318                 : 
     319                 :     // Metadata emission.
     320                 :     void RewriteObjCClassMetaData(ObjCImplementationDecl *IDecl,
     321                 :                                   std::string &Result);
     322                 : 
     323                 :     void RewriteObjCCategoryImplDecl(ObjCCategoryImplDecl *CDecl,
     324                 :                                      std::string &Result);
     325                 : 
     326                 :     template<typename MethodIterator>
     327                 :     void RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
     328                 :                                     MethodIterator MethodEnd,
     329                 :                                     bool IsInstanceMethod,
     330                 :                                     const char *prefix,
     331                 :                                     const char *ClassName,
     332                 :                                     std::string &Result);
     333                 : 
     334                 :     void RewriteObjCProtocolMetaData(ObjCProtocolDecl *Protocol,
     335                 :                                      const char *prefix,
     336                 :                                      const char *ClassName,
     337                 :                                      std::string &Result);
     338                 :     void RewriteObjCProtocolListMetaData(const ObjCList<ObjCProtocolDecl> &Prots,
     339                 :                                          const char *prefix,
     340                 :                                          const char *ClassName,
     341                 :                                          std::string &Result);
     342                 :     void SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl,
     343                 :                                       std::string &Result);
     344                 :     void SynthesizeIvarOffsetComputation(ObjCImplementationDecl *IDecl,
     345                 :                                          ObjCIvarDecl *ivar,
     346                 :                                          std::string &Result);
     347                 :     void RewriteImplementations();
     348                 :     void SynthesizeMetaDataIntoBuffer(std::string &Result);
     349                 : 
     350                 :     // Block rewriting.
     351                 :     void RewriteBlocksInFunctionProtoType(QualType funcType, NamedDecl *D);
     352                 :     void CheckFunctionPointerDecl(QualType dType, NamedDecl *ND);
     353                 : 
     354                 :     void InsertBlockLiteralsWithinFunction(FunctionDecl *FD);
     355                 :     void InsertBlockLiteralsWithinMethod(ObjCMethodDecl *MD);
     356                 : 
     357                 :     // Block specific rewrite rules.
     358                 :     void RewriteBlockCall(CallExpr *Exp);
     359                 :     void RewriteBlockPointerDecl(NamedDecl *VD);
     360                 :     void RewriteByRefVar(VarDecl *VD);
     361                 :     std::string SynthesizeByrefCopyDestroyHelper(VarDecl *VD, int flag);
     362                 :     Stmt *RewriteBlockDeclRefExpr(Expr *VD);
     363                 :     void RewriteBlockPointerFunctionArgs(FunctionDecl *FD);
     364                 : 
     365                 :     std::string SynthesizeBlockHelperFuncs(BlockExpr *CE, int i,
     366                 :                                       const char *funcName, std::string Tag);
     367                 :     std::string SynthesizeBlockFunc(BlockExpr *CE, int i,
     368                 :                                       const char *funcName, std::string Tag);
     369                 :     std::string SynthesizeBlockImpl(BlockExpr *CE, 
     370                 :                                     std::string Tag, std::string Desc);
     371                 :     std::string SynthesizeBlockDescriptor(std::string DescTag, 
     372                 :                                           std::string ImplTag,
     373                 :                                           int i, const char *funcName,
     374                 :                                           unsigned hasCopy);
     375                 :     Stmt *SynthesizeBlockCall(CallExpr *Exp, const Expr* BlockExp);
     376                 :     void SynthesizeBlockLiterals(SourceLocation FunLocStart,
     377                 :                                  const char *FunName);
     378                 :     void RewriteRecordBody(RecordDecl *RD);
     379                 : 
     380                 :     void CollectBlockDeclRefInfo(BlockExpr *Exp);
     381                 :     void GetBlockCallExprs(Stmt *S);
     382                 :     void GetBlockDeclRefExprs(Stmt *S);
     383                 : 
     384                 :     // We avoid calling Type::isBlockPointerType(), since it operates on the
     385                 :     // canonical type. We only care if the top-level type is a closure pointer.
     386              285:     bool isTopLevelBlockPointerType(QualType T) {
     387              285:       return isa<BlockPointerType>(T);
     388                 :     }
     389                 : 
     390                 :     // FIXME: This predicate seems like it would be useful to add to ASTContext.
     391                4:     bool isObjCType(QualType T) {
                        2: branch 0 taken
                        2: branch 1 taken
                        2: branch 2 taken
                        0: branch 3 not taken
     392                4:       if (!LangOpts.ObjC1 && !LangOpts.ObjC2)
     393                2:         return false;
     394                 : 
     395                2:       QualType OCT = Context->getCanonicalType(T).getUnqualifiedType();
     396                 : 
                        0: branch 4 not taken
                        2: branch 5 taken
                        0: branch 10 not taken
                        0: branch 11 not taken
                        2: branch 12 taken
                        0: branch 13 not taken
     397                2:       if (OCT == Context->getCanonicalType(Context->getObjCIdType()) ||
     398                 :           OCT == Context->getCanonicalType(Context->getObjCClassType()))
     399                2:         return true;
     400                 : 
                        0: branch 2 not taken
                        0: branch 3 not taken
     401                0:       if (const PointerType *PT = OCT->getAs<PointerType>()) {
                        0: branch 2 not taken
                        0: branch 3 not taken
                        0: branch 7 not taken
                        0: branch 8 not taken
                        0: branch 9 not taken
                        0: branch 10 not taken
     402                0:         if (isa<ObjCInterfaceType>(PT->getPointeeType()) ||
     403                 :             PT->getPointeeType()->isObjCQualifiedIdType())
     404                0:           return true;
     405                 :       }
     406                0:       return false;
     407                 :     }
     408                 :     bool PointerTypeTakesAnyBlockArguments(QualType QT);
     409                 :     void GetExtentOfArgList(const char *Name, const char *&LParen,
     410                 :                             const char *&RParen);
     411                 :     void RewriteCastExpr(CStyleCastExpr *CE);
     412                 : 
     413                 :     FunctionDecl *SynthBlockInitFunctionDecl(const char *name);
     414                 :     Stmt *SynthBlockInitExpr(BlockExpr *Exp);
     415                 : 
     416               24:     void QuoteDoublequotes(std::string &From, std::string &To) {
                      162: branch 1 taken
                       24: branch 2 taken
     417              186:       for (unsigned i = 0; i < From.length(); i++) {
                       18: branch 1 taken
                      144: branch 2 taken
     418              162:         if (From[i] == '"')
     419               18:           To += "\\\"";
     420                 :         else
     421              144:           To += From[i];
     422                 :       }
     423               24:     }
     424                 :   };
     425                 : 
     426                 :   // Helper function: create a CStyleCastExpr with trivial type source info.
     427                 :   CStyleCastExpr* NoTypeInfoCStyleCastExpr(ASTContext *Ctx, QualType Ty,
     428              295:                                            CastExpr::CastKind Kind, Expr *E) {
     429              295:     TypeSourceInfo *TInfo = Ctx->getTrivialTypeSourceInfo(Ty, SourceLocation());
     430                 :     return new (Ctx) CStyleCastExpr(Ty, Kind, E, TInfo,
                      295: branch 3 taken
                        0: branch 4 not taken
     431              295:                                     SourceLocation(), SourceLocation());
     432                 :   }
     433                 : }
     434                 : 
     435                 : void RewriteObjC::RewriteBlocksInFunctionProtoType(QualType funcType,
     436               61:                                                    NamedDecl *D) {
                       32: branch 1 taken
                       29: branch 2 taken
     437               61:   if (FunctionProtoType *fproto = dyn_cast<FunctionProtoType>(funcType)) {
                       61: branch 1 taken
                        0: branch 2 not taken
                       34: branch 3 taken
                       27: branch 4 taken
     438               93:     for (FunctionProtoType::arg_type_iterator I = fproto->arg_type_begin(),
     439               32:          E = fproto->arg_type_end(); I && (I != E); ++I)
                        5: branch 1 taken
                       29: branch 2 taken
     440               34:       if (isTopLevelBlockPointerType(*I)) {
     441                 :         // All the args are checked/rewritten. Don't call twice!
     442                5:         RewriteBlockPointerDecl(D);
     443                5:         break;
     444                 :       }
     445                 :   }
     446               61: }
     447                 : 
     448                1: void RewriteObjC::CheckFunctionPointerDecl(QualType funcType, NamedDecl *ND) {
     449                1:   const PointerType *PT = funcType->getAs<PointerType>();
                        1: branch 0 taken
                        0: branch 1 not taken
                        0: branch 3 not taken
                        1: branch 4 taken
                        0: branch 5 not taken
                        1: branch 6 taken
     450                1:   if (PT && PointerTypeTakesAnyBlockArguments(funcType))
     451                0:     RewriteBlocksInFunctionProtoType(PT->getPointeeType(), ND);
     452                1: }
     453                 : 
     454               51: static bool IsHeaderFile(const std::string &Filename) {
     455               51:   std::string::size_type DotPos = Filename.rfind('.');
     456                 : 
                        0: branch 0 not taken
                       51: branch 1 taken
     457               51:   if (DotPos == std::string::npos) {
     458                 :     // no file extension
     459                0:     return false;
     460                 :   }
     461                 : 
     462               51:   std::string Ext = std::string(Filename.begin()+DotPos+1, Filename.end());
     463                 :   // C header: .h
     464                 :   // C++ header: .hh or .H;
                       51: branch 1 taken
                        0: branch 2 not taken
                       51: branch 4 taken
                        0: branch 5 not taken
                        0: branch 7 not taken
                       51: branch 8 taken
     465               51:   return Ext == "h" || Ext == "hh" || Ext == "H";
     466                 : }
     467                 : 
     468                 : RewriteObjC::RewriteObjC(std::string inFile, llvm::raw_ostream* OS,
     469                 :                          Diagnostic &D, const LangOptions &LOpts,
     470               51:                          bool silenceMacroWarn)
     471                 :       : Diags(D), LangOpts(LOpts), InFileName(inFile), OutFile(OS),
     472               51:         SilenceRewriteMacroWarning(silenceMacroWarn) {
     473               51:   IsHeader = IsHeaderFile(inFile);
     474                 :   RewriteFailedDiag = Diags.getCustomDiagID(Diagnostic::Warning,
     475               51:                "rewriting sub-expression within a macro (may not be correct)");
     476                 :   TryFinallyContainsReturnDiag = Diags.getCustomDiagID(Diagnostic::Warning,
     477                 :                "rewriter doesn't support user-specified control flow semantics "
     478               51:                "for @try/@finally (code may not execute properly)");
     479               51: }
     480                 : 
     481                 : ASTConsumer *clang::CreateObjCRewriter(const std::string& InFile,
     482                 :                                        llvm::raw_ostream* OS,
     483                 :                                        Diagnostic &Diags,
     484                 :                                        const LangOptions &LOpts,
     485               51:                                        bool SilenceRewriteMacroWarning) {
     486               51:   return new RewriteObjC(InFile, OS, Diags, LOpts, SilenceRewriteMacroWarning);
     487                 : }
     488                 : 
     489               51: void RewriteObjC::Initialize(ASTContext &context) {
     490               51:   Context = &context;
     491               51:   SM = &Context->getSourceManager();
     492               51:   TUDecl = Context->getTranslationUnitDecl();
     493               51:   MsgSendFunctionDecl = 0;
     494               51:   MsgSendSuperFunctionDecl = 0;
     495               51:   MsgSendStretFunctionDecl = 0;
     496               51:   MsgSendSuperStretFunctionDecl = 0;
     497               51:   MsgSendFpretFunctionDecl = 0;
     498               51:   GetClassFunctionDecl = 0;
     499               51:   GetMetaClassFunctionDecl = 0;
     500               51:   SelGetUidFunctionDecl = 0;
     501               51:   CFStringFunctionDecl = 0;
     502               51:   ConstantStringClassReference = 0;
     503               51:   NSStringRecord = 0;
     504               51:   CurMethodDef = 0;
     505               51:   CurFunctionDef = 0;
     506               51:   CurFunctionDeclToDeclareForBlock = 0;
     507               51:   GlobalVarDecl = 0;
     508               51:   SuperStructDecl = 0;
     509               51:   ProtocolTypeDecl = 0;
     510               51:   ConstantStringDecl = 0;
     511               51:   BcLabelCount = 0;
     512               51:   SuperContructorFunctionDecl = 0;
     513               51:   NumObjCStringLiterals = 0;
     514               51:   PropParentMap = 0;
     515               51:   CurrentBody = 0;
     516               51:   DisableReplaceStmt = false;
     517               51:   objc_impl_method = false;
     518                 : 
     519                 :   // Get the ID and start/end of the main file.
     520               51:   MainFileID = SM->getMainFileID();
     521               51:   const llvm::MemoryBuffer *MainBuf = SM->getBuffer(MainFileID);
     522               51:   MainFileStart = MainBuf->getBufferStart();
     523               51:   MainFileEnd = MainBuf->getBufferEnd();
     524                 : 
     525               51:   Rewrite.setSourceMgr(Context->getSourceManager(), Context->getLangOptions());
     526                 : 
     527                 :   // declaring objc_selector outside the parameter list removes a silly
     528                 :   // scope related warning...
                        0: branch 0 not taken
                       51: branch 1 taken
     529               51:   if (IsHeader)
     530                0:     Preamble = "#pragma once\n";
     531               51:   Preamble += "struct objc_selector; struct objc_class;\n";
     532               51:   Preamble += "struct __rw_objc_super { struct objc_object *object; ";
     533               51:   Preamble += "struct objc_object *superClass; ";
                       12: branch 0 taken
                       39: branch 1 taken
     534               51:   if (LangOpts.Microsoft) {
     535                 :     // Add a constructor for creating temporary objects.
     536                 :     Preamble += "__rw_objc_super(struct objc_object *o, struct objc_object *s) "
     537               12:                 ": ";
     538               12:     Preamble += "object(o), superClass(s) {} ";
     539                 :   }
     540               51:   Preamble += "};\n";
     541               51:   Preamble += "#ifndef _REWRITER_typedef_Protocol\n";
     542               51:   Preamble += "typedef struct objc_object Protocol;\n";
     543               51:   Preamble += "#define _REWRITER_typedef_Protocol\n";
     544               51:   Preamble += "#endif\n";
                       12: branch 0 taken
                       39: branch 1 taken
     545               51:   if (LangOpts.Microsoft) {
     546               12:     Preamble += "#define __OBJC_RW_DLLIMPORT extern \"C\" __declspec(dllimport)\n";
     547               12:     Preamble += "#define __OBJC_RW_STATICIMPORT extern \"C\"\n";
     548                 :   } else
     549               39:     Preamble += "#define __OBJC_RW_DLLIMPORT extern\n";
     550               51:   Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend";
     551               51:   Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
     552               51:   Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper";
     553               51:   Preamble += "(struct objc_super *, struct objc_selector *, ...);\n";
     554               51:   Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSend_stret";
     555               51:   Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
     556               51:   Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_msgSendSuper_stret";
     557               51:   Preamble += "(struct objc_super *, struct objc_selector *, ...);\n";
     558               51:   Preamble += "__OBJC_RW_DLLIMPORT double objc_msgSend_fpret";
     559               51:   Preamble += "(struct objc_object *, struct objc_selector *, ...);\n";
     560               51:   Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getClass";
     561               51:   Preamble += "(const char *);\n";
     562               51:   Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_getMetaClass";
     563               51:   Preamble += "(const char *);\n";
     564               51:   Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_throw(struct objc_object *);\n";
     565               51:   Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_enter(void *);\n";
     566               51:   Preamble += "__OBJC_RW_DLLIMPORT void objc_exception_try_exit(void *);\n";
     567               51:   Preamble += "__OBJC_RW_DLLIMPORT struct objc_object *objc_exception_extract(void *);\n";
     568               51:   Preamble += "__OBJC_RW_DLLIMPORT int objc_exception_match";
     569               51:   Preamble += "(struct objc_class *, struct objc_object *);\n";
     570                 :   // @synchronized hooks.
     571               51:   Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_enter(struct objc_object *);\n";
     572               51:   Preamble += "__OBJC_RW_DLLIMPORT void objc_sync_exit(struct objc_object *);\n";
     573               51:   Preamble += "__OBJC_RW_DLLIMPORT Protocol *objc_getProtocol(const char *);\n";
     574               51:   Preamble += "#ifndef __FASTENUMERATIONSTATE\n";
     575               51:   Preamble += "struct __objcFastEnumerationState {\n\t";
     576               51:   Preamble += "unsigned long state;\n\t";
     577               51:   Preamble += "void **itemsPtr;\n\t";
     578               51:   Preamble += "unsigned long *mutationsPtr;\n\t";
     579               51:   Preamble += "unsigned long extra[5];\n};\n";
     580               51:   Preamble += "__OBJC_RW_DLLIMPORT void objc_enumerationMutation(struct objc_object *);\n";
     581               51:   Preamble += "#define __FASTENUMERATIONSTATE\n";
     582               51:   Preamble += "#endif\n";
     583               51:   Preamble += "#ifndef __NSCONSTANTSTRINGIMPL\n";
     584               51:   Preamble += "struct __NSConstantStringImpl {\n";
     585               51:   Preamble += "  int *isa;\n";
     586               51:   Preamble += "  int flags;\n";
     587               51:   Preamble += "  char *str;\n";
     588               51:   Preamble += "  long length;\n";
     589               51:   Preamble += "};\n";
     590               51:   Preamble += "#ifdef CF_EXPORT_CONSTANT_STRING\n";
     591               51:   Preamble += "extern \"C\" __declspec(dllexport) int __CFConstantStringClassReference[];\n";
     592               51:   Preamble += "#else\n";
     593               51:   Preamble += "__OBJC_RW_DLLIMPORT int __CFConstantStringClassReference[];\n";
     594               51:   Preamble += "#endif\n";
     595               51:   Preamble += "#define __NSCONSTANTSTRINGIMPL\n";
     596               51:   Preamble += "#endif\n";
     597                 :   // Blocks preamble.
     598               51:   Preamble += "#ifndef BLOCK_IMPL\n";
     599               51:   Preamble += "#define BLOCK_IMPL\n";
     600               51:   Preamble += "struct __block_impl {\n";
     601               51:   Preamble += "  void *isa;\n";
     602               51:   Preamble += "  int Flags;\n";
     603               51:   Preamble += "  int Reserved;\n";
     604               51:   Preamble += "  void *FuncPtr;\n";
     605               51:   Preamble += "};\n";
     606               51:   Preamble += "// Runtime copy/destroy helper functions (from Block_private.h)\n";
     607               51:   Preamble += "#ifdef __OBJC_EXPORT_BLOCKS\n";
     608               51:   Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_assign(void *, const void *, const int);\n";
     609               51:   Preamble += "extern \"C\" __declspec(dllexport) void _Block_object_dispose(const void *, const int);\n";
     610               51:   Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteGlobalBlock[32];\n";
     611               51:   Preamble += "extern \"C\" __declspec(dllexport) void *_NSConcreteStackBlock[32];\n";
     612               51:   Preamble += "#else\n";
     613               51:   Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_assign(void *, const void *, const int);\n";
     614               51:   Preamble += "__OBJC_RW_DLLIMPORT void _Block_object_dispose(const void *, const int);\n";
     615               51:   Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteGlobalBlock[32];\n";
     616               51:   Preamble += "__OBJC_RW_DLLIMPORT void *_NSConcreteStackBlock[32];\n";
     617               51:   Preamble += "#endif\n";
     618               51:   Preamble += "#endif\n";
                       12: branch 0 taken
                       39: branch 1 taken
     619               51:   if (LangOpts.Microsoft) {
     620               12:     Preamble += "#undef __OBJC_RW_DLLIMPORT\n";
     621               12:     Preamble += "#undef __OBJC_RW_STATICIMPORT\n";
     622               12:     Preamble += "#define __attribute__(X)\n";
     623               12:     Preamble += "#define __weak\n";
     624                 :   }
     625                 :   else {
     626               39:     Preamble += "#define __block\n";
     627               39:     Preamble += "#define __weak\n";
     628                 :   }
     629               51: }
     630                 : 
     631                 : 
     632                 : //===----------------------------------------------------------------------===//
     633                 : // Top Level Driver Code
     634                 : //===----------------------------------------------------------------------===//
     635                 : 
     636              339: void RewriteObjC::HandleTopLevelSingleDecl(Decl *D) {
                        0: branch 1 not taken
                      339: branch 2 taken
     637              339:   if (Diags.hasErrorOccurred())
     638                0:     return;
     639                 : 
     640                 :   // Two cases: either the decl could be in the main file, or it could be in a
     641                 :   // #included file.  If the former, rewrite it now.  If the later, check to see
     642                 :   // if we rewrote the #include/#import.
     643              339:   SourceLocation Loc = D->getLocation();
     644              339:   Loc = SM->getInstantiationLoc(Loc);
     645                 : 
     646                 :   // If this is for a builtin, ignore it.
                      339: branch 1 taken
                        0: branch 2 not taken
     647              339:   if (Loc.isInvalid()) return;
     648                 : 
     649                 :   // Look for built-in declarations that we need to refer during the rewrite.
                       61: branch 1 taken
                      278: branch 2 taken
     650              339:   if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
     651               61:     RewriteFunctionDecl(FD);
                       15: branch 1 taken
                      263: branch 2 taken
     652              278:   } else if (VarDecl *FVD = dyn_cast<VarDecl>(D)) {
     653                 :     // declared in <Foundation/NSString.h>
                        0: branch 2 not taken
                       15: branch 3 taken
     654               15:     if (strcmp(FVD->getNameAsCString(), "_NSConstantStringClassReference") == 0) {
     655                0:       ConstantStringClassReference = FVD;
     656                0:       return;
     657                 :     }
                       62: branch 1 taken
                      201: branch 2 taken
     658              263:   } else if (ObjCInterfaceDecl *MD = dyn_cast<ObjCInterfaceDecl>(D)) {
     659               62:     RewriteInterfaceDecl(MD);
                        6: branch 1 taken
                      195: branch 2 taken
     660              201:   } else if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) {
     661                6:     RewriteCategoryDecl(CD);
                       12: branch 1 taken
                      183: branch 2 taken
     662              195:   } else if (ObjCProtocolDecl *PD = dyn_cast<ObjCProtocolDecl>(D)) {
     663               12:     RewriteProtocolDecl(PD);
                        2: branch 0 taken
                      181: branch 1 taken
     664              183:   } else if (ObjCForwardProtocolDecl *FP =
     665              183:              dyn_cast<ObjCForwardProtocolDecl>(D)){
     666                2:     RewriteForwardProtocolDecl(FP);
                        8: branch 1 taken
                      173: branch 2 taken
     667              181:   } else if (LinkageSpecDecl *LSD = dyn_cast<LinkageSpecDecl>(D)) {
     668                 :     // Recurse into linkage specifications
                        9: branch 3 taken
                        8: branch 4 taken
     669               25:     for (DeclContext::decl_iterator DI = LSD->decls_begin(),
     670                8:                                  DIEnd = LSD->decls_end();
     671                 :          DI != DIEnd; ++DI)
     672                9:       HandleTopLevelSingleDecl(*DI);
     673                 :   }
     674                 :   // If we have a decl in the main file, see if we should rewrite it.
                      286: branch 1 taken
                       53: branch 2 taken
     675              339:   if (SM->isFromMainFile(Loc))
     676              286:     return HandleDeclInMainFile(D);
     677                 : }
     678                 : 
     679                 : //===----------------------------------------------------------------------===//
     680                 : // Syntactic (non-AST) Rewriting Code
     681                 : //===----------------------------------------------------------------------===//
     682                 : 
     683               51: void RewriteObjC::RewriteInclude() {
     684               51:   SourceLocation LocStart = SM->getLocForStartOfFile(MainFileID);
     685               51:   std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
     686               51:   const char *MainBufStart = MainBuf.first;
     687               51:   const char *MainBufEnd = MainBuf.second;
     688               51:   size_t ImportLen = strlen("import");
     689               51:   size_t IncludeLen = strlen("include");
     690                 : 
     691                 :   // Loop over the whole file, looking for includes.
                    24038: branch 0 taken
                       51: branch 1 taken
     692            24089:   for (const char *BufPtr = MainBufStart; BufPtr < MainBufEnd; ++BufPtr) {
                        2: branch 0 taken
                    24036: branch 1 taken
     693            24038:     if (*BufPtr == '#') {
                        0: branch 0 not taken
                        2: branch 1 taken
     694                2:       if (++BufPtr == MainBufEnd)
     695                0:         return;
                        0: branch 0 not taken
                        2: branch 1 taken
                        0: branch 2 not taken
                        2: branch 3 taken
     696                4:       while (*BufPtr == ' ' || *BufPtr == '\t')
                        0: branch 0 not taken
                        0: branch 1 not taken
     697                0:         if (++BufPtr == MainBufEnd)
     698                0:           return;
                        0: branch 1 not taken
                        2: branch 2 taken
     699                2:       if (!strncmp(BufPtr, "import", ImportLen)) {
     700                 :         // replace import with include
     701                 :         SourceLocation ImportLoc =
     702                0:           LocStart.getFileLocWithOffset(BufPtr-MainBufStart);
     703                0:         ReplaceText(ImportLoc, ImportLen, "include", IncludeLen);
     704                0:         BufPtr += ImportLen;
     705                 :       }
     706                 :     }
     707                 :   }
     708                 : }
     709                 : 
     710                0: void RewriteObjC::RewriteTabs() {
     711                0:   std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
     712                0:   const char *MainBufStart = MainBuf.first;
     713                0:   const char *MainBufEnd = MainBuf.second;
     714                 : 
     715                 :   // Loop over the whole file, looking for tabs.
                        0: branch 0 not taken
                        0: branch 1 not taken
     716                0:   for (const char *BufPtr = MainBufStart; BufPtr != MainBufEnd; ++BufPtr) {
                        0: branch 0 not taken
                        0: branch 1 not taken
     717                0:     if (*BufPtr != '\t')
     718                0:       continue;
     719                 : 
     720                 :     // Okay, we found a tab.  This tab will turn into at least one character,
     721                 :     // but it depends on which 'virtual column' it is in.  Compute that now.
     722                0:     unsigned VCol = 0;
                        0: branch 0 not taken
                        0: branch 1 not taken
                        0: branch 2 not taken
                        0: branch 3 not taken
                        0: branch 4 not taken
                        0: branch 5 not taken
                        0: branch 6 not taken
                        0: branch 7 not taken
     723                0:     while (BufPtr-VCol != MainBufStart && BufPtr[-VCol-1] != '\t' &&
     724                 :            BufPtr[-VCol-1] != '\n' && BufPtr[-VCol-1] != '\r')
     725                0:       ++VCol;
     726                 : 
     727                 :     // Okay, now that we know the virtual column, we know how many spaces to
     728                 :     // insert.  We assume 8-character tab-stops.
     729                0:     unsigned Spaces = 8-(VCol & 7);
     730                 : 
     731                 :     // Get the location of the tab.
     732                0:     SourceLocation TabLoc = SM->getLocForStartOfFile(MainFileID);
     733                0:     TabLoc = TabLoc.getFileLocWithOffset(BufPtr-MainBufStart);
     734                 : 
     735                 :     // Rewrite the single tab character into a sequence of spaces.
     736                0:     ReplaceText(TabLoc, 1, "        ", Spaces);
     737                 :   }
     738                0: }
     739                 : 
     740                 : static std::string getIvarAccessString(ObjCInterfaceDecl *ClassDecl,
     741                5:                                        ObjCIvarDecl *OID) {
     742                5:   std::string S;
     743                5:   S = "((struct ";
     744                5:   S += ClassDecl->getIdentifier()->getName();
     745                5:   S += "_IMPL *)self)->";
     746                5:   S += OID->getName();
     747                 :   return S;
     748                 : }
     749                 : 
     750                 : void RewriteObjC::RewritePropertyImplDecl(ObjCPropertyImplDecl *PID,
     751                 :                                           ObjCImplementationDecl *IMD,
     752                4:                                           ObjCCategoryImplDecl *CID) {
     753                4:   SourceLocation startLoc = PID->getLocStart();
     754                4:   InsertText(startLoc, "// ", 3);
     755                4:   const char *startBuf = SM->getCharacterData(startLoc);
                        0: branch 0 not taken
                        4: branch 1 taken
     756                4:   assert((*startBuf == '@') && "bogus @synthesize location");
     757                4:   const char *semiBuf = strchr(startBuf, ';');
                        0: branch 0 not taken
                        4: branch 1 taken
     758                4:   assert((*semiBuf == ';') && "@synthesize: can't find ';'");
     759                 :   SourceLocation onePastSemiLoc =
     760                4:     startLoc.getFileLocWithOffset(semiBuf-startBuf+1);
     761                 : 
                        1: branch 1 taken
                        3: branch 2 taken
     762                4:   if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic)
     763                1:     return; // FIXME: is this correct?
     764                 : 
     765                 :   // Generate the 'getter' function.
     766                3:   ObjCPropertyDecl *PD = PID->getPropertyDecl();
     767                3:   ObjCInterfaceDecl *ClassDecl = PD->getGetterMethodDecl()->getClassInterface();
     768                3:   ObjCIvarDecl *OID = PID->getPropertyIvarDecl();
     769                 : 
                        0: branch 0 not taken
                        3: branch 1 taken
     770                3:   if (!OID)
     771                0:     return;
     772                 : 
     773                3:   std::string Getr;
     774                3:   RewriteObjCMethodDecl(PD->getGetterMethodDecl(), Getr);
     775                3:   Getr += "{ ";
     776                 :   // Synthesize an explicit cast to gain access to the ivar.
     777                 :   // FIXME: deal with code generation implications for various property
     778                 :   // attributes (copy, retain, nonatomic).
     779                 :   // See objc-act.c:objc_synthesize_new_getter() for details.
     780                3:   Getr += "return " + getIvarAccessString(ClassDecl, OID);
     781                3:   Getr += "; }";
     782                3:   InsertText(onePastSemiLoc, Getr.c_str(), Getr.size());
                        1: branch 1 taken
                        2: branch 2 taken
     783                3:   if (PD->isReadOnly())
     784                1:     return;
     785                 : 
     786                 :   // Generate the 'setter' function.
     787                2:   std::string Setr;
     788                2:   RewriteObjCMethodDecl(PD->getSetterMethodDecl(), Setr);
     789                2:   Setr += "{ ";
     790                 :   // Synthesize an explicit cast to initialize the ivar.
     791                 :   // FIXME: deal with code generation implications for various property
     792                 :   // attributes (copy, retain, nonatomic).
     793                 :   // See objc-act.c:objc_synthesize_new_setter() for details.
     794                2:   Setr += getIvarAccessString(ClassDecl, OID) + " = ";
     795                2:   Setr += PD->getNameAsCString();
     796                2:   Setr += "; }";
                        2: branch 5 taken
                        1: branch 6 taken
     797                2:   InsertText(onePastSemiLoc, Setr.c_str(), Setr.size());
     798                 : }
     799                 : 
     800                8: void RewriteObjC::RewriteForwardClassDecl(ObjCClassDecl *ClassDecl) {
     801                 :   // Get the start location and compute the semi location.
     802                8:   SourceLocation startLoc = ClassDecl->getLocation();
     803                8:   const char *startBuf = SM->getCharacterData(startLoc);
     804                8:   const char *semiPtr = strchr(startBuf, ';');
     805                 : 
     806                 :   // Translate to typedef's that forward reference structs with the same name
     807                 :   // as the class. As a convenience, we include the original declaration
     808                 :   // as a comment.
     809                8:   std::string typedefString;
     810                8:   typedefString += "// @class ";
                       18: branch 2 taken
                        8: branch 3 taken
     811               26:   for (ObjCClassDecl::iterator I = ClassDecl->begin(), E = ClassDecl->end();
     812                 :        I != E; ++I) {
     813               18:     ObjCInterfaceDecl *ForwardDecl = I->getInterface();
     814               18:     typedefString += ForwardDecl->getNameAsString();
                       10: branch 0 taken
                        8: branch 1 taken
     815               18:     if (I+1 != E)
     816               10:       typedefString += ", ";
     817                 :     else
     818                8:       typedefString += ";\n";
     819                 :   }
     820                 :   
                       18: branch 2 taken
                        8: branch 3 taken
     821               26:   for (ObjCClassDecl::iterator I = ClassDecl->begin(), E = ClassDecl->end();
     822                 :        I != E; ++I) {
     823               18:     ObjCInterfaceDecl *ForwardDecl = I->getInterface();
     824               18:     typedefString += "#ifndef _REWRITER_typedef_";
     825               18:     typedefString += ForwardDecl->getNameAsString();
     826               18:     typedefString += "\n";
     827               18:     typedefString += "#define _REWRITER_typedef_";
     828               18:     typedefString += ForwardDecl->getNameAsString();
     829               18:     typedefString += "\n";
     830               18:     typedefString += "typedef struct objc_object ";
     831               18:     typedefString += ForwardDecl->getNameAsString();
     832               18:     typedefString += ";\n#endif\n";
     833                 :   }
     834                 : 
     835                 :   // Replace the @class with typedefs corresponding to the classes.
     836                 :   ReplaceText(startLoc, semiPtr-startBuf+1,
     837                8:               typedefString.c_str(), typedefString.size());
     838                8: }
     839                 : 
     840               55: void RewriteObjC::RewriteMethodDeclaration(ObjCMethodDecl *Method) {
     841                 :   // When method is a synthesized one, such as a getter/setter there is
     842                 :   // nothing to rewrite.
                       11: branch 1 taken
                       44: branch 2 taken
     843               55:   if (Method->isSynthesized())
     844               11:     return;
     845               44:   SourceLocation LocStart = Method->getLocStart();
     846               44:   SourceLocation LocEnd = Method->getLocEnd();
     847                 : 
                        0: branch 2 not taken
                       44: branch 3 taken
     848               44:   if (SM->getInstantiationLineNumber(LocEnd) >
     849                 :       SM->getInstantiationLineNumber(LocStart)) {
     850                0:     InsertText(LocStart, "#if 0\n", 6);
     851                0:     ReplaceText(LocEnd, 1, ";\n#endif\n", 9);
     852                 :   } else {
     853               44:     InsertText(LocStart, "// ", 3);
     854                 :   }
     855                 : }
     856                 : 
     857                7: void RewriteObjC::RewriteProperty(ObjCPropertyDecl *prop) {
     858                7:   SourceLocation Loc = prop->getAtLoc();
     859                 : 
     860                7:   ReplaceText(Loc, 0, "// ", 3);
     861                 :   // FIXME: handle properties that are declared across multiple lines.
     862                7: }
     863                 : 
     864                6: void RewriteObjC::RewriteCategoryDecl(ObjCCategoryDecl *CatDecl) {
     865                6:   SourceLocation LocStart = CatDecl->getLocStart();
     866                 : 
     867                 :   // FIXME: handle category headers that are declared across multiple lines.
     868                6:   ReplaceText(LocStart, 0, "// ", 3);
     869                 : 
                        1: branch 3 taken
                        6: branch 4 taken
     870               13:   for (ObjCCategoryDecl::prop_iterator I = CatDecl->prop_begin(),
     871                6:        E = CatDecl->prop_end(); I != E; ++I)
     872                1:     RewriteProperty(*I);
     873                 :   
                        6: branch 2 taken
                        6: branch 3 taken
     874               12:   for (ObjCCategoryDecl::instmeth_iterator
     875                6:          I = CatDecl->instmeth_begin(), E = CatDecl->instmeth_end();
     876                 :        I != E; ++I)
     877                6:     RewriteMethodDeclaration(*I);
                        0: branch 2 not taken
                        6: branch 3 taken
     878                6:   for (ObjCCategoryDecl::classmeth_iterator
     879                6:          I = CatDecl->classmeth_begin(), E = CatDecl->classmeth_end();
     880                 :        I != E; ++I)
     881                0:     RewriteMethodDeclaration(*I);
     882                 : 
     883                 :   // Lastly, comment out the @end.
     884                6:   ReplaceText(CatDecl->getAtEndRange().getBegin(), 0, "// ", 3);
     885                6: }
     886                 : 
     887               12: void RewriteObjC::RewriteProtocolDecl(ObjCProtocolDecl *PDecl) {
     888               12:   std::pair<const char*, const char*> MainBuf = SM->getBufferData(MainFileID);
     889                 : 
     890               12:   SourceLocation LocStart = PDecl->getLocStart();
     891                 : 
     892                 :   // FIXME: handle protocol headers that are declared across multiple lines.
     893               12:   ReplaceText(LocStart, 0, "// ", 3);
     894                 : 
                        5: branch 2 taken
                       12: branch 3 taken
     895               17:   for (ObjCProtocolDecl::instmeth_iterator
     896               12:          I = PDecl->instmeth_begin(), E = PDecl->instmeth_end();
     897                 :        I != E; ++I)
     898                5:     RewriteMethodDeclaration(*I);
                        1: branch 2 taken
                       12: branch 3 taken
     899               13:   for (ObjCProtocolDecl::classmeth_iterator
     900               12:          I = PDecl->classmeth_begin(), E = PDecl->classmeth_end();
     901                 :        I != E; ++I)
     902                1:     RewriteMethodDeclaration(*I);
     903                 : 
     904                 :   // Lastly, comment out the @end.
     905               12:   SourceLocation LocEnd = PDecl->getAtEndRange().getBegin();
     906               12:   ReplaceText(LocEnd, 0, "// ", 3);
     907                 : 
     908                 :   // Must comment out @optional/@required
     909               12:   const char *startBuf = SM->getCharacterData(LocStart);
     910               12:   const char *endBuf = SM->getCharacterData(LocEnd);
                      384: branch 0 taken
                       12: branch 1 taken
     911              396:   for (const char *p = startBuf; p < endBuf; p++) {
                       12: branch 0 taken
                      372: branch 1 taken
                        0: branch 3 not taken
                       12: branch 4 taken
     912              384:     if (*p == '@' && !strncmp(p+1, "optional", strlen("optional"))) {
     913                0:       std::string CommentedOptional = "/* @optional */";
     914                0:       SourceLocation OptionalLoc = LocStart.getFileLocWithOffset(p-startBuf);
     915                 :       ReplaceText(OptionalLoc, strlen("@optional"),
     916                0:                   CommentedOptional.c_str(), CommentedOptional.size());
     917                 : 
     918                 :     }
                       12: branch 0 taken
                      372: branch 1 taken
                        0: branch 3 not taken
                       12: branch 4 taken
     919              384:     else if (*p == '@' && !strncmp(p+1, "required", strlen("required"))) {
     920                0:       std::string CommentedRequired = "/* @required */";
     921                0:       SourceLocation OptionalLoc = LocStart.getFileLocWithOffset(p-startBuf);
     922                 :       ReplaceText(OptionalLoc, strlen("@required"),
     923                0:                   CommentedRequired.c_str(), CommentedRequired.size());
     924                 : 
     925                 :     }
     926                 :   }
     927               12: }
     928                 : 
     929                2: void RewriteObjC::RewriteForwardProtocolDecl(ObjCForwardProtocolDecl *PDecl) {
     930                2:   SourceLocation LocStart = PDecl->getLocation();
                        0: branch 1 not taken
                        2: branch 2 taken
     931                2:   if (LocStart.isInvalid())
     932                0:     assert(false && "Invalid SourceLocation");
     933                 :   // FIXME: handle forward protocol that are declared across multiple lines.
     934                2:   ReplaceText(LocStart, 0, "// ", 3);
     935                2: }
     936                 : 
     937                 : void RewriteObjC::RewriteObjCMethodDecl(ObjCMethodDecl *OMD,
     938               53:                                         std::string &ResultStr) {
     939                 :   //fprintf(stderr,"In RewriteObjCMethodDecl\n");
     940               53:   const FunctionType *FPRetType = 0;
     941               53:   ResultStr += "\nstatic ";
                        2: branch 3 taken
                       51: branch 4 taken
     942               53:   if (OMD->getResultType()->isObjCQualifiedIdType())
     943                2:     ResultStr += "id";
                       51: branch 3 taken
                        0: branch 4 not taken
                        0: branch 8 not taken
                       51: branch 9 taken
                        0: branch 10 not taken
                       51: branch 11 taken
     944               51:   else if (OMD->getResultType()->isFunctionPointerType() ||
     945                 :            OMD->getResultType()->isBlockPointerType()) {
     946                 :     // needs special handling, since pointer-to-functions have special
     947                 :     // syntax (where a decaration models use).
     948                0:     QualType retType = OMD->getResultType();
     949                0:     QualType PointeeTy;
                        0: branch 2 not taken
                        0: branch 3 not taken
     950                0:     if (const PointerType* PT = retType->getAs<PointerType>())
     951                0:       PointeeTy = PT->getPointeeType();
                        0: branch 2 not taken
                        0: branch 3 not taken
     952                0:     else if (const BlockPointerType *BPT = retType->getAs<BlockPointerType>())
     953                0:       PointeeTy = BPT->getPointeeType();
                        0: branch 2 not taken
                        0: branch 3 not taken
     954                0:     if ((FPRetType = PointeeTy->getAs<FunctionType>())) {
     955                0:       ResultStr += FPRetType->getResultType().getAsString();
     956                0:       ResultStr += "(*";
     957                 :     }
     958                 :   } else
     959               51:     ResultStr += OMD->getResultType().getAsString();
     960               53:   ResultStr += " ";
     961                 : 
     962                 :   // Unique method name
     963               53:   std::string NameStr;
     964                 : 
                       48: branch 1 taken
                        5: branch 2 taken
     965               53:   if (OMD->isInstanceMethod())
     966               48:     NameStr += "_I_";
     967                 :   else
     968                5:     NameStr += "_C_";
     969                 : 
     970               53:   NameStr += OMD->getClassInterface()->getNameAsString();
     971               53:   NameStr += "_";
     972                 : 
                        6: branch 0 taken
                       47: branch 1 taken
     973               53:   if (ObjCCategoryImplDecl *CID =
     974               53:       dyn_cast<ObjCCategoryImplDecl>(OMD->getDeclContext())) {
     975                6:     NameStr += CID->getNameAsString();
     976                6:     NameStr += "_";
     977                 :   }
     978                 :   // Append selector names, replacing ':' with '_'
     979                 :   {
     980               53:     std::string selString = OMD->getSelector().getAsString();
     981               53:     int len = selString.size();
                      682: branch 0 taken
                       53: branch 1 taken
     982              735:     for (int i = 0; i < len; i++)
                       34: branch 1 taken
                      648: branch 2 taken
     983              682:       if (selString[i] == ':')
     984               34:         selString[i] = '_';
     985               53:     NameStr += selString;
     986                 :   }
     987                 :   // Remember this name for metadata emission
     988               53:   MethodInternalNames[OMD] = NameStr;
     989               53:   ResultStr += NameStr;
     990                 : 
     991                 :   // Rewrite arguments
     992               53:   ResultStr += "(";
     993                 : 
     994                 :   // invisible arguments
                       48: branch 1 taken
                        5: branch 2 taken
     995               53:   if (OMD->isInstanceMethod()) {
     996               48:     QualType selfTy = Context->getObjCInterfaceType(OMD->getClassInterface());
     997               48:     selfTy = Context->getPointerType(selfTy);
                       40: branch 0 taken
                        8: branch 1 taken
     998               48:     if (!LangOpts.Microsoft) {
                       13: branch 2 taken
                       27: branch 3 taken
     999               40:       if (ObjCSynthesizedStructs.count(OMD->getClassInterface()))
    1000               13:         ResultStr += "struct ";
    1001                 :     }
    1002                 :     // When rewriting for Microsoft, explicitly omit the structure name.
    1003               48:     ResultStr += OMD->getClassInterface()->getNameAsString();
    1004               48:     ResultStr += " *";
    1005                 :   }
    1006                 :   else
    1007                5:     ResultStr += Context->getObjCClassType().getAsString();
    1008                 : 
    1009               53:   ResultStr += " self, ";
    1010               53:   ResultStr += Context->getObjCSelType().getAsString();
    1011               53:   ResultStr += " _cmd";
    1012                 : 
    1013                 :   // Method arguments.
                       34: branch 1 taken
                       53: branch 2 taken
    1014              140:   for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(),
    1015               53:        E = OMD->param_end(); PI != E; ++PI) {
    1016               34:     ParmVarDecl *PDecl = *PI;
    1017               34:     ResultStr += ", ";
                        1: branch 3 taken
                       33: branch 4 taken
    1018               34:     if (PDecl->getType()->isObjCQualifiedIdType()) {
    1019                1:       ResultStr += "id ";
    1020                1:       ResultStr += PDecl->getNameAsString();
    1021                 :     } else {
    1022               33:       std::string Name = PDecl->getNameAsString();
                        0: branch 2 not taken
                       33: branch 3 taken
    1023               33:       if (isTopLevelBlockPointerType(PDecl->getType())) {
    1024                 :         // Make sure we convert "t (^)(...)" to "t (*)(...)".
    1025                0:         const BlockPointerType *BPT = PDecl->getType()->getAs<BlockPointerType>();
    1026                 :         Context->getPointerType(BPT->getPointeeType()).getAsStringInternal(Name,
    1027                0:                                                         Context->PrintingPolicy);
    1028                 :       } else
    1029               33:         PDecl->getType().getAsStringInternal(Name, Context->PrintingPolicy);
    1030               33:       ResultStr += Name;
    1031                 :     }
    1032                 :   }
                        1: branch 1 taken
                       52: branch 2 taken
    1033               53:   if (OMD->isVariadic())
    1034                1:     ResultStr += ", ...";
    1035               53:   ResultStr += ") ";
    1036                 : 
                        0: branch 0 not taken
                       53: branch 1 taken
    1037               53:   if (FPRetType) {
    1038                0:     ResultStr += ")"; // close the precedence "scope" for "*".
    1039                 : 
    1040                 :     // Now, emit the argument types (if any).
                        0: branch 1 not taken
                        0: branch 2 not taken
    1041                0:     if (const FunctionProtoType *FT = dyn_cast<FunctionProtoType>(FPRetType)) {
    1042                0:       ResultStr += "(";
                        0: branch 2 not taken
                        0: branch 3 not taken
    1043                0:       for (unsigned i = 0, e = FT->getNumArgs(); i != e; ++i) {
                        0: branch 0 not taken
                        0: branch 1 not taken
    1044                0:         if (i) ResultStr += ", ";
    1045                0:         std::string ParamStr = FT->getArgType(i).getAsString();
    1046                0:         ResultStr += ParamStr;
    1047                 :       }
                        0: branch 1 not taken
                        0: branch 2 not taken
    1048                0:       if (FT->isVariadic()) {
                        0: branch 1 not taken
                        0: branch 2 not taken
    1049                0:         if (FT->getNumArgs()) ResultStr += ", ";
    1050                0:         ResultStr += "...";
    1051                 :       }
    1052                0:       ResultStr += ")";
    1053                 :     } else {
    1054                0:       ResultStr += "()";
    1055                 :     }
    1056               53:   }
    1057               53: }
    1058               41: void RewriteObjC::RewriteImplementationDecl(Decl *OID) {
    1059               41:   ObjCImplementationDecl *IMD = dyn_cast<ObjCImplementationDecl>(OID);
    1060               41:   ObjCCategoryImplDecl *CID = dyn_cast<ObjCCategoryImplDecl>(OID);
    1061                 : 
                       35: branch 0 taken
                        6: branch 1 taken
    1062               41:   if (IMD)
    1063               35:     InsertText(IMD->getLocStart(), "// ", 3);
    1064                 :   else
    1065                6:     InsertText(CID->getLocStart(), "// ", 3);
    1066                 : 
                       43: branch 3 taken
                       41: branch 4 taken
    1067               84:   for (ObjCCategoryImplDecl::instmeth_iterator
                       35: branch 0 taken
                        6: branch 1 taken
    1068               41:        I = IMD ? IMD->instmeth_begin() : CID->instmeth_begin(),
                       35: branch 0 taken
                        6: branch 1 taken
    1069               41:        E = IMD ? IMD->instmeth_end() : CID->instmeth_end();
    1070                 :        I != E; ++I) {
    1071               43:     std::string ResultStr;
    1072               43:     ObjCMethodDecl *OMD = *I;
    1073               43:     RewriteObjCMethodDecl(OMD, ResultStr);
    1074               43:     SourceLocation LocStart = OMD->getLocStart();
    1075               43:     SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart();
    1076                 : 
    1077               43:     const char *startBuf = SM->getCharacterData(LocStart);
    1078               43:     const char *endBuf = SM->getCharacterData(LocEnd);
    1079                 :     ReplaceText(LocStart, endBuf-startBuf,
    1080               43:                 ResultStr.c_str(), ResultStr.size());
    1081                 :   }
    1082                 : 
                        5: branch 3 taken
                       41: branch 4 taken
    1083               46:   for (ObjCCategoryImplDecl::classmeth_iterator
                       35: branch 0 taken
                        6: branch 1 taken
    1084               41:        I = IMD ? IMD->classmeth_begin() : CID->classmeth_begin(),
                       35: branch 0 taken
                        6: branch 1 taken
    1085               41:        E = IMD ? IMD->classmeth_end() : CID->classmeth_end();
    1086                 :        I != E; ++I) {
    1087                5:     std::string ResultStr;
    1088                5:     ObjCMethodDecl *OMD = *I;
    1089                5:     RewriteObjCMethodDecl(OMD, ResultStr);
    1090                5:     SourceLocation LocStart = OMD->getLocStart();
    1091                5:     SourceLocation LocEnd = OMD->getCompoundBody()->getLocStart();
    1092                 : 
    1093                5:     const char *startBuf = SM->getCharacterData(LocStart);
    1094                5:     const char *endBuf = SM->getCharacterData(LocEnd);
    1095                 :     ReplaceText(LocStart, endBuf-startBuf,
    1096                5:                 ResultStr.c_str(), ResultStr.size());
    1097                 :   }
                        4: branch 2 taken
                       41: branch 3 taken
    1098               45:   for (ObjCCategoryImplDecl::propimpl_iterator
                       35: branch 0 taken
                        6: branch 1 taken
    1099               41:        I = IMD ? IMD->propimpl_begin() : CID->propimpl_begin(),
                       35: branch 0 taken
                        6: branch 1 taken
    1100               41:        E = IMD ? IMD->propimpl_end() : CID->propimpl_end();
    1101                 :        I != E; ++I) {
    1102                4:     RewritePropertyImplDecl(*I, IMD, CID);
    1103                 :   }
    1104                 : 
                       35: branch 0 taken
                        6: branch 1 taken
    1105               41:   if (IMD)
    1106               35:     InsertText(IMD->getLocEnd(), "// ", 3);
    1107                 :   else
    1108                6:    InsertText(CID->getLocEnd(), "// ", 3);
    1109               41: }
    1110                 : 
    1111               62: void RewriteObjC::RewriteInterfaceDecl(ObjCInterfaceDecl *ClassDecl) {
    1112               62:   std::string ResultStr;
                       62: branch 1 taken
                        0: branch 2 not taken
    1113               62:   if (!ObjCForwardDecls.count(ClassDecl)) {
    1114                 :     // we haven't seen a forward decl - generate a typedef.
    1115               62:     ResultStr = "#ifndef _REWRITER_typedef_";
    1116               62:     ResultStr += ClassDecl->getNameAsString();
    1117               62:     ResultStr += "\n";
    1118               62:     ResultStr += "#define _REWRITER_typedef_";
    1119               62:     ResultStr += ClassDecl->getNameAsString();
    1120               62:     ResultStr += "\n";
    1121               62:     ResultStr += "typedef struct objc_object ";
    1122               62:     ResultStr += ClassDecl->getNameAsString();
    1123               62:     ResultStr += ";\n#endif\n";
    1124                 :     // Mark this typedef as having been generated.
    1125               62:     ObjCForwardDecls.insert(ClassDecl);
    1126                 :   }
    1127               62:   SynthesizeObjCInternalStruct(ClassDecl, ResultStr);
    1128                 : 
                        6: branch 3 taken
                       62: branch 4 taken
    1129              130:   for (ObjCInterfaceDecl::prop_iterator I = ClassDecl->prop_begin(),
    1130               62:          E = ClassDecl->prop_end(); I != E; ++I)
    1131                6:     RewriteProperty(*I);
                       36: branch 2 taken
                       62: branch 3 taken
    1132               98:   for (ObjCInterfaceDecl::instmeth_iterator
    1133               62:          I = ClassDecl->instmeth_begin(), E = ClassDecl->instmeth_end();
    1134                 :        I != E; ++I)
    1135               36:     RewriteMethodDeclaration(*I);
                        7: branch 2 taken
                       62: branch 3 taken
    1136               69:   for (ObjCInterfaceDecl::classmeth_iterator
    1137               62:          I = ClassDecl->classmeth_begin(), E = ClassDecl->classmeth_end();
    1138                 :        I != E; ++I)
    1139                7:     RewriteMethodDeclaration(*I);
    1140                 : 
    1141                 :   // Lastly, comment out the @end.
    1142               62:   ReplaceText(ClassDecl->getAtEndRange().getBegin(), 0, "// ", 3);
    1143               62: }
    1144                 : 
    1145                 : Stmt *RewriteObjC::RewritePropertySetter(BinaryOperator *BinOp, Expr *newStmt,
    1146                7:                                          SourceRange SrcRange) {
    1147                 :   // Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr.
    1148                 :   // This allows us to reuse all the fun and games in SynthMessageExpr().
    1149                7:   ObjCPropertyRefExpr *PropRefExpr = dyn_cast<ObjCPropertyRefExpr>(BinOp->getLHS());
    1150                 :   ObjCMessageExpr *MsgExpr;
    1151                7:   ObjCPropertyDecl *PDecl = PropRefExpr->getProperty();
    1152                7:   llvm::SmallVector<Expr *, 1> ExprVec;
    1153                7:   ExprVec.push_back(newStmt);
    1154                 : 
    1155                7:   Stmt *Receiver = PropRefExpr->getBase();
    1156                7:   ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(Receiver);
                        1: branch 0 taken
                        6: branch 1 taken
                        1: branch 3 taken
                        0: branch 4 not taken
                        1: branch 5 taken
                        6: branch 6 taken
    1157                7:   if (PRE && PropGetters[PRE]) {
    1158                 :     // This allows us to handle chain/nested property getters.
    1159                1:     Receiver = PropGetters[PRE];
    1160                 :   }
    1161                 :   MsgExpr = new (Context) ObjCMessageExpr(dyn_cast<Expr>(Receiver),
    1162                 :                                 PDecl->getSetterName(), PDecl->getType(),
    1163                 :                                 PDecl->getSetterMethodDecl(),
    1164                 :                                 SourceLocation(), SourceLocation(),
                        7: branch 8 taken
                        0: branch 9 not taken
    1165                7:                                 &ExprVec[0], 1);
    1166                7:   Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr);
    1167                 : 
    1168                 :   // Now do the actual rewrite.
    1169                7:   ReplaceStmtWithRange(BinOp, ReplacingStmt, SrcRange);
    1170                 :   //delete BinOp;
    1171                 :   // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references
    1172                 :   // to things that stay around.
    1173                7:   Context->Deallocate(MsgExpr);
    1174                7:   return ReplacingStmt;
    1175                 : }
    1176                 : 
    1177                9: Stmt *RewriteObjC::RewritePropertyGetter(ObjCPropertyRefExpr *PropRefExpr) {
    1178                 :   // Synthesize a ObjCMessageExpr from a ObjCPropertyRefExpr.
    1179                 :   // This allows us to reuse all the fun and games in SynthMessageExpr().
    1180                 :   ObjCMessageExpr *MsgExpr;
    1181                9:   ObjCPropertyDecl *PDecl = PropRefExpr->getProperty();
    1182                 : 
    1183                9:   Stmt *Receiver = PropRefExpr->getBase();
    1184                 : 
    1185                9:   ObjCPropertyRefExpr *PRE = dyn_cast<ObjCPropertyRefExpr>(Receiver);
                        1: branch 0 taken
                        8: branch 1 taken
                        1: branch 3 taken
                        0: branch 4 not taken
                        1: branch 5 taken
                        8: branch 6 taken
    1186                9:   if (PRE && PropGetters[PRE]) {
    1187                 :     // This allows us to handle chain/nested property getters.
    1188                1:     Receiver = PropGetters[PRE];
    1189                 :   }
    1190                 :   MsgExpr = new (Context) ObjCMessageExpr(dyn_cast<Expr>(Receiver),
    1191                 :                                 PDecl->getGetterName(), PDecl->getType(),
    1192                 :                                 PDecl->getGetterMethodDecl(),
    1193                 :                                 SourceLocation(), SourceLocation(),
                        9: branch 7 taken
                        0: branch 8 not taken
    1194                9:                                 0, 0);
    1195                 : 
    1196                9:   Stmt *ReplacingStmt = SynthMessageExpr(MsgExpr);
    1197                 : 
                        1: branch 0 taken
                        8: branch 1 taken
    1198                9:   if (!PropParentMap)
    1199                1:     PropParentMap = new ParentMap(CurrentBody);
    1200                 : 
    1201                9:   Stmt *Parent = PropParentMap->getParent(PropRefExpr);
                        9: branch 0 taken
                        0: branch 1 not taken
                        2: branch 3 taken
                        7: branch 4 taken
                        2: branch 5 taken
                        7: branch 6 taken
    1202                9:   if (Parent && isa<ObjCPropertyRefExpr>(Parent)) {
    1203                 :     // We stash away the ReplacingStmt since actually doing the
    1204                 :     // replacement/rewrite won't work for nested getters (e.g. obj.p.i)
    1205                2:     PropGetters[PropRefExpr] = ReplacingStmt;
    1206                 :     // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references
    1207                 :     // to things that stay around.
    1208                2:     Context->Deallocate(MsgExpr);
    1209                2:     return PropRefExpr; // return the original...
    1210                 :   } else {
    1211                7:     ReplaceStmt(PropRefExpr, ReplacingStmt);
    1212                 :     // delete PropRefExpr; elsewhere...
    1213                 :     // NOTE: We don't want to call MsgExpr->Destroy(), as it holds references
    1214                 :     // to things that stay around.
    1215                7:     Context->Deallocate(MsgExpr);
    1216                7:     return ReplacingStmt;
    1217                 :   }
    1218                 : }
    1219                 : 
    1220                 : Stmt *RewriteObjC::RewriteObjCIvarRefExpr(ObjCIvarRefExpr *IV,
    1221                 :                                           SourceLocation OrigStart,
    1222               28:                                           bool &replaced) {
    1223               28:   ObjCIvarDecl *D = IV->getDecl();
    1224               28:   const Expr *BaseExpr = IV->getBase();
                       23: branch 0 taken
                        5: branch 1 taken
    1225               28:   if (CurMethodDef) {
                       23: branch 3 taken
                        0: branch 4 not taken
    1226               23:     if (BaseExpr->getType()->isObjCObjectPointerType()) {
    1227                 :       ObjCInterfaceType *iFaceDecl =
    1228               23:         dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
                        0: branch 0 not taken
                       23: branch 1 taken
    1229               23:       assert(iFaceDecl && "RewriteObjCIvarRefExpr - iFaceDecl is null");
    1230                 :       // lookup which class implements the instance variable.
    1231               23:       ObjCInterfaceDecl *clsDeclared = 0;
    1232                 :       iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
    1233               23:                                                    clsDeclared);
                        0: branch 0 not taken
                       23: branch 1 taken
    1234               23:       assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");
    1235                 : 
    1236                 :       // Synthesize an explicit cast to gain access to the ivar.
    1237               23:       std::string RecName = clsDeclared->getIdentifier()->getName();
    1238               23:       RecName += "_IMPL";
    1239               23:       IdentifierInfo *II = &Context->Idents.get(RecName.c_str());
    1240                 :       RecordDecl *RD = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl,
                       23: branch 2 taken
                        0: branch 3 not taken
    1241               23:                                           SourceLocation(), II);
                        0: branch 0 not taken
                       23: branch 1 taken
    1242               23:       assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");
    1243               23:       QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
    1244                 :       CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT,
    1245                 :                                                     CastExpr::CK_Unknown,
    1246               23:                                                     IV->getBase());
    1247                 :       // Don't forget the parens to enforce the proper binding.
    1248                 :       ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(),
    1249                 :                                                IV->getBase()->getLocEnd(),
                       23: branch 5 taken
                        0: branch 6 not taken
    1250               23:                                                castExpr);
    1251               23:       replaced = true;
                       13: branch 1 taken
                       10: branch 2 taken
                       13: branch 5 taken
                        0: branch 6 not taken
                       13: branch 7 taken
                       10: branch 8 taken
    1252               23:       if (IV->isFreeIvar() &&
    1253                 :           CurMethodDef->getClassInterface() == iFaceDecl->getDecl()) {
    1254                 :         MemberExpr *ME = new (Context) MemberExpr(PE, true, D,
    1255                 :                                                    IV->getLocation(),
                       13: branch 3 taken
                        0: branch 4 not taken
    1256               13:                                                    D->getType());
    1257                 :         // delete IV; leak for now, see RewritePropertySetter() usage for more info.
    1258               13:         return ME;
    1259                 :       }
    1260                 :       // Get the new text
    1261                 :       // Cannot delete IV->getBase(), since PE points to it.
    1262                 :       // Replace the old base with the cast. This is important when doing
    1263                 :       // embedded rewrites. For example, [newInv->_container addObject:0].
    1264               10:       IV->setBase(PE);
    1265               10:       return IV;
    1266                 :     }
    1267                 :   } else { // we are outside a method.
                        5: branch 1 taken
                        0: branch 2 not taken
    1268                5:     assert(!IV->isFreeIvar() && "Cannot have a free standing ivar outside a method");
    1269                 : 
    1270                 :     // Explicit ivar refs need to have a cast inserted.
    1271                 :     // FIXME: consider sharing some of this code with the code above.
                        5: branch 3 taken
                        0: branch 4 not taken
    1272                5:     if (BaseExpr->getType()->isObjCObjectPointerType()) {
    1273                 :       ObjCInterfaceType *iFaceDecl =
    1274                5:         dyn_cast<ObjCInterfaceType>(BaseExpr->getType()->getPointeeType());
    1275                 :       // lookup which class implements the instance variable.
    1276                5:       ObjCInterfaceDecl *clsDeclared = 0;
    1277                 :       iFaceDecl->getDecl()->lookupInstanceVariable(D->getIdentifier(),
    1278                5:                                                    clsDeclared);
                        0: branch 0 not taken
                        5: branch 1 taken
    1279                5:       assert(clsDeclared && "RewriteObjCIvarRefExpr(): Can't find class");
    1280                 : 
    1281                 :       // Synthesize an explicit cast to gain access to the ivar.
    1282                5:       std::string RecName = clsDeclared->getIdentifier()->getName();
    1283                5:       RecName += "_IMPL";
    1284                5:       IdentifierInfo *II = &Context->Idents.get(RecName.c_str());
    1285                 :       RecordDecl *RD = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl,
                        5: branch 2 taken
                        0: branch 3 not taken
    1286                5:                                           SourceLocation(), II);
                        0: branch 0 not taken
                        5: branch 1 taken
    1287                5:       assert(RD && "RewriteObjCIvarRefExpr(): Can't find RecordDecl");
    1288                5:       QualType castT = Context->getPointerType(Context->getTagDeclType(RD));
    1289                 :       CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, castT,
    1290                 :                                                     CastExpr::CK_Unknown,
    1291                5:                                                     IV->getBase());
    1292                 :       // Don't forget the parens to enforce the proper binding.
    1293                 :       ParenExpr *PE = new (Context) ParenExpr(IV->getBase()->getLocStart(),
                        5: branch 5 taken
                        0: branch 6 not taken
    1294                5:                                     IV->getBase()->getLocEnd(), castExpr);
    1295                5:       replaced = true;
    1296                 :       // Cannot delete IV->getBase(), since PE points to it.
    1297                 :       // Replace the old base with the cast. This is important when doing
    1298                 :       // embedded rewrites. For example, [newInv->_container addObject:0].
    1299                5:       IV->setBase(PE);
    1300                5:       return IV;
    1301                 :     }
    1302                 :   }
    1303                0:   return IV;
    1304                 : }
    1305                 : 
    1306               69: Stmt *RewriteObjC::RewriteObjCNestedIvarRefExpr(Stmt *S, bool &replaced) {
                       45: branch 4 taken
                       69: branch 5 taken
    1307              114:   for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
    1308                 :        CI != E; ++CI) {
                       45: branch 1 taken
                        0: branch 2 not taken
    1309               45:     if (*CI) {
    1310               45:       Stmt *newStmt = RewriteObjCNestedIvarRefExpr(*CI, replaced);
                       45: branch 0 taken
                        0: branch 1 not taken
    1311               45:       if (newStmt)
    1312               45:         *CI = newStmt;
    1313                 :     }
    1314                 :   }
                       28: branch 1 taken
                       41: branch 2 taken
    1315               69:   if (ObjCIvarRefExpr *IvarRefExpr = dyn_cast<ObjCIvarRefExpr>(S)) {
    1316               28:     SourceRange OrigStmtRange = S->getSourceRange();
    1317                 :     Stmt *newStmt = RewriteObjCIvarRefExpr(IvarRefExpr, OrigStmtRange.getBegin(),
    1318               28:                                            replaced);
    1319               28:     return newStmt;
    1320                 :   } 
                        3: branch 1 taken
                       38: branch 2 taken
    1321               41:   if (ObjCMessageExpr *MsgRefExpr = dyn_cast<ObjCMessageExpr>(S)) {
    1322                3:     Stmt *newStmt = SynthMessageExpr(MsgRefExpr);
    1323                3:     return newStmt;
    1324                 :   }
    1325               38:   return S;
    1326                 : }
    1327                 : 
    1328                 : /// SynthCountByEnumWithState - To print:
    1329                 : /// ((unsigned int (*)
    1330                 : ///  (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int))
    1331                 : ///  (void *)objc_msgSend)((id)l_collection,
    1332                 : ///                        sel_registerName(
    1333                 : ///                          "countByEnumeratingWithState:objects:count:"),
    1334                 : ///                        &enumState,
    1335                 : ///                        (id *)items, (unsigned int)16)
    1336                 : ///
    1337               32: void RewriteObjC::SynthCountByEnumWithState(std::string &buf) {
    1338                 :   buf += "((unsigned int (*) (id, SEL, struct __objcFastEnumerationState *, "
    1339               32:   "id *, unsigned int))(void *)objc_msgSend)";
    1340               32:   buf += "\n\t\t";
    1341               32:   buf += "((id)l_collection,\n\t\t";
    1342               32:   buf += "sel_registerName(\"countByEnumeratingWithState:objects:count:\"),";
    1343               32:   buf += "\n\t\t";
    1344                 :   buf += "&enumState, "
    1345               32:          "(id *)items, (unsigned int)16)";
    1346               32: }
    1347                 : 
    1348                 : /// RewriteBreakStmt - Rewrite for a break-stmt inside an ObjC2's foreach
    1349                 : /// statement to exit to its outer synthesized loop.
    1350                 : ///
    1351                6: Stmt *RewriteObjC::RewriteBreakStmt(BreakStmt *S) {
                        6: branch 1 taken
                        0: branch 2 not taken
                        4: branch 5 taken
                        2: branch 6 taken
                        4: branch 7 taken
                        2: branch 8 taken
    1352                6:   if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
    1353                4:     return S;
    1354                 :   // replace break with goto __break_label
    1355                2:   std::string buf;
    1356                 : 
    1357                2:   SourceLocation startLoc = S->getLocStart();
    1358                2:   buf = "goto __break_label_";
    1359                2:   buf += utostr(ObjCBcLabelNo.back());
    1360                2:   ReplaceText(startLoc, strlen("break"), buf.c_str(), buf.size());
    1361                 : 
    1362                2:   return 0;
    1363                 : }
    1364                 : 
    1365                 : /// RewriteContinueStmt - Rewrite for a continue-stmt inside an ObjC2's foreach
    1366                 : /// statement to continue with its inner synthesized loop.
    1367                 : ///
    1368                2: Stmt *RewriteObjC::RewriteContinueStmt(ContinueStmt *S) {
                        2: branch 1 taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                        2: branch 6 taken
                        0: branch 7 not taken
                        2: branch 8 taken
    1369                2:   if (Stmts.empty() || !isa<ObjCForCollectionStmt>(Stmts.back()))
    1370                0:     return S;
    1371                 :   // replace continue with goto __continue_label
    1372                2:   std::string buf;
    1373                 : 
    1374                2:   SourceLocation startLoc = S->getLocStart();
    1375                2:   buf = "goto __continue_label_";
    1376                2:   buf += utostr(ObjCBcLabelNo.back());
    1377                2:   ReplaceText(startLoc, strlen("continue"), buf.c_str(), buf.size());
    1378                 : 
    1379                2:   return 0;
    1380                 : }
    1381                 : 
    1382                 : /// RewriteObjCForCollectionStmt - Rewriter for ObjC2's foreach statement.
    1383                 : ///  It rewrites:
    1384                 : /// for ( type elem in collection) { stmts; }
    1385                 : 
    1386                 : /// Into:
    1387                 : /// {
    1388                 : ///   type elem;
    1389                 : ///   struct __objcFastEnumerationState enumState = { 0 };
    1390                 : ///   id items[16];
    1391                 : ///   id l_collection = (id)collection;
    1392                 : ///   unsigned long limit = [l_collection countByEnumeratingWithState:&enumState
    1393                 : ///                                       objects:items count:16];
    1394                 : /// if (limit) {
    1395                 : ///   unsigned long startMutations = *enumState.mutationsPtr;
    1396                 : ///   do {
    1397                 : ///        unsigned long counter = 0;
    1398                 : ///        do {
    1399                 : ///             if (startMutations != *enumState.mutationsPtr)
    1400                 : ///               objc_enumerationMutation(l_collection);
    1401                 : ///             elem = (type)enumState.itemsPtr[counter++];
    1402                 : ///             stmts;
    1403                 : ///             __continue_label: ;
    1404                 : ///        } while (counter < limit);
    1405                 : ///   } while (limit = [l_collection countByEnumeratingWithState:&enumState
    1406                 : ///                                  objects:items count:16]);
    1407                 : ///   elem = nil;
    1408                 : ///   __break_label: ;
    1409                 : ///  }
    1410                 : ///  else
    1411                 : ///       elem = nil;
    1412                 : ///  }
    1413                 : ///
    1414                 : Stmt *RewriteObjC::RewriteObjCForCollectionStmt(ObjCForCollectionStmt *S,
    1415               16:                                                 SourceLocation OrigEnd) {
                       16: branch 1 taken
                        0: branch 2 not taken
    1416               16:   assert(!Stmts.empty() && "ObjCForCollectionStmt - Statement stack empty");
    1417                 :   assert(isa<ObjCForCollectionStmt>(Stmts.back()) &&
                       16: branch 2 taken
                        0: branch 3 not taken
    1418               16:          "ObjCForCollectionStmt Statement stack mismatch");
    1419                 :   assert(!ObjCBcLabelNo.empty() &&
                       16: branch 1 taken
                        0: branch 2 not taken
    1420               16:          "ObjCForCollectionStmt - Label No stack empty");
    1421                 : 
    1422               16:   SourceLocation startLoc = S->getLocStart();
    1423               16:   const char *startBuf = SM->getCharacterData(startLoc);
    1424                 :   const char *elementName;
    1425               16:   std::string elementTypeAsString;
    1426               16:   std::string buf;
    1427               16:   buf = "\n{\n\t";
                        7: branch 2 taken
                        9: branch 3 taken
    1428               16:   if (DeclStmt *DS = dyn_cast<DeclStmt>(S->getElement())) {
    1429                 :     // type elem;
    1430                7:     NamedDecl* D = cast<NamedDecl>(DS->getSingleDecl());
    1431                7:     QualType ElementType = cast<ValueDecl>(D)->getType();
                        7: branch 2 taken
                        0: branch 3 not taken
                        0: branch 6 not taken
                        7: branch 7 taken
                        0: branch 8 not taken
                        7: branch 9 taken
    1432                7:     if (ElementType->isObjCQualifiedIdType() ||
    1433                 :         ElementType->isObjCQualifiedInterfaceType())
    1434                 :       // Simply use 'id' for all qualified types.
    1435                0:       elementTypeAsString = "id";
    1436                 :     else
    1437                7:       elementTypeAsString = ElementType.getAsString();
    1438                7:     buf += elementTypeAsString;
    1439                7:     buf += " ";
    1440                7:     elementName = D->getNameAsCString();
    1441                7:     buf += elementName;
    1442                7:     buf += ";\n\t";
    1443                 :   }
    1444                 :   else {
    1445                9:     DeclRefExpr *DR = cast<DeclRefExpr>(S->getElement());
    1446                9:     elementName = DR->getDecl()->getNameAsCString();
    1447                9:     ValueDecl *VD = cast<ValueDecl>(DR->getDecl());
                        9: branch 3 taken
                        0: branch 4 not taken
                        0: branch 8 not taken
                        9: branch 9 taken
                        0: branch 10 not taken
                        9: branch 11 taken
    1448                9:     if (VD->getType()->isObjCQualifiedIdType() ||
    1449                 :         VD->getType()->isObjCQualifiedInterfaceType())
    1450                 :       // Simply use 'id' for all qualified types.
    1451                0:       elementTypeAsString = "id";
    1452                 :     else
    1453                9:       elementTypeAsString = VD->getType().getAsString();
    1454                 :   }
    1455                 : 
    1456                 :   // struct __objcFastEnumerationState enumState = { 0 };
    1457               16:   buf += "struct __objcFastEnumerationState enumState = { 0 };\n\t";
    1458                 :   // id items[16];
    1459               16:   buf += "id items[16];\n\t";
    1460                 :   // id l_collection = (id)
    1461               16:   buf += "id l_collection = (id)";
    1462                 :   // Find start location of 'collection' the hard way!
    1463               16:   const char *startCollectionBuf = startBuf;
    1464               16:   startCollectionBuf += 3;  // skip 'for'
    1465               16:   startCollectionBuf = strchr(startCollectionBuf, '(');
    1466               16:   startCollectionBuf++; // skip '('
    1467                 :   // find 'in' and skip it.
                       81: branch 0 taken
                       25: branch 1 taken
                        9: branch 2 taken
                       16: branch 3 taken
                        0: branch 4 not taken
                       16: branch 5 taken
                        3: branch 6 taken
                       13: branch 7 taken
                        1: branch 8 taken
                        2: branch 9 taken
                        0: branch 10 not taken
                        1: branch 11 taken
    1468              122:   while (*startCollectionBuf != ' ' ||
    1469                 :          *(startCollectionBuf+1) != 'i' || *(startCollectionBuf+2) != 'n' ||
    1470                 :          (*(startCollectionBuf+3) != ' ' &&
    1471                 :           *(startCollectionBuf+3) != '[' && *(startCollectionBuf+3) != '('))
    1472               90:     startCollectionBuf++;
    1473               16:   startCollectionBuf += 3;
    1474                 : 
    1475                 :   // Replace: "for (type element in" with string constructed thus far.
    1476                 :   ReplaceText(startLoc, startCollectionBuf - startBuf,
    1477               16:               buf.c_str(), buf.size());
    1478                 :   // Replace ')' in for '(' type elem in collection ')' with ';'
    1479               16:   SourceLocation rightParenLoc = S->getRParenLoc();
    1480               16:   const char *rparenBuf = SM->getCharacterData(rightParenLoc);
    1481               16:   SourceLocation lparenLoc = startLoc.getFileLocWithOffset(rparenBuf-startBuf);
    1482               16:   buf = ";\n\t";
    1483                 : 
    1484                 :   // unsigned long limit = [l_collection countByEnumeratingWithState:&enumState
    1485                 :   //                                   objects:items count:16];
    1486                 :   // which is synthesized into:
    1487                 :   // unsigned int limit =
    1488                 :   // ((unsigned int (*)
    1489                 :   //  (id, SEL, struct __objcFastEnumerationState *, id *, unsigned int))
    1490                 :   //  (void *)objc_msgSend)((id)l_collection,
    1491                 :   //                        sel_registerName(
    1492                 :   //                          "countByEnumeratingWithState:objects:count:"),
    1493                 :   //                        (struct __objcFastEnumerationState *)&state,
    1494                 :   //                        (id *)items, (unsigned int)16);
    1495               16:   buf += "unsigned long limit =\n\t\t";
    1496               16:   SynthCountByEnumWithState(buf);
    1497               16:   buf += ";\n\t";
    1498                 :   /// if (limit) {
    1499                 :   ///   unsigned long startMutations = *enumState.mutationsPtr;
    1500                 :   ///   do {
    1501                 :   ///        unsigned long counter = 0;
    1502                 :   ///        do {
    1503                 :   ///             if (startMutations != *enumState.mutationsPtr)
    1504                 :   ///               objc_enumerationMutation(l_collection);
    1505                 :   ///             elem = (type)enumState.itemsPtr[counter++];
    1506               16:   buf += "if (limit) {\n\t";
    1507               16:   buf += "unsigned long startMutations = *enumState.mutationsPtr;\n\t";
    1508               16:   buf += "do {\n\t\t";
    1509               16:   buf += "unsigned long counter = 0;\n\t\t";
    1510               16:   buf += "do {\n\t\t\t";
    1511               16:   buf += "if (startMutations != *enumState.mutationsPtr)\n\t\t\t\t";
    1512               16:   buf += "objc_enumerationMutation(l_collection);\n\t\t\t";
    1513               16:   buf += elementName;
    1514               16:   buf += " = (";
    1515               16:   buf += elementTypeAsString;
    1516               16:   buf += ")enumState.itemsPtr[counter++];";
    1517                 :   // Replace ')' in for '(' type elem in collection ')' with all of these.
    1518               16:   ReplaceText(lparenLoc, 1, buf.c_str(), buf.size());
    1519                 : 
    1520                 :   ///            __continue_label: ;
    1521                 :   ///        } while (counter < limit);
    1522                 :   ///   } while (limit = [l_collection countByEnumeratingWithState:&enumState
    1523                 :   ///                                  objects:items count:16]);
    1524                 :   ///   elem = nil;
    1525                 :   ///   __break_label: ;
    1526                 :   ///  }
    1527                 :   ///  else
    1528                 :   ///       elem = nil;
    1529                 :   ///  }
    1530                 :   ///
    1531               16:   buf = ";\n\t";
    1532               16:   buf += "__continue_label_";
    1533               16:   buf += utostr(ObjCBcLabelNo.back());
    1534               16:   buf += ": ;";
    1535               16:   buf += "\n\t\t";
    1536               16:   buf += "} while (counter < limit);\n\t";
    1537               16:   buf += "} while (limit = ";
    1538               16:   SynthCountByEnumWithState(buf);
    1539               16:   buf += ");\n\t";
    1540               16:   buf += elementName;
    1541               16:   buf += " = ((";
    1542               16:   buf += elementTypeAsString;
    1543               16:   buf += ")0);\n\t";
    1544               16:   buf += "__break_label_";
    1545               16:   buf += utostr(ObjCBcLabelNo.back());
    1546               16:   buf += ": ;\n\t";
    1547               16:   buf += "}\n\t";
    1548               16:   buf += "else\n\t\t";
    1549               16:   buf += elementName;
    1550               16:   buf += " = ((";
    1551               16:   buf += elementTypeAsString;
    1552               16:   buf += ")0);\n\t";
    1553               16:   buf += "}\n";
    1554                 : 
    1555                 :   // Insert all these *after* the statement body.
    1556                 :   // FIXME: If this should support Obj-C++, support CXXTryStmt
                       10: branch 2 taken
                        6: branch 3 taken
    1557               16:   if (isa<CompoundStmt>(S->getBody())) {
    1558               10:     SourceLocation endBodyLoc = OrigEnd.getFileLocWithOffset(1);
    1559               10:     InsertText(endBodyLoc, buf.c_str(), buf.size());
    1560                 :   } else {
    1561                 :     /* Need to treat single statements specially. For example:
    1562                 :      *
    1563                 :      *     for (A *a in b) if (stuff()) break;
    1564                 :      *     for (A *a in b) xxxyy;
    1565                 :      *
    1566                 :      * The following code simply scans ahead to the semi to find the actual end.
    1567                 :      */
    1568                6:     const char *stmtBuf = SM->getCharacterData(OrigEnd);
    1569                6:     const char *semiBuf = strchr(stmtBuf, ';');
                        0: branch 0 not taken
                        6: branch 1 taken
    1570                6:     assert(semiBuf && "Can't find ';'");
    1571                6:     SourceLocation endBodyLoc = OrigEnd.getFileLocWithOffset(semiBuf-stmtBuf+1);
    1572                6:     InsertText(endBodyLoc, buf.c_str(), buf.size());
    1573                 :   }
    1574               16:   Stmts.pop_back();
    1575               16:   ObjCBcLabelNo.pop_back();
    1576               16:   return 0;
    1577                 : }
    1578                 : 
    1579                 : /// RewriteObjCSynchronizedStmt -
    1580                 : /// This routine rewrites @synchronized(expr) stmt;
    1581                 : /// into:
    1582                 : /// objc_sync_enter(expr);
    1583                 : /// @try stmt @finally { objc_sync_exit(expr); }
    1584                 : ///
    1585                3: Stmt *RewriteObjC::RewriteObjCSynchronizedStmt(ObjCAtSynchronizedStmt *S) {
    1586                 :   // Get the start location and compute the semi location.
    1587                3:   SourceLocation startLoc = S->getLocStart();
    1588                3:   const char *startBuf = SM->getCharacterData(startLoc);
    1589                 : 
                        0: branch 0 not taken
                        3: branch 1 taken
    1590                3:   assert((*startBuf == '@') && "bogus @synchronized location");
    1591                 : 
    1592                3:   std::string buf;
    1593                3:   buf = "objc_sync_enter((id)";
    1594                3:   const char *lparenBuf = startBuf;
                       42: branch 0 taken
                        3: branch 1 taken
    1595                3:   while (*lparenBuf != '(') lparenBuf++;
    1596                3:   ReplaceText(startLoc, lparenBuf-startBuf+1, buf.c_str(), buf.size());
    1597                 :   // We can't use S->getSynchExpr()->getLocEnd() to find the end location, since
    1598                 :   // the sync expression is typically a message expression that's already
    1599                 :   // been rewritten! (which implies the SourceLocation's are invalid).
    1600                3:   SourceLocation endLoc = S->getSynchBody()->getLocStart();
    1601                3:   const char *endBuf = SM->getCharacterData(endLoc);
                        6: branch 0 taken
                        3: branch 1 taken
    1602                3:   while (*endBuf != ')') endBuf--;
    1603                3:   SourceLocation rparenLoc = startLoc.getFileLocWithOffset(endBuf-startBuf);
    1604                3:   buf = ");\n";
    1605                 :   // declare a new scope with two variables, _stack and _rethrow.
    1606                3:   buf += "/* @try scope begin */ \n{ struct _objc_exception_data {\n";
    1607                3:   buf += "int buf[18/*32-bit i386*/];\n";
    1608                3:   buf += "char *pointers[4];} _stack;\n";
    1609                3:   buf += "id volatile _rethrow = 0;\n";
    1610                3:   buf += "objc_exception_try_enter(&_stack);\n";
    1611                3:   buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n";
    1612                3:   ReplaceText(rparenLoc, 1, buf.c_str(), buf.size());
    1613                3:   startLoc = S->getSynchBody()->getLocEnd();
    1614                3:   startBuf = SM->getCharacterData(startLoc);
    1615                 : 
                        0: branch 0 not taken
                        3: branch 1 taken
    1616                3:   assert((*startBuf == '}') && "bogus @synchronized block");
    1617                3:   SourceLocation lastCurlyLoc = startLoc;
    1618                3:   buf = "}\nelse {\n";
    1619                3:   buf += "  _rethrow = objc_exception_extract(&_stack);\n";
    1620                3:   buf += "}\n";
    1621                3:   buf += "{ /* implicit finally clause */\n";
    1622                3:   buf += "  if (!_rethrow) objc_exception_try_exit(&_stack);\n";
    1623                 :   
    1624                3:   std::string syncBuf;
    1625                3:   syncBuf += " objc_sync_exit(";
    1626                 :   Expr *syncExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
    1627                 :                                             CastExpr::CK_Unknown,
    1628                3:                                             S->getSynchExpr());
    1629                3:   std::string syncExprBufS;
    1630                3:   llvm::raw_string_ostream syncExprBuf(syncExprBufS);
    1631                 :   syncExpr->printPretty(syncExprBuf, *Context, 0,
    1632                3:                         PrintingPolicy(LangOpts));
    1633                3:   syncBuf += syncExprBuf.str();
    1634                3:   syncBuf += ");";
    1635                 :   
    1636                3:   buf += syncBuf;
    1637                3:   buf += "\n  if (_rethrow) objc_exception_throw(_rethrow);\n";
    1638                3:   buf += "}\n";
    1639                3:   buf += "}";
    1640                 : 
    1641                3:   ReplaceText(lastCurlyLoc, 1, buf.c_str(), buf.size());
    1642                 : 
    1643                3:   bool hasReturns = false;
    1644                3:   HasReturnStmts(S->getSynchBody(), hasReturns);
                        3: branch 0 taken
                        0: branch 1 not taken
    1645                3:   if (hasReturns)
    1646                3:     RewriteSyncReturnStmts(S->getSynchBody(), syncBuf);
    1647                 : 
    1648                3:   return 0;
    1649                 : }
    1650                 : 
    1651               26: void RewriteObjC::WarnAboutReturnGotoStmts(Stmt *S)
    1652                 : {
    1653                 :   // Perform a bottom up traversal of all children.
                       22: branch 4 taken
                       26: branch 5 taken
    1654               48:   for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
    1655                 :        CI != E; ++CI)
                       22: branch 1 taken
                        0: branch 2 not taken
    1656               22:     if (*CI)
    1657               22:       WarnAboutReturnGotoStmts(*CI);
    1658                 : 
                       25: branch 1 taken
                        1: branch 2 taken
                        0: branch 4 not taken
                       25: branch 5 taken
                        1: branch 6 taken
                       25: branch 7 taken
    1659               26:   if (isa<ReturnStmt>(S) || isa<GotoStmt>(S)) {
    1660                 :     Diags.Report(Context->getFullLoc(S->getLocStart()),
    1661                1:                  TryFinallyContainsReturnDiag);
    1662                 :   }
    1663                 :   return;
    1664                 : }
    1665                 : 
    1666               23: void RewriteObjC::HasReturnStmts(Stmt *S, bool &hasReturns) 
    1667                 : {  
    1668                 :   // Perform a bottom up traversal of all children.
                       16: branch 4 taken
                       23: branch 5 taken
    1669               39:   for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
    1670                 :         CI != E; ++CI)
                       16: branch 1 taken
                        0: branch 2 not taken
    1671               16:    if (*CI)
    1672               16:      HasReturnStmts(*CI, hasReturns);
    1673                 : 
                        4: branch 1 taken
                       19: branch 2 taken
    1674               23:  if (isa<ReturnStmt>(S))
    1675                4:    hasReturns = true;
    1676                 :  return;
    1677                 : }
    1678                 : 
    1679                2: void RewriteObjC::RewriteTryReturnStmts(Stmt *S) {
    1680                 :  // Perform a bottom up traversal of all children.
                        1: branch 4 taken
                        2: branch 5 taken
    1681                3:  for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
    1682                 :       CI != E; ++CI)
                        1: branch 1 taken
                        0: branch 2 not taken
    1683                1:    if (*CI) {
    1684                1:      RewriteTryReturnStmts(*CI);
    1685                 :    }
                        1: branch 1 taken
                        1: branch 2 taken
    1686                2:  if (isa<ReturnStmt>(S)) {
    1687                1:    SourceLocation startLoc = S->getLocStart();
    1688                1:    const char *startBuf = SM->getCharacterData(startLoc);
    1689                 : 
    1690                1:    const char *semiBuf = strchr(startBuf, ';');
                        0: branch 0 not taken
                        1: branch 1 taken
    1691                1:    assert((*semiBuf == ';') && "RewriteTryReturnStmts: can't find ';'");
    1692                1:    SourceLocation onePastSemiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf+1);
    1693                 : 
    1694                1:    std::string buf;
    1695                1:    buf = "{ objc_exception_try_exit(&_stack); return";
    1696                 :    
    1697                1:    ReplaceText(startLoc, 6, buf.c_str(), buf.size());
    1698                1:    InsertText(onePastSemiLoc, "}", 1);
    1699                 :  }
    1700                 :  return;
    1701                 : }
    1702                 : 
    1703               12: void RewriteObjC::RewriteSyncReturnStmts(Stmt *S, std::string syncExitBuf) {
    1704                 :   // Perform a bottom up traversal of all children.
                        9: branch 4 taken
                       12: branch 5 taken
    1705               21:   for (Stmt::child_iterator CI = S->child_begin(), E = S->child_end();
    1706                 :        CI != E; ++CI)
                        9: branch 1 taken
                        0: branch 2 not taken
    1707                9:     if (*CI) {
    1708                9:       RewriteSyncReturnStmts(*CI, syncExitBuf);
    1709                 :     }
                        3: branch 1 taken
                        9: branch 2 taken
    1710               12:   if (isa<ReturnStmt>(S)) {
    1711                3:     SourceLocation startLoc = S->getLocStart();
    1712                3:     const char *startBuf = SM->getCharacterData(startLoc);
    1713                 : 
    1714                3:     const char *semiBuf = strchr(startBuf, ';');
                        0: branch 0 not taken
                        3: branch 1 taken
    1715                3:     assert((*semiBuf == ';') && "RewriteSyncReturnStmts: can't find ';'");
    1716                3:     SourceLocation onePastSemiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf+1);
    1717                 : 
    1718                3:     std::string buf;
    1719                3:     buf = "{ objc_exception_try_exit(&_stack);";
    1720                3:     buf += syncExitBuf;
    1721                3:     buf += " return";
    1722                 :     
    1723                3:     ReplaceText(startLoc, 6, buf.c_str(), buf.size());
    1724                3:     InsertText(onePastSemiLoc, "}", 1);
    1725                 :   }
    1726                 :   return;
    1727                 : }
    1728                 : 
    1729                8: Stmt *RewriteObjC::RewriteObjCTryStmt(ObjCAtTryStmt *S) {
    1730                 :   // Get the start location and compute the semi location.
    1731                8:   SourceLocation startLoc = S->getLocStart();
    1732                8:   const char *startBuf = SM->getCharacterData(startLoc);
    1733                 : 
                        0: branch 0 not taken
                        8: branch 1 taken
    1734                8:   assert((*startBuf == '@') && "bogus @try location");
    1735                 : 
    1736                8:   std::string buf;
    1737                 :   // declare a new scope with two variables, _stack and _rethrow.
    1738                8:   buf = "/* @try scope begin */ { struct _objc_exception_data {\n";
    1739                8:   buf += "int buf[18/*32-bit i386*/];\n";
    1740                8:   buf += "char *pointers[4];} _stack;\n";
    1741                8:   buf += "id volatile _rethrow = 0;\n";
    1742                8:   buf += "objc_exception_try_enter(&_stack);\n";
    1743                8:   buf += "if (!_setjmp(_stack.buf)) /* @try block continue */\n";
    1744                 : 
    1745                8:   ReplaceText(startLoc, 4, buf.c_str(), buf.size());
    1746                 : 
    1747                8:   startLoc = S->getTryBody()->getLocEnd();
    1748                8:   startBuf = SM->getCharacterData(startLoc);
    1749                 : 
                        0: branch 0 not taken
                        8: branch 1 taken
    1750                8:   assert((*startBuf == '}') && "bogus @try block");
    1751                 : 
    1752                8:   SourceLocation lastCurlyLoc = startLoc;
    1753                8:   ObjCAtCatchStmt *catchList = S->getCatchStmts();
                        4: branch 0 taken
                        4: branch 1 taken
    1754                8:   if (catchList) {
    1755                4:     startLoc = startLoc.getFileLocWithOffset(1);
    1756                4:     buf = " /* @catch begin */ else {\n";
    1757                4:     buf += " id _caught = objc_exception_extract(&_stack);\n";
    1758                4:     buf += " objc_exception_try_enter (&_stack);\n";
    1759                4:     buf += " if (_setjmp(_stack.buf))\n";
    1760                4:     buf += "   _rethrow = objc_exception_extract(&_stack);\n";
    1761                4:     buf += " else { /* @catch continue */";
    1762                 : 
    1763                4:     InsertText(startLoc, buf.c_str(), buf.size());
    1764                 :   } else { /* no catch list */
    1765                4:     buf = "}\nelse {\n";
    1766                4:     buf += "  _rethrow = objc_exception_extract(&_stack);\n";
    1767                4:     buf += "}";
    1768                4:     ReplaceText(lastCurlyLoc, 1, buf.c_str(), buf.size());
    1769                 :   }
    1770                8:   bool sawIdTypedCatch = false;
    1771                8:   Stmt *lastCatchBody = 0;
                        6: branch 0 taken
                        8: branch 1 taken
    1772               22:   while (catchList) {
    1773                6:     ParmVarDecl *catchDecl = catchList->getCatchParamDecl();
    1774                 : 
                        4: branch 1 taken
                        2: branch 2 taken
    1775                6:     if (catchList == S->getCatchStmts())
    1776                4:       buf = "if ("; // we are generating code for the first catch clause
    1777                 :     else
    1778                2:       buf = "else if (";
    1779                6:     startLoc = catchList->getLocStart();
    1780                6:     startBuf = SM->getCharacterData(startLoc);
    1781                 : 
                        0: branch 0 not taken
                        6: branch 1 taken
    1782                6:     assert((*startBuf == '@') && "bogus @catch location");
    1783                 : 
    1784                6:     const char *lParenLoc = strchr(startBuf, '(');
    1785                 : 
                        2: branch 1 taken
                        4: branch 2 taken
    1786                6:     if (catchList->hasEllipsis()) {
    1787                 :       // Now rewrite the body...
    1788                2:       lastCatchBody = catchList->getCatchBody();
    1789                2:       SourceLocation bodyLoc = lastCatchBody->getLocStart();
    1790                2:       const char *bodyBuf = SM->getCharacterData(bodyLoc);
    1791                 :       assert(*SM->getCharacterData(catchList->getRParenLoc()) == ')' &&
                        2: branch 2 taken
                        0: branch 3 not taken
    1792                2:              "bogus @catch paren location");
                        0: branch 0 not taken
                        2: branch 1 taken
    1793                2:       assert((*bodyBuf == '{') && "bogus @catch body location");
    1794                 : 
    1795                2:       buf += "1) { id _tmp = _caught;";
    1796                2:       Rewrite.ReplaceText(startLoc, bodyBuf-startBuf+1, buf);
                        4: branch 0 taken
                        0: branch 1 not taken
    1797                4:     } else if (catchDecl) {
    1798                4:       QualType t = catchDecl->getType();
                        1: branch 2 taken
                        3: branch 3 taken
    1799                4:       if (t == Context->getObjCIdType()) {
    1800                1:         buf += "1) { ";
    1801                1:         ReplaceText(startLoc, lParenLoc-startBuf+1, buf.c_str(), buf.size());
    1802                1:         sawIdTypedCatch = true;
                        3: branch 2 taken
                        0: branch 3 not taken
    1803                3:       } else if (t->isObjCObjectPointerType()) {
    1804                3:         QualType InterfaceTy = t->getPointeeType();
    1805                 :         const ObjCInterfaceType *cls = // Should be a pointer to a class.
    1806                3:           InterfaceTy->getAs<ObjCInterfaceType>();
                        3: branch 0 taken
                        0: branch 1 not taken
    1807                3:         if (cls) {
    1808                3:           buf += "objc_exception_match((struct objc_class *)objc_getClass(\"";
    1809                3:           buf += cls->getDecl()->getNameAsString();
    1810                3:           buf += "\"), (struct objc_object *)_caught)) { ";
    1811                3:           ReplaceText(startLoc, lParenLoc-startBuf+1, buf.c_str(), buf.size());
    1812                 :         }
    1813                 :       }
    1814                 :       // Now rewrite the body...
    1815                4:       lastCatchBody = catchList->getCatchBody();
    1816                4:       SourceLocation rParenLoc = catchList->getRParenLoc();
    1817                4:       SourceLocation bodyLoc = lastCatchBody->getLocStart();
    1818                4:       const char *bodyBuf = SM->getCharacterData(bodyLoc);
    1819                4:       const char *rParenBuf = SM->getCharacterData(rParenLoc);
                        0: branch 0 not taken
                        4: branch 1 taken
    1820                4:       assert((*rParenBuf == ')') && "bogus @catch paren location");
                        0: branch 0 not taken
                        4: branch 1 taken
    1821                4:       assert((*bodyBuf == '{') && "bogus @catch body location");
    1822                 : 
    1823                4:       buf = " = _caught;";
    1824                 :       // Here we replace ") {" with "= _caught;" (which initializes and
    1825                 :       // declares the @catch parameter).
    1826                4:       ReplaceText(rParenLoc, bodyBuf-rParenBuf+1, buf.c_str(), buf.size());
    1827                 :     } else {
    1828                0:       assert(false && "@catch rewrite bug");
    1829                 :     }
    1830                 :     // make sure all the catch bodies get rewritten!
    1831                6:     catchList = catchList->getNextCatchStmt();
    1832                 :   }
    1833                 :   // Complete the catch list...
                        4: branch 0 taken
                        4: branch 1 taken
    1834                8:   if (lastCatchBody) {
    1835                4:     SourceLocation bodyLoc = lastCatchBody->getLocEnd();
    1836                 :     assert(*SM->getCharacterData(bodyLoc) == '}' &&
                        4: branch 1 taken
                        0: branch 2 not taken
    1837                4:            "bogus @catch body location");
    1838                 : 
    1839                 :     // Insert the last (implicit) else clause *before* the right curly brace.
    1840                4:     bodyLoc = bodyLoc.getFileLocWithOffset(-1);
    1841                4:     buf = "} /* last catch end */\n";
    1842                4:     buf += "else {\n";
    1843                4:     buf += " _rethrow = _caught;\n";
    1844                4:     buf += " objc_exception_try_exit(&_stack);\n";
    1845                4:     buf += "} } /* @catch end */\n";
                        4: branch 1 taken
                        0: branch 2 not taken
    1846                4:     if (!S->getFinallyStmt())
    1847                4:       buf += "}\n";
    1848                4:     InsertText(bodyLoc, buf.c_str(), buf.size());
    1849                 : 
    1850                 :     // Set lastCurlyLoc
    1851                4:     lastCurlyLoc = lastCatchBody->getLocEnd();
    1852                 :   }
                        4: branch 1 taken
                        4: branch 2 taken
    1853                8:   if (ObjCAtFinallyStmt *finalStmt = S->getFinallyStmt()) {
    1854                4:     startLoc = finalStmt->getLocStart();
    1855                4:     startBuf = SM->getCharacterData(startLoc);
                        0: branch 0 not taken
                        4: branch 1 taken
    1856                4:     assert((*startBuf == '@') && "bogus @finally start");
    1857                 : 
    1858                4:     buf = "/* @finally */";
    1859                4:     ReplaceText(startLoc, 8, buf.c_str(), buf.size());
    1860                 : 
    1861                4:     Stmt *body = finalStmt->getFinallyBody();
    1862                4:     SourceLocation startLoc = body->getLocStart();
    1863                4:     SourceLocation endLoc = body->getLocEnd();
    1864                 :     assert(*SM->getCharacterData(startLoc) == '{' &&
                        4: branch 1 taken
                        0: branch 2 not taken
    1865                4:            "bogus @finally body location");
    1866                 :     assert(*SM->getCharacterData(endLoc) == '}' &&
                        4: branch 1 taken
                        0: branch 2 not taken
    1867                4:            "bogus @finally body location");
    1868                 : 
    1869                4:     startLoc = startLoc.getFileLocWithOffset(1);
    1870                4:     buf = " if (!_rethrow) objc_exception_try_exit(&_stack);\n";
    1871                4:     InsertText(startLoc, buf.c_str(), buf.size());
    1872                4:     endLoc = endLoc.getFileLocWithOffset(-1);
    1873                4:     buf = " if (_rethrow) objc_exception_throw(_rethrow);\n";
    1874                4:     InsertText(endLoc, buf.c_str(), buf.size());
    1875                 : 
    1876                 :     // Set lastCurlyLoc
    1877                4:     lastCurlyLoc = body->getLocEnd();
    1878                 : 
    1879                 :     // Now check for any return/continue/go statements within the @try.
    1880                4:     WarnAboutReturnGotoStmts(S->getTryBody());
    1881                 :   } else { /* no finally clause - make sure we synthesize an implicit one */
    1882                4:     buf = "{ /* implicit finally clause */\n";
    1883                4:     buf += " if (!_rethrow) objc_exception_try_exit(&_stack);\n";
    1884                4:     buf += " if (_rethrow) objc_exception_throw(_rethrow);\n";
    1885                4:     buf += "}";
    1886                4:     ReplaceText(lastCurlyLoc, 1, buf.c_str(), buf.size());
    1887                 :     
    1888                 :     // Now check for any return/continue/go statements within the @try.
    1889                 :     // The implicit finally clause won't called if the @try contains any
    1890                 :     // jump statements.
    1891                4:     bool hasReturns = false;
    1892                4:     HasReturnStmts(S->getTryBody(), hasReturns);
                        1: branch 0 taken
                        3: branch 1 taken
    1893                4:     if (hasReturns)
    1894                1:       RewriteTryReturnStmts(S->getTryBody());
    1895                 :   }
    1896                 :   // Now emit the final closing curly brace...
    1897                8:   lastCurlyLoc = lastCurlyLoc.getFileLocWithOffset(1);
    1898                8:   buf = " } /* @try scope end */\n";
    1899                8:   InsertText(lastCurlyLoc, buf.c_str(), buf.size());
    1900                8:   return 0;
    1901                 : }
    1902                 : 
    1903                0: Stmt *RewriteObjC::RewriteObjCCatchStmt(ObjCAtCatchStmt *S) {
    1904                0:   return 0;
    1905                 : }
    1906                 : 
    1907                0: Stmt *RewriteObjC::RewriteObjCFinallyStmt(ObjCAtFinallyStmt *S) {
    1908                0:   return 0;
    1909                 : }
    1910                 : 
    1911                 : // This can't be done with ReplaceStmt(S, ThrowExpr), since
    1912                 : // the throw expression is typically a message expression that's already
    1913                 : // been rewritten! (which implies the SourceLocation's are invalid).
    1914                2: Stmt *RewriteObjC::RewriteObjCThrowStmt(ObjCAtThrowStmt *S) {
    1915                 :   // Get the start location and compute the semi location.
    1916                2:   SourceLocation startLoc = S->getLocStart();
    1917                2:   const char *startBuf = SM->getCharacterData(startLoc);
    1918                 : 
                        0: branch 0 not taken
                        2: branch 1 taken
    1919                2:   assert((*startBuf == '@') && "bogus @throw location");
    1920                 : 
    1921                2:   std::string buf;
    1922                 :   /* void objc_exception_throw(id) __attribute__((noreturn)); */
                        0: branch 1 not taken
                        2: branch 2 taken
    1923                2:   if (S->getThrowExpr())
    1924                0:     buf = "objc_exception_throw(";
    1925                 :   else // add an implicit argument
    1926                2:     buf = "objc_exception_throw(_caught";
    1927                 : 
    1928                 :   // handle "@  throw" correctly.
    1929                2:   const char *wBuf = strchr(startBuf, 'w');
                        0: branch 0 not taken
                        2: branch 1 taken
    1930                2:   assert((*wBuf == 'w') && "@throw: can't find 'w'");
    1931                2:   ReplaceText(startLoc, wBuf-startBuf+1, buf.c_str(), buf.size());
    1932                 : 
    1933                2:   const char *semiBuf = strchr(startBuf, ';');
                        0: branch 0 not taken
                        2: branch 1 taken
    1934                2:   assert((*semiBuf == ';') && "@throw: can't find ';'");
    1935                2:   SourceLocation semiLoc = startLoc.getFileLocWithOffset(semiBuf-startBuf);
    1936                2:   buf = ");";
    1937                2:   ReplaceText(semiLoc, 1, buf.c_str(), buf.size());
    1938                2:   return 0;
    1939                 : }
    1940                 : 
    1941                0: Stmt *RewriteObjC::RewriteAtEncode(ObjCEncodeExpr *Exp) {
    1942                 :   // Create a new string expression.
    1943                0:   QualType StrType = Context->getPointerType(Context->CharTy);
    1944                0:   std::string StrEncoding;
    1945                0:   Context->getObjCEncodingForType(Exp->getEncodedType(), StrEncoding);
    1946                 :   Expr *Replacement = StringLiteral::Create(*Context,StrEncoding.c_str(),
    1947                 :                                             StrEncoding.length(), false,StrType,
    1948                0:                                             SourceLocation());
    1949                0:   ReplaceStmt(Exp, Replacement);
    1950                 : 
    1951                 :   // Replace this subexpr in the parent.
    1952                 :   // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
    1953                0:   return Replacement;
    1954                 : }
    1955                 : 
    1956                0: Stmt *RewriteObjC::RewriteAtSelector(ObjCSelectorExpr *Exp) {
                        0: branch 0 not taken
                        0: branch 1 not taken
    1957                0:   if (!SelGetUidFunctionDecl)
    1958                0:     SynthSelGetUidFunctionDecl();
                        0: branch 0 not taken
                        0: branch 1 not taken
    1959                0:   assert(SelGetUidFunctionDecl && "Can't find sel_registerName() decl");
    1960                 :   // Create a call to sel_registerName("selName").
    1961                0:   llvm::SmallVector<Expr*, 8> SelExprs;
    1962                0:   QualType argType = Context->getPointerType(Context->CharTy);
    1963                 :   SelExprs.push_back(StringLiteral::Create(*Context,
    1964                 :                                        Exp->getSelector().getAsString().c_str(),
    1965                 :                                        Exp->getSelector().getAsString().size(),
    1966                0:                                        false, argType, SourceLocation()));
    1967                 :   CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
    1968                0:                                                  &SelExprs[0], SelExprs.size());
    1969                0:   ReplaceStmt(Exp, SelExp);
    1970                 :   // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
    1971                0:   return SelExp;
    1972                 : }
    1973                 : 
    1974                 : CallExpr *RewriteObjC::SynthesizeCallToFunctionDecl(
    1975               56:   FunctionDecl *FD, Expr **args, unsigned nargs) {
    1976                 :   // Get the type, we will need to reference it in a couple spots.
    1977               56:   QualType msgSendType = FD->getType();
    1978                 : 
    1979                 :   // Create a reference to the objc_msgSend() declaration.
                       56: branch 2 taken
                        0: branch 3 not taken
    1980               56:   DeclRefExpr *DRE = new (Context) DeclRefExpr(FD, msgSendType, SourceLocation());
    1981                 : 
    1982                 :   // Now, we cast the reference to a pointer to the objc_msgSend type.
    1983               56:   QualType pToFunc = Context->getPointerType(msgSendType);
    1984                 :   ImplicitCastExpr *ICE = new (Context) ImplicitCastExpr(pToFunc,
    1985                 :                                                          CastExpr::CK_Unknown,
    1986                 :                                                          DRE,
                       56: branch 1 taken
                        0: branch 2 not taken
    1987               56:                                                /*isLvalue=*/false);
    1988                 : 
    1989               56:   const FunctionType *FT = msgSendType->getAs<FunctionType>();
    1990                 : 
    1991                 :   return new (Context) CallExpr(*Context, ICE, args, nargs, FT->getResultType(),
                       56: branch 3 taken
                        0: branch 4 not taken
    1992               56:                                 SourceLocation());
    1993                 : }
    1994                 : 
    1995                 : static bool scanForProtocolRefs(const char *startBuf, const char *endBuf,
    1996               22:                                 const char *&startRef, const char *&endRef) {
                      313: branch 0 taken
                        0: branch 1 not taken
    1997              335:   while (startBuf < endBuf) {
                       22: branch 0 taken
                      291: branch 1 taken
    1998              313:     if (*startBuf == '<')
    1999               22:       startRef = startBuf; // mark the start.
                       22: branch 0 taken
                      291: branch 1 taken
    2000              313:     if (*startBuf == '>') {
                       22: branch 0 taken
                        0: branch 1 not taken
                       22: branch 2 taken
                        0: branch 3 not taken
    2001               22:       if (startRef && *startRef == '<') {
    2002               22:         endRef = startBuf; // mark the end.
    2003               22:         return true;
    2004                 :       }
    2005                0:       return false;
    2006                 :     }
    2007              291:     startBuf++;
    2008                 :   }
    2009                0:   return false;
    2010                 : }
    2011                 : 
    2012                6: static void scanToNextArgument(const char *&argRef) {
    2013                6:   int angle = 0;
                      144: branch 0 taken
                        3: branch 1 taken
                      139: branch 2 taken
                        5: branch 3 taken
                        2: branch 4 taken
                        3: branch 5 taken
    2014              153:   while (*argRef != ')' && (*argRef != ',' || angle > 0)) {
                        6: branch 0 taken
                      135: branch 1 taken
    2015              141:     if (*argRef == '<')
    2016                6:       angle++;
                        6: branch 0 taken
                      129: branch 1 taken
    2017              135:     else if (*argRef == '>')
    2018                6:       angle--;
    2019              141:     argRef++;
    2020                 :   }
                        0: branch 0 not taken
                        6: branch 1 taken
    2021                6:   assert(angle == 0 && "scanToNextArgument - bad protocol type syntax");
    2022                6: }
    2023                 : 
    2024              181: bool RewriteObjC::needToScanForQualifiers(QualType T) {
                        7: branch 2 taken
                      174: branch 3 taken
    2025              181:   if (T->isObjCQualifiedIdType())
    2026                7:     return true;
                       29: branch 2 taken
                      145: branch 3 taken
    2027              174:   if (const PointerType *PT = T->getAs<PointerType>()) {
                        1: branch 3 taken
                       28: branch 4 taken
    2028               29:     if (PT->getPointeeType()->isObjCQualifiedIdType())
    2029                1:       return true;
    2030                 :   }
                       62: branch 2 taken
                      111: branch 3 taken
    2031              173:   if (T->isObjCObjectPointerType()) {
    2032               62:     T = T->getPointeeType();
    2033               62:     return T->isObjCQualifiedInterfaceType();
    2034                 :   }
    2035              111:   return false;
    2036                 : }
    2037                 : 
    2038               25: void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Expr *E) {
    2039               25:   QualType Type = E->getType();
                        8: branch 1 taken
                       17: branch 2 taken
    2040               25:   if (needToScanForQualifiers(Type)) {
    2041                8:     SourceLocation Loc, EndLoc;
    2042                 : 
                        8: branch 1 taken
                        0: branch 2 not taken
    2043                8:     if (const CStyleCastExpr *ECE = dyn_cast<CStyleCastExpr>(E)) {
    2044                8:       Loc = ECE->getLParenLoc();
    2045                8:       EndLoc = ECE->getRParenLoc();
    2046                 :     } else {
    2047                0:       Loc = E->getLocStart();
    2048                0:       EndLoc = E->getLocEnd();
    2049                 :     }
    2050                 :     // This will defend against trying to rewrite synthesized expressions.
                        8: branch 1 taken
                        0: branch 2 not taken
                        0: branch 4 not taken
                        8: branch 5 taken
                        0: branch 6 not taken
                        8: branch 7 taken
    2051                8:     if (Loc.isInvalid() || EndLoc.isInvalid())
    2052                0:       return;
    2053                 : 
    2054                8:     const char *startBuf = SM->getCharacterData(Loc);
    2055                8:     const char *endBuf = SM->getCharacterData(EndLoc);
    2056                8:     const char *startRef = 0, *endRef = 0;
                        8: branch 1 taken
                        0: branch 2 not taken
    2057                8:     if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
    2058                 :       // Get the locations of the startRef, endRef.
    2059                8:       SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-startBuf);
    2060                8:       SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-startBuf+1);
    2061                 :       // Comment out the protocol references.
    2062                8:       InsertText(LessLoc, "/*", 2);
    2063                8:       InsertText(GreaterLoc, "*/", 2);
    2064                 :     }
    2065                 :   }
    2066                 : }
    2067                 : 
    2068              151: void RewriteObjC::RewriteObjCQualifiedInterfaceTypes(Decl *Dcl) {
    2069              151:   SourceLocation Loc;
    2070              151:   QualType Type;
    2071              151:   const FunctionProtoType *proto = 0;
                       90: branch 1 taken
                       61: branch 2 taken
    2072              151:   if (VarDecl *VD = dyn_cast<VarDecl>(Dcl)) {
    2073               90:     Loc = VD->getLocation();
    2074               90:     Type = VD->getType();
    2075                 :   }
                       61: branch 1 taken
                        0: branch 2 not taken
    2076               61:   else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Dcl)) {
    2077               61:     Loc = FD->getLocation();
    2078                 :     // Check for ObjC 'id' and class types that have been adorned with protocol
    2079                 :     // information (id<p>, C<p>*). The protocol references need to be rewritten!
    2080               61:     const FunctionType *funcType = FD->getType()->getAs<FunctionType>();
                        0: branch 0 not taken
                       61: branch 1 taken
    2081               61:     assert(funcType && "missing function type");
    2082               61:     proto = dyn_cast<FunctionProtoType>(funcType);
                       29: branch 0 taken
                       32: branch 1 taken
    2083               61:     if (!proto)
    2084               29:       return;
    2085               32:     Type = proto->getResultType();
    2086                 :   }
                        0: branch 1 not taken
                        0: branch 2 not taken
    2087                0:   else if (FieldDecl *FD = dyn_cast<FieldDecl>(Dcl)) {
    2088                0:     Loc = FD->getLocation();
    2089                0:     Type = FD->getType();
    2090                 :   }
    2091                 :   else
    2092                0:     return;
    2093                 : 
                        8: branch 1 taken
                      114: branch 2 taken
    2094              122:   if (needToScanForQualifiers(Type)) {
    2095                 :     // Since types are unique, we need to scan the buffer.
    2096                 : 
    2097                8:     const char *endBuf = SM->getCharacterData(Loc);
    2098                8:     const char *startBuf = endBuf;
                      145: branch 0 taken
                        0: branch 1 not taken
                      137: branch 2 taken
                        8: branch 3 taken
                      137: branch 4 taken
                        0: branch 5 not taken
    2099              153:     while (*startBuf != ';' && *startBuf != '<' && startBuf != MainFileStart)
    2100              137:       startBuf--; // scan backward (from the decl location) for return type.
    2101                8:     const char *startRef = 0, *endRef = 0;
                        8: branch 1 taken
                        0: branch 2 not taken
    2102                8:     if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
    2103                 :       // Get the locations of the startRef, endRef.
    2104                8:       SourceLocation LessLoc = Loc.getFileLocWithOffset(startRef-endBuf);
    2105                8:       SourceLocation GreaterLoc = Loc.getFileLocWithOffset(endRef-endBuf+1);
    2106                 :       // Comment out the protocol references.
    2107                8:       InsertText(LessLoc, "/*", 2);
    2108                8:       InsertText(GreaterLoc, "*/", 2);
    2109                 :     }
    2110                 :   }
                       90: branch 0 taken
                       32: branch 1 taken
    2111              122:   if (!proto)
    2112               90:       return; // most likely, was a variable
    2113                 :   // Now check arguments.
    2114               32:   const char *startBuf = SM->getCharacterData(Loc);
    2115               32:   const char *startFuncBuf = startBuf;
                       34: branch 1 taken
                       32: branch 2 taken
    2116               66:   for (unsigned i = 0; i < proto->getNumArgs(); i++) {
                        6: branch 2 taken
                       28: branch 3 taken
    2117               34:     if (needToScanForQualifiers(proto->getArgType(i))) {
    2118                 :       // Since types are unique, we need to scan the buffer.
    2119                 : 
    2120                6:       const char *endBuf = startBuf;
    2121                 :       // scan forward (from the decl location) for argument types.
    2122                6:       scanToNextArgument(endBuf);
    2123                6:       const char *startRef = 0, *endRef = 0;
                        6: branch 1 taken
                        0: branch 2 not taken
    2124                6:       if (scanForProtocolRefs(startBuf, endBuf, startRef, endRef)) {
    2125                 :         // Get the locations of the startRef, endRef.
    2126                 :         SourceLocation LessLoc =
    2127                6:           Loc.getFileLocWithOffset(startRef-startFuncBuf);
    2128                 :         SourceLocation GreaterLoc =
    2129                6:           Loc.getFileLocWithOffset(endRef-startFuncBuf+1);
    2130                 :         // Comment out the protocol references.
    2131                6:         InsertText(LessLoc, "/*", 2);
    2132                6:         InsertText(GreaterLoc, "*/", 2);
    2133                 :       }
    2134                6:       startBuf = ++endBuf;
    2135                 :     }
    2136                 :     else {
    2137                 :       // If the function name is derived from a macro expansion, then the
    2138                 :       // argument buffer will not follow the name. Need to speak with Chris.
                      512: branch 0 taken
                        0: branch 1 not taken
                      491: branch 2 taken
                       21: branch 3 taken
                      484: branch 4 taken
                        7: branch 5 taken
    2139              540:       while (*startBuf && *startBuf != ')' && *startBuf != ',')
    2140              484:         startBuf++; // scan forward (from the decl location) for argument types.
    2141               28:       startBuf++;
    2142                 :     }
    2143                 :   }
    2144                 : }
    2145                 : 
    2146                 : // SynthSelGetUidFunctionDecl - SEL sel_registerName(const char *str);
    2147               19: void RewriteObjC::SynthSelGetUidFunctionDecl() {
    2148               19:   IdentifierInfo *SelGetUidIdent = &Context->Idents.get("sel_registerName");
    2149               19:   llvm::SmallVector<QualType, 16> ArgTys;
    2150               19:   ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
    2151                 :   QualType getFuncType = Context->getFunctionType(Context->getObjCSelType(),
    2152                 :                                                    &ArgTys[0], ArgTys.size(),
    2153               19:                                                    false /*isVariadic*/, 0);
    2154                 :   SelGetUidFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
    2155                 :                                            SourceLocation(),
    2156                 :                                            SelGetUidIdent, getFuncType, 0,
                       19: branch 2 taken
                        0: branch 3 not taken
    2157               19:                                            FunctionDecl::Extern, false);
    2158               19: }
    2159                 : 
    2160               61: void RewriteObjC::RewriteFunctionDecl(FunctionDecl *FD) {
    2161                 :   // declared in <objc/objc.h>
                       61: branch 1 taken
                        0: branch 2 not taken
                        0: branch 5 not taken
                       61: branch 6 taken
                        0: branch 7 not taken
                       61: branch 8 taken
    2162               61:   if (FD->getIdentifier() &&
    2163                 :       strcmp(FD->getNameAsCString(), "sel_registerName") == 0) {
    2164                0:     SelGetUidFunctionDecl = FD;
    2165                0:     return;
    2166                 :   }
    2167               61:   RewriteObjCQualifiedInterfaceTypes(FD);
    2168                 : }
    2169                 : 
    2170               17: void RewriteObjC::RewriteBlockLiteralFunctionDecl(FunctionDecl *FD) {
    2171               17:   SourceLocation FunLocStart = FD->getTypeSpecStartLoc();
    2172               17:   const FunctionType *funcType = FD->getType()->getAs<FunctionType>();
    2173               17:   const FunctionProtoType *proto = dyn_cast<FunctionProtoType>(funcType);
                       11: branch 0 taken
                        6: branch 1 taken
    2174               17:   if (!proto)
    2175               11:     return;
    2176                6:   QualType Type = proto->getResultType();
    2177                6:   std::string FdStr = Type.getAsString();
    2178                6:   FdStr += " ";
    2179                6:   FdStr += FD->getNameAsCString();
    2180                6:   FdStr +=  "(";
    2181                6:   unsigned numArgs = proto->getNumArgs();
                        4: branch 0 taken
                        6: branch 1 taken
    2182               10:   for (unsigned i = 0; i < numArgs; i++) {
    2183                4:     QualType ArgType = proto->getArgType(i);
    2184                4:     FdStr += ArgType.getAsString();
    2185                 :     
                        1: branch 0 taken
                        3: branch 1 taken
    2186                4:     if (i+1 < numArgs)
    2187                1:       FdStr += ", ";
    2188                 :   }
    2189                6:   FdStr +=  ");\n";
    2190                6:   InsertText(FunLocStart, FdStr.c_str(), FdStr.size());
    2191                6:   CurFunctionDeclToDeclareForBlock = 0;
    2192                 : }
    2193                 : 
    2194                 : // SynthSuperContructorFunctionDecl - id objc_super(id obj, id super);
    2195                0: void RewriteObjC::SynthSuperContructorFunctionDecl() {
                        0: branch 0 not taken
                        0: branch 1 not taken
    2196                0:   if (SuperContructorFunctionDecl)
    2197                0:     return;
    2198                0:   IdentifierInfo *msgSendIdent = &Context->Idents.get("__rw_objc_super");
    2199                0:   llvm::SmallVector<QualType, 16> ArgTys;
    2200                0:   QualType argT = Context->getObjCIdType();
                        0: branch 1 not taken
                        0: branch 2 not taken
    2201                0:   assert(!argT.isNull() && "Can't find 'id' type");
    2202                0:   ArgTys.push_back(argT);
    2203                0:   ArgTys.push_back(argT);
    2204                 :   QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(),
    2205                 :                                                   &ArgTys[0], ArgTys.size(),
    2206                0:                                                   false, 0);
    2207                 :   SuperContructorFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
    2208                 :                                          SourceLocation(),
    2209                 :                                          msgSendIdent, msgSendType, 0,
                        0: branch 2 not taken
                        0: branch 3 not taken
    2210                0:                                          FunctionDecl::Extern, false);
    2211                 : }
    2212                 : 
    2213                 : // SynthMsgSendFunctionDecl - id objc_msgSend(id self, SEL op, ...);
    2214               19: void RewriteObjC::SynthMsgSendFunctionDecl() {
    2215               19:   IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend");
    2216               19:   llvm::SmallVector<QualType, 16> ArgTys;
    2217               19:   QualType argT = Context->getObjCIdType();
                       19: branch 1 taken
                        0: branch 2 not taken
    2218               19:   assert(!argT.isNull() && "Can't find 'id' type");
    2219               19:   ArgTys.push_back(argT);
    2220               19:   argT = Context->getObjCSelType();
                       19: branch 1 taken
                        0: branch 2 not taken
    2221               19:   assert(!argT.isNull() && "Can't find 'SEL' type");
    2222               19:   ArgTys.push_back(argT);
    2223                 :   QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(),
    2224                 :                                                   &ArgTys[0], ArgTys.size(),
    2225               19:                                                   true /*isVariadic*/, 0);
    2226                 :   MsgSendFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
    2227                 :                                          SourceLocation(),
    2228                 :                                          msgSendIdent, msgSendType, 0,
                       19: branch 2 taken
                        0: branch 3 not taken
    2229               38:                                          FunctionDecl::Extern, false);
    2230               19: }
    2231                 : 
    2232                 : // SynthMsgSendSuperFunctionDecl - id objc_msgSendSuper(struct objc_super *, SEL op, ...);
    2233               19: void RewriteObjC::SynthMsgSendSuperFunctionDecl() {
    2234               19:   IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSendSuper");
    2235               19:   llvm::SmallVector<QualType, 16> ArgTys;
    2236                 :   RecordDecl *RD = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl,
    2237                 :                                       SourceLocation(),
                       19: branch 4 taken
                        0: branch 5 not taken
    2238               19:                                       &Context->Idents.get("objc_super"));
    2239               19:   QualType argT = Context->getPointerType(Context->getTagDeclType(RD));
                       19: branch 1 taken
                        0: branch 2 not taken
    2240               19:   assert(!argT.isNull() && "Can't build 'struct objc_super *' type");
    2241               19:   ArgTys.push_back(argT);
    2242               19:   argT = Context->getObjCSelType();
                       19: branch 1 taken
                        0: branch 2 not taken
    2243               19:   assert(!argT.isNull() && "Can't find 'SEL' type");
    2244               19:   ArgTys.push_back(argT);
    2245                 :   QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(),
    2246                 :                                                   &ArgTys[0], ArgTys.size(),
    2247               19:                                                   true /*isVariadic*/, 0);
    2248                 :   MsgSendSuperFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
    2249                 :                                               SourceLocation(),
    2250                 :                                               msgSendIdent, msgSendType, 0,
                       19: branch 2 taken
                        0: branch 3 not taken
    2251               38:                                               FunctionDecl::Extern, false);
    2252               19: }
    2253                 : 
    2254                 : // SynthMsgSendStretFunctionDecl - id objc_msgSend_stret(id self, SEL op, ...);
    2255               19: void RewriteObjC::SynthMsgSendStretFunctionDecl() {
    2256               19:   IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_stret");
    2257               19:   llvm::SmallVector<QualType, 16> ArgTys;
    2258               19:   QualType argT = Context->getObjCIdType();
                       19: branch 1 taken
                        0: branch 2 not taken
    2259               19:   assert(!argT.isNull() && "Can't find 'id' type");
    2260               19:   ArgTys.push_back(argT);
    2261               19:   argT = Context->getObjCSelType();
                       19: branch 1 taken
                        0: branch 2 not taken
    2262               19:   assert(!argT.isNull() && "Can't find 'SEL' type");
    2263               19:   ArgTys.push_back(argT);
    2264                 :   QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(),
    2265                 :                                                   &ArgTys[0], ArgTys.size(),
    2266               19:                                                   true /*isVariadic*/, 0);
    2267                 :   MsgSendStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
    2268                 :                                          SourceLocation(),
    2269                 :                                          msgSendIdent, msgSendType, 0,
                       19: branch 2 taken
                        0: branch 3 not taken
    2270               38:                                          FunctionDecl::Extern, false);
    2271               19: }
    2272                 : 
    2273                 : // SynthMsgSendSuperStretFunctionDecl -
    2274                 : // id objc_msgSendSuper_stret(struct objc_super *, SEL op, ...);
    2275               19: void RewriteObjC::SynthMsgSendSuperStretFunctionDecl() {
    2276                 :   IdentifierInfo *msgSendIdent =
    2277               19:     &Context->Idents.get("objc_msgSendSuper_stret");
    2278               19:   llvm::SmallVector<QualType, 16> ArgTys;
    2279                 :   RecordDecl *RD = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl,
    2280                 :                                       SourceLocation(),
                       19: branch 4 taken
                        0: branch 5 not taken
    2281               19:                                       &Context->Idents.get("objc_super"));
    2282               19:   QualType argT = Context->getPointerType(Context->getTagDeclType(RD));
                       19: branch 1 taken
                        0: branch 2 not taken
    2283               19:   assert(!argT.isNull() && "Can't build 'struct objc_super *' type");
    2284               19:   ArgTys.push_back(argT);
    2285               19:   argT = Context->getObjCSelType();
                       19: branch 1 taken
                        0: branch 2 not taken
    2286               19:   assert(!argT.isNull() && "Can't find 'SEL' type");
    2287               19:   ArgTys.push_back(argT);
    2288                 :   QualType msgSendType = Context->getFunctionType(Context->getObjCIdType(),
    2289                 :                                                   &ArgTys[0], ArgTys.size(),
    2290               19:                                                   true /*isVariadic*/, 0);
    2291                 :   MsgSendSuperStretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
    2292                 :                                                        SourceLocation(),
    2293                 :                                               msgSendIdent, msgSendType, 0,
                       19: branch 2 taken
                        0: branch 3 not taken
    2294               38:                                               FunctionDecl::Extern, false);
    2295               19: }
    2296                 : 
    2297                 : // SynthMsgSendFpretFunctionDecl - double objc_msgSend_fpret(id self, SEL op, ...);
    2298               19: void RewriteObjC::SynthMsgSendFpretFunctionDecl() {
    2299               19:   IdentifierInfo *msgSendIdent = &Context->Idents.get("objc_msgSend_fpret");
    2300               19:   llvm::SmallVector<QualType, 16> ArgTys;
    2301               19:   QualType argT = Context->getObjCIdType();
                       19: branch 1 taken
                        0: branch 2 not taken
    2302               19:   assert(!argT.isNull() && "Can't find 'id' type");
    2303               19:   ArgTys.push_back(argT);
    2304               19:   argT = Context->getObjCSelType();
                       19: branch 1 taken
                        0: branch 2 not taken
    2305               19:   assert(!argT.isNull() && "Can't find 'SEL' type");
    2306               19:   ArgTys.push_back(argT);
    2307                 :   QualType msgSendType = Context->getFunctionType(Context->DoubleTy,
    2308                 :                                                   &ArgTys[0], ArgTys.size(),
    2309               19:                                                   true /*isVariadic*/, 0);
    2310                 :   MsgSendFpretFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
    2311                 :                                               SourceLocation(),
    2312                 :                                               msgSendIdent, msgSendType, 0,
                       19: branch 2 taken
                        0: branch 3 not taken
    2313               38:                                               FunctionDecl::Extern, false);
    2314               19: }
    2315                 : 
    2316                 : // SynthGetClassFunctionDecl - id objc_getClass(const char *name);
    2317               19: void RewriteObjC::SynthGetClassFunctionDecl() {
    2318               19:   IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getClass");
    2319               19:   llvm::SmallVector<QualType, 16> ArgTys;
    2320               19:   ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
    2321                 :   QualType getClassType = Context->getFunctionType(Context->getObjCIdType(),
    2322                 :                                                    &ArgTys[0], ArgTys.size(),
    2323               19:                                                    false /*isVariadic*/, 0);
    2324                 :   GetClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
    2325                 :                                           SourceLocation(),
    2326                 :                                           getClassIdent, getClassType, 0,
                       19: branch 2 taken
                        0: branch 3 not taken
    2327               19:                                           FunctionDecl::Extern, false);
    2328               19: }
    2329                 : 
    2330                 : // SynthGetMetaClassFunctionDecl - id objc_getClass(const char *name);
    2331               19: void RewriteObjC::SynthGetMetaClassFunctionDecl() {
    2332               19:   IdentifierInfo *getClassIdent = &Context->Idents.get("objc_getMetaClass");
    2333               19:   llvm::SmallVector<QualType, 16> ArgTys;
    2334               19:   ArgTys.push_back(Context->getPointerType(Context->CharTy.withConst()));
    2335                 :   QualType getClassType = Context->getFunctionType(Context->getObjCIdType(),
    2336                 :                                                    &ArgTys[0], ArgTys.size(),
    2337               19:                                                    false /*isVariadic*/, 0);
    2338                 :   GetMetaClassFunctionDecl = FunctionDecl::Create(*Context, TUDecl,
    2339                 :                                               SourceLocation(),
    2340                 :                                               getClassIdent, getClassType, 0,
                       19: branch 2 taken
                        0: branch 3 not taken
    2341               19:                                               FunctionDecl::Extern, false);
    2342               19: }
    2343                 : 
    2344               16: Stmt *RewriteObjC::RewriteObjCStringLiteral(ObjCStringLiteral *Exp) {
    2345               16:   QualType strType = getConstantStringStructType();
    2346                 : 
    2347               16:   std::string S = "__NSConstantStringImpl_";
    2348                 : 
    2349               16:   std::string tmpName = InFileName;
    2350                 :   unsigned i;
                     1004: branch 1 taken
                       16: branch 2 taken
    2351             1020:   for (i=0; i < tmpName.length(); i++) {
    2352             1004:     char c = tmpName.at(i);
    2353                 :     // replace any non alphanumeric characters with '_'.
                      192: branch 1 taken
                      812: branch 2 taken
                        4: branch 3 taken
                      188: branch 4 taken
                        0: branch 5 not taken
                        4: branch 6 taken
    2354             1004:     if (!isalpha(c) && (c < '0' || c > '9'))
    2355              188:       tmpName[i] = '_';
    2356                 :   }
    2357               16:   S += tmpName;
    2358               16:   S += "_";
    2359               16:   S += utostr(NumObjCStringLiterals++);
    2360                 : 
    2361               16:   Preamble += "static __NSConstantStringImpl " + S;
    2362               16:   Preamble += " __attribute__ ((section (\"__DATA, __cfstring\"))) = {__CFConstantStringClassReference,";
    2363               16:   Preamble += "0x000007c8,"; // utf8_str
    2364                 :   // The pretty printer for StringLiteral handles escape characters properly.
    2365               16:   std::string prettyBufS;
    2366               16:   llvm::raw_string_ostream prettyBuf(prettyBufS);
    2367                 :   Exp->getString()->printPretty(prettyBuf, *Context, 0,
    2368               16:                                 PrintingPolicy(LangOpts));
    2369               16:   Preamble += prettyBuf.str();
    2370               16:   Preamble += ",";
    2371               16:   Preamble += utostr(Exp->getString()->getByteLength()) + "};\n";
    2372                 : 
    2373                 :   VarDecl *NewVD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
    2374                 :                                     &Context->Idents.get(S.c_str()), strType, 0,
                       16: branch 4 taken
                        0: branch 5 not taken
    2375               16:                                     VarDecl::Static);
                       16: branch 2 taken
                        0: branch 3 not taken
    2376               16:   DeclRefExpr *DRE = new (Context) DeclRefExpr(NewVD, strType, SourceLocation());
    2377                 :   Expr *Unop = new (Context) UnaryOperator(DRE, UnaryOperator::AddrOf,
    2378                 :                                  Context->getPointerType(DRE->getType()),
                       16: branch 4 taken
                        0: branch 5 not taken
    2379               16:                                  SourceLocation());
    2380                 :   // cast to NSConstantString *
    2381                 :   CastExpr *cast = NoTypeInfoCStyleCastExpr(Context, Exp->getType(),
    2382               16:                                             CastExpr::CK_Unknown, Unop);
    2383               16:   ReplaceStmt(Exp, cast);
    2384                 :   // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
    2385               16:   return cast;
    2386                 : }
    2387                 : 
    2388               43: ObjCInterfaceDecl *RewriteObjC::isSuperReceiver(Expr *recExpr) {
    2389                 :   // check if we are sending a message to 'super'
                       37: branch 0 taken
                        6: branch 1 taken
                        6: branch 3 taken
                       31: branch 4 taken
                       12: branch 5 taken
                       31: branch 6 taken
    2390               43:   if (!CurMethodDef || !CurMethodDef->isInstanceMethod()) return 0;
    2391                 : 
                        1: branch 1 taken
                       30: branch 2 taken
    2392               31:   if (ObjCSuperExpr *Super = dyn_cast<ObjCSuperExpr>(recExpr)) {
    2393                 :       const ObjCObjectPointerType *OPT =
    2394                1:         Super->getType()->getAs<ObjCObjectPointerType>();
                        0: branch 0 not taken
                        1: branch 1 taken
    2395                1:       assert(OPT);
    2396                1:       const ObjCInterfaceType *IT = OPT->getInterfaceType();
    2397                1:       return IT->getDecl();
    2398                 :     }
    2399               30:   return 0;
    2400                 : }
    2401                 : 
    2402                 : // struct objc_super { struct objc_object *receiver; struct objc_class *super; };
    2403                2: QualType RewriteObjC::getSuperStructType() {
                        1: branch 0 taken
                        1: branch 1 taken
    2404                2:   if (!SuperStructDecl) {
    2405                 :     SuperStructDecl = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl,
    2406                 :                                          SourceLocation(),
                        1: branch 4 taken
                        0: branch 5 not taken
    2407                1:                                          &Context->Idents.get("objc_super"));
                        2: branch 1 taken
                        1: branch 2 taken
    2408                1:     QualType FieldTypes[2];
    2409                 : 
    2410                 :     // struct objc_object *receiver;
    2411                1:     FieldTypes[0] = Context->getObjCIdType();
    2412                 :     // struct objc_class *super;
    2413                1:     FieldTypes[1] = Context->getObjCClassType();
    2414                 : 
    2415                 :     // Create fields
                        2: branch 0 taken
                        1: branch 1 taken
    2416                3:     for (unsigned i = 0; i < 2; ++i) {
    2417                 :       SuperStructDecl->addDecl(FieldDecl::Create(*Context, SuperStructDecl,
    2418                 :                                                  SourceLocation(), 0,
    2419                 :                                                  FieldTypes[i], 0,
    2420                 :                                                  /*BitWidth=*/0,
                        2: branch 1 taken
                        0: branch 2 not taken
    2421                2:                                                  /*Mutable=*/false));
    2422                 :     }
    2423                 : 
    2424                1:     SuperStructDecl->completeDefinition(*Context);
    2425                 :   }
    2426                2:   return Context->getTagDeclType(SuperStructDecl);
    2427                 : }
    2428                 : 
    2429               16: QualType RewriteObjC::getConstantStringStructType() {
                        2: branch 0 taken
                       14: branch 1 taken
    2430               16:   if (!ConstantStringDecl) {
    2431                 :     ConstantStringDecl = RecordDecl::Create(*Context, TagDecl::TK_struct, TUDecl,
    2432                 :                                             SourceLocation(),
                        2: branch 4 taken
                        0: branch 5 not taken
    2433                2:                          &Context->Idents.get("__NSConstantStringImpl"));
                        8: branch 1 taken
                        2: branch 2 taken
    2434                2:     QualType FieldTypes[4];
    2435                 : 
    2436                 :     // struct objc_object *receiver;
    2437                2:     FieldTypes[0] = Context->getObjCIdType();
    2438                 :     // int flags;
    2439                2:     FieldTypes[1] = Context->IntTy;
    2440                 :     // char *str;
    2441                2:     FieldTypes[2] = Context->getPointerType(Context->CharTy);
    2442                 :     // long length;
    2443                2:     FieldTypes[3] = Context->LongTy;
    2444                 : 
    2445                 :     // Create fields
                        8: branch 0 taken
                        2: branch 1 taken
    2446               10:     for (unsigned i = 0; i < 4; ++i) {
    2447                 :       ConstantStringDecl->addDecl(FieldDecl::Create(*Context,
    2448                 :                                                     ConstantStringDecl,
    2449                 :                                                     SourceLocation(), 0,
    2450                 :                                                     FieldTypes[i], 0,
    2451                 :                                                     /*BitWidth=*/0,
                        8: branch 1 taken
                        0: branch 2 not taken
    2452                8:                                                     /*Mutable=*/true));
    2453                 :     }
    2454                 : 
    2455                2:     ConstantStringDecl->completeDefinition(*Context);
    2456                 :   }
    2457               16:   return Context->getTagDeclType(ConstantStringDecl);
    2458                 : }
    2459                 : 
    2460               49: Stmt *RewriteObjC::SynthMessageExpr(ObjCMessageExpr *Exp) {
                       19: branch 0 taken
                       30: branch 1 taken
    2461               49:   if (!SelGetUidFunctionDecl)
    2462               19:     SynthSelGetUidFunctionDecl();
                       19: branch 0 taken
                       30: branch 1 taken
    2463               49:   if (!MsgSendFunctionDecl)
    2464               19:     SynthMsgSendFunctionDecl();
                       19: branch 0 taken
                       30: branch 1 taken
    2465               49:   if (!MsgSendSuperFunctionDecl)
    2466               19:     SynthMsgSendSuperFunctionDecl();
                       19: branch 0 taken
                       30: branch 1 taken
    2467               49:   if (!MsgSendStretFunctionDecl)
    2468               19:     SynthMsgSendStretFunctionDecl();
                       19: branch 0 taken
                       30: branch 1 taken
    2469               49:   if (!MsgSendSuperStretFunctionDecl)
    2470               19:     SynthMsgSendSuperStretFunctionDecl();
                       19: branch 0 taken
                       30: branch 1 taken
    2471               49:   if (!MsgSendFpretFunctionDecl)
    2472               19:     SynthMsgSendFpretFunctionDecl();
                       19: branch 0 taken
                       30: branch 1 taken
    2473               49:   if (!GetClassFunctionDecl)
    2474               19:     SynthGetClassFunctionDecl();
                       19: branch 0 taken
                       30: branch 1 taken
    2475               49:   if (!GetMetaClassFunctionDecl)
    2476               19:     SynthGetMetaClassFunctionDecl();
    2477                 : 
    2478                 :   // default to objc_msgSend().
    2479               49:   FunctionDecl *MsgSendFlavor = MsgSendFunctionDecl;
    2480                 :   // May need to use objc_msgSend_stret() as well.
    2481               49:   FunctionDecl *MsgSendStretFlavor = 0;
                       43: branch 1 taken
                        6: branch 2 taken
    2482               49:   if (ObjCMethodDecl *mDecl = Exp->getMethodDecl()) {
    2483               43:     QualType resultType = mDecl->getResultType();
                       42: branch 2 taken
                        1: branch 3 taken
                        0: branch 6 not taken
                       42: branch 7 taken
                        1: branch 8 taken
                       42: branch 9 taken
    2484               43:     if (resultType->isStructureType() || resultType->isUnionType())
    2485                1:       MsgSendStretFlavor = MsgSendStretFunctionDecl;
                        0: branch 2 not taken
                       42: branch 3 taken
    2486               42:     else if (resultType->isRealFloatingType())
    2487                0:       MsgSendFlavor = MsgSendFpretFunctionDecl;
    2488                 :   }
    2489                 : 
    2490                 :   // Synthesize a call to objc_msgSend().
    2491               49:   llvm::SmallVector<Expr*, 8> MsgExprs;
    2492               49:   IdentifierInfo *clsName = Exp->getClassName();
    2493                 : 
    2494                 :   // Derive/push the receiver/selector, 2 implicit arguments to objc_msgSend().
                        6: branch 0 taken
                       43: branch 1 taken
    2495               49:   if (clsName) { // class message.
    2496                 :     // FIXME: We need to fix Sema (and the AST for ObjCMessageExpr) to handle
    2497                 :     // the 'super' idiom within a class method.
                        0: branch 3 not taken
                        6: branch 4 taken
    2498                6:     if (clsName->getName() == "super") {
    2499                0:       MsgSendFlavor = MsgSendSuperFunctionDecl;
                        0: branch 0 not taken
                        0: branch 1 not taken
    2500                0:       if (MsgSendStretFlavor)
    2501                0:         MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
                        0: branch 0 not taken
                        0: branch 1 not taken
    2502                0:       assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
    2503                 : 
    2504                 :       ObjCInterfaceDecl *SuperDecl =
    2505                0:         CurMethodDef->getClassInterface()->getSuperClass();
    2506                 : 
    2507                0:       llvm::SmallVector<Expr*, 4> InitExprs;
    2508                 : 
    2509                 :       // set the receiver to self, the first argument to all methods.
    2510                 :       InitExprs.push_back(
    2511                 :         NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
    2512                 :                                  CastExpr::CK_Unknown,
    2513                 :                      new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(),
    2514                 :                                      Context->getObjCIdType(),
    2515                 :                                      SourceLocation()))
                        0: branch 4 not taken
                        0: branch 5 not taken
    2516                0:                           ); // set the 'receiver'.
    2517                 : 
    2518                0:       llvm::SmallVector<Expr*, 8> ClsExprs;
    2519                0:       QualType argType = Context->getPointerType(Context->CharTy);
    2520                 :       ClsExprs.push_back(StringLiteral::Create(*Context,
    2521                 :                                      SuperDecl->getIdentifier()->getNameStart(),
    2522                 :                                      SuperDecl->getIdentifier()->getLength(),
    2523                0:                                      false, argType, SourceLocation()));
    2524                 :       CallExpr *Cls = SynthesizeCallToFunctionDecl(GetMetaClassFunctionDecl,
    2525                 :                                                    &ClsExprs[0],
    2526                0:                                                    ClsExprs.size());
    2527                 :       // To turn off a warning, type-cast to 'id'
    2528                 :       InitExprs.push_back( // set 'super class', using objc_getClass().
    2529                 :                           NoTypeInfoCStyleCastExpr(Context,
    2530                 :                                                    Context->getObjCIdType(),
    2531                0:                                                    CastExpr::CK_Unknown, Cls));
    2532                 :       // struct objc_super
    2533                0:       QualType superType = getSuperStructType();
    2534                 :       Expr *SuperRep;
    2535                 : 
                        0: branch 0 not taken
                        0: branch 1 not taken
    2536                0:       if (LangOpts.Microsoft) {
    2537                0:         SynthSuperContructorFunctionDecl();
    2538                 :         // Simulate a contructor call...
    2539                 :         DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl,
                        0: branch 2 not taken
                        0: branch 3 not taken
    2540                0:                                            superType, SourceLocation());
    2541                 :         SuperRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0],
    2542                 :                                           InitExprs.size(),
                        0: branch 4 not taken
                        0: branch 5 not taken
    2543                0:                                           superType, SourceLocation());
    2544                 :         // The code for super is a little tricky to prevent collision with
    2545                 :         // the structure definition in the header. The rewriter has it's own
    2546                 :         // internal definition (__rw_objc_super) that is uses. This is why
    2547                 :         // we need the cast below. For example:
    2548                 :         // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
    2549                 :         //
    2550                 :         SuperRep = new (Context) UnaryOperator(SuperRep, UnaryOperator::AddrOf,
    2551                 :                                  Context->getPointerType(SuperRep->getType()),
                        0: branch 4 not taken
                        0: branch 5 not taken
    2552                0:                                  SourceLocation());
    2553                 :         SuperRep = NoTypeInfoCStyleCastExpr(Context,
    2554                 :                                             Context->getPointerType(superType),
    2555                0:                                             CastExpr::CK_Unknown, SuperRep);
    2556                 :       } else {
    2557                 :         // (struct objc_super) { <exprs from above> }
    2558                 :         InitListExpr *ILE = new (Context) InitListExpr(SourceLocation(),
    2559                 :                                              &InitExprs[0], InitExprs.size(),
                        0: branch 5 not taken
                        0: branch 6 not taken
    2560                0:                                              SourceLocation());
    2561                 :         TypeSourceInfo *superTInfo
    2562                0:           = Context->getTrivialTypeSourceInfo(superType);
    2563                 :         SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,
                        0: branch 2 not taken
                        0: branch 3 not taken
    2564                0:                                                      superType, ILE, false);
    2565                 :         // struct objc_super *
    2566                 :         SuperRep = new (Context) UnaryOperator(SuperRep, UnaryOperator::AddrOf,
    2567                 :                                  Context->getPointerType(SuperRep->getType()),
                        0: branch 4 not taken
                        0: branch 5 not taken
    2568                0:                                  SourceLocation());
    2569                 :       }
    2570                0:       MsgExprs.push_back(SuperRep);
    2571                 :     } else {
    2572                6:       llvm::SmallVector<Expr*, 8> ClsExprs;
    2573                6:       QualType argType = Context->getPointerType(Context->CharTy);
    2574                 :       ClsExprs.push_back(StringLiteral::Create(*Context,
    2575                 :                                                clsName->getNameStart(),
    2576                 :                                                clsName->getLength(),
    2577                 :                                                false, argType,
    2578                6:                                                SourceLocation()));
    2579                 :       CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
    2580                 :                                                    &ClsExprs[0],
    2581                6:                                                    ClsExprs.size());
    2582                6:       MsgExprs.push_back(Cls);
    2583                 :     }
    2584                 :   } else { // instance message.
    2585               43:     Expr *recExpr = Exp->getReceiver();
    2586                 : 
                        1: branch 1 taken
                       42: branch 2 taken
    2587               43:     if (ObjCInterfaceDecl *SuperDecl = isSuperReceiver(recExpr)) {
    2588                1:       MsgSendFlavor = MsgSendSuperFunctionDecl;
                        0: branch 0 not taken
                        1: branch 1 taken
    2589                1:       if (MsgSendStretFlavor)
    2590                0:         MsgSendStretFlavor = MsgSendSuperStretFunctionDecl;
                        0: branch 0 not taken
                        1: branch 1 taken
    2591                1:       assert(MsgSendFlavor && "MsgSendFlavor is NULL!");
    2592                 : 
    2593                1:       llvm::SmallVector<Expr*, 4> InitExprs;
    2594                 : 
    2595                 :       InitExprs.push_back(
    2596                 :         NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
    2597                 :                                  CastExpr::CK_Unknown,
    2598                 :                      new (Context) DeclRefExpr(CurMethodDef->getSelfDecl(),
    2599                 :                                      Context->getObjCIdType(),
    2600                 :                                      SourceLocation()))
                        1: branch 4 taken
                        0: branch 5 not taken
    2601                1:                           ); // set the 'receiver'.
    2602                 : 
    2603                1:       llvm::SmallVector<Expr*, 8> ClsExprs;
    2604                1:       QualType argType = Context->getPointerType(Context->CharTy);
    2605                 :       ClsExprs.push_back(StringLiteral::Create(*Context,
    2606                 :                                      SuperDecl->getIdentifier()->getNameStart(),
    2607                 :                                      SuperDecl->getIdentifier()->getLength(),
    2608                1:                                      false, argType, SourceLocation()));
    2609                 :       CallExpr *Cls = SynthesizeCallToFunctionDecl(GetClassFunctionDecl,
    2610                 :                                                    &ClsExprs[0],
    2611                1:                                                    ClsExprs.size());
    2612                 :       // To turn off a warning, type-cast to 'id'
    2613                 :       InitExprs.push_back(
    2614                 :         // set 'super class', using objc_getClass().
    2615                 :         NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
    2616                1:                                  CastExpr::CK_Unknown, Cls));
    2617                 :       // struct objc_super
    2618                1:       QualType superType = getSuperStructType();
    2619                 :       Expr *SuperRep;
    2620                 : 
                        0: branch 0 not taken
                        1: branch 1 taken
    2621                1:       if (LangOpts.Microsoft) {
    2622                0:         SynthSuperContructorFunctionDecl();
    2623                 :         // Simulate a contructor call...
    2624                 :         DeclRefExpr *DRE = new (Context) DeclRefExpr(SuperContructorFunctionDecl,
                        0: branch 2 not taken
                        0: branch 3 not taken
    2625                0:                                            superType, SourceLocation());
    2626                 :         SuperRep = new (Context) CallExpr(*Context, DRE, &InitExprs[0],
    2627                 :                                           InitExprs.size(),
                        0: branch 4 not taken
                        0: branch 5 not taken
    2628                0:                                           superType, SourceLocation());
    2629                 :         // The code for super is a little tricky to prevent collision with
    2630                 :         // the structure definition in the header. The rewriter has it's own
    2631                 :         // internal definition (__rw_objc_super) that is uses. This is why
    2632                 :         // we need the cast below. For example:
    2633                 :         // (struct objc_super *)&__rw_objc_super((id)self, (id)objc_getClass("SUPER"))
    2634                 :         //
    2635                 :         SuperRep = new (Context) UnaryOperator(SuperRep, UnaryOperator::AddrOf,
    2636                 :                                  Context->getPointerType(SuperRep->getType()),
                        0: branch 4 not taken
                        0: branch 5 not taken
    2637                0:                                  SourceLocation());
    2638                 :         SuperRep = NoTypeInfoCStyleCastExpr(Context,
    2639                 :                                  Context->getPointerType(superType),
    2640                0:                                  CastExpr::CK_Unknown, SuperRep);
    2641                 :       } else {
    2642                 :         // (struct objc_super) { <exprs from above> }
    2643                 :         InitListExpr *ILE = new (Context) InitListExpr(SourceLocation(),
    2644                 :                                              &InitExprs[0], InitExprs.size(),
                        1: branch 5 taken
                        0: branch 6 not taken
    2645                1:                                              SourceLocation());
    2646                 :         TypeSourceInfo *superTInfo
    2647                1:           = Context->getTrivialTypeSourceInfo(superType);
    2648                 :         SuperRep = new (Context) CompoundLiteralExpr(SourceLocation(), superTInfo,
                        1: branch 2 taken
                        0: branch 3 not taken
    2649                1:                                                      superType, ILE, false);
    2650                 :       }
    2651                1:       MsgExprs.push_back(SuperRep);
    2652                 :     } else {
    2653                 :       // Remove all type-casts because it may contain objc-style types; e.g.
    2654                 :       // Foo<Proto> *.
                        5: branch 1 taken
                       42: branch 2 taken
    2655               52:       while (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(recExpr))
    2656                5:         recExpr = CE->getSubExpr();
    2657                 :       recExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
    2658               42:                                          CastExpr::CK_Unknown, recExpr);
    2659               42:       MsgExprs.push_back(recExpr);
    2660                 :     }
    2661                 :   }
    2662                 :   // Create a call to sel_registerName("selName"), it will be the 2nd argument.
    2663               49:   llvm::SmallVector<Expr*, 8> SelExprs;
    2664               49:   QualType argType = Context->getPointerType(Context->CharTy);
    2665                 :   SelExprs.push_back(StringLiteral::Create(*Context,
    2666                 :                                        Exp->getSelector().getAsString().c_str(),
    2667                 :                                        Exp->getSelector().getAsString().size(),
    2668               49:                                        false, argType, SourceLocation()));
    2669                 :   CallExpr *SelExp = SynthesizeCallToFunctionDecl(SelGetUidFunctionDecl,
    2670               49:                                                  &SelExprs[0], SelExprs.size());
    2671               49:   MsgExprs.push_back(SelExp);
    2672                 : 
    2673                 :   // Now push any user supplied arguments.
                       31: branch 1 taken
                       49: branch 2 taken
    2674               80:   for (unsigned i = 0; i < Exp->getNumArgs(); i++) {
    2675               31:     Expr *userExpr = Exp->getArg(i);
    2676                 :     // Make all implicit casts explicit...ICE comes in handy:-)
                        4: branch 1 taken
                       27: branch 2 taken
    2677               31:     if (ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(userExpr)) {
    2678                 :       // Reuse the ICE type, it is exactly what the doctor ordered.
    2679                 :       QualType type = ICE->getType()->isObjCQualifiedIdType()
    2680                 :                                 ? Context->getObjCIdType()
                        0: branch 3 not taken
                        4: branch 4 taken
    2681                4:                                 : ICE->getType();
    2682                 :       userExpr = NoTypeInfoCStyleCastExpr(Context, type, CastExpr::CK_Unknown,
    2683                4:                                           userExpr);
    2684                 :     }
    2685                 :     // Make id<P...> cast into an 'id' cast.
                       13: branch 1 taken
                       14: branch 2 taken
    2686               27:     else if (CStyleCastExpr *CE = dyn_cast<CStyleCastExpr>(userExpr)) {
                        1: branch 3 taken
                       12: branch 4 taken
    2687               13:       if (CE->getType()->isObjCQualifiedIdType()) {
                        1: branch 1 taken
                        1: branch 2 taken
    2688                3:         while ((CE = dyn_cast<CStyleCastExpr>(userExpr)))
    2689                1:           userExpr = CE->getSubExpr();
    2690                 :         userExpr = NoTypeInfoCStyleCastExpr(Context, Context->getObjCIdType(),
    2691                1:                                             CastExpr::CK_Unknown, userExpr);
    2692                 :       }
    2693                 :     }
    2694               31:     MsgExprs.push_back(userExpr);
    2695                 :     // We've transferred the ownership to MsgExprs. For now, we *don't* null
    2696                 :     // out the argument in the original expression (since we aren't deleting
    2697                 :     // the ObjCMessageExpr). See RewritePropertySetter() usage for more info.
    2698                 :     //Exp->setArg(i, 0);
    2699                 :   }
    2700                 :   // Generate the funky cast.
    2701                 :   CastExpr *cast;
    2702               49:   llvm::SmallVector<QualType, 8> ArgTypes;
    2703               49:   QualType returnType;
    2704                 : 
    2705                 :   // Push 'id' and 'SEL', the 2 implicit arguments.
                        1: branch 0 taken
                       48: branch 1 taken
    2706               49:   if (MsgSendFlavor == MsgSendSuperFunctionDecl)
    2707                1:     ArgTypes.push_back(Context->getPointerType(getSuperStructType()));
    2708                 :   else
    2709               48:     ArgTypes.push_back(Context->getObjCIdType());
    2710               49:   ArgTypes.push_back(Context->getObjCSelType());
                       43: branch 1 taken
                        6: branch 2 taken
    2711               49:   if (ObjCMethodDecl *OMD = Exp->getMethodDecl()) {
    2712                 :     // Push any user argument types.
                       18: branch 1 taken
                       43: branch 2 taken
    2713              104:     for (ObjCMethodDecl::param_iterator PI = OMD->param_begin(),
    2714               43:          E = OMD->param_end(); PI != E; ++PI) {
    2715                 :       QualType t = (*PI)->getType()->isObjCQualifiedIdType()
    2716                 :                      ? Context->getObjCIdType()
                        1: branch 3 taken
                       17: branch 4 taken
    2717               18:                      : (*PI)->getType();
    2718                 :       // Make sure we convert "t (^)(...)" to "t (*)(...)".
                        0: branch 1 not taken
                       18: branch 2 taken
    2719               18:       if (isTopLevelBlockPointerType(t)) {
    2720                0:         const BlockPointerType *BPT = t->getAs<BlockPointerType>();
    2721                0:         t = Context->getPointerType(BPT->getPointeeType());
    2722                 :       }
    2723               18:       ArgTypes.push_back(t);
    2724                 :     }
    2725                 :     returnType = OMD->getResultType()->isObjCQualifiedIdType()
                        1: branch 3 taken
                       42: branch 4 taken
    2726               43:                    ? Context->getObjCIdType() : OMD->getResultType();
    2727                 :   } else {
    2728                6:     returnType = Context->getObjCIdType();
    2729                 :   }
    2730                 :   // Get the type, we will need to reference it in a couple spots.
    2731               49:   QualType msgSendType = MsgSendFlavor->getType();
    2732                 : 
    2733                 :   // Create a reference to the objc_msgSend() declaration.
    2734                 :   DeclRefExpr *DRE = new (Context) DeclRefExpr(MsgSendFlavor, msgSendType,
                       49: branch 2 taken
                        0: branch 3 not taken
    2735               49:                                      SourceLocation());
    2736                 : 
    2737                 :   // Need to cast objc_msgSend to "void *" (to workaround a GCC bandaid).
    2738                 :   // If we don't do this cast, we get the following bizarre warning/note:
    2739                 :   // xx.m:13: warning: function called through a non-compatible type
    2740                 :   // xx.m:13: note: if this code is reached, the program will abort
    2741                 :   cast = NoTypeInfoCStyleCastExpr(Context,
    2742                 :                                   Context->getPointerType(Context->VoidTy),
    2743               49:                                   CastExpr::CK_Unknown, DRE);
    2744                 : 
    2745                 :   // Now do the "normal" pointer to function cast.
    2746                 :   QualType castType = Context->getFunctionType(returnType,
    2747                 :     &ArgTypes[0], ArgTypes.size(),
    2748                 :     // If we don't have a method decl, force a variadic cast.
                       43: branch 1 taken
                        6: branch 2 taken
    2749               49:     Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : true, 0);
    2750               49:   castType = Context->getPointerType(castType);
    2751                 :   cast = NoTypeInfoCStyleCastExpr(Context, castType, CastExpr::CK_Unknown,
    2752               49:                                   cast);
    2753                 : 
    2754                 :   // Don't forget the parens to enforce the proper binding.
                       49: branch 3 taken
                        0: branch 4 not taken
    2755               49:   ParenExpr *PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast);
    2756                 : 
    2757               49:   const FunctionType *FT = msgSendType->getAs<FunctionType>();
    2758                 :   CallExpr *CE = new (Context) CallExpr(*Context, PE, &MsgExprs[0],
    2759                 :                                         MsgExprs.size(),
                       49: branch 5 taken
                        0: branch 6 not taken
    2760               49:                                         FT->getResultType(), SourceLocation());
    2761               49:   Stmt *ReplacingStmt = CE;
                        1: branch 0 taken
                       48: branch 1 taken
    2762               49:   if (MsgSendStretFlavor) {
    2763                 :     // We have the method which returns a struct/union. Must also generate
    2764                 :     // call to objc_msgSend_stret and hang both varieties on a conditional
    2765                 :     // expression which dictate which one to envoke depending on size of
    2766                 :     // method's return type.
    2767                 : 
    2768                 :     // Create a reference to the objc_msgSend_stret() declaration.
    2769                 :     DeclRefExpr *STDRE = new (Context) DeclRefExpr(MsgSendStretFlavor, msgSendType,
                        1: branch 2 taken
                        0: branch 3 not taken
    2770                1:                                          SourceLocation());
    2771                 :     // Need to cast objc_msgSend_stret to "void *" (see above comment).
    2772                 :     cast = NoTypeInfoCStyleCastExpr(Context,
    2773                 :                                     Context->getPointerType(Context->VoidTy),
    2774                1:                                     CastExpr::CK_Unknown, STDRE);
    2775                 :     // Now do the "normal" pointer to function cast.
    2776                 :     castType = Context->getFunctionType(returnType,
    2777                 :       &ArgTypes[0], ArgTypes.size(),
                        1: branch 1 taken
                        0: branch 2 not taken
    2778                1:       Exp->getMethodDecl() ? Exp->getMethodDecl()->isVariadic() : false, 0);
    2779                1:     castType = Context->getPointerType(castType);
    2780                 :     cast = NoTypeInfoCStyleCastExpr(Context, castType, CastExpr::CK_Unknown,
    2781                1:                                     cast);
    2782                 : 
    2783                 :     // Don't forget the parens to enforce the proper binding.
                        1: branch 3 taken
                        0: branch 4 not taken
    2784                1:     PE = new (Context) ParenExpr(SourceLocation(), SourceLocation(), cast);
    2785                 : 
    2786                1:     FT = msgSendType->getAs<FunctionType>();
    2787                 :     CallExpr *STCE = new (Context) CallExpr(*Context, PE, &MsgExprs[0],
    2788                 :                                             MsgExprs.size(),
                        1: branch 5 taken
                        0: branch 6 not taken
    2789                1:                                             FT->getResultType(), SourceLocation());
    2790                 : 
    2791                 :     // Build sizeof(returnType)
    2792                 :     SizeOfAlignOfExpr *sizeofExpr = new (Context) SizeOfAlignOfExpr(true,
    2793                 :                             Context->getTrivialTypeSourceInfo(returnType),
    2794                 :                                       Context->getSizeType(),
                        1: branch 7 taken
                        0: branch 8 not taken
    2795                1:                                       SourceLocation(), SourceLocation());
    2796                 :     // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
    2797                 :     // FIXME: Value of 8 is base on ppc32/x86 ABI for the most common cases.
    2798                 :     // For X86 it is more complicated and some kind of target specific routine
    2799                 :     // is needed to decide what to do.
    2800                 :     unsigned IntSize =
    2801                1:       static_cast<unsigned>(Context->getTypeSize(Context->IntTy));
    2802                 :     IntegerLiteral *limit = new (Context) IntegerLiteral(llvm::APInt(IntSize, 8),
    2803                 :                                                Context->IntTy,
                        1: branch 4 taken
                        0: branch 5 not taken
    2804                1:                                                SourceLocation());
    2805                 :     BinaryOperator *lessThanExpr = new (Context) BinaryOperator(sizeofExpr, limit,
    2806                 :                                                       BinaryOperator::LE,
    2807                 :                                                       Context->IntTy,
                        1: branch 3 taken
                        0: branch 4 not taken
    2808                1:                                                       SourceLocation());
    2809                 :     // (sizeof(returnType) <= 8 ? objc_msgSend(...) : objc_msgSend_stret(...))
    2810                 :     ConditionalOperator *CondExpr =
    2811                 :       new (Context) ConditionalOperator(lessThanExpr,
    2812                 :                                         SourceLocation(), CE,
                        1: branch 3 taken
                        0: branch 4 not taken
    2813                1:                                         SourceLocation(), STCE, returnType);
                        1: branch 3 taken
                        0: branch 4 not taken
    2814                1:     ReplacingStmt = new (Context) ParenExpr(SourceLocation(), SourceLocation(), CondExpr);
    2815                 :   }
    2816                 :   // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
    2817               49:   return ReplacingStmt;
    2818                 : }
    2819                 : 
    2820               30: Stmt *RewriteObjC::RewriteMessageExpr(ObjCMessageExpr *Exp) {
    2821               30:   Stmt *ReplacingStmt = SynthMessageExpr(Exp);
    2822                 : 
    2823                 :   // Now do the actual rewrite.
    2824               30:   ReplaceStmt(Exp, ReplacingStmt);
    2825                 : 
    2826                 :   // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
    2827               30:   return ReplacingStmt;
    2828                 : }
    2829                 : 
    2830                 : // typedef struct objc_object Protocol;
    2831                2: QualType RewriteObjC::getProtocolType() {
                        1: branch 0 taken
                        1: branch 1 taken
    2832                2:   if (!ProtocolTypeDecl) {
    2833                 :     TypeSourceInfo *TInfo
    2834                1:       = Context->getTrivialTypeSourceInfo(Context->getObjCIdType());
    2835                 :     ProtocolTypeDecl = TypedefDecl::Create(*Context, TUDecl,
    2836                 :                                            SourceLocation(),
    2837                 :                                            &Context->Idents.get("Protocol"),
                        1: branch 3 taken
                        0: branch 4 not taken
    2838                1:                                            TInfo);
    2839                 :   }
    2840                2:   return Context->getTypeDeclType(ProtocolTypeDecl);
    2841                 : }
    2842                 : 
    2843                 : /// RewriteObjCProtocolExpr - Rewrite a protocol expression into
    2844                 : /// a synthesized/forward data reference (to the protocol's metadata).
    2845                 : /// The forward references (and metadata) are generated in
    2846                 : /// RewriteObjC::HandleTranslationUnit().
    2847                1: Stmt *RewriteObjC::RewriteObjCProtocolExpr(ObjCProtocolExpr *Exp) {
    2848                1:   std::string Name = "_OBJC_PROTOCOL_" + Exp->getProtocol()->getNameAsString();
    2849                1:   IdentifierInfo *ID = &Context->Idents.get(Name);
    2850                 :   VarDecl *VD = VarDecl::Create(*Context, TUDecl, SourceLocation(),
                        1: branch 2 taken
                        0: branch 3 not taken
    2851                1:                                 ID, getProtocolType(), 0, VarDecl::Extern);
                        1: branch 3 taken
                        0: branch 4 not taken
    2852                1:   DeclRefExpr *DRE = new (Context) DeclRefExpr(VD, getProtocolType(), SourceLocation());
    2853                 :   Expr *DerefExpr = new (Context) UnaryOperator(DRE, UnaryOperator::AddrOf,
    2854                 :                              Context->getPointerType(DRE->getType()),
                        1: branch 4 taken
                        0: branch 5 not taken
    2855                1:                              SourceLocation());
    2856                 :   CastExpr *castExpr = NoTypeInfoCStyleCastExpr(Context, DerefExpr->getType(),
    2857                 :                                                 CastExpr::CK_Unknown,
    2858                1:                                                 DerefExpr);
    2859                1:   ReplaceStmt(Exp, castExpr);
    2860                1:   ProtocolExprDecls.insert(Exp->getProtocol());
    2861                 :   // delete Exp; leak for now, see RewritePropertySetter() usage for more info.
    2862                1:   return castExpr;
    2863                 : 
    2864                 : }
    2865                 : 
    2866                 : bool RewriteObjC::BufferContainsPPDirectives(const char *startBuf,
    2867               21:                                              const char *endBuf) {
                      499: branch 0 taken
                       21: branch 1 taken
    2868              541:   while (startBuf < endBuf) {
                        0: branch 0 not taken
                      499: branch 1 taken
    2869              499:     if (*startBuf == '#') {
    2870                 :       // Skip whitespace.
                        0: branch 0 not taken
                        0: branch 1 not taken
                        0: branch 2 not taken
                        0: branch 3 not taken
    2871                0:       for (++startBuf; startBuf[0] == ' ' || startBuf[0] == '\t'; ++startBuf)
    2872                 :         ;
                        0: branch 1 not taken
                        0: branch 2 not taken
                        0: branch 4 not taken
                        0: branch 5 not taken
                        0: branch 7 not taken
                        0: branch 8 not taken
                        0: branch 10 not taken
                        0: branch 11 not taken
                        0: branch 13 not taken
                        0: branch 14 not taken
                        0: branch 16 not taken
                        0: branch 17 not taken
                        0: branch 19 not taken
                        0: branch 20 not taken
                        0: branch 22 not taken
                        0: branch 23 not taken
                        0: branch 25 not taken
                        0: branch 26 not taken
                        0: branch 28 not taken
                        0: branch 29 not taken
                        0: branch 31 not taken
                        0: branch 32 not taken
                        0: branch 34 not taken
                        0: branch 35 not taken
    2873                0:       if (!strncmp(startBuf, "if", strlen("if")) ||
    2874                 :           !strncmp(startBuf, "ifdef", strlen("ifdef")) ||
    2875                 :           !strncmp(startBuf, "ifndef", strlen("ifndef")) ||
    2876                 :           !strncmp(startBuf, "define", strlen("define")) ||
    2877                 :           !strncmp(startBuf, "undef", strlen("undef")) ||
    2878                 :           !strncmp(startBuf, "else", strlen("else")) ||
    2879                 :           !strncmp(startBuf, "elif", strlen("elif")) ||
    2880                 :           !strncmp(startBuf, "endif", strlen("endif")) ||
    2881                 :           !strncmp(startBuf, "pragma", strlen("pragma")) ||
    2882                 :           !strncmp(startBuf, "include", strlen("include")) ||
    2883                 :           !strncmp(startBuf, "import", strlen("import")) ||
    2884                 :           !strncmp(startBuf, "include_next", strlen("include_next")))
    2885                0:         return true;
    2886                 :     }
    2887              499:     startBuf++;
    2888                 :   }
    2889               21:   return false;
    2890                 : }
    2891                 : 
    2892                 : /// SynthesizeObjCInternalStruct - Rewrite one internal struct corresponding to
    2893                 : /// an objective-c class with ivars.
    2894                 : void RewriteObjC::SynthesizeObjCInternalStruct(ObjCInterfaceDecl *CDecl,
    2895               64:                                                std::string &Result) {
                        0: branch 0 not taken
                       64: branch 1 taken
    2896               64:   assert(CDecl && "Class missing in SynthesizeObjCInternalStruct");
    2897                 :   assert(CDecl->getNameAsCString() &&
                       64: branch 1 taken
                        0: branch 2 not taken
    2898               64:          "Name missing in SynthesizeObjCInternalStruct");
    2899                 :   // Do not synthesize more than once.
                       64: branch 1 taken
                        0: branch 2 not taken
    2900               64:   if (ObjCSynthesizedStructs.count(CDecl))
    2901                0:     return;
    2902               64:   ObjCInterfaceDecl *RCDecl = CDecl->getSuperClass();
    2903               64:   int NumIvars = CDecl->ivar_size();
    2904               64:   SourceLocation LocStart = CDecl->getLocStart();
    2905               64:   SourceLocation LocEnd = CDecl->getLocEnd();
    2906                 : 
    2907               64:   const char *startBuf = SM->getCharacterData(LocStart);
    2908               64:   const char *endBuf = SM->getCharacterData(LocEnd);
    2909                 : 
    2910                 :   // If no ivars and no root or if its root, directly or indirectly,
    2911                 :   // have no ivars (thus not synthesized) then no need to synthesize this class.
                       64: branch 1 taken
                        0: branch 2 not taken
                       43: branch 3 taken
                       21: branch 4 taken
                        3: branch 5 taken
                       40: branch 6 taken
                        3: branch 8 taken
                        0: branch 9 not taken
                       43: branch 10 taken
                       21: branch 11 taken
    2912               64:   if ((CDecl->isForwardDecl() || NumIvars == 0) &&
    2913                 :       (!RCDecl || !ObjCSynthesizedStructs.count(RCDecl))) {
    2914               43:     endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
    2915               43:     ReplaceText(LocStart, endBuf-startBuf, Result.c_str(), Result.size());
    2916               43:     return;
    2917                 :   }
    2918                 : 
    2919                 :   // FIXME: This has potential of causing problem. If
    2920                 :   // SynthesizeObjCInternalStruct is ever called recursively.
    2921               21:   Result += "\nstruct ";
    2922               21:   Result += CDecl->getNameAsString();
                       10: branch 0 taken
                       11: branch 1 taken
    2923               21:   if (LangOpts.Microsoft)
    2924               10:     Result += "_IMPL";
    2925                 : 
                       21: branch 0 taken
                        0: branch 1 not taken
    2926               21:   if (NumIvars > 0) {
    2927               21:     const char *cursor = strchr(startBuf, '{');
    2928                 :     assert((cursor && endBuf)
                       21: branch 0 taken
                        0: branch 1 not taken
                        0: branch 2 not taken
                       21: branch 3 taken
    2929               21:            && "SynthesizeObjCInternalStruct - malformed @interface");
    2930                 :     // If the buffer contains preprocessor directives, we do more fine-grained
    2931                 :     // rewrites. This is intended to fix code that looks like (which occurs in
    2932                 :     // NSURL.h, for example):
    2933                 :     //
    2934                 :     // #ifdef XYZ
    2935                 :     // @interface Foo : NSObject
    2936                 :     // #else
    2937                 :     // @interface FooBar : NSObject
    2938                 :     // #endif
    2939                 :     // {
    2940                 :     //    int i;
    2941                 :     // }
    2942                 :     // @end
    2943                 :     //
    2944                 :     // This clause is segregated to avoid breaking the common case.
                        0: branch 1 not taken
                       21: branch 2 taken
    2945               21:     if (BufferContainsPPDirectives(startBuf, cursor)) {
    2946                 :       SourceLocation L = RCDecl ? CDecl->getSuperClassLoc() :
                        0: branch 0 not taken
                        0: branch 1 not taken
    2947                0:                                   CDecl->getClassLoc();
    2948                0:       const char *endHeader = SM->getCharacterData(L);
    2949                0:       endHeader += Lexer::MeasureTokenLength(L, *SM, LangOpts);
    2950                 : 
                        0: branch 2 not taken
                        0: branch 3 not taken
    2951                0:       if (CDecl->protocol_begin() != CDecl->protocol_end()) {
    2952                 :         // advance to the end of the referenced protocols.
                        0: branch 0 not taken
                        0: branch 1 not taken
                        0: branch 2 not taken
                        0: branch 3 not taken
    2953                0:         while (endHeader < cursor && *endHeader != '>') endHeader++;
    2954                0:         endHeader++;
    2955                 :       }
    2956                 :       // rewrite the original header
    2957                0:       ReplaceText(LocStart, endHeader-startBuf, Result.c_str(), Result.size());
    2958                 :     } else {
    2959                 :       // rewrite the original header *without* disturbing the '{'
    2960               21:       ReplaceText(LocStart, cursor-startBuf, Result.c_str(), Result.size());
    2961                 :     }
                        4: branch 0 taken
                       17: branch 1 taken
                        1: branch 3 taken
                        3: branch 4 taken
                        1: branch 5 taken
                       20: branch 6 taken
    2962               21:     if (RCDecl && ObjCSynthesizedStructs.count(RCDecl)) {
    2963                1:       Result = "\n    struct ";
    2964                1:       Result += RCDecl->getNameAsString();
    2965                1:       Result += "_IMPL ";
    2966                1:       Result += RCDecl->getNameAsString();
    2967                1:       Result += "_IVARS;\n";
    2968                 : 
    2969                 :       // insert the super class structure definition.
    2970                 :       SourceLocation OnePastCurly =
    2971                1:         LocStart.getFileLocWithOffset(cursor-startBuf+1);
    2972                1:       InsertText(OnePastCurly, Result.c_str(), Result.size());
    2973                 :     }
    2974               21:     cursor++; // past '{'
    2975                 : 
    2976                 :     // Now comment out any visibility specifiers.
                      677: branch 0 taken
                       21: branch 1 taken
    2977              719:     while (cursor < endBuf) {
                       10: branch 0 taken
                      667: branch 1 taken
    2978              677:       if (*cursor == '@') {
    2979               10:         SourceLocation atLoc = LocStart.getFileLocWithOffset(cursor-startBuf);
    2980                 :         // Skip whitespace.
                        0: branch 0 not taken
                       10: branch 1 taken
                        0: branch 2 not taken
                       10: branch 3 taken
    2981               10:         for (++cursor; cursor[0] == ' ' || cursor[0] == '\t'; ++cursor)
    2982                 :           /*scan*/;
    2983                 : 
    2984                 :         // FIXME: presence of @public, etc. inside comment results in
    2985                 :         // this transformation as well, which is still correct c-code.
                        3: branch 1 taken
                        7: branch 2 taken
                        0: branch 4 not taken
                        3: branch 5 taken
                        0: branch 7 not taken
                        0: branch 8 not taken
                        0: branch 10 not taken
                        0: branch 11 not taken
    2986               10:         if (!strncmp(cursor, "public", strlen("public")) ||
    2987                 :             !strncmp(cursor, "private", strlen("private")) ||
    2988                 :             !strncmp(cursor, "package", strlen("package")) ||
    2989                 :             !strncmp(cursor, "protected", strlen("protected")))
    2990               10:           InsertText(atLoc, "// ", 3);
    2991                 :       }
    2992                 :       // FIXME: If there are cases where '<' is used in ivar declaration part
    2993                 :       // of user code, then scan the ivar list and use needToScanForQualifiers
    2994                 :       // for type checking.
                        0: branch 0 not taken
                      667: branch 1 taken
    2995              667:       else if (*cursor == '<') {
    2996                0:         SourceLocation atLoc = LocStart.getFileLocWithOffset(cursor-startBuf);
    2997                0:         InsertText(atLoc, "/* ", 3);
    2998                0:         cursor = strchr(cursor, '>');
    2999                0:         cursor++;
    3000                0:         atLoc = LocStart.getFileLocWithOffset(cursor-startBuf);
    3001                0:         InsertText(atLoc, " */", 3);
                        1: branch 0 taken
                      666: branch 1 taken
    3002              667:       } else if (*cursor == '^') { // rewrite block specifier.
    3003                1:         SourceLocation caretLoc = LocStart.getFileLocWithOffset(cursor-startBuf);
    3004                1:         ReplaceText(caretLoc, 1, "*", 1);
    3005                 :       }
    3006              677:       cursor++;
    3007                 :     }
    3008                 :     // Don't forget to add a ';'!!
    3009               21:     InsertText(LocEnd.getFileLocWithOffset(1), ";", 1);
    3010                 :   } else { // we don't have any instance variables - insert super struct.
    3011                0:     endBuf += Lexer::MeasureTokenLength(LocEnd, *SM, LangOpts);
    3012                0:     Result += " {\n    struct ";
    3013                0:     Result += RCDecl->getNameAsString();
    3014                0:     Result += "_IMPL ";
    3015                0:     Result += RCDecl->getNameAsString();
    3016                0:     Result += "_IVARS;\n};\n";
    3017                0:     ReplaceText(LocStart, endBuf-startBuf, Result.c_str(), Result.size());
    3018                 :   }
    3019                 :   // Mark this struct as having been generated.
                        0: branch 1 not taken
                       21: branch 2 taken
    3020               21:   if (!ObjCSynthesizedStructs.insert(CDecl))
    3021                0:     assert(false && "struct already synthesize- SynthesizeObjCInternalStruct");
    3022                 : }
    3023                 : 
    3024                 : // RewriteObjCMethodsMetaData - Rewrite methods metadata for instance or
    3025                 : /// class methods.
    3026                 : template<typename MethodIterator>
    3027                 : void RewriteObjC::RewriteObjCMethodsMetaData(MethodIterator MethodBegin,
    3028                 :                                              MethodIterator MethodEnd,
    3029                 :                                              bool Is