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())
194 CInvok->getPreprocessorOpts().ImplicitPTHInclude.clear();
197 CInvok->getPreprocessorOpts().addMacroDef(define);
198 CInvok->getLangOpts()->ObjCAutoRefCount =
true;
200 CInvok->getDiagnosticOpts().ErrorLimit = 0;
201 CInvok->getDiagnosticOpts().PedanticErrors = 0;
204 std::vector<std::string> WarnOpts;
205 for (std::vector<std::string>::iterator
206 I = CInvok->getDiagnosticOpts().Warnings.begin(),
207 E = CInvok->getDiagnosticOpts().Warnings.end(); I != E; ++I) {
208 if (!StringRef(*I).startswith(
"error"))
209 WarnOpts.push_back(*I);
211 WarnOpts.push_back(
"error=arc-unsafe-retained-assign");
212 CInvok->getDiagnosticOpts().Warnings = std::move(WarnOpts);
214 CInvok->getLangOpts()->ObjCWeakRuntime =
HasARCRuntime(origCI);
215 CInvok->getLangOpts()->ObjCWeak = CInvok->getLangOpts()->ObjCWeakRuntime;
217 return CInvok.release();
241 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
243 StringRef plistOut) {
253 assert(!transforms.empty());
255 std::unique_ptr<CompilerInvocation> CInvok;
258 CInvok->getFrontendOpts().Inputs.clear();
259 CInvok->getFrontendOpts().Inputs.push_back(Input);
270 CaptureDiagnosticConsumer errRec(*Diags, *DiagClient, capturedDiags);
271 Diags->setClient(&errRec,
false);
274 std::move(CInvok), PCHContainerOps, Diags));
276 errRec.FinishCapture();
281 Diags->setClient(DiagClient,
false);
285 if (Diags->hasFatalErrorOccurred()) {
290 errRec.FinishCapture();
294 if (emitPremigrationARCErrors)
296 Unit->getPreprocessor());
297 if (!plistOut.empty()) {
300 I = capturedDiags.
begin(), E = capturedDiags.
end(); I != E; ++I)
301 arcDiags.push_back(*I);
315 std::vector<SourceLocation> ARCMTMacroLocs;
317 TransformActions testAct(*Diags, capturedDiags, Ctx, Unit->getPreprocessor());
318 MigrationPass pass(Ctx, OrigGCMode, Unit->getSema(), testAct, capturedDiags,
321 if (!NoNSAllocReallocError)
325 for (
unsigned i=0, e = transforms.size(); i != e; ++i)
328 capturedDiags.reportDiagnostics(*Diags);
331 errRec.FinishCapture();
333 return capturedDiags.hasErrors() || testAct.hasReportedErrors();
342 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
344 bool emitPremigrationARCErrors, StringRef plistOut) {
353 DiagClient, emitPremigrationARCErrors,
366 assert(!transforms.empty());
368 for (
unsigned i=0, e = transforms.size(); i != e; ++i) {
370 if (err)
return true;
378 if (outputDir.empty()) {
388 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
391 StringRef(),
false, StringRef());
396 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
398 bool emitPremigrationARCErrors, StringRef plistOut) {
399 assert(!outputDir.empty() &&
"Expected output directory path");
400 return applyTransforms(origCI, Input, PCHContainerOps, DiagClient, outputDir,
401 emitPremigrationARCErrors, plistOut);
408 assert(!outputDir.empty());
435 class ARCMTMacroTrackerPPCallbacks :
public PPCallbacks {
436 std::vector<SourceLocation> &ARCMTMacroLocs;
439 ARCMTMacroTrackerPPCallbacks(std::vector<SourceLocation> &ARCMTMacroLocs)
440 : ARCMTMacroLocs(ARCMTMacroLocs) { }
445 ARCMTMacroLocs.push_back(MacroNameTok.
getLocation());
450 std::vector<SourceLocation> &ARCMTMacroLocs;
453 ARCMTMacroTrackerAction(std::vector<SourceLocation> &ARCMTMacroLocs)
454 : ARCMTMacroLocs(ARCMTMacroLocs) { }
457 StringRef InFile)
override {
459 llvm::make_unique<ARCMTMacroTrackerPPCallbacks>(ARCMTMacroLocs));
460 return llvm::make_unique<ASTConsumer>();
471 : rewriter(rewriter), Listener(listener) {
473 Listener->
start(ctx);
475 ~RewritesApplicator()
override {
481 bool err = rewriter.
InsertText(loc, text,
true,
483 if (!err && Listener)
484 Listener->
insert(loc, text);
493 bool err = rewriter.
RemoveText(range, removeOpts);
494 if (!err && Listener)
511 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
513 : OrigCI(CI), PCHContainerOps(
std::move(PCHContainerOps)),
514 DiagClient(diagClient), HadARCErrors(
false) {
515 if (!outputDir.empty()) {
526 std::unique_ptr<CompilerInvocation> CInvok;
529 CInvok->getDiagnosticOpts().IgnoreWarnings =
true;
534 std::vector<SourceLocation> ARCMTMacroLocs;
543 CaptureDiagnosticConsumer errRec(*Diags, *DiagClient, capturedDiags);
544 Diags->setClient(&errRec,
false);
546 std::unique_ptr<ARCMTMacroTrackerAction> ASTAction;
547 ASTAction.reset(
new ARCMTMacroTrackerAction(ARCMTMacroLocs));
550 std::move(CInvok), PCHContainerOps, Diags, ASTAction.get()));
552 errRec.FinishCapture();
555 Unit->setOwnsRemappedFileBuffers(
false);
560 Diags->setClient(DiagClient,
false);
564 if (Diags->hasFatalErrorOccurred()) {
569 errRec.FinishCapture();
583 Unit->getSema(), TA, capturedDiags, ARCMTMacroLocs);
588 RewritesApplicator applicator(rewriter, Ctx, listener);
589 TA.applyRewrites(applicator);
593 errRec.FinishCapture();
599 I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) {
604 std::string newFname = file->
getName();
605 newFname +=
"-trans";
607 llvm::raw_svector_ostream vecOS(newText);
609 std::unique_ptr<llvm::MemoryBuffer> memBuf(
610 llvm::MemoryBuffer::getMemBufferCopy(
611 StringRef(newText.data(), newText.size()), newFname));
613 Unit->getFileManager().FixupRelativePath(filePath);
614 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...