22 #include "llvm/ADT/Triple.h"
23 #include "llvm/Support/MemoryBuffer.h"
24 using namespace clang;
25 using namespace arcmt;
33 ListTy::iterator I = List.begin();
34 while (I != List.end()) {
37 std::find(IDs.begin(), IDs.end(), I->getID()) != IDs.end()) &&
39 (diagLoc == range.
getEnd() ||
42 ListTy::iterator eraseS = I++;
47 I = List.erase(eraseS, I);
62 ListTy::const_iterator I = List.begin();
63 while (I != List.end()) {
66 std::find(IDs.begin(), IDs.end(), I->getID()) != IDs.end()) &&
68 (diagLoc == range.
getEnd() ||
80 for (ListTy::const_iterator I = List.begin(), E = List.end(); I != E; ++I)
85 for (ListTy::const_iterator I = List.begin(), E = List.end(); I != E; ++I)
98 bool HasBegunSourceFile;
103 : Diags(diags), DiagClient(client), CapturedDiags(capturedDiags),
104 HasBegunSourceFile(
false) { }
111 if (!HasBegunSourceFile) {
112 DiagClient.BeginSourceFile(Opts, PP);
113 HasBegunSourceFile =
true;
117 void FinishCapture() {
121 if (HasBegunSourceFile) {
122 DiagClient.EndSourceFile();
123 HasBegunSourceFile =
false;
127 ~CaptureDiagnosticConsumer()
override {
128 assert(!HasBegunSourceFile &&
"FinishCapture not called!");
141 Diags.setLastDiagnosticIgnored();
154 return triple.getOSMajorVersion() >= 5;
156 if (triple.getOS() == llvm::Triple::Darwin)
157 return triple.getOSMajorVersion() >= 11;
159 if (triple.getOS() == llvm::Triple::MacOSX) {
160 unsigned Major, Minor, Micro;
161 triple.getOSVersion(Major, Minor, Micro);
162 return Major > 10 || (Major == 10 && Minor >= 7);
171 std::unique_ptr<CompilerInvocation> CInvok;
184 if (!OriginalFile.empty())
189 CInvok->getPreprocessorOpts().ImplicitPTHInclude.clear();
192 CInvok->getPreprocessorOpts().addMacroDef(define);
193 CInvok->getLangOpts()->ObjCAutoRefCount =
true;
195 CInvok->getDiagnosticOpts().ErrorLimit = 0;
196 CInvok->getDiagnosticOpts().PedanticErrors = 0;
199 std::vector<std::string> WarnOpts;
200 for (std::vector<std::string>::iterator
201 I = CInvok->getDiagnosticOpts().Warnings.begin(),
202 E = CInvok->getDiagnosticOpts().Warnings.end(); I != E; ++I) {
203 if (!StringRef(*I).startswith(
"error"))
204 WarnOpts.push_back(*I);
206 WarnOpts.push_back(
"error=arc-unsafe-retained-assign");
207 CInvok->getDiagnosticOpts().Warnings = std::move(WarnOpts);
211 return CInvok.release();
235 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
237 StringRef plistOut) {
247 assert(!transforms.empty());
249 std::unique_ptr<CompilerInvocation> CInvok;
252 CInvok->getFrontendOpts().Inputs.clear();
253 CInvok->getFrontendOpts().Inputs.push_back(Input);
264 CaptureDiagnosticConsumer errRec(*Diags, *DiagClient, capturedDiags);
265 Diags->setClient(&errRec,
false);
268 CInvok.release(), PCHContainerOps, Diags));
270 errRec.FinishCapture();
275 Diags->setClient(DiagClient,
false);
279 if (Diags->hasFatalErrorOccurred()) {
284 errRec.FinishCapture();
288 if (emitPremigrationARCErrors)
290 Unit->getPreprocessor());
291 if (!plistOut.empty()) {
294 I = capturedDiags.
begin(), E = capturedDiags.
end(); I != E; ++I)
295 arcDiags.push_back(*I);
309 std::vector<SourceLocation> ARCMTMacroLocs;
311 TransformActions testAct(*Diags, capturedDiags, Ctx, Unit->getPreprocessor());
312 MigrationPass pass(Ctx, OrigGCMode, Unit->getSema(), testAct, capturedDiags,
315 if (!NoNSAllocReallocError)
319 for (
unsigned i=0, e = transforms.size(); i != e; ++i)
322 capturedDiags.reportDiagnostics(*Diags);
325 errRec.FinishCapture();
327 return capturedDiags.hasErrors() || testAct.hasReportedErrors();
336 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
338 bool emitPremigrationARCErrors, StringRef plistOut) {
347 DiagClient, emitPremigrationARCErrors,
360 assert(!transforms.empty());
362 for (
unsigned i=0, e = transforms.size(); i != e; ++i) {
364 if (err)
return true;
372 if (outputDir.empty()) {
382 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
385 StringRef(),
false, StringRef());
390 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
392 bool emitPremigrationARCErrors, StringRef plistOut) {
393 assert(!outputDir.empty() &&
"Expected output directory path");
394 return applyTransforms(origCI, Input, PCHContainerOps, DiagClient, outputDir,
395 emitPremigrationARCErrors, plistOut);
402 assert(!outputDir.empty());
429 class ARCMTMacroTrackerPPCallbacks :
public PPCallbacks {
430 std::vector<SourceLocation> &ARCMTMacroLocs;
433 ARCMTMacroTrackerPPCallbacks(std::vector<SourceLocation> &ARCMTMacroLocs)
434 : ARCMTMacroLocs(ARCMTMacroLocs) { }
439 ARCMTMacroLocs.push_back(MacroNameTok.
getLocation());
444 std::vector<SourceLocation> &ARCMTMacroLocs;
447 ARCMTMacroTrackerAction(std::vector<SourceLocation> &ARCMTMacroLocs)
448 : ARCMTMacroLocs(ARCMTMacroLocs) { }
451 StringRef InFile)
override {
453 llvm::make_unique<ARCMTMacroTrackerPPCallbacks>(ARCMTMacroLocs));
454 return llvm::make_unique<ASTConsumer>();
465 : rewriter(rewriter), Listener(listener) {
467 Listener->start(ctx);
469 ~RewritesApplicator()
override {
475 bool err = rewriter.
InsertText(loc, text,
true,
477 if (!err && Listener)
478 Listener->insert(loc, text);
487 bool err = rewriter.
RemoveText(range, removeOpts);
488 if (!err && Listener)
489 Listener->remove(range);
505 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
507 : OrigCI(CI), PCHContainerOps(PCHContainerOps), DiagClient(diagClient),
509 if (!outputDir.empty()) {
520 std::unique_ptr<CompilerInvocation> CInvok;
523 CInvok->getDiagnosticOpts().IgnoreWarnings =
true;
528 std::vector<SourceLocation> ARCMTMacroLocs;
537 CaptureDiagnosticConsumer errRec(*Diags, *DiagClient, capturedDiags);
538 Diags->setClient(&errRec,
false);
540 std::unique_ptr<ARCMTMacroTrackerAction> ASTAction;
541 ASTAction.reset(
new ARCMTMacroTrackerAction(ARCMTMacroLocs));
544 CInvok.release(), PCHContainerOps, Diags, ASTAction.get()));
546 errRec.FinishCapture();
549 Unit->setOwnsRemappedFileBuffers(
false);
554 Diags->setClient(DiagClient,
false);
558 if (Diags->hasFatalErrorOccurred()) {
563 errRec.FinishCapture();
577 Unit->getSema(), TA, capturedDiags, ARCMTMacroLocs);
582 RewritesApplicator applicator(rewriter, Ctx, listener);
583 TA.applyRewrites(applicator);
587 errRec.FinishCapture();
598 std::string newFname = file->
getName();
599 newFname +=
"-trans";
601 llvm::raw_svector_ostream vecOS(newText);
604 std::unique_ptr<llvm::MemoryBuffer> memBuf(
605 llvm::MemoryBuffer::getMemBufferCopy(
606 StringRef(newText.data(), newText.size()), newFname));
608 Unit->getFileManager().FixupRelativePath(filePath);
609 Remapper.
remap(filePath.str(), std::move(memBuf));
SourceManager & getSourceManager() const
SourceLocation getEnd() const
void(* TransformFn)(MigrationPass &pass)
unsigned NoFinalizeRemoval
void reportDiagnostics(DiagnosticsEngine &diags) const
bool IncreaseIndentation(CharSourceRange range, SourceLocation parentIndent)
Increase indentation for the lines between the given source range. To determine what the indentation ...
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.
bool RemoveText(SourceLocation Start, unsigned Length, RewriteOptions opts=RewriteOptions())
RemoveText - Remove the specified text region.
virtual void EndSourceFile()
Callback to inform the diagnostic client that processing of a source file has ended.
Abstract interface, implemented by clients of the front-end, which formats and prints fully processed...
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 ...
const LangOptions & getLangOpts() const
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
bool clearDiagnostic(ArrayRef< unsigned > IDs, SourceRange range)
const LangOptions & getLangOpts() const
const SourceLocation & getLocation() const
void remap(StringRef filePath, std::unique_ptr< llvm::MemoryBuffer > memBuf)
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)
Present this diagnostic as an error.
bool hasDiagnostic(ArrayRef< unsigned > IDs, SourceRange range) const
Preprocessor & getPreprocessor() const
Return the current preprocessor.
buffer_iterator buffer_end()
FrontendOptions & getFrontendOpts()
MigratorOptions & getMigratorOpts()
const FileEntry * getFileEntryForID(FileID FID) const
Returns the FileEntry record for the provided FileID.
StringRef getName() const
Return the actual identifier string.
Represents a character-granular source range.
Defines the clang::Preprocessor interface.
void writeARCDiagsToPlist(const std::string &outPath, ArrayRef< StoredDiagnostic > diags, SourceManager &SM, const LangOptions &LangOpts)
SourceLocation getLocation() const
Return a source location identifier for the specified offset in the current file. ...
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.
void applyMappings(PreprocessorOptions &PPOpts) const
MigrationProcess(const CompilerInvocation &CI, std::shared_ptr< PCHContainerOperations > PCHContainerOps, DiagnosticConsumer *diagClient, StringRef outputDir=StringRef())
unsigned NoNSAllocReallocError
static CompilerInvocation * createInvocationForMigration(CompilerInvocation &origCI, const PCHContainerReader &PCHContainerRdr)
bool overwriteOriginal(DiagnosticsEngine &Diag, StringRef outputDir=StringRef())
const char * getName() const
Encodes a location in the source. The SourceManager can decode this to get at the full include stack...
std::string ImplicitPCHInclude
The implicit PCH included at the start of the translation unit, or empty.
bool flushToDisk(StringRef outputDir, DiagnosticsEngine &Diag)
bool isValid() const
Return true if this is a valid SourceLocation object.
Options for controlling the compiler diagnostics engine.
std::vector< FrontendInputFile > Inputs
The input files and their types.
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)
Abstract base class to use for AST consumer-based frontend actions.
bool RemoveLineIfEmpty
If true and removing some text leaves a blank line also remove the empty line (false by default)...
SourceLocation getBegin() const
static ASTUnit * LoadFromCompilerInvocationAction(CompilerInvocation *CI, std::shared_ptr< PCHContainerOperations > PCHContainerOps, IntrusiveRefCntPtr< DiagnosticsEngine > Diags, ASTFrontendAction *Action=nullptr, ASTUnit *Unit=nullptr, bool Persistent=true, StringRef ResourceFilesPath=StringRef(), bool OnlyLocalDecls=false, bool CaptureDiagnostics=false, bool PrecompilePreamble=false, 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...
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...
An opaque identifier used by SourceManager which refers to a source file (MemoryBuffer) along with it...
A diagnostic client that ignores all diagnostics.
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.
DiagnosticOptions & getDiagnosticOpts() const
raw_ostream & write(raw_ostream &Stream) const
Write to Stream the result of applying all changes to the original buffer. Note that it isn't safe to...
bool IncludeInsertsAtBeginOfRange
Given a source range, true to include previous inserts at the beginning of the range as part of the r...
std::map< FileID, RewriteBuffer >::iterator buffer_iterator
buffer_iterator buffer_begin()
SourceManager & getSourceManager()
bool initFromDisk(StringRef outputDir, DiagnosticsEngine &Diag, bool ignoreIfFilesChanged)
static bool isARCDiagnostic(unsigned DiagID)
Return true if a given diagnostic falls into an ARC diagnostic category.
bool isBeforeInTranslationUnitThan(SourceLocation Loc) const
Determines the order of 2 source locations in the translation unit.
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...
FileRemapper & getRemapper()
A SourceLocation and its associated SourceManager.
Defines the clang::FrontendAction interface and various convenience abstract classes (clang::ASTFront...
unsigned getNumErrors() const
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.
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...
IdentifierInfo * getIdentifierInfo() const