23 #include "llvm/ADT/Triple.h" 24 #include "llvm/Support/MemoryBuffer.h" 26 using namespace clang;
27 using namespace arcmt;
35 ListTy::iterator I = List.begin();
36 while (I != List.end()) {
39 std::find(IDs.begin(), IDs.end(), I->getID()) != IDs.end()) &&
41 (diagLoc == range.
getEnd() ||
44 ListTy::iterator eraseS = I++;
49 I = List.erase(eraseS, I);
64 ListTy::const_iterator I = List.begin();
65 while (I != List.end()) {
68 std::find(IDs.begin(), IDs.end(), I->getID()) != IDs.end()) &&
70 (diagLoc == range.
getEnd() ||
82 for (ListTy::const_iterator I = List.begin(), E = List.end(); I != E; ++I)
87 for (ListTy::const_iterator I = List.begin(), E = List.end(); I != E; ++I)
100 bool HasBegunSourceFile;
105 : Diags(diags), DiagClient(client), CapturedDiags(capturedDiags),
106 HasBegunSourceFile(
false) { }
113 if (!HasBegunSourceFile) {
115 HasBegunSourceFile =
true;
119 void FinishCapture() {
123 if (HasBegunSourceFile) {
125 HasBegunSourceFile =
false;
129 ~CaptureDiagnosticConsumer()
override {
130 assert(!HasBegunSourceFile &&
"FinishCapture not called!");
156 return triple.getOSMajorVersion() >= 5;
158 if (triple.isWatchOS())
161 if (triple.getOS() == llvm::Triple::Darwin)
162 return triple.getOSMajorVersion() >= 11;
164 if (triple.getOS() == llvm::Triple::MacOSX) {
165 unsigned Major, Minor, Micro;
166 triple.getOSVersion(Major, Minor, Micro);
167 return Major > 10 || (Major == 10 && Minor >= 7);
176 std::unique_ptr<CompilerInvocation> CInvok;
189 if (!OriginalFile.empty())
195 CInvok->getPreprocessorOpts().addMacroDef(define);
196 CInvok->getLangOpts()->ObjCAutoRefCount =
true;
198 CInvok->getDiagnosticOpts().ErrorLimit = 0;
199 CInvok->getDiagnosticOpts().PedanticErrors = 0;
202 std::vector<std::string> WarnOpts;
203 for (std::vector<std::string>::iterator
204 I = CInvok->getDiagnosticOpts().Warnings.begin(),
205 E = CInvok->getDiagnosticOpts().Warnings.end(); I != E; ++I) {
206 if (!StringRef(*I).startswith(
"error"))
207 WarnOpts.push_back(*I);
209 WarnOpts.push_back(
"error=arc-unsafe-retained-assign");
210 CInvok->getDiagnosticOpts().Warnings = std::move(WarnOpts);
212 CInvok->getLangOpts()->ObjCWeakRuntime =
HasARCRuntime(origCI);
213 CInvok->getLangOpts()->ObjCWeak = CInvok->getLangOpts()->ObjCWeakRuntime;
215 return CInvok.release();
239 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
241 StringRef plistOut) {
251 assert(!transforms.empty());
253 std::unique_ptr<CompilerInvocation> CInvok;
256 CInvok->getFrontendOpts().Inputs.clear();
257 CInvok->getFrontendOpts().Inputs.push_back(Input);
268 CaptureDiagnosticConsumer errRec(*Diags, *DiagClient, capturedDiags);
269 Diags->setClient(&errRec,
false);
272 std::move(CInvok), PCHContainerOps, Diags));
274 errRec.FinishCapture();
279 Diags->setClient(DiagClient,
false);
283 if (Diags->hasFatalErrorOccurred()) {
288 errRec.FinishCapture();
292 if (emitPremigrationARCErrors)
294 Unit->getPreprocessor());
295 if (!plistOut.empty()) {
298 I = capturedDiags.
begin(), E = capturedDiags.
end(); I != E; ++I)
299 arcDiags.push_back(*I);
313 std::vector<SourceLocation> ARCMTMacroLocs;
315 TransformActions testAct(*Diags, capturedDiags, Ctx, Unit->getPreprocessor());
316 MigrationPass pass(Ctx, OrigGCMode, Unit->getSema(), testAct, capturedDiags,
319 if (!NoNSAllocReallocError)
323 for (
unsigned i=0, e = transforms.size(); i != e; ++i)
326 capturedDiags.reportDiagnostics(*Diags);
329 errRec.FinishCapture();
331 return capturedDiags.hasErrors() || testAct.hasReportedErrors();
340 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
342 bool emitPremigrationARCErrors, StringRef plistOut) {
351 DiagClient, emitPremigrationARCErrors,
364 assert(!transforms.empty());
366 for (
unsigned i=0, e = transforms.size(); i != e; ++i) {
368 if (err)
return true;
376 if (outputDir.empty()) {
386 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
389 StringRef(),
false, StringRef());
394 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
396 bool emitPremigrationARCErrors, StringRef plistOut) {
397 assert(!outputDir.empty() &&
"Expected output directory path");
398 return applyTransforms(origCI, Input, PCHContainerOps, DiagClient, outputDir,
399 emitPremigrationARCErrors, plistOut);
406 assert(!outputDir.empty());
433 class ARCMTMacroTrackerPPCallbacks :
public PPCallbacks {
434 std::vector<SourceLocation> &ARCMTMacroLocs;
437 ARCMTMacroTrackerPPCallbacks(std::vector<SourceLocation> &ARCMTMacroLocs)
438 : ARCMTMacroLocs(ARCMTMacroLocs) { }
443 ARCMTMacroLocs.push_back(MacroNameTok.
getLocation());
448 std::vector<SourceLocation> &ARCMTMacroLocs;
451 ARCMTMacroTrackerAction(std::vector<SourceLocation> &ARCMTMacroLocs)
452 : ARCMTMacroLocs(ARCMTMacroLocs) { }
455 StringRef InFile)
override {
457 llvm::make_unique<ARCMTMacroTrackerPPCallbacks>(ARCMTMacroLocs));
458 return llvm::make_unique<ASTConsumer>();
469 : rewriter(rewriter), Listener(listener) {
471 Listener->
start(ctx);
473 ~RewritesApplicator()
override {
479 bool err = rewriter.
InsertText(loc, text,
true,
481 if (!err && Listener)
482 Listener->
insert(loc, text);
491 bool err = rewriter.
RemoveText(range, removeOpts);
492 if (!err && Listener)
509 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
511 : OrigCI(CI), PCHContainerOps(
std::move(PCHContainerOps)),
512 DiagClient(diagClient), HadARCErrors(
false) {
513 if (!outputDir.empty()) {
524 std::unique_ptr<CompilerInvocation> CInvok;
527 CInvok->getDiagnosticOpts().IgnoreWarnings =
true;
532 std::vector<SourceLocation> ARCMTMacroLocs;
541 CaptureDiagnosticConsumer errRec(*Diags, *DiagClient, capturedDiags);
542 Diags->setClient(&errRec,
false);
544 std::unique_ptr<ARCMTMacroTrackerAction> ASTAction;
545 ASTAction.reset(
new ARCMTMacroTrackerAction(ARCMTMacroLocs));
548 std::move(CInvok), PCHContainerOps, Diags, ASTAction.get()));
550 errRec.FinishCapture();
553 Unit->setOwnsRemappedFileBuffers(
false);
558 Diags->setClient(DiagClient,
false);
562 if (Diags->hasFatalErrorOccurred()) {
567 errRec.FinishCapture();
581 Unit->getSema(), TA, capturedDiags, ARCMTMacroLocs);
586 RewritesApplicator applicator(rewriter, Ctx, listener);
587 TA.applyRewrites(applicator);
591 errRec.FinishCapture();
597 I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) {
602 std::string newFname = file->
getName();
603 newFname +=
"-trans";
605 llvm::raw_svector_ostream vecOS(newText);
607 std::unique_ptr<llvm::MemoryBuffer> memBuf(
608 llvm::MemoryBuffer::getMemBufferCopy(
609 StringRef(newText.data(), newText.size()), newFname));
611 Unit->getFileManager().FixupRelativePath(filePath);
612 Remapper.
remap(filePath.str(), std::move(memBuf));
unsigned NoFinalizeRemoval
bool IncreaseIndentation(CharSourceRange range, SourceLocation parentIndent)
Increase indentation for the lines between the given source range.
Implements support for file system lookup, file system caching, and directory search management...
TargetOptions & getTargetOpts()
ListTy::const_iterator iterator
static StringRef getARCMTMacroName()
Represents a diagnostic in a form that can be retained until its corresponding source manager is dest...
bool applyTransformations(CompilerInvocation &origCI, const FrontendInputFile &Input, std::shared_ptr< PCHContainerOperations > PCHContainerOps, DiagnosticConsumer *DiagClient)
Works similar to checkForManualIssues but instead of checking, it applies automatic modifications to ...
std::vector< std::string > Includes
A description of the current definition of a macro.
StringRef getOriginalSourceFile()
Retrieve the name of the original source file name for the primary module file.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
void push_back(const StoredDiagnostic &diag)
PreprocessorOptions - This class is used for passing the various options used in preprocessor initial...
bool RemoveText(SourceLocation Start, unsigned Length, RewriteOptions opts=RewriteOptions())
RemoveText - Remove the specified text region.
bool hasDiagnostic(ArrayRef< unsigned > IDs, SourceRange range) const
virtual void EndSourceFile()
Callback to inform the diagnostic client that processing of a source file has ended.
void applyMappings(PreprocessorOptions &PPOpts) const
Abstract interface, implemented by clients of the front-end, which formats and prints fully processed...
RewriteBuffer - As code is rewritten, SourceBuffer's from the original input with modifications get a...
This interface provides a way to observe the actions of the preprocessor as it does its thing...
void setNoFinalizeRemoval(bool val)
virtual ~RewriteListener()
Anchor for VTable.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
unsigned getNumErrors() const
Token - This structure provides full information about a lexed token.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
const LangOptions & getLangOpts() const
bool clearDiagnostic(ArrayRef< unsigned > IDs, SourceRange range)
void remap(StringRef filePath, std::unique_ptr< llvm::MemoryBuffer > memBuf)
const SourceLocation & getLocation() const
void reportDiagnostics(DiagnosticsEngine &diags) const
void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) override
Callback to inform the diagnostic client that processing of a source file is beginning.
Concrete class used by the front-end to report problems and issues.
static void emitPremigrationErrors(const CapturedDiagList &arcDiags, DiagnosticOptions *diagOpts, Preprocessor &PP)
virtual void remove(CharSourceRange range)
Present this diagnostic as an error.
This abstract interface provides operations for unwrapping containers for serialized ASTs (precompile...
FrontendOptions & getFrontendOpts()
MigratorOptions & getMigratorOpts()
Represents a character-granular source range.
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
MacroArgs - An instance of this class captures information about the formal arguments specified to a ...
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
Defines the clang::Preprocessor interface.
void writeARCDiagsToPlist(const std::string &outPath, ArrayRef< StoredDiagnostic > diags, SourceManager &SM, const LangOptions &LangOpts)
static bool applyTransforms(CompilerInvocation &origCI, const FrontendInputFile &Input, std::shared_ptr< PCHContainerOperations > PCHContainerOps, DiagnosticConsumer *DiagClient, StringRef outputDir, bool emitPremigrationARCErrors, StringRef plistOut)
bool checkForManualIssues(CompilerInvocation &CI, const FrontendInputFile &Input, std::shared_ptr< PCHContainerOperations > PCHContainerOps, DiagnosticConsumer *DiagClient, bool emitPremigrationARCErrors=false, StringRef plistOut=StringRef())
Creates an AST with the provided CompilerInvocation but with these changes: -if a PCH/PTH is set...
static bool HasARCRuntime(CompilerInvocation &origCI)
void EndSourceFile() override
Callback to inform the diagnostic client that processing of a source file has ended.
MigrationProcess(const CompilerInvocation &CI, std::shared_ptr< PCHContainerOperations > PCHContainerOps, DiagnosticConsumer *diagClient, StringRef outputDir=StringRef())
SourceLocation getEnd() const
unsigned NoNSAllocReallocError
virtual void insert(SourceLocation loc, StringRef text)
SourceManager & getSourceManager() const
static CompilerInvocation * createInvocationForMigration(CompilerInvocation &origCI, const PCHContainerReader &PCHContainerRdr)
bool overwriteOriginal(DiagnosticsEngine &Diag, StringRef outputDir=StringRef())
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
Encodes a location in the source.
bool isBeforeInTranslationUnitThan(SourceLocation Loc) const
Determines the order of 2 source locations in the translation unit.
raw_ostream & write(raw_ostream &Stream) const
Write to Stream the result of applying all changes to the original buffer.
StringRef getName() const
std::string ImplicitPCHInclude
The implicit PCH included at the start of the translation unit, or empty.
bool flushToDisk(StringRef outputDir, DiagnosticsEngine &Diag)
Options for controlling the compiler diagnostics engine.
std::vector< FrontendInputFile > Inputs
The input files and their types.
IdentifierInfo * getIdentifierInfo() const
Cached information about one file (either on disk or in the virtual file system). ...
bool InsertText(SourceLocation Loc, StringRef Str, bool InsertAfter=true, bool indentNewLines=false)
InsertText - Insert the specified string at the specified location in the original buffer...
Abstract base class to use for AST consumer-based frontend actions.
DiagnosticOptions & getDiagnosticOpts() const
bool RemoveLineIfEmpty
If true and removing some text leaves a blank line also remove the empty line (false by default)...
bool migrateWithTemporaryFiles(CompilerInvocation &origCI, const FrontendInputFile &Input, std::shared_ptr< PCHContainerOperations > PCHContainerOps, DiagnosticConsumer *DiagClient, StringRef outputDir, bool emitPremigrationARCErrors, StringRef plistOut)
Applies automatic modifications and produces temporary files and metadata into the outputDir path...
std::map< FileID, RewriteBuffer >::iterator buffer_iterator
static ASTUnit * LoadFromCompilerInvocationAction(std::shared_ptr< CompilerInvocation > CI, std::shared_ptr< PCHContainerOperations > PCHContainerOps, IntrusiveRefCntPtr< DiagnosticsEngine > Diags, FrontendAction *Action=nullptr, ASTUnit *Unit=nullptr, bool Persistent=true, StringRef ResourceFilesPath=StringRef(), bool OnlyLocalDecls=false, bool CaptureDiagnostics=false, unsigned PrecompilePreambleAfterNParses=0, bool CacheCodeCompletionResults=false, bool IncludeBriefCommentsInCodeCompletion=false, bool UserFilesAreVolatile=false, std::unique_ptr< ASTUnit > *ErrAST=nullptr)
Create an ASTUnit from a source file, via a CompilerInvocation object, by invoking the optionally pro...
void setLastDiagnosticIgnored(bool Ignored=true)
Pretend that the last diagnostic issued was ignored, so any subsequent notes will be suppressed...
void(* TransformFn)(MigrationPass &pass)
StringRef getName() const
Return the actual identifier string.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Dataflow Directional Tag Classes.
A diagnostic client that ignores all diagnostics.
bool isValid() const
Return true if this is a valid SourceLocation object.
std::vector< TransformFn > getAllTransformations(LangOptions::GCMode OrigGCMode, bool NoFinalizeRemoval)
Used for handling and querying diagnostic IDs.
Helper class for holding the data necessary to invoke the compiler.
virtual void start(ASTContext &Ctx)
bool IncludeInsertsAtBeginOfRange
Given a source range, true to include previous inserts at the beginning of the range as part of the r...
SourceManager & getSourceManager()
Preprocessor & getPreprocessor() const
Return the current preprocessor.
bool initFromDisk(StringRef outputDir, DiagnosticsEngine &Diag, bool ignoreIfFilesChanged)
Rewriter - This is the main interface to the rewrite buffers.
static bool isARCDiagnostic(unsigned DiagID)
Return true if a given diagnostic falls into an ARC diagnostic category.
Level
The level of the diagnostic, after it has been through mapping.
FileSystemOptions & getFileSystemOpts()
std::vector< std::pair< std::string, std::string > > RemappedFiles
The set of file remappings, which take existing files on the system (the first part of each pair) and...
A little helper class (which is basically a smart pointer that forwards info from DiagnosticsEngine) ...
FileRemapper & getRemapper()
A SourceLocation and its associated SourceManager.
Defines the clang::FrontendAction interface and various convenience abstract classes (clang::ASTFront...
bool applyTransform(TransformFn trans, RewriteListener *listener=nullptr)
A trivial tuple used to represent a source range.
LangOptions * getLangOpts()
virtual void BeginSourceFile(const LangOptions &LangOpts, const Preprocessor *PP=nullptr)
Callback to inform the diagnostic client that processing of a source file is beginning.
SourceLocation getBegin() const
std::string Triple
The name of the target triple to compile for.
const LangOptions & getLangOpts() const
bool getFileRemappings(std::vector< std::pair< std::string, std::string > > &remap, StringRef outputDir, DiagnosticConsumer *DiagClient)
Get the set of file remappings from the outputDir path that migrateWithTemporaryFiles produced...
void addPPCallbacks(std::unique_ptr< PPCallbacks > C)
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
bool IncludeInsertsAtEndOfRange
Given a source range, true to include previous inserts at the end of the range as part of the range i...