23#include "llvm/Support/MemoryBuffer.h"
24#include "llvm/TargetParser/Triple.h"
31 if (range.isInvalid())
35 ListTy::iterator I = List.begin();
36 while (I != List.end()) {
39 llvm::is_contained(IDs, I->getID())) &&
41 (diagLoc == range.getEnd() ||
44 ListTy::iterator eraseS = I++;
49 I = List.erase(eraseS, I);
61 if (range.isInvalid())
64 ListTy::const_iterator I = List.begin();
65 while (I != List.end()) {
68 llvm::is_contained(IDs, I->getID())) &&
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 return triple.getOSVersion() >= VersionTuple(10, 7);
174 std::unique_ptr<CompilerInvocation> CInvok;
187 if (!OriginalFile.empty())
193 CInvok->getPreprocessorOpts().addMacroDef(define);
194 CInvok->getLangOpts().ObjCAutoRefCount =
true;
196 CInvok->getDiagnosticOpts().ErrorLimit = 0;
197 CInvok->getDiagnosticOpts().PedanticErrors = 0;
200 std::vector<std::string> WarnOpts;
201 for (std::vector<std::string>::iterator
202 I = CInvok->getDiagnosticOpts().Warnings.begin(),
203 E = CInvok->getDiagnosticOpts().Warnings.end(); I !=
E; ++I) {
204 if (!StringRef(*I).starts_with(
"error"))
205 WarnOpts.push_back(*I);
207 WarnOpts.push_back(
"error=arc-unsafe-retained-assign");
208 CInvok->getDiagnosticOpts().Warnings = std::move(WarnOpts);
210 CInvok->getLangOpts().ObjCWeakRuntime =
HasARCRuntime(origCI);
211 CInvok->getLangOpts().ObjCWeak = CInvok->getLangOpts().ObjCWeakRuntime;
213 return CInvok.release();
237 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
239 StringRef plistOut) {
249 assert(!transforms.empty());
251 std::unique_ptr<CompilerInvocation> CInvok;
254 CInvok->getFrontendOpts().Inputs.clear();
255 CInvok->getFrontendOpts().Inputs.push_back(Input);
266 CaptureDiagnosticConsumer errRec(*Diags, *DiagClient, capturedDiags);
267 Diags->setClient(&errRec,
false);
270 std::move(CInvok), PCHContainerOps, Diags));
272 errRec.FinishCapture();
277 Diags->setClient(DiagClient,
false);
281 if (Diags->hasFatalErrorOccurred()) {
286 errRec.FinishCapture();
290 if (emitPremigrationARCErrors)
292 Unit->getPreprocessor());
293 if (!plistOut.empty()) {
296 I = capturedDiags.
begin(),
E = capturedDiags.
end(); I !=
E; ++I)
297 arcDiags.push_back(*I);
311 std::vector<SourceLocation> ARCMTMacroLocs;
313 TransformActions testAct(*Diags, capturedDiags, Ctx, Unit->getPreprocessor());
314 MigrationPass pass(Ctx, OrigGCMode, Unit->getSema(), testAct, capturedDiags,
317 if (!NoNSAllocReallocError)
321 for (
unsigned i=0, e = transforms.size(); i != e; ++i)
327 errRec.FinishCapture();
338 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
340 bool emitPremigrationARCErrors, StringRef plistOut) {
349 DiagClient, emitPremigrationARCErrors,
362 assert(!transforms.empty());
364 for (
unsigned i=0, e = transforms.size(); i != e; ++i) {
366 if (err)
return true;
374 if (outputDir.empty()) {
384 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
387 StringRef(),
false, StringRef());
392 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
394 bool emitPremigrationARCErrors, StringRef plistOut) {
395 assert(!outputDir.empty() &&
"Expected output directory path");
396 return applyTransforms(origCI, Input, PCHContainerOps, DiagClient, outputDir,
397 emitPremigrationARCErrors, plistOut);
404 assert(!outputDir.empty());
418 [&](StringRef From, StringRef To) {
419 remap.push_back(std::make_pair(From.str(), To.str()));
421 [](StringRef,
const llvm::MemoryBufferRef &) {});
433class 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 std::make_unique<ARCMTMacroTrackerPPCallbacks>(ARCMTMacroLocs));
458 return std::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)),
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);
591 errRec.FinishCapture();
599 llvm::RewriteBuffer &buf = I->second;
603 std::string newFname = std::string(file->
getName());
604 newFname +=
"-trans";
606 llvm::raw_svector_ostream vecOS(newText);
608 std::unique_ptr<llvm::MemoryBuffer> memBuf(
609 llvm::MemoryBuffer::getMemBufferCopy(newText.str(), newFname));
611 Unit->getFileManager().FixupRelativePath(filePath);
612 Remapper.
remap(filePath.str(), std::move(memBuf));
static void emitPremigrationErrors(const CapturedDiagList &arcDiags, DiagnosticOptions *diagOpts, Preprocessor &PP)
static CompilerInvocation * createInvocationForMigration(CompilerInvocation &origCI, const PCHContainerReader &PCHContainerRdr)
static bool applyTransforms(CompilerInvocation &origCI, const FrontendInputFile &Input, std::shared_ptr< PCHContainerOperations > PCHContainerOps, DiagnosticConsumer *DiagClient, StringRef outputDir, bool emitPremigrationARCErrors, StringRef plistOut)
static bool HasARCRuntime(CompilerInvocation &origCI)
Defines the clang::FrontendAction interface and various convenience abstract classes (clang::ASTFront...
Defines the clang::Preprocessor interface.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
SourceManager & getSourceManager()
const LangOptions & getLangOpts() const
Abstract base class to use for AST consumer-based frontend actions.
StringRef getOriginalSourceFile()
Retrieve the name of the original source file name for the primary module file.
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, CaptureDiagsKind CaptureDiagnostics=CaptureDiagsKind::None, unsigned PrecompilePreambleAfterNParses=0, bool CacheCodeCompletionResults=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...
Represents a character-granular source range.
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
Preprocessor & getPreprocessor() const
Return the current preprocessor.
Helper class for holding the data necessary to invoke the compiler.
MigratorOptions & getMigratorOpts()
LangOptions & getLangOpts()
Mutable getters.
FrontendOptions & getFrontendOpts()
FileSystemOptions & getFileSystemOpts()
TargetOptions & getTargetOpts()
DiagnosticOptions & getDiagnosticOpts()
Abstract interface, implemented by clients of the front-end, which formats and prints fully processed...
virtual void EndSourceFile()
Callback to inform the diagnostic client that processing of a source file has ended.
unsigned getNumErrors() const
virtual void BeginSourceFile(const LangOptions &LangOpts, const Preprocessor *PP=nullptr)
Callback to inform the diagnostic client that processing of a source file is beginning.
Used for handling and querying diagnostic IDs.
static bool isARCDiagnostic(unsigned DiagID)
Return true if a given diagnostic falls into an ARC diagnostic category.
Options for controlling the compiler diagnostics engine.
A little helper class (which is basically a smart pointer that forwards info from DiagnosticsEngine) ...
const SourceLocation & getLocation() const
Concrete class used by the front-end to report problems and issues.
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
void setLastDiagnosticIgnored(bool Ignored)
Pretend that the last diagnostic issued was ignored, so any subsequent notes will be suppressed,...
Level
The level of the diagnostic, after it has been through mapping.
StringRef getName() const
The name of this FileEntry.
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
Implements support for file system lookup, file system caching, and directory search management.
SmallVector< FrontendInputFile, 0 > Inputs
The input files and their types.
A SourceLocation and its associated SourceManager.
bool isBeforeInTranslationUnitThan(SourceLocation Loc) const
Determines the order of 2 source locations in the translation unit.
StringRef getName() const
Return the actual identifier string.
A diagnostic client that ignores all diagnostics.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
MacroArgs - An instance of this class captures information about the formal arguments specified to a ...
A description of the current definition of a macro.
unsigned NoNSAllocReallocError
unsigned NoFinalizeRemoval
This abstract interface provides operations for unwrapping containers for serialized ASTs (precompile...
This interface provides a way to observe the actions of the preprocessor as it does its thing.
PreprocessorOptions - This class is used for passing the various options used in preprocessor initial...
std::vector< std::string > Includes
std::string ImplicitPCHInclude
The implicit PCH included at the start of the translation unit, or empty.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
void addPPCallbacks(std::unique_ptr< PPCallbacks > C)
SourceManager & getSourceManager() const
const LangOptions & getLangOpts() const
Rewriter - This is the main interface to the rewrite buffers.
std::map< FileID, llvm::RewriteBuffer >::iterator buffer_iterator
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.
bool RemoveText(SourceLocation Start, unsigned Length, RewriteOptions opts=RewriteOptions())
RemoveText - Remove the specified text region.
buffer_iterator buffer_end()
buffer_iterator buffer_begin()
bool IncreaseIndentation(CharSourceRange range, SourceLocation parentIndent)
Increase indentation for the lines between the given source range.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
OptionalFileEntryRef getFileEntryRefForID(FileID FID) const
Returns the FileEntryRef for the provided FileID.
A trivial tuple used to represent a source range.
Represents a diagnostic in a form that can be retained until its corresponding source manager is dest...
std::string Triple
The name of the target triple to compile for.
void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) override
Callback to inform the diagnostic client that processing of a source file is beginning.
void EndSourceFile() override
Callback to inform the diagnostic client that processing of a source file has ended.
Token - This structure provides full information about a lexed token.
IdentifierInfo * getIdentifierInfo() const
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file.
bool clearDiagnostic(ArrayRef< unsigned > IDs, SourceRange range)
void push_back(const StoredDiagnostic &diag)
bool hasDiagnostic(ArrayRef< unsigned > IDs, SourceRange range) const
ListTy::const_iterator iterator
void reportDiagnostics(DiagnosticsEngine &diags) const
void forEachMapping(llvm::function_ref< void(StringRef, StringRef)> CaptureFile, llvm::function_ref< void(StringRef, const llvm::MemoryBufferRef &)> CaptureBuffer) const
Iterate through all the mappings.
bool flushToDisk(StringRef outputDir, DiagnosticsEngine &Diag)
void remap(StringRef filePath, std::unique_ptr< llvm::MemoryBuffer > memBuf)
void applyMappings(PreprocessorOptions &PPOpts) const
bool initFromDisk(StringRef outputDir, DiagnosticsEngine &Diag, bool ignoreIfFilesChanged)
bool overwriteOriginal(DiagnosticsEngine &Diag, StringRef outputDir=StringRef())
void setNoFinalizeRemoval(bool val)
virtual void start(ASTContext &Ctx)
virtual void remove(CharSourceRange range)
virtual ~RewriteListener()
Anchor for VTable.
virtual void insert(SourceLocation loc, StringRef text)
FileRemapper & getRemapper()
MigrationProcess(CompilerInvocation &CI, std::shared_ptr< PCHContainerOperations > PCHContainerOps, DiagnosticConsumer *diagClient, StringRef outputDir=StringRef())
bool applyTransform(TransformFn trans, RewriteListener *listener=nullptr)
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.
static StringRef getARCMTMacroName()
std::vector< TransformFn > getAllTransformations(LangOptions::GCMode OrigGCMode, bool NoFinalizeRemoval)
void writeARCDiagsToPlist(const std::string &outPath, ArrayRef< StoredDiagnostic > diags, SourceManager &SM, const LangOptions &LangOpts)
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.
void(* TransformFn)(MigrationPass &pass)
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 ...
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,...
@ Error
Present this diagnostic as an error.
The JSON file list parser is used to communicate input to InstallAPI.
bool IncludeInsertsAtBeginOfRange
Given a source range, true to include previous inserts at the beginning of the range as part of the r...
bool IncludeInsertsAtEndOfRange
Given a source range, true to include previous inserts at the end of the range as part of the range i...
bool RemoveLineIfEmpty
If true and removing some text leaves a blank line also remove the empty line (false by default).