From b5c6babd3d8e0233b8ea5a4eb1e2700e30c0d396 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Wed, 25 Jan 2012 00:20:29 +0000 Subject: [PATCH] arc migrator: Provide infrastructure to add options specific to migrator. Use its first option to warn migrating from GC to arc when NSAllocateCollectable/NSReallocateCollectable is used. // rdar://10532541 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148887 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Driver/CC1Options.td | 6 +++++ include/clang/Frontend/CompilerInvocation.h | 8 ++++++ include/clang/Frontend/MigratorOptions.h | 29 +++++++++++++++++++++ lib/ARCMigrate/ARCMT.cpp | 2 ++ lib/ARCMigrate/Internals.h | 8 +++++- lib/ARCMigrate/TransGCCalls.cpp | 11 +++++--- lib/ARCMigrate/TransformActions.cpp | 19 ++++++++++++++ lib/Frontend/CompilerInvocation.cpp | 6 +++++ test/ARCMT/GC-check-warn-nsalloc.m | 12 +++++++++ 9 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 include/clang/Frontend/MigratorOptions.h create mode 100644 test/ARCMT/GC-check-warn-nsalloc.m diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 3d599061b0..86457d9e78 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -100,6 +100,12 @@ def analyzer_disable_checker_EQ : Joined<"-analyzer-disable-checker=">, def analyzer_checker_help : Flag<"-analyzer-checker-help">, HelpText<"Display the list of analyzer checkers that are available">; +//===----------------------------------------------------------------------===// +// Migrator Options +//===----------------------------------------------------------------------===// +def migrator_no_nsalloc_error : Flag<"-no-ns-alloc-error">, + HelpText<"Do not error on use of NSAllocateCollectable/NSReallocateCollectable">; + //===----------------------------------------------------------------------===// // CodeGen Options //===----------------------------------------------------------------------===// diff --git a/include/clang/Frontend/CompilerInvocation.h b/include/clang/Frontend/CompilerInvocation.h index 821336c32c..e1af7b0d8d 100644 --- a/include/clang/Frontend/CompilerInvocation.h +++ b/include/clang/Frontend/CompilerInvocation.h @@ -14,6 +14,7 @@ #include "clang/Basic/TargetOptions.h" #include "clang/Basic/FileSystemOptions.h" #include "clang/Frontend/AnalyzerOptions.h" +#include "clang/Frontend/MigratorOptions.h" #include "clang/Frontend/CodeGenOptions.h" #include "clang/Frontend/DependencyOutputOptions.h" #include "clang/Frontend/DiagnosticOptions.h" @@ -56,6 +57,8 @@ class CompilerInvocation : public CompilerInvocationBase { /// Options controlling the static analyzer. AnalyzerOptions AnalyzerOpts; + MigratorOptions MigratorOpts; + /// Options controlling IRgen and the backend. CodeGenOptions CodeGenOpts; @@ -147,6 +150,11 @@ public: return AnalyzerOpts; } + MigratorOptions &getMigratorOpts() { return MigratorOpts; } + const MigratorOptions &getMigratorOpts() const { + return MigratorOpts; + } + CodeGenOptions &getCodeGenOpts() { return CodeGenOpts; } const CodeGenOptions &getCodeGenOpts() const { return CodeGenOpts; diff --git a/include/clang/Frontend/MigratorOptions.h b/include/clang/Frontend/MigratorOptions.h new file mode 100644 index 0000000000..23263d7aa0 --- /dev/null +++ b/include/clang/Frontend/MigratorOptions.h @@ -0,0 +1,29 @@ +//===--- MigratorOptions.h - MigratorOptions Options ------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This header contains the structures necessary for a front-end to specify +// various migration analysis. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_MIGRATOROPTIONS +#define LLVM_CLANG_FRONTEND_MIGRATOROPTIONS + +namespace clang { + +class MigratorOptions { +public: + unsigned NoNSAllocReallocError : 1; + MigratorOptions() { + NoNSAllocReallocError = 0; + } +}; + +} +#endif diff --git a/lib/ARCMigrate/ARCMT.cpp b/lib/ARCMigrate/ARCMT.cpp index 9a07245e2c..09752f0d61 100644 --- a/lib/ARCMigrate/ARCMT.cpp +++ b/lib/ARCMigrate/ARCMT.cpp @@ -229,6 +229,7 @@ bool arcmt::checkForManualIssues(CompilerInvocation &origCI, return false; LangOptions::GCMode OrigGCMode = origCI.getLangOpts()->getGC(); + bool NoNSAllocReallocError = origCI.getMigratorOpts().NoNSAllocReallocError; std::vector transforms = arcmt::getAllTransformations(OrigGCMode); assert(!transforms.empty()); @@ -292,6 +293,7 @@ bool arcmt::checkForManualIssues(CompilerInvocation &origCI, TransformActions testAct(*Diags, capturedDiags, Ctx, Unit->getPreprocessor()); MigrationPass pass(Ctx, OrigGCMode, Unit->getSema(), testAct, ARCMTMacroLocs); + pass.setNSAllocReallocError(NoNSAllocReallocError); for (unsigned i=0, e = transforms.size(); i != e; ++i) transforms[i](pass); diff --git a/lib/ARCMigrate/Internals.h b/lib/ARCMigrate/Internals.h index 06d9f8259f..78bf341fe6 100644 --- a/lib/ARCMigrate/Internals.h +++ b/lib/ARCMigrate/Internals.h @@ -94,6 +94,8 @@ public: void reportError(StringRef error, SourceLocation loc, SourceRange range = SourceRange()); + void reportWarning(StringRef warning, SourceLocation loc, + SourceRange range = SourceRange()); void reportNote(StringRef note, SourceLocation loc, SourceRange range = SourceRange()); @@ -138,6 +140,7 @@ class MigrationPass { public: ASTContext &Ctx; LangOptions::GCMode OrigGCMode; + MigratorOptions MigOptions; Sema &SemaRef; TransformActions &TA; std::vector &ARCMTMacroLocs; @@ -145,10 +148,13 @@ public: MigrationPass(ASTContext &Ctx, LangOptions::GCMode OrigGCMode, Sema &sema, TransformActions &TA, std::vector &ARCMTMacroLocs) - : Ctx(Ctx), OrigGCMode(OrigGCMode), SemaRef(sema), TA(TA), + : Ctx(Ctx), OrigGCMode(OrigGCMode), MigOptions(), + SemaRef(sema), TA(TA), ARCMTMacroLocs(ARCMTMacroLocs) { } bool isGCMigration() const { return OrigGCMode != LangOptions::NonGC; } + bool noNSAllocReallocError() const { return MigOptions.NoNSAllocReallocError; } + void setNSAllocReallocError(bool val) { MigOptions.NoNSAllocReallocError = val; } }; static inline StringRef getARCMTMacroName() { diff --git a/lib/ARCMigrate/TransGCCalls.cpp b/lib/ARCMigrate/TransGCCalls.cpp index 7c0819a677..1be902088c 100644 --- a/lib/ARCMigrate/TransGCCalls.cpp +++ b/lib/ARCMigrate/TransGCCalls.cpp @@ -38,9 +38,14 @@ public: TransformActions &TA = MigrateCtx.Pass.TA; if (MigrateCtx.isGCOwnedNonObjC(E->getType())) { - TA.reportError("call returns pointer to GC managed memory; " - "it will become unmanaged in ARC", - E->getLocStart(), E->getSourceRange()); + if (MigrateCtx.Pass.noNSAllocReallocError()) + TA.reportWarning("call returns pointer to GC managed memory; " + "it will become unmanaged in ARC", + E->getLocStart(), E->getSourceRange()); + else + TA.reportError("call returns pointer to GC managed memory; " + "it will become unmanaged in ARC", + E->getLocStart(), E->getSourceRange()); return true; } diff --git a/lib/ARCMigrate/TransformActions.cpp b/lib/ARCMigrate/TransformActions.cpp index 7ad9b6005d..0ecfeb54f8 100644 --- a/lib/ARCMigrate/TransformActions.cpp +++ b/lib/ARCMigrate/TransformActions.cpp @@ -692,6 +692,25 @@ void TransformActions::reportError(StringRef error, SourceLocation loc, ReportedErrors = true; } +void TransformActions::reportWarning(StringRef warning, SourceLocation loc, + SourceRange range) { + assert(!static_cast(Impl)->isInTransaction() && + "Warning should be emitted out of a transaction"); + + SourceManager &SM = static_cast(Impl)-> + getASTContext().getSourceManager(); + if (SM.isInSystemHeader(SM.getExpansionLoc(loc))) + return; + + // FIXME: Use a custom category name to distinguish rewriter errors. + std::string rewriterWarn = "[rewriter] "; + rewriterWarn += warning; + unsigned diagID + = Diags.getDiagnosticIDs()->getCustomDiagID(DiagnosticIDs::Warning, + rewriterWarn); + Diags.Report(loc, diagID) << range; +} + void TransformActions::reportNote(StringRef note, SourceLocation loc, SourceRange range) { assert(!static_cast(Impl)->isInTransaction() && diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index f4576093d8..aa367b0a74 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -1053,6 +1053,11 @@ static bool ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args, return Success; } +static bool ParseMigratorArgs(MigratorOptions &Opts, ArgList &Args) { + Opts.NoNSAllocReallocError = Args.hasArg(OPT_migrator_no_nsalloc_error); + return true; +} + static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, InputKind IK, DiagnosticsEngine &Diags) { using namespace cc1options; @@ -2051,6 +2056,7 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res, } Success = ParseAnalyzerArgs(Res.getAnalyzerOpts(), *Args, Diags) && Success; + Success = ParseMigratorArgs(Res.getMigratorOpts(), *Args) && Success; ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), *Args); Success = ParseDiagnosticArgs(Res.getDiagnosticOpts(), *Args, Diags) && Success; diff --git a/test/ARCMT/GC-check-warn-nsalloc.m b/test/ARCMT/GC-check-warn-nsalloc.m new file mode 100644 index 0000000000..5ce36c40d6 --- /dev/null +++ b/test/ARCMT/GC-check-warn-nsalloc.m @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -arcmt-check -verify -no-ns-alloc-error -triple x86_64-apple-darwin10 -fobjc-gc-only %s +// RUN: %clang_cc1 -arcmt-check -verify -no-ns-alloc-error -triple x86_64-apple-darwin10 -fobjc-gc-only -x objective-c++ %s +// DISABLE: mingw32 +// rdar://10532541 +// XFAIL: * + +typedef unsigned NSUInteger; +void *__strong NSAllocateCollectable(NSUInteger size, NSUInteger options); + +void test1() { + NSAllocateCollectable(100, 0); // expected-warning {{call returns pointer to GC managed memory; it will become unmanaged in ARC}} +} -- 2.40.0