22 #include "llvm/ADT/Triple.h" 23 #include "llvm/Support/MemoryBuffer.h" 25 using namespace clang;
26 using namespace arcmt;
34 ListTy::iterator I = List.begin();
35 while (I != List.end()) {
38 llvm::is_contained(IDs, I->getID())) &&
40 (diagLoc == range.
getEnd() ||
43 ListTy::iterator eraseS = I++;
48 I = List.erase(eraseS, I);
63 ListTy::const_iterator I = List.begin();
64 while (I != List.end()) {
67 llvm::find(IDs, I->getID()) != IDs.end()) &&
69 (diagLoc == range.
getEnd() ||
81 for (ListTy::const_iterator I = List.begin(), E = List.end(); I != E; ++I)
86 for (ListTy::const_iterator I = List.begin(), E = List.end(); I != E; ++I)
99 bool HasBegunSourceFile;
104 : Diags(diags), DiagClient(client), CapturedDiags(capturedDiags),
105 HasBegunSourceFile(
false) { }
112 if (!HasBegunSourceFile) {
114 HasBegunSourceFile =
true;
118 void FinishCapture() {
122 if (HasBegunSourceFile) {
124 HasBegunSourceFile =
false;
128 ~CaptureDiagnosticConsumer()
override {
129 assert(!HasBegunSourceFile &&
"FinishCapture not called!");
155 return triple.getOSMajorVersion() >= 5;
157 if (triple.isWatchOS())
160 if (triple.getOS() == llvm::Triple::Darwin)
161 return triple.getOSMajorVersion() >= 11;
163 if (triple.getOS() == llvm::Triple::MacOSX) {
164 unsigned Major, Minor, Micro;
165 triple.getOSVersion(Major, Minor, Micro);
166 return Major > 10 || (Major == 10 && Minor >= 7);
175 std::unique_ptr<CompilerInvocation> CInvok;
188 if (!OriginalFile.empty())
194 CInvok->getPreprocessorOpts().addMacroDef(define);
195 CInvok->getLangOpts()->ObjCAutoRefCount =
true;
197 CInvok->getDiagnosticOpts().ErrorLimit = 0;
198 CInvok->getDiagnosticOpts().PedanticErrors = 0;
201 std::vector<std::string> WarnOpts;
202 for (std::vector<std::string>::iterator
203 I = CInvok->getDiagnosticOpts().Warnings.begin(),
204 E = CInvok->getDiagnosticOpts().Warnings.end(); I != E; ++I) {
205 if (!StringRef(*I).startswith(
"error"))
206 WarnOpts.push_back(*I);
208 WarnOpts.push_back(
"error=arc-unsafe-retained-assign");
209 CInvok->getDiagnosticOpts().Warnings = std::move(WarnOpts);
211 CInvok->getLangOpts()->ObjCWeakRuntime =
HasARCRuntime(origCI);
212 CInvok->getLangOpts()->ObjCWeak = CInvok->getLangOpts()->ObjCWeakRuntime;
214 return CInvok.release();
238 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
240 StringRef plistOut) {
250 assert(!transforms.empty());
252 std::unique_ptr<CompilerInvocation> CInvok;
255 CInvok->getFrontendOpts().Inputs.clear();
256 CInvok->getFrontendOpts().Inputs.push_back(Input);
267 CaptureDiagnosticConsumer errRec(*Diags, *DiagClient, capturedDiags);
268 Diags->setClient(&errRec,
false);
271 std::move(CInvok), PCHContainerOps, Diags));
273 errRec.FinishCapture();
278 Diags->setClient(DiagClient,
false);
282 if (Diags->hasFatalErrorOccurred()) {
287 errRec.FinishCapture();
291 if (emitPremigrationARCErrors)
293 Unit->getPreprocessor());
294 if (!plistOut.empty()) {
297 I = capturedDiags.
begin(), E = capturedDiags.
end(); I != E; ++I)
298 arcDiags.push_back(*I);
312 std::vector<SourceLocation> ARCMTMacroLocs;
314 TransformActions testAct(*Diags, capturedDiags, Ctx, Unit->getPreprocessor());
315 MigrationPass pass(Ctx, OrigGCMode, Unit->getSema(), testAct, capturedDiags,
318 if (!NoNSAllocReallocError)
322 for (
unsigned i=0, e = transforms.size(); i != e; ++i)
325 capturedDiags.reportDiagnostics(*Diags);
328 errRec.FinishCapture();
330 return capturedDiags.hasErrors() || testAct.hasReportedErrors();
339 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
341 bool emitPremigrationARCErrors, StringRef plistOut) {
350 DiagClient, emitPremigrationARCErrors,
363 assert(!transforms.empty());
365 for (
unsigned i=0, e = transforms.size(); i != e; ++i) {
367 if (err)
return true;
375 if (outputDir.empty()) {
385 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
388 StringRef(),
false, StringRef());
393 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
395 bool emitPremigrationARCErrors, StringRef plistOut) {
396 assert(!outputDir.empty() &&
"Expected output directory path");
397 return applyTransforms(origCI, Input, PCHContainerOps, DiagClient, outputDir,
398 emitPremigrationARCErrors, plistOut);
405 assert(!outputDir.empty());
432 class ARCMTMacroTrackerPPCallbacks :
public PPCallbacks {
433 std::vector<SourceLocation> &ARCMTMacroLocs;
436 ARCMTMacroTrackerPPCallbacks(std::vector<SourceLocation> &ARCMTMacroLocs)
437 : ARCMTMacroLocs(ARCMTMacroLocs) { }
442 ARCMTMacroLocs.push_back(MacroNameTok.
getLocation());
447 std::vector<SourceLocation> &ARCMTMacroLocs;
450 ARCMTMacroTrackerAction(std::vector<SourceLocation> &ARCMTMacroLocs)
451 : ARCMTMacroLocs(ARCMTMacroLocs) { }
454 StringRef InFile)
override {
456 std::make_unique<ARCMTMacroTrackerPPCallbacks>(ARCMTMacroLocs));
457 return std::make_unique<ASTConsumer>();
468 : rewriter(rewriter), Listener(listener) {
470 Listener->
start(ctx);
472 ~RewritesApplicator()
override {
478 bool err = rewriter.
InsertText(loc, text,
true,
480 if (!err && Listener)
481 Listener->
insert(loc, text);
491 if (!err && Listener)
508 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
510 : OrigCI(CI), PCHContainerOps(
std::move(PCHContainerOps)),
511 DiagClient(diagClient), HadARCErrors(
false) {
512 if (!outputDir.empty()) {
523 std::unique_ptr<CompilerInvocation> CInvok;
526 CInvok->getDiagnosticOpts().IgnoreWarnings =
true;
531 std::vector<SourceLocation> ARCMTMacroLocs;
540 CaptureDiagnosticConsumer errRec(*Diags, *DiagClient, capturedDiags);
541 Diags->setClient(&errRec,
false);
543 std::unique_ptr<ARCMTMacroTrackerAction> ASTAction;
544 ASTAction.reset(
new ARCMTMacroTrackerAction(ARCMTMacroLocs));
547 std::move(CInvok), PCHContainerOps, Diags, ASTAction.get()));
549 errRec.FinishCapture();
552 Unit->setOwnsRemappedFileBuffers(
false);
557 Diags->setClient(DiagClient,
false);
561 if (Diags->hasFatalErrorOccurred()) {
566 errRec.FinishCapture();
580 Unit->getSema(), TA, capturedDiags, ARCMTMacroLocs);
585 RewritesApplicator applicator(rewriter, Ctx, listener);
586 TA.applyRewrites(applicator);
590 errRec.FinishCapture();
596 I = rewriter.buffer_begin(), E = rewriter.buffer_end(); I != E; ++I) {
601 std::string newFname = file->
getName();
602 newFname +=
"-trans";
604 llvm::raw_svector_ostream vecOS(newText);
606 std::unique_ptr<llvm::MemoryBuffer> memBuf(
607 llvm::MemoryBuffer::getMemBufferCopy(
608 StringRef(newText.data(), newText.size()), newFname));
610 Unit->getFileManager().FixupRelativePath(filePath);
611 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.
SmallVector< FrontendInputFile, 0 > Inputs
The input files and their types.
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.
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...
void setLastDiagnosticIgnored(bool Ignored)
Pretend that the last diagnostic issued was ignored, so any subsequent notes will be suppressed...
std::map< FileID, RewriteBuffer >::iterator buffer_iterator
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.
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 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...
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...