130660a898545416f0fea2d717f16f75640001e38Ted Kremenek//===--- ObjCMT.cpp - ObjC Migrate Tool -----------------------------------===//
230660a898545416f0fea2d717f16f75640001e38Ted Kremenek//
330660a898545416f0fea2d717f16f75640001e38Ted Kremenek//                     The LLVM Compiler Infrastructure
430660a898545416f0fea2d717f16f75640001e38Ted Kremenek//
530660a898545416f0fea2d717f16f75640001e38Ted Kremenek// This file is distributed under the University of Illinois Open Source
630660a898545416f0fea2d717f16f75640001e38Ted Kremenek// License. See LICENSE.TXT for details.
730660a898545416f0fea2d717f16f75640001e38Ted Kremenek//
830660a898545416f0fea2d717f16f75640001e38Ted Kremenek//===----------------------------------------------------------------------===//
930660a898545416f0fea2d717f16f75640001e38Ted Kremenek
1030660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/ARCMigrate/ARCMTActions.h"
1130660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Frontend/CompilerInstance.h"
1230660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Frontend/MultiplexConsumer.h"
1330660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/AST/RecursiveASTVisitor.h"
1430660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/AST/NSAPI.h"
1530660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/AST/ASTConsumer.h"
1630660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Edit/Rewriters.h"
1730660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Edit/EditedSource.h"
1830660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Edit/Commit.h"
1930660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Edit/EditsReceiver.h"
2030660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Rewrite/Rewriter.h"
2130660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Lex/Preprocessor.h"
2230660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "clang/Basic/FileManager.h"
2330660a898545416f0fea2d717f16f75640001e38Ted Kremenek#include "llvm/ADT/SmallString.h"
2430660a898545416f0fea2d717f16f75640001e38Ted Kremenek
2530660a898545416f0fea2d717f16f75640001e38Ted Kremenekusing namespace clang;
2630660a898545416f0fea2d717f16f75640001e38Ted Kremenekusing namespace arcmt;
2730660a898545416f0fea2d717f16f75640001e38Ted Kremenek
2830660a898545416f0fea2d717f16f75640001e38Ted Kremeneknamespace {
2930660a898545416f0fea2d717f16f75640001e38Ted Kremenek
3030660a898545416f0fea2d717f16f75640001e38Ted Kremenekclass ObjCMigrateASTConsumer : public ASTConsumer {
3130660a898545416f0fea2d717f16f75640001e38Ted Kremenek  void migrateDecl(Decl *D);
3230660a898545416f0fea2d717f16f75640001e38Ted Kremenek
3330660a898545416f0fea2d717f16f75640001e38Ted Kremenekpublic:
3430660a898545416f0fea2d717f16f75640001e38Ted Kremenek  std::string MigrateDir;
3530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  bool MigrateLiterals;
3630660a898545416f0fea2d717f16f75640001e38Ted Kremenek  bool MigrateSubscripting;
3730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  llvm::OwningPtr<NSAPI> NSAPIObj;
3830660a898545416f0fea2d717f16f75640001e38Ted Kremenek  llvm::OwningPtr<edit::EditedSource> Editor;
3930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  FileRemapper &Remapper;
4030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  FileManager &FileMgr;
4130660a898545416f0fea2d717f16f75640001e38Ted Kremenek  const PreprocessingRecord *PPRec;
4230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  bool IsOutputFile;
4330660a898545416f0fea2d717f16f75640001e38Ted Kremenek
4430660a898545416f0fea2d717f16f75640001e38Ted Kremenek  ObjCMigrateASTConsumer(StringRef migrateDir,
4530660a898545416f0fea2d717f16f75640001e38Ted Kremenek                         bool migrateLiterals,
4630660a898545416f0fea2d717f16f75640001e38Ted Kremenek                         bool migrateSubscripting,
4730660a898545416f0fea2d717f16f75640001e38Ted Kremenek                         FileRemapper &remapper,
4830660a898545416f0fea2d717f16f75640001e38Ted Kremenek                         FileManager &fileMgr,
4930660a898545416f0fea2d717f16f75640001e38Ted Kremenek                         const PreprocessingRecord *PPRec,
5030660a898545416f0fea2d717f16f75640001e38Ted Kremenek                         bool isOutputFile = false)
5130660a898545416f0fea2d717f16f75640001e38Ted Kremenek  : MigrateDir(migrateDir),
5230660a898545416f0fea2d717f16f75640001e38Ted Kremenek    MigrateLiterals(migrateLiterals),
5330660a898545416f0fea2d717f16f75640001e38Ted Kremenek    MigrateSubscripting(migrateSubscripting),
5430660a898545416f0fea2d717f16f75640001e38Ted Kremenek    Remapper(remapper), FileMgr(fileMgr), PPRec(PPRec),
5530660a898545416f0fea2d717f16f75640001e38Ted Kremenek    IsOutputFile(isOutputFile) { }
5630660a898545416f0fea2d717f16f75640001e38Ted Kremenek
5730660a898545416f0fea2d717f16f75640001e38Ted Kremenekprotected:
5830660a898545416f0fea2d717f16f75640001e38Ted Kremenek  virtual void Initialize(ASTContext &Context) {
5930660a898545416f0fea2d717f16f75640001e38Ted Kremenek    NSAPIObj.reset(new NSAPI(Context));
6030660a898545416f0fea2d717f16f75640001e38Ted Kremenek    Editor.reset(new edit::EditedSource(Context.getSourceManager(),
614e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie                                        Context.getLangOpts(),
6230660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                        PPRec));
6330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
6430660a898545416f0fea2d717f16f75640001e38Ted Kremenek
6530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  virtual bool HandleTopLevelDecl(DeclGroupRef DG) {
6630660a898545416f0fea2d717f16f75640001e38Ted Kremenek    for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I)
6730660a898545416f0fea2d717f16f75640001e38Ted Kremenek      migrateDecl(*I);
6830660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return true;
6930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
7030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  virtual void HandleInterestingDecl(DeclGroupRef DG) {
7130660a898545416f0fea2d717f16f75640001e38Ted Kremenek    // Ignore decls from the PCH.
7230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
7330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) {
7430660a898545416f0fea2d717f16f75640001e38Ted Kremenek    ObjCMigrateASTConsumer::HandleTopLevelDecl(DG);
7530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
7630660a898545416f0fea2d717f16f75640001e38Ted Kremenek
7730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  virtual void HandleTranslationUnit(ASTContext &Ctx);
7830660a898545416f0fea2d717f16f75640001e38Ted Kremenek};
7930660a898545416f0fea2d717f16f75640001e38Ted Kremenek
8030660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
8130660a898545416f0fea2d717f16f75640001e38Ted Kremenek
8230660a898545416f0fea2d717f16f75640001e38Ted KremenekObjCMigrateAction::ObjCMigrateAction(FrontendAction *WrappedAction,
8330660a898545416f0fea2d717f16f75640001e38Ted Kremenek                             StringRef migrateDir,
8430660a898545416f0fea2d717f16f75640001e38Ted Kremenek                             bool migrateLiterals,
8530660a898545416f0fea2d717f16f75640001e38Ted Kremenek                             bool migrateSubscripting)
8630660a898545416f0fea2d717f16f75640001e38Ted Kremenek  : WrapperFrontendAction(WrappedAction), MigrateDir(migrateDir),
8730660a898545416f0fea2d717f16f75640001e38Ted Kremenek    MigrateLiterals(migrateLiterals), MigrateSubscripting(migrateSubscripting),
8830660a898545416f0fea2d717f16f75640001e38Ted Kremenek    CompInst(0) {
8930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (MigrateDir.empty())
9030660a898545416f0fea2d717f16f75640001e38Ted Kremenek    MigrateDir = "."; // user current directory if none is given.
9130660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
9230660a898545416f0fea2d717f16f75640001e38Ted Kremenek
9330660a898545416f0fea2d717f16f75640001e38Ted KremenekASTConsumer *ObjCMigrateAction::CreateASTConsumer(CompilerInstance &CI,
9430660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                                  StringRef InFile) {
9530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  ASTConsumer *
9630660a898545416f0fea2d717f16f75640001e38Ted Kremenek    WrappedConsumer = WrapperFrontendAction::CreateASTConsumer(CI, InFile);
9730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  ASTConsumer *MTConsumer = new ObjCMigrateASTConsumer(MigrateDir,
9830660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                                       MigrateLiterals,
9930660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                                       MigrateSubscripting,
10030660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                                       Remapper,
10130660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                                    CompInst->getFileManager(),
10230660a898545416f0fea2d717f16f75640001e38Ted Kremenek                          CompInst->getPreprocessor().getPreprocessingRecord());
10330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  ASTConsumer *Consumers[] = { MTConsumer, WrappedConsumer };
10430660a898545416f0fea2d717f16f75640001e38Ted Kremenek  return new MultiplexConsumer(Consumers);
10530660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
10630660a898545416f0fea2d717f16f75640001e38Ted Kremenek
10730660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool ObjCMigrateAction::BeginInvocation(CompilerInstance &CI) {
10830660a898545416f0fea2d717f16f75640001e38Ted Kremenek  Remapper.initFromDisk(MigrateDir, CI.getDiagnostics(),
10930660a898545416f0fea2d717f16f75640001e38Ted Kremenek                        /*ignoreIfFilesChanges=*/true);
11030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  CompInst = &CI;
11130660a898545416f0fea2d717f16f75640001e38Ted Kremenek  CI.getDiagnostics().setIgnoreAllWarnings(true);
11230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  CI.getPreprocessorOpts().DetailedRecord = true;
11330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  CI.getPreprocessorOpts().DetailedRecordConditionalDirectives = true;
11430660a898545416f0fea2d717f16f75640001e38Ted Kremenek  return true;
11530660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
11630660a898545416f0fea2d717f16f75640001e38Ted Kremenek
11730660a898545416f0fea2d717f16f75640001e38Ted Kremeneknamespace {
11830660a898545416f0fea2d717f16f75640001e38Ted Kremenekclass ObjCMigrator : public RecursiveASTVisitor<ObjCMigrator> {
11930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  ObjCMigrateASTConsumer &Consumer;
12030660a898545416f0fea2d717f16f75640001e38Ted Kremenek
12130660a898545416f0fea2d717f16f75640001e38Ted Kremenekpublic:
12230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  ObjCMigrator(ObjCMigrateASTConsumer &consumer) : Consumer(consumer) { }
12330660a898545416f0fea2d717f16f75640001e38Ted Kremenek
12430660a898545416f0fea2d717f16f75640001e38Ted Kremenek  bool shouldVisitTemplateInstantiations() const { return false; }
12530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  bool shouldWalkTypesOfTypeLocs() const { return false; }
12630660a898545416f0fea2d717f16f75640001e38Ted Kremenek
12730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
12830660a898545416f0fea2d717f16f75640001e38Ted Kremenek    if (Consumer.MigrateLiterals) {
12930660a898545416f0fea2d717f16f75640001e38Ted Kremenek      edit::Commit commit(*Consumer.Editor);
13030660a898545416f0fea2d717f16f75640001e38Ted Kremenek      edit::rewriteToObjCLiteralSyntax(E, *Consumer.NSAPIObj, commit);
13130660a898545416f0fea2d717f16f75640001e38Ted Kremenek      Consumer.Editor->commit(commit);
13230660a898545416f0fea2d717f16f75640001e38Ted Kremenek    }
13330660a898545416f0fea2d717f16f75640001e38Ted Kremenek
13430660a898545416f0fea2d717f16f75640001e38Ted Kremenek    if (Consumer.MigrateSubscripting) {
13530660a898545416f0fea2d717f16f75640001e38Ted Kremenek      edit::Commit commit(*Consumer.Editor);
13630660a898545416f0fea2d717f16f75640001e38Ted Kremenek      edit::rewriteToObjCSubscriptSyntax(E, *Consumer.NSAPIObj, commit);
13730660a898545416f0fea2d717f16f75640001e38Ted Kremenek      Consumer.Editor->commit(commit);
13830660a898545416f0fea2d717f16f75640001e38Ted Kremenek    }
13930660a898545416f0fea2d717f16f75640001e38Ted Kremenek
14030660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return true;
14130660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
14230660a898545416f0fea2d717f16f75640001e38Ted Kremenek
14330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  bool TraverseObjCMessageExpr(ObjCMessageExpr *E) {
14430660a898545416f0fea2d717f16f75640001e38Ted Kremenek    // Do depth first; we want to rewrite the subexpressions first so that if
14530660a898545416f0fea2d717f16f75640001e38Ted Kremenek    // we have to move expressions we will move them already rewritten.
14630660a898545416f0fea2d717f16f75640001e38Ted Kremenek    for (Stmt::child_range range = E->children(); range; ++range)
14730660a898545416f0fea2d717f16f75640001e38Ted Kremenek      if (!TraverseStmt(*range))
14830660a898545416f0fea2d717f16f75640001e38Ted Kremenek        return false;
14930660a898545416f0fea2d717f16f75640001e38Ted Kremenek
15030660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return WalkUpFromObjCMessageExpr(E);
15130660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
15230660a898545416f0fea2d717f16f75640001e38Ted Kremenek};
15330660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
15430660a898545416f0fea2d717f16f75640001e38Ted Kremenek
15530660a898545416f0fea2d717f16f75640001e38Ted Kremenekvoid ObjCMigrateASTConsumer::migrateDecl(Decl *D) {
15630660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (!D)
15730660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return;
15830660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (isa<ObjCMethodDecl>(D))
15930660a898545416f0fea2d717f16f75640001e38Ted Kremenek    return; // Wait for the ObjC container declaration.
16030660a898545416f0fea2d717f16f75640001e38Ted Kremenek
16130660a898545416f0fea2d717f16f75640001e38Ted Kremenek  ObjCMigrator(*this).TraverseDecl(D);
16230660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
16330660a898545416f0fea2d717f16f75640001e38Ted Kremenek
16430660a898545416f0fea2d717f16f75640001e38Ted Kremeneknamespace {
16530660a898545416f0fea2d717f16f75640001e38Ted Kremenek
16630660a898545416f0fea2d717f16f75640001e38Ted Kremenekclass RewritesReceiver : public edit::EditsReceiver {
16730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  Rewriter &Rewrite;
16830660a898545416f0fea2d717f16f75640001e38Ted Kremenek
16930660a898545416f0fea2d717f16f75640001e38Ted Kremenekpublic:
17030660a898545416f0fea2d717f16f75640001e38Ted Kremenek  RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) { }
17130660a898545416f0fea2d717f16f75640001e38Ted Kremenek
17230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  virtual void insert(SourceLocation loc, StringRef text) {
17330660a898545416f0fea2d717f16f75640001e38Ted Kremenek    Rewrite.InsertText(loc, text);
17430660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
17530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  virtual void replace(CharSourceRange range, StringRef text) {
17630660a898545416f0fea2d717f16f75640001e38Ted Kremenek    Rewrite.ReplaceText(range.getBegin(), Rewrite.getRangeSize(range), text);
17730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
17830660a898545416f0fea2d717f16f75640001e38Ted Kremenek};
17930660a898545416f0fea2d717f16f75640001e38Ted Kremenek
18030660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
18130660a898545416f0fea2d717f16f75640001e38Ted Kremenek
18230660a898545416f0fea2d717f16f75640001e38Ted Kremenekvoid ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) {
1834e4d08403ca5cfd4d558fa2936215d3a4e5a528dDavid Blaikie  Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts());
18430660a898545416f0fea2d717f16f75640001e38Ted Kremenek  RewritesReceiver Rec(rewriter);
18530660a898545416f0fea2d717f16f75640001e38Ted Kremenek  Editor->applyRewrites(Rec);
18630660a898545416f0fea2d717f16f75640001e38Ted Kremenek
18730660a898545416f0fea2d717f16f75640001e38Ted Kremenek  for (Rewriter::buffer_iterator
18830660a898545416f0fea2d717f16f75640001e38Ted Kremenek        I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) {
18930660a898545416f0fea2d717f16f75640001e38Ted Kremenek    FileID FID = I->first;
19030660a898545416f0fea2d717f16f75640001e38Ted Kremenek    RewriteBuffer &buf = I->second;
19130660a898545416f0fea2d717f16f75640001e38Ted Kremenek    const FileEntry *file = Ctx.getSourceManager().getFileEntryForID(FID);
19230660a898545416f0fea2d717f16f75640001e38Ted Kremenek    assert(file);
19330660a898545416f0fea2d717f16f75640001e38Ted Kremenek    llvm::SmallString<512> newText;
19430660a898545416f0fea2d717f16f75640001e38Ted Kremenek    llvm::raw_svector_ostream vecOS(newText);
19530660a898545416f0fea2d717f16f75640001e38Ted Kremenek    buf.write(vecOS);
19630660a898545416f0fea2d717f16f75640001e38Ted Kremenek    vecOS.flush();
19730660a898545416f0fea2d717f16f75640001e38Ted Kremenek    llvm::MemoryBuffer *memBuf = llvm::MemoryBuffer::getMemBufferCopy(
19830660a898545416f0fea2d717f16f75640001e38Ted Kremenek                   StringRef(newText.data(), newText.size()), file->getName());
19930660a898545416f0fea2d717f16f75640001e38Ted Kremenek    llvm::SmallString<64> filePath(file->getName());
20030660a898545416f0fea2d717f16f75640001e38Ted Kremenek    FileMgr.FixupRelativePath(filePath);
20130660a898545416f0fea2d717f16f75640001e38Ted Kremenek    Remapper.remap(filePath.str(), memBuf);
20230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
20330660a898545416f0fea2d717f16f75640001e38Ted Kremenek
20430660a898545416f0fea2d717f16f75640001e38Ted Kremenek  if (IsOutputFile) {
20530660a898545416f0fea2d717f16f75640001e38Ted Kremenek    Remapper.flushToFile(MigrateDir, Ctx.getDiagnostics());
20630660a898545416f0fea2d717f16f75640001e38Ted Kremenek  } else {
20730660a898545416f0fea2d717f16f75640001e38Ted Kremenek    Remapper.flushToDisk(MigrateDir, Ctx.getDiagnostics());
20830660a898545416f0fea2d717f16f75640001e38Ted Kremenek  }
20930660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
21030660a898545416f0fea2d717f16f75640001e38Ted Kremenek
21130660a898545416f0fea2d717f16f75640001e38Ted Kremenekbool MigrateSourceAction::BeginInvocation(CompilerInstance &CI) {
21230660a898545416f0fea2d717f16f75640001e38Ted Kremenek  CI.getPreprocessorOpts().DetailedRecord = true;
21330660a898545416f0fea2d717f16f75640001e38Ted Kremenek  CI.getPreprocessorOpts().DetailedRecordConditionalDirectives = true;
21430660a898545416f0fea2d717f16f75640001e38Ted Kremenek  return true;
21530660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
21630660a898545416f0fea2d717f16f75640001e38Ted Kremenek
21730660a898545416f0fea2d717f16f75640001e38Ted KremenekASTConsumer *MigrateSourceAction::CreateASTConsumer(CompilerInstance &CI,
21830660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                                  StringRef InFile) {
21930660a898545416f0fea2d717f16f75640001e38Ted Kremenek  return new ObjCMigrateASTConsumer(CI.getFrontendOpts().OutputFile,
22030660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                    /*MigrateLiterals=*/true,
22130660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                    /*MigrateSubscripting=*/true,
22230660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                    Remapper,
22330660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                    CI.getFileManager(),
22430660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                  CI.getPreprocessor().getPreprocessingRecord(),
22530660a898545416f0fea2d717f16f75640001e38Ted Kremenek                                    /*isOutputFile=*/true);
22630660a898545416f0fea2d717f16f75640001e38Ted Kremenek}
227