summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/ARCMigrate
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/ARCMigrate')
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/ARCMT.cpp154
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/ARCMTActions.cpp18
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/CMakeLists.txt24
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/FileRemapper.cpp82
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/Internals.h47
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/Makefile18
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/PlistReporter.cpp195
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransAPIUses.cpp109
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransARCAssign.cpp1
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransAutoreleasePool.cpp24
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp5
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp86
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransProperties.cpp105
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp8
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransUnbridgedCasts.cpp127
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransUnusedInitDelegate.cpp1
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp1
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/TransformActions.cpp81
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.cpp30
-rw-r--r--contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.h13
20 files changed, 835 insertions, 294 deletions
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/ARCMT.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/ARCMT.cpp
index f1d947d..6e1b0e5 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/ARCMT.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/ARCMT.cpp
@@ -10,6 +10,7 @@
#include "Internals.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/TextDiagnosticPrinter.h"
#include "clang/Frontend/Utils.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/Rewrite/Rewriter.h"
@@ -18,12 +19,10 @@
#include "clang/Lex/Preprocessor.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/ADT/Triple.h"
-
using namespace clang;
using namespace arcmt;
-using llvm::StringRef;
-bool CapturedDiagList::clearDiagnostic(llvm::ArrayRef<unsigned> IDs,
+bool CapturedDiagList::clearDiagnostic(ArrayRef<unsigned> IDs,
SourceRange range) {
if (range.isInvalid())
return false;
@@ -39,7 +38,7 @@ bool CapturedDiagList::clearDiagnostic(llvm::ArrayRef<unsigned> IDs,
diagLoc.isBeforeInTranslationUnitThan(range.getEnd()))) {
cleared = true;
ListTy::iterator eraseS = I++;
- while (I != List.end() && I->getLevel() == Diagnostic::Note)
+ while (I != List.end() && I->getLevel() == DiagnosticsEngine::Note)
++I;
// Clear the diagnostic and any notes following it.
List.erase(eraseS, I);
@@ -52,7 +51,7 @@ bool CapturedDiagList::clearDiagnostic(llvm::ArrayRef<unsigned> IDs,
return cleared;
}
-bool CapturedDiagList::hasDiagnostic(llvm::ArrayRef<unsigned> IDs,
+bool CapturedDiagList::hasDiagnostic(ArrayRef<unsigned> IDs,
SourceRange range) const {
if (range.isInvalid())
return false;
@@ -74,14 +73,14 @@ bool CapturedDiagList::hasDiagnostic(llvm::ArrayRef<unsigned> IDs,
return false;
}
-void CapturedDiagList::reportDiagnostics(Diagnostic &Diags) const {
+void CapturedDiagList::reportDiagnostics(DiagnosticsEngine &Diags) const {
for (ListTy::const_iterator I = List.begin(), E = List.end(); I != E; ++I)
Diags.Report(*I);
}
bool CapturedDiagList::hasErrors() const {
for (ListTy::const_iterator I = List.begin(), E = List.end(); I != E; ++I)
- if (I->getLevel() >= Diagnostic::Error)
+ if (I->getLevel() >= DiagnosticsEngine::Error)
return true;
return false;
@@ -89,18 +88,18 @@ bool CapturedDiagList::hasErrors() const {
namespace {
-class CaptureDiagnosticClient : public DiagnosticClient {
- Diagnostic &Diags;
+class CaptureDiagnosticConsumer : public DiagnosticConsumer {
+ DiagnosticsEngine &Diags;
CapturedDiagList &CapturedDiags;
public:
- CaptureDiagnosticClient(Diagnostic &diags,
- CapturedDiagList &capturedDiags)
+ CaptureDiagnosticConsumer(DiagnosticsEngine &diags,
+ CapturedDiagList &capturedDiags)
: Diags(diags), CapturedDiags(capturedDiags) { }
- virtual void HandleDiagnostic(Diagnostic::Level level,
- const DiagnosticInfo &Info) {
+ virtual void HandleDiagnostic(DiagnosticsEngine::Level level,
+ const Diagnostic &Info) {
if (arcmt::isARCDiagnostic(Info.getID(), Diags) ||
- level >= Diagnostic::Error || level == Diagnostic::Note) {
+ level >= DiagnosticsEngine::Error || level == DiagnosticsEngine::Note) {
CapturedDiags.push_back(StoredDiagnostic(level, Info));
return;
}
@@ -108,11 +107,17 @@ public:
// Non-ARC warnings are ignored.
Diags.setLastDiagnosticIgnored();
}
+
+ DiagnosticConsumer *clone(DiagnosticsEngine &Diags) const {
+ // Just drop any diagnostics that come from cloned consumers; they'll
+ // have different source managers anyway.
+ return new IgnoringDiagConsumer();
+ }
};
} // end anonymous namespace
-static inline llvm::StringRef SimulatorVersionDefineName() {
+static inline StringRef SimulatorVersionDefineName() {
return "__IPHONE_OS_VERSION_MIN_REQUIRED=";
}
@@ -121,11 +126,11 @@ static inline llvm::StringRef SimulatorVersionDefineName() {
// and return the grouped values as integers, e.g:
// __IPHONE_OS_VERSION_MIN_REQUIRED=40201
// will return Major=4, Minor=2, Micro=1.
-static bool GetVersionFromSimulatorDefine(llvm::StringRef define,
+static bool GetVersionFromSimulatorDefine(StringRef define,
unsigned &Major, unsigned &Minor,
unsigned &Micro) {
assert(define.startswith(SimulatorVersionDefineName()));
- llvm::StringRef name, version;
+ StringRef name, version;
llvm::tie(name, version) = define.split('=');
if (version.empty())
return false;
@@ -154,7 +159,7 @@ static bool HasARCRuntime(CompilerInvocation &origCI) {
continue;
if (!define.startswith(SimulatorVersionDefineName()))
continue;
- unsigned Major, Minor, Micro;
+ unsigned Major = 0, Minor = 0, Micro = 0;
if (GetVersionFromSimulatorDefine(define, Major, Minor, Micro) &&
Major < 10 && Minor < 100 && Micro < 100)
return Major >= 5;
@@ -177,7 +182,8 @@ static bool HasARCRuntime(CompilerInvocation &origCI) {
return false;
}
-CompilerInvocation *createInvocationForMigration(CompilerInvocation &origCI) {
+static CompilerInvocation *
+createInvocationForMigration(CompilerInvocation &origCI) {
llvm::OwningPtr<CompilerInvocation> CInvok;
CInvok.reset(new CompilerInvocation(origCI));
CInvok->getPreprocessorOpts().ImplicitPCHInclude = std::string();
@@ -194,13 +200,29 @@ CompilerInvocation *createInvocationForMigration(CompilerInvocation &origCI) {
return CInvok.take();
}
+static void emitPremigrationErrors(const CapturedDiagList &arcDiags,
+ const DiagnosticOptions &diagOpts,
+ Preprocessor &PP) {
+ TextDiagnosticPrinter printer(llvm::errs(), diagOpts);
+ llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
+ llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
+ new DiagnosticsEngine(DiagID, &printer, /*ShouldOwnClient=*/false));
+ Diags->setSourceManager(&PP.getSourceManager());
+
+ printer.BeginSourceFile(PP.getLangOptions(), &PP);
+ arcDiags.reportDiagnostics(*Diags);
+ printer.EndSourceFile();
+}
+
//===----------------------------------------------------------------------===//
// checkForManualIssues.
//===----------------------------------------------------------------------===//
bool arcmt::checkForManualIssues(CompilerInvocation &origCI,
- llvm::StringRef Filename, InputKind Kind,
- DiagnosticClient *DiagClient) {
+ StringRef Filename, InputKind Kind,
+ DiagnosticConsumer *DiagClient,
+ bool emitPremigrationARCErrors,
+ StringRef plistOut) {
if (!origCI.getLangOpts().ObjC1)
return false;
@@ -216,11 +238,11 @@ bool arcmt::checkForManualIssues(CompilerInvocation &origCI,
assert(DiagClient);
llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- llvm::IntrusiveRefCntPtr<Diagnostic> Diags(
- new Diagnostic(DiagID, DiagClient, /*ShouldOwnClient=*/false));
+ llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
+ new DiagnosticsEngine(DiagID, DiagClient, /*ShouldOwnClient=*/false));
// Filter of all diagnostics.
- CaptureDiagnosticClient errRec(*Diags, capturedDiags);
+ CaptureDiagnosticConsumer errRec(*Diags, capturedDiags);
Diags->setClient(&errRec, /*ShouldOwnClient=*/false);
llvm::OwningPtr<ASTUnit> Unit(
@@ -241,9 +263,21 @@ bool arcmt::checkForManualIssues(CompilerInvocation &origCI,
return true;
}
+ if (emitPremigrationARCErrors)
+ emitPremigrationErrors(capturedDiags, origCI.getDiagnosticOpts(),
+ Unit->getPreprocessor());
+ if (!plistOut.empty()) {
+ SmallVector<StoredDiagnostic, 8> arcDiags;
+ for (CapturedDiagList::iterator
+ I = capturedDiags.begin(), E = capturedDiags.end(); I != E; ++I)
+ arcDiags.push_back(*I);
+ writeARCDiagsToPlist(plistOut, arcDiags,
+ Ctx.getSourceManager(), Ctx.getLangOptions());
+ }
+
// After parsing of source files ended, we want to reuse the
// diagnostics objects to emit further diagnostics.
- // We call BeginSourceFile because DiagnosticClient requires that
+ // We call BeginSourceFile because DiagnosticConsumer requires that
// diagnostics with source range information are emitted only in between
// BeginSourceFile() and EndSourceFile().
DiagClient->BeginSourceFile(Ctx.getLangOptions(), &Unit->getPreprocessor());
@@ -266,7 +300,7 @@ bool arcmt::checkForManualIssues(CompilerInvocation &origCI,
// to remove it so that we don't get errors from normal compilation.
origCI.getLangOpts().ObjCAutoRefCount = false;
- return capturedDiags.hasErrors();
+ return capturedDiags.hasErrors() || testAct.hasReportedErrors();
}
//===----------------------------------------------------------------------===//
@@ -274,15 +308,18 @@ bool arcmt::checkForManualIssues(CompilerInvocation &origCI,
//===----------------------------------------------------------------------===//
static bool applyTransforms(CompilerInvocation &origCI,
- llvm::StringRef Filename, InputKind Kind,
- DiagnosticClient *DiagClient,
- llvm::StringRef outputDir) {
+ StringRef Filename, InputKind Kind,
+ DiagnosticConsumer *DiagClient,
+ StringRef outputDir,
+ bool emitPremigrationARCErrors,
+ StringRef plistOut) {
if (!origCI.getLangOpts().ObjC1)
return false;
// Make sure checking is successful first.
CompilerInvocation CInvokForCheck(origCI);
- if (arcmt::checkForManualIssues(CInvokForCheck, Filename, Kind, DiagClient))
+ if (arcmt::checkForManualIssues(CInvokForCheck, Filename, Kind, DiagClient,
+ emitPremigrationARCErrors, plistOut))
return true;
CompilerInvocation CInvok(origCI);
@@ -300,8 +337,8 @@ static bool applyTransforms(CompilerInvocation &origCI,
}
llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- llvm::IntrusiveRefCntPtr<Diagnostic> Diags(
- new Diagnostic(DiagID, DiagClient, /*ShouldOwnClient=*/false));
+ llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
+ new DiagnosticsEngine(DiagID, DiagClient, /*ShouldOwnClient=*/false));
if (outputDir.empty()) {
origCI.getLangOpts().ObjCAutoRefCount = true;
@@ -315,28 +352,32 @@ static bool applyTransforms(CompilerInvocation &origCI,
}
bool arcmt::applyTransformations(CompilerInvocation &origCI,
- llvm::StringRef Filename, InputKind Kind,
- DiagnosticClient *DiagClient) {
- return applyTransforms(origCI, Filename, Kind, DiagClient, llvm::StringRef());
+ StringRef Filename, InputKind Kind,
+ DiagnosticConsumer *DiagClient) {
+ return applyTransforms(origCI, Filename, Kind, DiagClient,
+ StringRef(), false, StringRef());
}
bool arcmt::migrateWithTemporaryFiles(CompilerInvocation &origCI,
- llvm::StringRef Filename, InputKind Kind,
- DiagnosticClient *DiagClient,
- llvm::StringRef outputDir) {
+ StringRef Filename, InputKind Kind,
+ DiagnosticConsumer *DiagClient,
+ StringRef outputDir,
+ bool emitPremigrationARCErrors,
+ StringRef plistOut) {
assert(!outputDir.empty() && "Expected output directory path");
- return applyTransforms(origCI, Filename, Kind, DiagClient, outputDir);
+ return applyTransforms(origCI, Filename, Kind, DiagClient,
+ outputDir, emitPremigrationARCErrors, plistOut);
}
bool arcmt::getFileRemappings(std::vector<std::pair<std::string,std::string> > &
remap,
- llvm::StringRef outputDir,
- DiagnosticClient *DiagClient) {
+ StringRef outputDir,
+ DiagnosticConsumer *DiagClient) {
assert(!outputDir.empty());
llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- llvm::IntrusiveRefCntPtr<Diagnostic> Diags(
- new Diagnostic(DiagID, DiagClient, /*ShouldOwnClient=*/false));
+ llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
+ new DiagnosticsEngine(DiagID, DiagClient, /*ShouldOwnClient=*/false));
FileRemapper remapper;
bool err = remapper.initFromDisk(outputDir, *Diags,
@@ -364,7 +405,8 @@ public:
ARCMTMacroTrackerPPCallbacks(std::vector<SourceLocation> &ARCMTMacroLocs)
: ARCMTMacroLocs(ARCMTMacroLocs) { }
- virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo *MI) {
+ virtual void MacroExpands(const Token &MacroNameTok, const MacroInfo *MI,
+ SourceRange Range) {
if (MacroNameTok.getIdentifierInfo()->getName() == getARCMTMacroName())
ARCMTMacroLocs.push_back(MacroNameTok.getLocation());
}
@@ -378,7 +420,7 @@ public:
: ARCMTMacroLocs(ARCMTMacroLocs) { }
virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,
- llvm::StringRef InFile) {
+ StringRef InFile) {
CI.getPreprocessor().addPPCallbacks(
new ARCMTMacroTrackerPPCallbacks(ARCMTMacroLocs));
return new ASTConsumer();
@@ -402,7 +444,7 @@ public:
Listener->finish();
}
- virtual void insert(SourceLocation loc, llvm::StringRef text) {
+ virtual void insert(SourceLocation loc, StringRef text) {
bool err = rewriter.InsertText(loc, text, /*InsertAfter=*/true,
/*indentNewLines=*/true);
if (!err && Listener)
@@ -432,13 +474,13 @@ public:
MigrationProcess::RewriteListener::~RewriteListener() { }
MigrationProcess::MigrationProcess(const CompilerInvocation &CI,
- DiagnosticClient *diagClient,
- llvm::StringRef outputDir)
+ DiagnosticConsumer *diagClient,
+ StringRef outputDir)
: OrigCI(CI), DiagClient(diagClient) {
if (!outputDir.empty()) {
llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- llvm::IntrusiveRefCntPtr<Diagnostic> Diags(
- new Diagnostic(DiagID, DiagClient, /*ShouldOwnClient=*/false));
+ llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
+ new DiagnosticsEngine(DiagID, DiagClient, /*ShouldOwnClient=*/false));
Remapper.initFromDisk(outputDir, *Diags, /*ignoreIfFilesChanges=*/true);
}
}
@@ -456,11 +498,11 @@ bool MigrationProcess::applyTransform(TransformFn trans,
assert(DiagClient);
llvm::IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
- llvm::IntrusiveRefCntPtr<Diagnostic> Diags(
- new Diagnostic(DiagID, DiagClient, /*ShouldOwnClient=*/false));
+ llvm::IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
+ new DiagnosticsEngine(DiagID, DiagClient, /*ShouldOwnClient=*/false));
// Filter of all diagnostics.
- CaptureDiagnosticClient errRec(*Diags, capturedDiags);
+ CaptureDiagnosticConsumer errRec(*Diags, capturedDiags);
Diags->setClient(&errRec, /*ShouldOwnClient=*/false);
llvm::OwningPtr<ARCMTMacroTrackerAction> ASTAction;
@@ -488,7 +530,7 @@ bool MigrationProcess::applyTransform(TransformFn trans,
// After parsing of source files ended, we want to reuse the
// diagnostics objects to emit further diagnostics.
- // We call BeginSourceFile because DiagnosticClient requires that
+ // We call BeginSourceFile because DiagnosticConsumer requires that
// diagnostics with source range information are emitted only in between
// BeginSourceFile() and EndSourceFile().
DiagClient->BeginSourceFile(Ctx.getLangOptions(), &Unit->getPreprocessor());
@@ -522,7 +564,7 @@ bool MigrationProcess::applyTransform(TransformFn trans,
buf.write(vecOS);
vecOS.flush();
llvm::MemoryBuffer *memBuf = llvm::MemoryBuffer::getMemBufferCopy(
- llvm::StringRef(newText.data(), newText.size()), newFname);
+ StringRef(newText.data(), newText.size()), newFname);
llvm::SmallString<64> filePath(file->getName());
Unit->getFileManager().FixupRelativePath(filePath);
Remapper.remap(filePath.str(), memBuf);
@@ -535,7 +577,7 @@ bool MigrationProcess::applyTransform(TransformFn trans,
// isARCDiagnostic.
//===----------------------------------------------------------------------===//
-bool arcmt::isARCDiagnostic(unsigned diagID, Diagnostic &Diag) {
+bool arcmt::isARCDiagnostic(unsigned diagID, DiagnosticsEngine &Diag) {
return Diag.getDiagnosticIDs()->getCategoryNumberForDiag(diagID) ==
diag::DiagCat_Automatic_Reference_Counting_Issue;
}
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/ARCMTActions.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/ARCMTActions.cpp
index 345c745..dea867a 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/ARCMTActions.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/ARCMTActions.cpp
@@ -38,16 +38,26 @@ ModifyAction::ModifyAction(FrontendAction *WrappedAction)
: WrapperFrontendAction(WrappedAction) {}
bool MigrateAction::BeginInvocation(CompilerInstance &CI) {
- return !arcmt::migrateWithTemporaryFiles(CI.getInvocation(),
+ if (arcmt::migrateWithTemporaryFiles(CI.getInvocation(),
getCurrentFile(),
getCurrentFileKind(),
CI.getDiagnostics().getClient(),
- MigrateDir);
+ MigrateDir,
+ EmitPremigrationARCErros,
+ PlistOut))
+ return false; // errors, stop the action.
+
+ // We only want to see diagnostics emitted by migrateWithTemporaryFiles.
+ CI.getDiagnostics().setIgnoreAllWarnings(true);
+ return true;
}
MigrateAction::MigrateAction(FrontendAction *WrappedAction,
- llvm::StringRef migrateDir)
- : WrapperFrontendAction(WrappedAction), MigrateDir(migrateDir) {
+ StringRef migrateDir,
+ StringRef plistOut,
+ bool emitPremigrationARCErrors)
+ : WrapperFrontendAction(WrappedAction), MigrateDir(migrateDir),
+ PlistOut(plistOut), EmitPremigrationARCErros(emitPremigrationARCErrors) {
if (MigrateDir.empty())
MigrateDir = "."; // user current directory if none is given.
}
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/CMakeLists.txt b/contrib/llvm/tools/clang/lib/ARCMigrate/CMakeLists.txt
deleted file mode 100644
index 5f2711e..0000000
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/CMakeLists.txt
+++ /dev/null
@@ -1,24 +0,0 @@
-set(LLVM_USED_LIBS clangBasic clangAST clangParse clangFrontend clangRewrite)
-
-add_clang_library(clangARCMigrate
- ARCMT.cpp
- ARCMTActions.cpp
- FileRemapper.cpp
- TransARCAssign.cpp
- TransAutoreleasePool.cpp
- TransBlockObjCVariable.cpp
- TransEmptyStatementsAndDealloc.cpp
- TransformActions.cpp
- Transforms.cpp
- TransProperties.cpp
- TransRetainReleaseDealloc.cpp
- TransUnbridgedCasts.cpp
- TransUnusedInitDelegate.cpp
- TransZeroOutPropsInDealloc.cpp
- )
-
-add_dependencies(clangARCMigrate
- ClangAttrClasses
- ClangAttrList
- ClangDeclNodes
- ClangStmtNodes)
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/FileRemapper.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/FileRemapper.cpp
index db26c29..c6e6ce4 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/FileRemapper.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/FileRemapper.cpp
@@ -27,7 +27,7 @@ FileRemapper::~FileRemapper() {
clear();
}
-void FileRemapper::clear(llvm::StringRef outputDir) {
+void FileRemapper::clear(StringRef outputDir) {
for (MappingsTy::iterator
I = FromToMappings.begin(), E = FromToMappings.end(); I != E; ++I)
resetTarget(I->second);
@@ -40,7 +40,7 @@ void FileRemapper::clear(llvm::StringRef outputDir) {
}
}
-std::string FileRemapper::getRemapInfoFile(llvm::StringRef outputDir) {
+std::string FileRemapper::getRemapInfoFile(StringRef outputDir) {
assert(!outputDir.empty());
llvm::sys::Path dir(outputDir);
llvm::sys::Path infoFile = dir;
@@ -48,7 +48,7 @@ std::string FileRemapper::getRemapInfoFile(llvm::StringRef outputDir) {
return infoFile.str();
}
-bool FileRemapper::initFromDisk(llvm::StringRef outputDir, Diagnostic &Diag,
+bool FileRemapper::initFromDisk(StringRef outputDir, DiagnosticsEngine &Diag,
bool ignoreIfFilesChanged) {
assert(FromToMappings.empty() &&
"initFromDisk should be called before any remap calls");
@@ -59,38 +59,38 @@ bool FileRemapper::initFromDisk(llvm::StringRef outputDir, Diagnostic &Diag,
return false;
std::vector<std::pair<const FileEntry *, const FileEntry *> > pairs;
-
- std::ifstream fin(infoFile.c_str());
- if (!fin.good())
- return report(std::string("Error opening file: ") + infoFile, Diag);
-
- while (true) {
- std::string fromFilename, toFilename;
- uint64_t timeModified;
-
- fin >> fromFilename >> timeModified >> toFilename;
- if (fin.eof())
- break;
- if (!fin.good())
- return report(std::string("Error in format of file: ") + infoFile, Diag);
-
+
+ llvm::OwningPtr<llvm::MemoryBuffer> fileBuf;
+ if (llvm::error_code ec = llvm::MemoryBuffer::getFile(infoFile.c_str(),
+ fileBuf))
+ return report("Error opening file: " + infoFile, Diag);
+
+ SmallVector<StringRef, 64> lines;
+ fileBuf->getBuffer().split(lines, "\n");
+
+ for (unsigned idx = 0; idx+3 <= lines.size(); idx += 3) {
+ StringRef fromFilename = lines[idx];
+ unsigned long long timeModified;
+ lines[idx+1].getAsInteger(10, timeModified);
+ StringRef toFilename = lines[idx+2];
+
const FileEntry *origFE = FileMgr->getFile(fromFilename);
if (!origFE) {
if (ignoreIfFilesChanged)
continue;
- return report(std::string("File does not exist: ") + fromFilename, Diag);
+ return report("File does not exist: " + fromFilename, Diag);
}
const FileEntry *newFE = FileMgr->getFile(toFilename);
if (!newFE) {
if (ignoreIfFilesChanged)
continue;
- return report(std::string("File does not exist: ") + toFilename, Diag);
+ return report("File does not exist: " + toFilename, Diag);
}
if ((uint64_t)origFE->getModificationTime() != timeModified) {
if (ignoreIfFilesChanged)
continue;
- return report(std::string("File was modified: ") + fromFilename, Diag);
+ return report("File was modified: " + fromFilename, Diag);
}
pairs.push_back(std::make_pair(origFE, newFE));
@@ -102,13 +102,12 @@ bool FileRemapper::initFromDisk(llvm::StringRef outputDir, Diagnostic &Diag,
return false;
}
-bool FileRemapper::flushToDisk(llvm::StringRef outputDir, Diagnostic &Diag) {
+bool FileRemapper::flushToDisk(StringRef outputDir, DiagnosticsEngine &Diag) {
using namespace llvm::sys;
bool existed;
if (fs::create_directory(outputDir, existed) != llvm::errc::success)
- return report(std::string("Could not create directory: ") + outputDir.str(),
- Diag);
+ return report("Could not create directory: " + outputDir, Diag);
std::string errMsg;
std::string infoFile = getRemapInfoFile(outputDir);
@@ -121,13 +120,13 @@ bool FileRemapper::flushToDisk(llvm::StringRef outputDir, Diagnostic &Diag) {
I = FromToMappings.begin(), E = FromToMappings.end(); I != E; ++I) {
const FileEntry *origFE = I->first;
- llvm::SmallString<200> origPath = llvm::StringRef(origFE->getName());
+ llvm::SmallString<200> origPath = StringRef(origFE->getName());
fs::make_absolute(origPath);
infoOut << origPath << '\n';
infoOut << (uint64_t)origFE->getModificationTime() << '\n';
if (const FileEntry *FE = I->second.dyn_cast<const FileEntry *>()) {
- llvm::SmallString<200> newPath = llvm::StringRef(FE->getName());
+ llvm::SmallString<200> newPath = StringRef(FE->getName());
fs::make_absolute(newPath);
infoOut << newPath << '\n';
} else {
@@ -138,8 +137,7 @@ bool FileRemapper::flushToDisk(llvm::StringRef outputDir, Diagnostic &Diag) {
tempPath += path::extension(origFE->getName());
int fd;
if (fs::unique_file(tempPath.str(), fd, tempPath) != llvm::errc::success)
- return report(std::string("Could not create file: ") + tempPath.c_str(),
- Diag);
+ return report("Could not create file: " + tempPath.str(), Diag);
llvm::raw_fd_ostream newOut(fd, /*shouldClose=*/true);
llvm::MemoryBuffer *mem = I->second.get<llvm::MemoryBuffer *>();
@@ -156,8 +154,8 @@ bool FileRemapper::flushToDisk(llvm::StringRef outputDir, Diagnostic &Diag) {
return false;
}
-bool FileRemapper::overwriteOriginal(Diagnostic &Diag,
- llvm::StringRef outputDir) {
+bool FileRemapper::overwriteOriginal(DiagnosticsEngine &Diag,
+ StringRef outputDir) {
using namespace llvm::sys;
for (MappingsTy::iterator
@@ -165,20 +163,15 @@ bool FileRemapper::overwriteOriginal(Diagnostic &Diag,
const FileEntry *origFE = I->first;
if (const FileEntry *newFE = I->second.dyn_cast<const FileEntry *>()) {
if (fs::copy_file(newFE->getName(), origFE->getName(),
- fs::copy_option::overwrite_if_exists) != llvm::errc::success) {
- std::string err = "Could not copy file '";
- llvm::raw_string_ostream os(err);
- os << "Could not copy file '" << newFE->getName() << "' to file '"
- << origFE->getName() << "'";
- os.flush();
- return report(err, Diag);
- }
+ fs::copy_option::overwrite_if_exists) != llvm::errc::success)
+ return report(StringRef("Could not copy file '") + newFE->getName() +
+ "' to file '" + origFE->getName() + "'", Diag);
} else {
bool fileExists = false;
fs::exists(origFE->getName(), fileExists);
if (!fileExists)
- return report(std::string("File does not exist: ") + origFE->getName(),
+ return report(StringRef("File does not exist: ") + origFE->getName(),
Diag);
std::string errMsg;
@@ -229,11 +222,11 @@ void FileRemapper::transferMappingsAndClear(CompilerInvocation &CI) {
clear();
}
-void FileRemapper::remap(llvm::StringRef filePath, llvm::MemoryBuffer *memBuf) {
+void FileRemapper::remap(StringRef filePath, llvm::MemoryBuffer *memBuf) {
remap(getOriginalFile(filePath), memBuf);
}
-void FileRemapper::remap(llvm::StringRef filePath, llvm::StringRef newPath) {
+void FileRemapper::remap(StringRef filePath, StringRef newPath) {
const FileEntry *file = getOriginalFile(filePath);
const FileEntry *newfile = FileMgr->getFile(newPath);
remap(file, newfile);
@@ -254,7 +247,7 @@ void FileRemapper::remap(const FileEntry *file, const FileEntry *newfile) {
ToFromMappings[newfile] = file;
}
-const FileEntry *FileRemapper::getOriginalFile(llvm::StringRef filePath) {
+const FileEntry *FileRemapper::getOriginalFile(StringRef filePath) {
const FileEntry *file = FileMgr->getFile(filePath);
// If we are updating a file that overriden an original file,
// actually update the original file.
@@ -283,9 +276,10 @@ void FileRemapper::resetTarget(Target &targ) {
}
}
-bool FileRemapper::report(const std::string &err, Diagnostic &Diag) {
+bool FileRemapper::report(const Twine &err, DiagnosticsEngine &Diag) {
+ llvm::SmallString<128> buf;
unsigned ID = Diag.getDiagnosticIDs()->getCustomDiagID(DiagnosticIDs::Error,
- err);
+ err.toStringRef(buf));
Diag.Report(ID);
return true;
}
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/Internals.h b/contrib/llvm/tools/clang/lib/ARCMigrate/Internals.h
index 4f9b138..46f3bb6 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/Internals.h
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/Internals.h
@@ -26,21 +26,30 @@ class CapturedDiagList {
public:
void push_back(const StoredDiagnostic &diag) { List.push_back(diag); }
- bool clearDiagnostic(llvm::ArrayRef<unsigned> IDs, SourceRange range);
- bool hasDiagnostic(llvm::ArrayRef<unsigned> IDs, SourceRange range) const;
+ bool clearDiagnostic(ArrayRef<unsigned> IDs, SourceRange range);
+ bool hasDiagnostic(ArrayRef<unsigned> IDs, SourceRange range) const;
- void reportDiagnostics(Diagnostic &diags) const;
+ void reportDiagnostics(DiagnosticsEngine &diags) const;
bool hasErrors() const;
+
+ typedef ListTy::const_iterator iterator;
+ iterator begin() const { return List.begin(); }
+ iterator end() const { return List.end(); }
};
+void writeARCDiagsToPlist(const std::string &outPath,
+ ArrayRef<StoredDiagnostic> diags,
+ SourceManager &SM, const LangOptions &LangOpts);
+
class TransformActions {
- Diagnostic &Diags;
+ DiagnosticsEngine &Diags;
CapturedDiagList &CapturedDiags;
+ bool ReportedErrors;
void *Impl; // TransformActionsImpl.
public:
- TransformActions(Diagnostic &diag, CapturedDiagList &capturedDiags,
+ TransformActions(DiagnosticsEngine &diag, CapturedDiagList &capturedDiags,
ASTContext &ctx, Preprocessor &PP);
~TransformActions();
@@ -48,21 +57,21 @@ public:
bool commitTransaction();
void abortTransaction();
- void insert(SourceLocation loc, llvm::StringRef text);
- void insertAfterToken(SourceLocation loc, llvm::StringRef text);
+ void insert(SourceLocation loc, StringRef text);
+ void insertAfterToken(SourceLocation loc, StringRef text);
void remove(SourceRange range);
void removeStmt(Stmt *S);
- void replace(SourceRange range, llvm::StringRef text);
+ void replace(SourceRange range, StringRef text);
void replace(SourceRange range, SourceRange replacementRange);
- void replaceStmt(Stmt *S, llvm::StringRef text);
- void replaceText(SourceLocation loc, llvm::StringRef text,
- llvm::StringRef replacementText);
+ void replaceStmt(Stmt *S, StringRef text);
+ void replaceText(SourceLocation loc, StringRef text,
+ StringRef replacementText);
void increaseIndentation(SourceRange range,
SourceLocation parentIndent);
- bool clearDiagnostic(llvm::ArrayRef<unsigned> IDs, SourceRange range);
+ bool clearDiagnostic(ArrayRef<unsigned> IDs, SourceRange range);
bool clearAllDiagnostics(SourceRange range) {
- return clearDiagnostic(llvm::ArrayRef<unsigned>(), range);
+ return clearDiagnostic(ArrayRef<unsigned>(), range);
}
bool clearDiagnostic(unsigned ID1, unsigned ID2, SourceRange range) {
unsigned IDs[] = { ID1, ID2 };
@@ -83,16 +92,18 @@ public:
return CapturedDiags.hasDiagnostic(IDs, range);
}
- void reportError(llvm::StringRef error, SourceLocation loc,
+ void reportError(StringRef error, SourceLocation loc,
SourceRange range = SourceRange());
- void reportNote(llvm::StringRef note, SourceLocation loc,
+ void reportNote(StringRef note, SourceLocation loc,
SourceRange range = SourceRange());
+ bool hasReportedErrors() const { return ReportedErrors; }
+
class RewriteReceiver {
public:
virtual ~RewriteReceiver();
- virtual void insert(SourceLocation loc, llvm::StringRef text) = 0;
+ virtual void insert(SourceLocation loc, StringRef text) = 0;
virtual void remove(CharSourceRange range) = 0;
virtual void increaseIndentation(CharSourceRange range,
SourceLocation parentIndent) = 0;
@@ -135,9 +146,9 @@ public:
: Ctx(Ctx), SemaRef(sema), TA(TA), ARCMTMacroLocs(ARCMTMacroLocs) { }
};
-bool isARCDiagnostic(unsigned diagID, Diagnostic &Diag);
+bool isARCDiagnostic(unsigned diagID, DiagnosticsEngine &Diag);
-static inline llvm::StringRef getARCMTMacroName() {
+static inline StringRef getARCMTMacroName() {
return "__IMPL_ARCMT_REMOVED_EXPR__";
}
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/Makefile b/contrib/llvm/tools/clang/lib/ARCMigrate/Makefile
deleted file mode 100644
index 5232c5e..0000000
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-##===- clang/lib/ARCMigrate/Makefile --------------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-#
-# This implements code transformation to ARC mode.
-#
-##===----------------------------------------------------------------------===##
-
-CLANG_LEVEL := ../..
-LIBRARYNAME := clangARCMigrate
-
-include $(CLANG_LEVEL)/Makefile
-
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/PlistReporter.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/PlistReporter.cpp
new file mode 100644
index 0000000..d1bc90f
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/PlistReporter.cpp
@@ -0,0 +1,195 @@
+//===--- PlistReporter.cpp - ARC Migrate Tool Plist Reporter ----*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Internals.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/FileManager.h"
+using namespace clang;
+using namespace arcmt;
+
+// FIXME: This duplicates significant functionality from PlistDiagnostics.cpp,
+// it would be jolly good if there was a reusable PlistWriter or something.
+
+typedef llvm::DenseMap<FileID, unsigned> FIDMap;
+
+static void AddFID(FIDMap &FIDs, SmallVectorImpl<FileID> &V,
+ const SourceManager &SM, SourceLocation L) {
+
+ FileID FID = SM.getFileID(SM.getExpansionLoc(L));
+ FIDMap::iterator I = FIDs.find(FID);
+ if (I != FIDs.end()) return;
+ FIDs[FID] = V.size();
+ V.push_back(FID);
+}
+
+static unsigned GetFID(const FIDMap& FIDs, const SourceManager &SM,
+ SourceLocation L) {
+ FileID FID = SM.getFileID(SM.getExpansionLoc(L));
+ FIDMap::const_iterator I = FIDs.find(FID);
+ assert(I != FIDs.end());
+ return I->second;
+}
+
+static raw_ostream& Indent(raw_ostream& o, const unsigned indent) {
+ for (unsigned i = 0; i < indent; ++i) o << ' ';
+ return o;
+}
+
+static void EmitLocation(raw_ostream& o, const SourceManager &SM,
+ const LangOptions &LangOpts,
+ SourceLocation L, const FIDMap &FM,
+ unsigned indent, bool extend = false) {
+
+ FullSourceLoc Loc(SM.getExpansionLoc(L), const_cast<SourceManager&>(SM));
+
+ // Add in the length of the token, so that we cover multi-char tokens.
+ unsigned offset =
+ extend ? Lexer::MeasureTokenLength(Loc, SM, LangOpts) - 1 : 0;
+
+ Indent(o, indent) << "<dict>\n";
+ Indent(o, indent) << " <key>line</key><integer>"
+ << Loc.getExpansionLineNumber() << "</integer>\n";
+ Indent(o, indent) << " <key>col</key><integer>"
+ << Loc.getExpansionColumnNumber() + offset << "</integer>\n";
+ Indent(o, indent) << " <key>file</key><integer>"
+ << GetFID(FM, SM, Loc) << "</integer>\n";
+ Indent(o, indent) << "</dict>\n";
+}
+
+static void EmitRange(raw_ostream& o, const SourceManager &SM,
+ const LangOptions &LangOpts,
+ CharSourceRange R, const FIDMap &FM,
+ unsigned indent) {
+ Indent(o, indent) << "<array>\n";
+ EmitLocation(o, SM, LangOpts, R.getBegin(), FM, indent+1);
+ EmitLocation(o, SM, LangOpts, R.getEnd(), FM, indent+1, R.isTokenRange());
+ Indent(o, indent) << "</array>\n";
+}
+
+static raw_ostream& EmitString(raw_ostream& o,
+ StringRef s) {
+ o << "<string>";
+ for (StringRef::const_iterator I=s.begin(), E=s.end(); I!=E; ++I) {
+ char c = *I;
+ switch (c) {
+ default: o << c; break;
+ case '&': o << "&amp;"; break;
+ case '<': o << "&lt;"; break;
+ case '>': o << "&gt;"; break;
+ case '\'': o << "&apos;"; break;
+ case '\"': o << "&quot;"; break;
+ }
+ }
+ o << "</string>";
+ return o;
+}
+
+void arcmt::writeARCDiagsToPlist(const std::string &outPath,
+ ArrayRef<StoredDiagnostic> diags,
+ SourceManager &SM,
+ const LangOptions &LangOpts) {
+ DiagnosticIDs DiagIDs;
+
+ // Build up a set of FIDs that we use by scanning the locations and
+ // ranges of the diagnostics.
+ FIDMap FM;
+ SmallVector<FileID, 10> Fids;
+
+ for (ArrayRef<StoredDiagnostic>::iterator
+ I = diags.begin(), E = diags.end(); I != E; ++I) {
+ const StoredDiagnostic &D = *I;
+
+ AddFID(FM, Fids, SM, D.getLocation());
+
+ for (StoredDiagnostic::range_iterator
+ RI = D.range_begin(), RE = D.range_end(); RI != RE; ++RI) {
+ AddFID(FM, Fids, SM, RI->getBegin());
+ AddFID(FM, Fids, SM, RI->getEnd());
+ }
+ }
+
+ std::string errMsg;
+ llvm::raw_fd_ostream o(outPath.c_str(), errMsg);
+ if (!errMsg.empty()) {
+ llvm::errs() << "error: could not create file: " << outPath << '\n';
+ return;
+ }
+
+ // Write the plist header.
+ o << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" "
+ "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n"
+ "<plist version=\"1.0\">\n";
+
+ // Write the root object: a <dict> containing...
+ // - "files", an <array> mapping from FIDs to file names
+ // - "diagnostics", an <array> containing the diagnostics
+ o << "<dict>\n"
+ " <key>files</key>\n"
+ " <array>\n";
+
+ for (SmallVectorImpl<FileID>::iterator I=Fids.begin(), E=Fids.end();
+ I!=E; ++I) {
+ o << " ";
+ EmitString(o, SM.getFileEntryForID(*I)->getName()) << '\n';
+ }
+
+ o << " </array>\n"
+ " <key>diagnostics</key>\n"
+ " <array>\n";
+
+ for (ArrayRef<StoredDiagnostic>::iterator
+ DI = diags.begin(), DE = diags.end(); DI != DE; ++DI) {
+
+ const StoredDiagnostic &D = *DI;
+
+ if (D.getLevel() == DiagnosticsEngine::Ignored)
+ continue;
+
+ o << " <dict>\n";
+
+ // Output the diagnostic.
+ o << " <key>description</key>";
+ EmitString(o, D.getMessage()) << '\n';
+ o << " <key>category</key>";
+ EmitString(o, DiagIDs.getCategoryNameFromID(
+ DiagIDs.getCategoryNumberForDiag(D.getID()))) << '\n';
+ o << " <key>type</key>";
+ if (D.getLevel() >= DiagnosticsEngine::Error)
+ EmitString(o, "error") << '\n';
+ else if (D.getLevel() == DiagnosticsEngine::Warning)
+ EmitString(o, "warning") << '\n';
+ else
+ EmitString(o, "note") << '\n';
+
+ // Output the location of the bug.
+ o << " <key>location</key>\n";
+ EmitLocation(o, SM, LangOpts, D.getLocation(), FM, 2);
+
+ // Output the ranges (if any).
+ StoredDiagnostic::range_iterator RI = D.range_begin(), RE = D.range_end();
+
+ if (RI != RE) {
+ o << " <key>ranges</key>\n";
+ o << " <array>\n";
+ for (; RI != RE; ++RI)
+ EmitRange(o, SM, LangOpts, *RI, FM, 4);
+ o << " </array>\n";
+ }
+
+ // Close up the entry.
+ o << " </dict>\n";
+ }
+
+ o << " </array>\n";
+
+ // Finish.
+ o << "</dict>\n</plist>";
+}
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransAPIUses.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransAPIUses.cpp
new file mode 100644
index 0000000..aaa82d8
--- /dev/null
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransAPIUses.cpp
@@ -0,0 +1,109 @@
+//===--- TransAPIUses.cpp - Tranformations to ARC mode --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// checkAPIUses:
+//
+// Emits error/fix with some API uses that are obsolete or not safe in ARC mode:
+//
+// - NSInvocation's [get/set]ReturnValue and [get/set]Argument are only safe
+// with __unsafe_unretained objects.
+// - Calling -zone gets replaced with 'nil'.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Transforms.h"
+#include "Internals.h"
+#include "clang/Sema/SemaDiagnostic.h"
+
+using namespace clang;
+using namespace arcmt;
+using namespace trans;
+
+namespace {
+
+class APIChecker : public RecursiveASTVisitor<APIChecker> {
+ MigrationPass &Pass;
+
+ Selector getReturnValueSel, setReturnValueSel;
+ Selector getArgumentSel, setArgumentSel;
+
+ Selector zoneSel;
+public:
+ APIChecker(MigrationPass &pass) : Pass(pass) {
+ SelectorTable &sels = Pass.Ctx.Selectors;
+ IdentifierTable &ids = Pass.Ctx.Idents;
+ getReturnValueSel = sels.getUnarySelector(&ids.get("getReturnValue"));
+ setReturnValueSel = sels.getUnarySelector(&ids.get("setReturnValue"));
+
+ IdentifierInfo *selIds[2];
+ selIds[0] = &ids.get("getArgument");
+ selIds[1] = &ids.get("atIndex");
+ getArgumentSel = sels.getSelector(2, selIds);
+ selIds[0] = &ids.get("setArgument");
+ setArgumentSel = sels.getSelector(2, selIds);
+
+ zoneSel = sels.getNullarySelector(&ids.get("zone"));
+ }
+
+ bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
+ // NSInvocation.
+ if (E->isInstanceMessage() &&
+ E->getReceiverInterface() &&
+ E->getReceiverInterface()->getName() == "NSInvocation") {
+ StringRef selName;
+ if (E->getSelector() == getReturnValueSel)
+ selName = "getReturnValue";
+ else if (E->getSelector() == setReturnValueSel)
+ selName = "setReturnValue";
+ else if (E->getSelector() == getArgumentSel)
+ selName = "getArgument";
+ else if (E->getSelector() == setArgumentSel)
+ selName = "setArgument";
+
+ if (selName.empty())
+ return true;
+
+ Expr *parm = E->getArg(0)->IgnoreParenCasts();
+ QualType pointee = parm->getType()->getPointeeType();
+ if (pointee.isNull())
+ return true;
+
+ if (pointee.getObjCLifetime() > Qualifiers::OCL_ExplicitNone) {
+ std::string err = "NSInvocation's ";
+ err += selName;
+ err += " is not safe to be used with an object with ownership other "
+ "than __unsafe_unretained";
+ Pass.TA.reportError(err, parm->getLocStart(), parm->getSourceRange());
+ }
+ return true;
+ }
+
+ // -zone.
+ if (E->isInstanceMessage() &&
+ E->getInstanceReceiver() &&
+ E->getSelector() == zoneSel &&
+ Pass.TA.hasDiagnostic(diag::err_unavailable,
+ diag::err_unavailable_message,
+ E->getInstanceReceiver()->getExprLoc())) {
+ // Calling -zone is meaningless in ARC, change it to nil.
+ Transaction Trans(Pass.TA);
+ Pass.TA.clearDiagnostic(diag::err_unavailable,
+ diag::err_unavailable_message,
+ E->getInstanceReceiver()->getExprLoc());
+ Pass.TA.replace(E->getSourceRange(), getNilString(Pass.Ctx));
+ }
+ return true;
+ }
+};
+
+} // anonymous namespace
+
+void trans::checkAPIUses(MigrationPass &pass) {
+ APIChecker(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl());
+}
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransARCAssign.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransARCAssign.cpp
index 8c00df5..1f10196 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransARCAssign.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransARCAssign.cpp
@@ -28,7 +28,6 @@
using namespace clang;
using namespace arcmt;
using namespace trans;
-using llvm::StringRef;
namespace {
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransAutoreleasePool.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransAutoreleasePool.cpp
index 5b84854..08561f9 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransAutoreleasePool.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransAutoreleasePool.cpp
@@ -36,16 +36,15 @@
using namespace clang;
using namespace arcmt;
using namespace trans;
-using llvm::StringRef;
namespace {
class ReleaseCollector : public RecursiveASTVisitor<ReleaseCollector> {
Decl *Dcl;
- llvm::SmallVectorImpl<ObjCMessageExpr *> &Releases;
+ SmallVectorImpl<ObjCMessageExpr *> &Releases;
public:
- ReleaseCollector(Decl *D, llvm::SmallVectorImpl<ObjCMessageExpr *> &releases)
+ ReleaseCollector(Decl *D, SmallVectorImpl<ObjCMessageExpr *> &releases)
: Dcl(D), Releases(releases) { }
bool VisitObjCMessageExpr(ObjCMessageExpr *E) {
@@ -82,7 +81,7 @@ public:
}
~AutoreleasePoolRewriter() {
- llvm::SmallVector<VarDecl *, 8> VarsToHandle;
+ SmallVector<VarDecl *, 8> VarsToHandle;
for (std::map<VarDecl *, PoolVarInfo>::iterator
I = PoolVars.begin(), E = PoolVars.end(); I != E; ++I) {
@@ -92,7 +91,7 @@ public:
// Check that we can handle/rewrite all references of the pool.
clearRefsIn(info.Dcl, info.Refs);
- for (llvm::SmallVectorImpl<PoolScope>::iterator
+ for (SmallVectorImpl<PoolScope>::iterator
scpI = info.Scopes.begin(),
scpE = info.Scopes.end(); scpI != scpE; ++scpI) {
PoolScope &scope = *scpI;
@@ -116,7 +115,7 @@ public:
Pass.TA.removeStmt(info.Dcl);
// Add "@autoreleasepool { }"
- for (llvm::SmallVectorImpl<PoolScope>::iterator
+ for (SmallVectorImpl<PoolScope>::iterator
scpI = info.Scopes.begin(),
scpE = info.Scopes.end(); scpI != scpE; ++scpI) {
PoolScope &scope = *scpI;
@@ -147,11 +146,11 @@ public:
}
// Remove rest of pool var references.
- for (llvm::SmallVectorImpl<PoolScope>::iterator
+ for (SmallVectorImpl<PoolScope>::iterator
scpI = info.Scopes.begin(),
scpE = info.Scopes.end(); scpI != scpE; ++scpI) {
PoolScope &scope = *scpI;
- for (llvm::SmallVectorImpl<ObjCMessageExpr *>::iterator
+ for (SmallVectorImpl<ObjCMessageExpr *>::iterator
relI = scope.Releases.begin(),
relE = scope.Releases.end(); relI != relE; ++relI) {
clearUnavailableDiags(*relI);
@@ -162,7 +161,7 @@ public:
}
bool VisitCompoundStmt(CompoundStmt *S) {
- llvm::SmallVector<PoolScope, 4> Scopes;
+ SmallVector<PoolScope, 4> Scopes;
for (Stmt::child_iterator
I = S->body_begin(), E = S->body_end(); I != E; ++I) {
@@ -228,7 +227,7 @@ private:
Stmt::child_iterator Begin;
Stmt::child_iterator End;
bool IsFollowedBySimpleReturnStmt;
- llvm::SmallVector<ObjCMessageExpr *, 4> Releases;
+ SmallVector<ObjCMessageExpr *, 4> Releases;
PoolScope() : PoolVar(0), CompoundParent(0), Begin(), End(),
IsFollowedBySimpleReturnStmt(false) { }
@@ -287,6 +286,9 @@ private:
}
bool isInScope(SourceLocation loc) {
+ if (loc.isInvalid())
+ return false;
+
SourceManager &SM = Ctx.getSourceManager();
if (SM.isBeforeInTranslationUnit(loc, ScopeRange.getBegin()))
return false;
@@ -420,7 +422,7 @@ private:
struct PoolVarInfo {
DeclStmt *Dcl;
ExprSet Refs;
- llvm::SmallVector<PoolScope, 2> Scopes;
+ SmallVector<PoolScope, 2> Scopes;
PoolVarInfo() : Dcl(0) { }
};
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp
index 0e342b7..48c0ca9 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransBlockObjCVariable.cpp
@@ -32,7 +32,6 @@
using namespace clang;
using namespace arcmt;
using namespace trans;
-using llvm::StringRef;
namespace {
@@ -75,7 +74,7 @@ public:
RootBlockObjCVarRewriter(MigrationPass &pass) : Pass(pass) { }
bool VisitBlockDecl(BlockDecl *block) {
- llvm::SmallVector<VarDecl *, 4> BlockVars;
+ SmallVector<VarDecl *, 4> BlockVars;
for (BlockDecl::capture_iterator
I = block->capture_begin(), E = block->capture_end(); I != E; ++I) {
@@ -101,7 +100,7 @@ public:
bool useWeak = canApplyWeak(Pass.Ctx, var->getType());
SourceManager &SM = Pass.Ctx.getSourceManager();
Transaction Trans(Pass.TA);
- Pass.TA.replaceText(SM.getInstantiationLoc(attr->getLocation()),
+ Pass.TA.replaceText(SM.getExpansionLoc(attr->getLocation()),
"__block",
useWeak ? "__weak" : "__unsafe_unretained");
}
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
index d0bc332..3ad05e6 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp
@@ -22,11 +22,53 @@
#include "Transforms.h"
#include "Internals.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/Basic/SourceManager.h"
using namespace clang;
using namespace arcmt;
using namespace trans;
-using llvm::StringRef;
+
+static bool isEmptyARCMTMacroStatement(NullStmt *S,
+ std::vector<SourceLocation> &MacroLocs,
+ ASTContext &Ctx) {
+ if (!S->hasLeadingEmptyMacro())
+ return false;
+
+ SourceLocation SemiLoc = S->getSemiLoc();
+ if (SemiLoc.isInvalid() || SemiLoc.isMacroID())
+ return false;
+
+ if (MacroLocs.empty())
+ return false;
+
+ SourceManager &SM = Ctx.getSourceManager();
+ std::vector<SourceLocation>::iterator
+ I = std::upper_bound(MacroLocs.begin(), MacroLocs.end(), SemiLoc,
+ SourceManager::LocBeforeThanCompare(SM));
+ --I;
+ SourceLocation
+ AfterMacroLoc = I->getLocWithOffset(getARCMTMacroName().size());
+ assert(AfterMacroLoc.isFileID());
+
+ if (AfterMacroLoc == SemiLoc)
+ return true;
+
+ int RelOffs = 0;
+ if (!SM.isInSameSLocAddrSpace(AfterMacroLoc, SemiLoc, &RelOffs))
+ return false;
+ if (RelOffs < 0)
+ return false;
+
+ // We make the reasonable assumption that a semicolon after 100 characters
+ // means that it is not the next token after our macro. If this assumption
+ // fails it is not critical, we will just fail to clear out, e.g., an empty
+ // 'if'.
+ if (RelOffs - getARCMTMacroName().size() > 100)
+ return false;
+
+ SourceLocation AfterMacroSemiLoc = findSemiAfterLocation(AfterMacroLoc, Ctx);
+ return AfterMacroSemiLoc == SemiLoc;
+}
namespace {
@@ -34,14 +76,14 @@ namespace {
/// transformations.
class EmptyChecker : public StmtVisitor<EmptyChecker, bool> {
ASTContext &Ctx;
- llvm::DenseSet<unsigned> &MacroLocs;
+ std::vector<SourceLocation> &MacroLocs;
public:
- EmptyChecker(ASTContext &ctx, llvm::DenseSet<unsigned> &macroLocs)
+ EmptyChecker(ASTContext &ctx, std::vector<SourceLocation> &macroLocs)
: Ctx(ctx), MacroLocs(macroLocs) { }
bool VisitNullStmt(NullStmt *S) {
- return isMacroLoc(S->getLeadingEmptyMacroLoc());
+ return isEmptyARCMTMacroStatement(S, MacroLocs, Ctx);
}
bool VisitCompoundStmt(CompoundStmt *S) {
if (S->body_empty())
@@ -103,23 +145,14 @@ public:
return false;
return Visit(S->getSubStmt());
}
-
-private:
- bool isMacroLoc(SourceLocation loc) {
- if (loc.isInvalid()) return false;
- return MacroLocs.count(loc.getRawEncoding());
- }
};
class EmptyStatementsRemover :
public RecursiveASTVisitor<EmptyStatementsRemover> {
MigrationPass &Pass;
- llvm::DenseSet<unsigned> &MacroLocs;
public:
- EmptyStatementsRemover(MigrationPass &pass,
- llvm::DenseSet<unsigned> &macroLocs)
- : Pass(pass), MacroLocs(macroLocs) { }
+ EmptyStatementsRemover(MigrationPass &pass) : Pass(pass) { }
bool TraverseStmtExpr(StmtExpr *E) {
CompoundStmt *S = E->getSubStmt();
@@ -139,17 +172,12 @@ public:
return true;
}
- bool isMacroLoc(SourceLocation loc) {
- if (loc.isInvalid()) return false;
- return MacroLocs.count(loc.getRawEncoding());
- }
-
ASTContext &getContext() { return Pass.Ctx; }
private:
void check(Stmt *S) {
if (!S) return;
- if (EmptyChecker(Pass.Ctx, MacroLocs).Visit(S)) {
+ if (EmptyChecker(Pass.Ctx, Pass.ARCMTMacroLocs).Visit(S)) {
Transaction Trans(Pass.TA);
Pass.TA.removeStmt(S);
}
@@ -158,8 +186,8 @@ private:
} // anonymous namespace
-static bool isBodyEmpty(CompoundStmt *body,
- ASTContext &Ctx, llvm::DenseSet<unsigned> &MacroLocs) {
+static bool isBodyEmpty(CompoundStmt *body, ASTContext &Ctx,
+ std::vector<SourceLocation> &MacroLocs) {
for (CompoundStmt::body_iterator
I = body->body_begin(), E = body->body_end(); I != E; ++I)
if (!EmptyChecker(Ctx, MacroLocs).Visit(*I))
@@ -168,8 +196,7 @@ static bool isBodyEmpty(CompoundStmt *body,
return true;
}
-static void removeDeallocMethod(MigrationPass &pass,
- llvm::DenseSet<unsigned> &MacroLocs) {
+static void removeDeallocMethod(MigrationPass &pass) {
ASTContext &Ctx = pass.Ctx;
TransformActions &TA = pass.TA;
DeclContext *DC = Ctx.getTranslationUnitDecl();
@@ -184,7 +211,7 @@ static void removeDeallocMethod(MigrationPass &pass,
ObjCMethodDecl *MD = *MI;
if (MD->getMethodFamily() == OMF_dealloc) {
if (MD->hasBody() &&
- isBodyEmpty(MD->getCompoundBody(), Ctx, MacroLocs)) {
+ isBodyEmpty(MD->getCompoundBody(), Ctx, pass.ARCMTMacroLocs)) {
Transaction Trans(TA);
TA.remove(MD->getSourceRange());
}
@@ -195,14 +222,9 @@ static void removeDeallocMethod(MigrationPass &pass,
}
void trans::removeEmptyStatementsAndDealloc(MigrationPass &pass) {
- llvm::DenseSet<unsigned> MacroLocs;
- for (unsigned i = 0, e = pass.ARCMTMacroLocs.size(); i != e; ++i)
- MacroLocs.insert(pass.ARCMTMacroLocs[i].getRawEncoding());
-
- EmptyStatementsRemover(pass, MacroLocs)
- .TraverseDecl(pass.Ctx.getTranslationUnitDecl());
+ EmptyStatementsRemover(pass).TraverseDecl(pass.Ctx.getTranslationUnitDecl());
- removeDeallocMethod(pass, MacroLocs);
+ removeDeallocMethod(pass);
for (unsigned i = 0, e = pass.ARCMTMacroLocs.size(); i != e; ++i) {
Transaction Trans(pass.TA);
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransProperties.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransProperties.cpp
index 872c95e..ca845b6 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransProperties.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransProperties.cpp
@@ -40,12 +40,12 @@
using namespace clang;
using namespace arcmt;
using namespace trans;
-using llvm::StringRef;
namespace {
class PropertiesRewriter {
MigrationPass &Pass;
+ ObjCImplementationDecl *CurImplD;
struct PropData {
ObjCPropertyDecl *PropD;
@@ -55,7 +55,7 @@ class PropertiesRewriter {
PropData(ObjCPropertyDecl *propD) : PropD(propD), IvarD(0), ImplD(0) { }
};
- typedef llvm::SmallVector<PropData, 2> PropsTy;
+ typedef SmallVector<PropData, 2> PropsTy;
typedef std::map<unsigned, PropsTy> AtPropDeclsTy;
AtPropDeclsTy AtProps;
@@ -63,6 +63,7 @@ public:
PropertiesRewriter(MigrationPass &pass) : Pass(pass) { }
void doTransform(ObjCImplementationDecl *D) {
+ CurImplD = D;
ObjCInterfaceDecl *iface = D->getClassInterface();
if (!iface)
return;
@@ -135,8 +136,16 @@ private:
return;
}
- if (propAttrs & ObjCPropertyDecl::OBJC_PR_assign)
+ if (propAttrs & ObjCPropertyDecl::OBJC_PR_assign) {
+ if (hasIvarAssignedAPlusOneObject(props)) {
+ rewriteAttribute("assign", "strong", atLoc);
+ return;
+ }
return rewriteAssign(props, atLoc);
+ }
+
+ if (hasIvarAssignedAPlusOneObject(props))
+ return maybeAddStrongAttr(props, atLoc);
return maybeAddWeakOrUnsafeUnretainedAttr(props, atLoc);
}
@@ -163,15 +172,15 @@ private:
void maybeAddWeakOrUnsafeUnretainedAttr(PropsTy &props,
SourceLocation atLoc) const {
ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props);
- if ((propAttrs & ObjCPropertyDecl::OBJC_PR_readonly) &&
- hasNoBackingIvars(props))
- return;
bool canUseWeak = canApplyWeak(Pass.Ctx, getPropertyType(props));
- bool addedAttr = addAttribute(canUseWeak ? "weak" : "unsafe_unretained",
- atLoc);
- if (!addedAttr)
- canUseWeak = false;
+ if (!(propAttrs & ObjCPropertyDecl::OBJC_PR_readonly) ||
+ !hasAllIvarsBacked(props)) {
+ bool addedAttr = addAttribute(canUseWeak ? "weak" : "unsafe_unretained",
+ atLoc);
+ if (!addedAttr)
+ canUseWeak = false;
+ }
for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
if (isUserDeclared(I->IvarD))
@@ -187,7 +196,26 @@ private:
}
}
- bool rewriteAttribute(llvm::StringRef fromAttr, llvm::StringRef toAttr,
+ void maybeAddStrongAttr(PropsTy &props, SourceLocation atLoc) const {
+ ObjCPropertyDecl::PropertyAttributeKind propAttrs = getPropertyAttrs(props);
+
+ if (!(propAttrs & ObjCPropertyDecl::OBJC_PR_readonly) ||
+ !hasAllIvarsBacked(props)) {
+ addAttribute("strong", atLoc);
+ }
+
+ for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
+ if (I->ImplD) {
+ Pass.TA.clearDiagnostic(diag::err_arc_assign_property_ownership,
+ I->ImplD->getLocation());
+ Pass.TA.clearDiagnostic(
+ diag::err_arc_objc_property_default_assign_on_object,
+ I->ImplD->getLocation());
+ }
+ }
+ }
+
+ bool rewriteAttribute(StringRef fromAttr, StringRef toAttr,
SourceLocation atLoc) const {
if (atLoc.isMacroID())
return false;
@@ -199,7 +227,7 @@ private:
// Try to load the file buffer.
bool invalidTemp = false;
- llvm::StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
+ StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
if (invalidTemp)
return false;
@@ -214,7 +242,7 @@ private:
if (tok.isNot(tok::at)) return false;
lexer.LexFromRawLexer(tok);
if (tok.isNot(tok::raw_identifier)) return false;
- if (llvm::StringRef(tok.getRawIdentifierData(), tok.getLength())
+ if (StringRef(tok.getRawIdentifierData(), tok.getLength())
!= "property")
return false;
lexer.LexFromRawLexer(tok);
@@ -226,7 +254,7 @@ private:
while (1) {
if (tok.isNot(tok::raw_identifier)) return false;
- llvm::StringRef ident(tok.getRawIdentifierData(), tok.getLength());
+ StringRef ident(tok.getRawIdentifierData(), tok.getLength());
if (ident == fromAttr) {
Pass.TA.replaceText(tok.getLocation(), fromAttr, toAttr);
return true;
@@ -243,7 +271,7 @@ private:
return false;
}
- bool addAttribute(llvm::StringRef attr, SourceLocation atLoc) const {
+ bool addAttribute(StringRef attr, SourceLocation atLoc) const {
if (atLoc.isMacroID())
return false;
@@ -254,7 +282,7 @@ private:
// Try to load the file buffer.
bool invalidTemp = false;
- llvm::StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
+ StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
if (invalidTemp)
return false;
@@ -269,7 +297,7 @@ private:
if (tok.isNot(tok::at)) return false;
lexer.LexFromRawLexer(tok);
if (tok.isNot(tok::raw_identifier)) return false;
- if (llvm::StringRef(tok.getRawIdentifierData(), tok.getLength())
+ if (StringRef(tok.getRawIdentifierData(), tok.getLength())
!= "property")
return false;
lexer.LexFromRawLexer(tok);
@@ -291,6 +319,45 @@ private:
return true;
}
+ class PlusOneAssign : public RecursiveASTVisitor<PlusOneAssign> {
+ ObjCIvarDecl *Ivar;
+ public:
+ PlusOneAssign(ObjCIvarDecl *D) : Ivar(D) {}
+
+ bool VisitBinAssign(BinaryOperator *E) {
+ Expr *lhs = E->getLHS()->IgnoreParenImpCasts();
+ if (ObjCIvarRefExpr *RE = dyn_cast<ObjCIvarRefExpr>(lhs)) {
+ if (RE->getDecl() != Ivar)
+ return true;
+
+ if (ObjCMessageExpr *
+ ME = dyn_cast<ObjCMessageExpr>(E->getRHS()->IgnoreParenCasts()))
+ if (ME->getMethodFamily() == OMF_retain)
+ return false;
+
+ ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(E->getRHS());
+ while (implCE && implCE->getCastKind() == CK_BitCast)
+ implCE = dyn_cast<ImplicitCastExpr>(implCE->getSubExpr());
+
+ if (implCE && implCE->getCastKind() == CK_ARCConsumeObject)
+ return false;
+ }
+
+ return true;
+ }
+ };
+
+ bool hasIvarAssignedAPlusOneObject(PropsTy &props) const {
+ for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
+ PlusOneAssign oneAssign(I->IvarD);
+ bool notFound = oneAssign.TraverseDecl(CurImplD);
+ if (!notFound)
+ return true;
+ }
+
+ return false;
+ }
+
bool hasIvarWithExplicitOwnership(PropsTy &props) const {
for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) {
if (isUserDeclared(I->IvarD)) {
@@ -305,9 +372,9 @@ private:
return false;
}
- bool hasNoBackingIvars(PropsTy &props) const {
+ bool hasAllIvarsBacked(PropsTy &props) const {
for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I)
- if (I->IvarD)
+ if (!isUserDeclared(I->IvarD))
return false;
return true;
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
index ed6ed0a..394f848 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransRetainReleaseDealloc.cpp
@@ -25,7 +25,6 @@
using namespace clang;
using namespace arcmt;
using namespace trans;
-using llvm::StringRef;
namespace {
@@ -130,10 +129,9 @@ public:
// Change the -release to "receiver = nil" in a finally to avoid a leak
// when an exception is thrown.
Pass.TA.replace(E->getSourceRange(), rec->getSourceRange());
- if (Pass.Ctx.Idents.get("nil").hasMacroDefinition())
- Pass.TA.insertAfterToken(rec->getLocEnd(), " = nil");
- else
- Pass.TA.insertAfterToken(rec->getLocEnd(), " = 0");
+ std::string str = " = ";
+ str += getNilString(Pass.Ctx);
+ Pass.TA.insertAfterToken(rec->getLocEnd(), str);
return true;
}
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransUnbridgedCasts.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransUnbridgedCasts.cpp
index 1cacd6d..69fb2e8 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransUnbridgedCasts.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransUnbridgedCasts.cpp
@@ -36,25 +36,32 @@
#include "Internals.h"
#include "clang/Analysis/DomainSpecific/CocoaConventions.h"
#include "clang/Sema/SemaDiagnostic.h"
+#include "clang/AST/ParentMap.h"
#include "clang/Basic/SourceManager.h"
using namespace clang;
using namespace arcmt;
using namespace trans;
-using llvm::StringRef;
namespace {
class UnbridgedCastRewriter : public RecursiveASTVisitor<UnbridgedCastRewriter>{
MigrationPass &Pass;
IdentifierInfo *SelfII;
+ llvm::OwningPtr<ParentMap> StmtMap;
+
public:
UnbridgedCastRewriter(MigrationPass &pass) : Pass(pass) {
SelfII = &Pass.Ctx.Idents.get("self");
}
+ void transformBody(Stmt *body) {
+ StmtMap.reset(new ParentMap(body));
+ TraverseStmt(body);
+ }
+
bool VisitCastExpr(CastExpr *E) {
- if (E->getCastKind() != CK_AnyPointerToObjCPointerCast
+ if (E->getCastKind() != CK_CPointerToObjCPointerCast
&& E->getCastKind() != CK_BitCast)
return true;
@@ -139,13 +146,21 @@ private:
}
void rewriteToBridgedCast(CastExpr *E, ObjCBridgeCastKind Kind) {
+ Transaction Trans(Pass.TA);
+ rewriteToBridgedCast(E, Kind, Trans);
+ }
+
+ void rewriteToBridgedCast(CastExpr *E, ObjCBridgeCastKind Kind,
+ Transaction &Trans) {
TransformActions &TA = Pass.TA;
// We will remove the compiler diagnostic.
if (!TA.hasDiagnostic(diag::err_arc_mismatched_cast,
diag::err_arc_cast_requires_bridge,
- E->getLocStart()))
+ E->getLocStart())) {
+ Trans.abort();
return;
+ }
StringRef bridge;
switch(Kind) {
@@ -157,7 +172,6 @@ private:
bridge = "__bridge_retained "; break;
}
- Transaction Trans(TA);
TA.clearDiagnostic(diag::err_arc_mismatched_cast,
diag::err_arc_cast_requires_bridge,
E->getLocStart());
@@ -168,7 +182,7 @@ private:
llvm::SmallString<128> newCast;
newCast += '(';
newCast += bridge;
- newCast += E->getType().getAsString(Pass.Ctx.PrintingPolicy);
+ newCast += E->getType().getAsString(Pass.Ctx.getPrintingPolicy());
newCast += ')';
if (isa<ParenExpr>(E->getSubExpr())) {
@@ -181,16 +195,111 @@ private:
}
}
+ void rewriteCastForCFRetain(CastExpr *castE, CallExpr *callE) {
+ Transaction Trans(Pass.TA);
+ Pass.TA.replace(callE->getSourceRange(), callE->getArg(0)->getSourceRange());
+ rewriteToBridgedCast(castE, OBC_BridgeRetained, Trans);
+ }
+
void transformObjCToNonObjCCast(CastExpr *E) {
if (isSelf(E->getSubExpr()))
return rewriteToBridgedCast(E, OBC_Bridge);
+
+ CallExpr *callE;
+ if (isPassedToCFRetain(E, callE))
+ return rewriteCastForCFRetain(E, callE);
+
+ ObjCMethodFamily family = getFamilyOfMessage(E->getSubExpr());
+ if (family == OMF_retain)
+ return rewriteToBridgedCast(E, OBC_BridgeRetained);
+
+ if (family == OMF_autorelease || family == OMF_release) {
+ std::string err = "it is not safe to cast to '";
+ err += E->getType().getAsString(Pass.Ctx.getPrintingPolicy());
+ err += "' the result of '";
+ err += family == OMF_autorelease ? "autorelease" : "release";
+ err += "' message; a __bridge cast may result in a pointer to a "
+ "destroyed object and a __bridge_retained may leak the object";
+ Pass.TA.reportError(err, E->getLocStart(),
+ E->getSubExpr()->getSourceRange());
+ Stmt *parent = E;
+ do {
+ parent = StmtMap->getParentIgnoreParenImpCasts(parent);
+ } while (parent && isa<ExprWithCleanups>(parent));
+
+ if (ReturnStmt *retS = dyn_cast_or_null<ReturnStmt>(parent)) {
+ std::string note = "remove the cast and change return type of function "
+ "to '";
+ note += E->getSubExpr()->getType().getAsString(Pass.Ctx.getPrintingPolicy());
+ note += "' to have the object automatically autoreleased";
+ Pass.TA.reportNote(note, retS->getLocStart());
+ }
+ }
+
+ if (ImplicitCastExpr *implCE = dyn_cast<ImplicitCastExpr>(E->getSubExpr())){
+ if (implCE->getCastKind() == CK_ARCConsumeObject)
+ return rewriteToBridgedCast(E, OBC_BridgeRetained);
+ if (implCE->getCastKind() == CK_ARCReclaimReturnedObject)
+ return rewriteToBridgedCast(E, OBC_Bridge);
+ }
+
+ bool isConsumed = false;
+ if (isPassedToCParamWithKnownOwnership(E, isConsumed))
+ return rewriteToBridgedCast(E, isConsumed ? OBC_BridgeRetained
+ : OBC_Bridge);
}
- bool isSelf(Expr *E) {
+ static ObjCMethodFamily getFamilyOfMessage(Expr *E) {
+ E = E->IgnoreParenCasts();
+ if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E))
+ return ME->getMethodFamily();
+
+ return OMF_None;
+ }
+
+ bool isPassedToCFRetain(Expr *E, CallExpr *&callE) const {
+ if ((callE = dyn_cast_or_null<CallExpr>(
+ StmtMap->getParentIgnoreParenImpCasts(E))))
+ if (FunctionDecl *
+ FD = dyn_cast_or_null<FunctionDecl>(callE->getCalleeDecl()))
+ if (FD->getName() == "CFRetain" && FD->getNumParams() == 1 &&
+ FD->getParent()->isTranslationUnit() &&
+ FD->getLinkage() == ExternalLinkage)
+ return true;
+
+ return false;
+ }
+
+ bool isPassedToCParamWithKnownOwnership(Expr *E, bool &isConsumed) const {
+ if (CallExpr *callE = dyn_cast_or_null<CallExpr>(
+ StmtMap->getParentIgnoreParenImpCasts(E)))
+ if (FunctionDecl *
+ FD = dyn_cast_or_null<FunctionDecl>(callE->getCalleeDecl())) {
+ unsigned i = 0;
+ for (unsigned e = callE->getNumArgs(); i != e; ++i) {
+ Expr *arg = callE->getArg(i);
+ if (arg == E || arg->IgnoreParenImpCasts() == E)
+ break;
+ }
+ if (i < callE->getNumArgs()) {
+ ParmVarDecl *PD = FD->getParamDecl(i);
+ if (PD->getAttr<CFConsumedAttr>()) {
+ isConsumed = true;
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ bool isSelf(Expr *E) const {
E = E->IgnoreParenLValueCasts();
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
- if (DRE->getDecl()->getIdentifier() == SelfII)
- return true;
+ if (ImplicitParamDecl *IPD = dyn_cast<ImplicitParamDecl>(DRE->getDecl()))
+ if (IPD->getIdentifier() == SelfII)
+ return true;
+
return false;
}
};
@@ -198,6 +307,6 @@ private:
} // end anonymous namespace
void trans::rewriteUnbridgedCasts(MigrationPass &pass) {
- UnbridgedCastRewriter trans(pass);
+ BodyTransform<UnbridgedCastRewriter> trans(pass);
trans.TraverseDecl(pass.Ctx.getTranslationUnitDecl());
}
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransUnusedInitDelegate.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransUnusedInitDelegate.cpp
index 1019ab4..e2aa6ff 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransUnusedInitDelegate.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransUnusedInitDelegate.cpp
@@ -27,7 +27,6 @@
using namespace clang;
using namespace arcmt;
using namespace trans;
-using llvm::StringRef;
namespace {
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp
index 07ccf70..1dbe811 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp
@@ -19,7 +19,6 @@
using namespace clang;
using namespace arcmt;
using namespace trans;
-using llvm::StringRef;
namespace {
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/TransformActions.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/TransformActions.cpp
index c99940b..ec676e9 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/TransformActions.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/TransformActions.cpp
@@ -13,10 +13,8 @@
#include "clang/Basic/SourceManager.h"
#include "llvm/ADT/DenseSet.h"
#include <map>
-
using namespace clang;
using namespace arcmt;
-using llvm::StringRef;
namespace {
@@ -46,9 +44,9 @@ class TransformActionsImpl {
ActionKind Kind;
SourceLocation Loc;
SourceRange R1, R2;
- llvm::StringRef Text1, Text2;
+ StringRef Text1, Text2;
Stmt *S;
- llvm::SmallVector<unsigned, 2> DiagIDs;
+ SmallVector<unsigned, 2> DiagIDs;
};
std::vector<ActionData> CachedActions;
@@ -70,11 +68,11 @@ class TransformActionsImpl {
SourceLocation beginLoc = range.getBegin(), endLoc = range.getEnd();
assert(beginLoc.isValid() && endLoc.isValid());
if (range.isTokenRange()) {
- Begin = FullSourceLoc(srcMgr.getInstantiationLoc(beginLoc), srcMgr);
+ Begin = FullSourceLoc(srcMgr.getExpansionLoc(beginLoc), srcMgr);
End = FullSourceLoc(getLocForEndOfToken(endLoc, srcMgr, PP), srcMgr);
} else {
- Begin = FullSourceLoc(srcMgr.getInstantiationLoc(beginLoc), srcMgr);
- End = FullSourceLoc(srcMgr.getInstantiationLoc(endLoc), srcMgr);
+ Begin = FullSourceLoc(srcMgr.getExpansionLoc(beginLoc), srcMgr);
+ End = FullSourceLoc(srcMgr.getExpansionLoc(endLoc), srcMgr);
}
assert(Begin.isValid() && End.isValid());
}
@@ -104,7 +102,7 @@ class TransformActionsImpl {
}
};
- typedef llvm::SmallVector<StringRef, 2> TextsVec;
+ typedef SmallVector<StringRef, 2> TextsVec;
typedef std::map<FullSourceLoc, TextsVec, FullSourceLoc::BeforeThanCompare>
InsertsMap;
InsertsMap Inserts;
@@ -130,19 +128,19 @@ public:
bool isInTransaction() const { return IsInTransaction; }
- void insert(SourceLocation loc, llvm::StringRef text);
- void insertAfterToken(SourceLocation loc, llvm::StringRef text);
+ void insert(SourceLocation loc, StringRef text);
+ void insertAfterToken(SourceLocation loc, StringRef text);
void remove(SourceRange range);
void removeStmt(Stmt *S);
- void replace(SourceRange range, llvm::StringRef text);
+ void replace(SourceRange range, StringRef text);
void replace(SourceRange range, SourceRange replacementRange);
- void replaceStmt(Stmt *S, llvm::StringRef text);
- void replaceText(SourceLocation loc, llvm::StringRef text,
- llvm::StringRef replacementText);
+ void replaceStmt(Stmt *S, StringRef text);
+ void replaceText(SourceLocation loc, StringRef text,
+ StringRef replacementText);
void increaseIndentation(SourceRange range,
SourceLocation parentIndent);
- bool clearDiagnostic(llvm::ArrayRef<unsigned> IDs, SourceRange range);
+ bool clearDiagnostic(ArrayRef<unsigned> IDs, SourceRange range);
void applyRewrites(TransformActions::RewriteReceiver &receiver);
@@ -151,17 +149,17 @@ private:
bool canInsertAfterToken(SourceLocation loc);
bool canRemoveRange(SourceRange range);
bool canReplaceRange(SourceRange range, SourceRange replacementRange);
- bool canReplaceText(SourceLocation loc, llvm::StringRef text);
+ bool canReplaceText(SourceLocation loc, StringRef text);
void commitInsert(SourceLocation loc, StringRef text);
void commitInsertAfterToken(SourceLocation loc, StringRef text);
void commitRemove(SourceRange range);
void commitRemoveStmt(Stmt *S);
void commitReplace(SourceRange range, SourceRange replacementRange);
- void commitReplaceText(SourceLocation loc, llvm::StringRef text,
- llvm::StringRef replacementText);
+ void commitReplaceText(SourceLocation loc, StringRef text,
+ StringRef replacementText);
void commitIncreaseIndentation(SourceRange range,SourceLocation parentIndent);
- void commitClearDiagnostic(llvm::ArrayRef<unsigned> IDs, SourceRange range);
+ void commitClearDiagnostic(ArrayRef<unsigned> IDs, SourceRange range);
void addRemoval(CharSourceRange range);
void addInsertion(SourceLocation loc, StringRef text);
@@ -364,7 +362,7 @@ void TransformActionsImpl::increaseIndentation(SourceRange range,
CachedActions.push_back(data);
}
-bool TransformActionsImpl::clearDiagnostic(llvm::ArrayRef<unsigned> IDs,
+bool TransformActionsImpl::clearDiagnostic(ArrayRef<unsigned> IDs,
SourceRange range) {
assert(IsInTransaction && "Actions only allowed during a transaction");
if (!CapturedDiags.hasDiagnostic(IDs, range))
@@ -383,7 +381,7 @@ bool TransformActionsImpl::canInsert(SourceLocation loc) {
return false;
SourceManager &SM = Ctx.getSourceManager();
- if (SM.isInSystemHeader(SM.getInstantiationLoc(loc)))
+ if (SM.isInSystemHeader(SM.getExpansionLoc(loc)))
return false;
if (loc.isFileID())
@@ -396,7 +394,7 @@ bool TransformActionsImpl::canInsertAfterToken(SourceLocation loc) {
return false;
SourceManager &SM = Ctx.getSourceManager();
- if (SM.isInSystemHeader(SM.getInstantiationLoc(loc)))
+ if (SM.isInSystemHeader(SM.getExpansionLoc(loc)))
return false;
if (loc.isFileID())
@@ -418,14 +416,14 @@ bool TransformActionsImpl::canReplaceText(SourceLocation loc, StringRef text) {
return false;
SourceManager &SM = Ctx.getSourceManager();
- loc = SM.getInstantiationLoc(loc);
+ loc = SM.getExpansionLoc(loc);
// Break down the source location.
std::pair<FileID, unsigned> locInfo = SM.getDecomposedLoc(loc);
// Try to load the file buffer.
bool invalidTemp = false;
- llvm::StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
+ StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
if (invalidTemp)
return false;
@@ -479,9 +477,9 @@ void TransformActionsImpl::commitReplaceText(SourceLocation loc,
StringRef text,
StringRef replacementText) {
SourceManager &SM = Ctx.getSourceManager();
- loc = SM.getInstantiationLoc(loc);
+ loc = SM.getExpansionLoc(loc);
// canReplaceText already checked if loc points at text.
- SourceLocation afterText = loc.getFileLocWithOffset(text.size());
+ SourceLocation afterText = loc.getLocWithOffset(text.size());
addRemoval(CharSourceRange::getCharRange(loc, afterText));
commitInsert(loc, replacementText);
@@ -493,17 +491,17 @@ void TransformActionsImpl::commitIncreaseIndentation(SourceRange range,
IndentationRanges.push_back(
std::make_pair(CharRange(CharSourceRange::getTokenRange(range),
SM, PP),
- SM.getInstantiationLoc(parentIndent)));
+ SM.getExpansionLoc(parentIndent)));
}
-void TransformActionsImpl::commitClearDiagnostic(llvm::ArrayRef<unsigned> IDs,
+void TransformActionsImpl::commitClearDiagnostic(ArrayRef<unsigned> IDs,
SourceRange range) {
CapturedDiags.clearDiagnostic(IDs, range);
}
void TransformActionsImpl::addInsertion(SourceLocation loc, StringRef text) {
SourceManager &SM = Ctx.getSourceManager();
- loc = SM.getInstantiationLoc(loc);
+ loc = SM.getExpansionLoc(loc);
for (std::list<CharRange>::reverse_iterator
I = Removals.rbegin(), E = Removals.rend(); I != E; ++I) {
if (!SM.isBeforeInTranslationUnit(loc, I->End))
@@ -591,16 +589,16 @@ SourceLocation TransformActionsImpl::getLocForEndOfToken(SourceLocation loc,
SourceManager &SM,
Preprocessor &PP) {
if (loc.isMacroID())
- loc = SM.getInstantiationRange(loc).second;
+ loc = SM.getExpansionRange(loc).second;
return PP.getLocForEndOfToken(loc);
}
TransformActions::RewriteReceiver::~RewriteReceiver() { }
-TransformActions::TransformActions(Diagnostic &diag,
+TransformActions::TransformActions(DiagnosticsEngine &diag,
CapturedDiagList &capturedDiags,
ASTContext &ctx, Preprocessor &PP)
- : Diags(diag), CapturedDiags(capturedDiags) {
+ : Diags(diag), CapturedDiags(capturedDiags), ReportedErrors(false) {
Impl = new TransformActionsImpl(capturedDiags, ctx, PP);
}
@@ -621,12 +619,12 @@ void TransformActions::abortTransaction() {
}
-void TransformActions::insert(SourceLocation loc, llvm::StringRef text) {
+void TransformActions::insert(SourceLocation loc, StringRef text) {
static_cast<TransformActionsImpl*>(Impl)->insert(loc, text);
}
void TransformActions::insertAfterToken(SourceLocation loc,
- llvm::StringRef text) {
+ StringRef text) {
static_cast<TransformActionsImpl*>(Impl)->insertAfterToken(loc, text);
}
@@ -638,7 +636,7 @@ void TransformActions::removeStmt(Stmt *S) {
static_cast<TransformActionsImpl*>(Impl)->removeStmt(S);
}
-void TransformActions::replace(SourceRange range, llvm::StringRef text) {
+void TransformActions::replace(SourceRange range, StringRef text) {
static_cast<TransformActionsImpl*>(Impl)->replace(range, text);
}
@@ -647,12 +645,12 @@ void TransformActions::replace(SourceRange range,
static_cast<TransformActionsImpl*>(Impl)->replace(range, replacementRange);
}
-void TransformActions::replaceStmt(Stmt *S, llvm::StringRef text) {
+void TransformActions::replaceStmt(Stmt *S, StringRef text) {
static_cast<TransformActionsImpl*>(Impl)->replaceStmt(S, text);
}
-void TransformActions::replaceText(SourceLocation loc, llvm::StringRef text,
- llvm::StringRef replacementText) {
+void TransformActions::replaceText(SourceLocation loc, StringRef text,
+ StringRef replacementText) {
static_cast<TransformActionsImpl*>(Impl)->replaceText(loc, text,
replacementText);
}
@@ -663,7 +661,7 @@ void TransformActions::increaseIndentation(SourceRange range,
parentIndent);
}
-bool TransformActions::clearDiagnostic(llvm::ArrayRef<unsigned> IDs,
+bool TransformActions::clearDiagnostic(ArrayRef<unsigned> IDs,
SourceRange range) {
return static_cast<TransformActionsImpl*>(Impl)->clearDiagnostic(IDs, range);
}
@@ -672,7 +670,7 @@ void TransformActions::applyRewrites(RewriteReceiver &receiver) {
static_cast<TransformActionsImpl*>(Impl)->applyRewrites(receiver);
}
-void TransformActions::reportError(llvm::StringRef error, SourceLocation loc,
+void TransformActions::reportError(StringRef error, SourceLocation loc,
SourceRange range) {
assert(!static_cast<TransformActionsImpl*>(Impl)->isInTransaction() &&
"Errors should be emitted out of a transaction");
@@ -683,9 +681,10 @@ void TransformActions::reportError(llvm::StringRef error, SourceLocation loc,
= Diags.getDiagnosticIDs()->getCustomDiagID(DiagnosticIDs::Error,
rewriteErr);
Diags.Report(loc, diagID) << range;
+ ReportedErrors = true;
}
-void TransformActions::reportNote(llvm::StringRef note, SourceLocation loc,
+void TransformActions::reportNote(StringRef note, SourceLocation loc,
SourceRange range) {
assert(!static_cast<TransformActionsImpl*>(Impl)->isInTransaction() &&
"Errors should be emitted out of a transaction");
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.cpp b/contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.cpp
index 7bd95e5..4244faf 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.cpp
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.cpp
@@ -23,7 +23,6 @@
using namespace clang;
using namespace arcmt;
using namespace trans;
-using llvm::StringRef;
//===----------------------------------------------------------------------===//
// Helpers.
@@ -92,11 +91,23 @@ bool trans::canApplyWeak(ASTContext &Ctx, QualType type) {
/// source location will be invalid.
SourceLocation trans::findLocationAfterSemi(SourceLocation loc,
ASTContext &Ctx) {
+ SourceLocation SemiLoc = findSemiAfterLocation(loc, Ctx);
+ if (SemiLoc.isInvalid())
+ return SourceLocation();
+ return SemiLoc.getLocWithOffset(1);
+}
+
+/// \brief \arg Loc is the end of a statement range. This returns the location
+/// of the semicolon following the statement.
+/// If no semicolon is found or the location is inside a macro, the returned
+/// source location will be invalid.
+SourceLocation trans::findSemiAfterLocation(SourceLocation loc,
+ ASTContext &Ctx) {
SourceManager &SM = Ctx.getSourceManager();
if (loc.isMacroID()) {
if (!Lexer::isAtEndOfMacroExpansion(loc, SM, Ctx.getLangOptions()))
return SourceLocation();
- loc = SM.getInstantiationRange(loc).second;
+ loc = SM.getExpansionRange(loc).second;
}
loc = Lexer::getLocForEndOfToken(loc, /*Offset=*/0, SM, Ctx.getLangOptions());
@@ -105,7 +116,7 @@ SourceLocation trans::findLocationAfterSemi(SourceLocation loc,
// Try to load the file buffer.
bool invalidTemp = false;
- llvm::StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
+ StringRef file = SM.getBufferData(locInfo.first, &invalidTemp);
if (invalidTemp)
return SourceLocation();
@@ -120,7 +131,7 @@ SourceLocation trans::findLocationAfterSemi(SourceLocation loc,
if (tok.isNot(tok::semi))
return SourceLocation();
- return tok.getLocation().getFileLocWithOffset(1);
+ return tok.getLocation();
}
bool trans::hasSideEffects(Expr *E, ASTContext &Ctx) {
@@ -155,7 +166,8 @@ bool trans::hasSideEffects(Expr *E, ASTContext &Ctx) {
bool trans::isGlobalVar(Expr *E) {
E = E->IgnoreParenCasts();
if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
- return DRE->getDecl()->getDeclContext()->isFileContext();
+ return DRE->getDecl()->getDeclContext()->isFileContext() &&
+ DRE->getDecl()->getLinkage() == ExternalLinkage;
if (ConditionalOperator *condOp = dyn_cast<ConditionalOperator>(E))
return isGlobalVar(condOp->getTrueExpr()) &&
isGlobalVar(condOp->getFalseExpr());
@@ -163,6 +175,13 @@ bool trans::isGlobalVar(Expr *E) {
return false;
}
+StringRef trans::getNilString(ASTContext &Ctx) {
+ if (Ctx.Idents.get("nil").hasMacroDefinition())
+ return "nil";
+ else
+ return "0";
+}
+
namespace {
class ReferenceClear : public RecursiveASTVisitor<ReferenceClear> {
@@ -283,6 +302,7 @@ static void independentTransforms(MigrationPass &pass) {
makeAssignARCSafe(pass);
rewriteUnbridgedCasts(pass);
rewriteBlockObjCVariable(pass);
+ checkAPIUses(pass);
}
std::vector<TransformFn> arcmt::getAllTransformations() {
diff --git a/contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.h b/contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.h
index b47d6d8..5e4db56 100644
--- a/contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.h
+++ b/contrib/llvm/tools/clang/lib/ARCMigrate/Transforms.h
@@ -37,6 +37,7 @@ void removeZeroOutPropsInDealloc(MigrationPass &pass);
void rewriteProperties(MigrationPass &pass);
void rewriteBlockObjCVariable(MigrationPass &pass);
void rewriteUnusedInitDelegate(MigrationPass &pass);
+void checkAPIUses(MigrationPass &pass);
void removeEmptyStatementsAndDealloc(MigrationPass &pass);
@@ -53,9 +54,16 @@ bool canApplyWeak(ASTContext &Ctx, QualType type);
/// source location will be invalid.
SourceLocation findLocationAfterSemi(SourceLocation loc, ASTContext &Ctx);
+/// \brief \arg Loc is the end of a statement range. This returns the location
+/// of the semicolon following the statement.
+/// If no semicolon is found or the location is inside a macro, the returned
+/// source location will be invalid.
+SourceLocation findSemiAfterLocation(SourceLocation loc, ASTContext &Ctx);
+
bool hasSideEffects(Expr *E, ASTContext &Ctx);
bool isGlobalVar(Expr *E);
-
+/// \brief Returns "nil" or "0" if 'nil' macro is not actually defined.
+StringRef getNilString(ASTContext &Ctx);
template <typename BODY_TRANS>
class BodyTransform : public RecursiveASTVisitor<BodyTransform<BODY_TRANS> > {
@@ -65,7 +73,8 @@ public:
BodyTransform(MigrationPass &pass) : Pass(pass) { }
bool TraverseStmt(Stmt *rootS) {
- BODY_TRANS(Pass).transformBody(rootS);
+ if (rootS)
+ BODY_TRANS(Pass).transformBody(rootS);
return true;
}
};
OpenPOWER on IntegriCloud