Index: cfe/trunk/include/clang/Driver/Action.h =================================================================== --- cfe/trunk/include/clang/Driver/Action.h +++ cfe/trunk/include/clang/Driver/Action.h @@ -32,6 +32,9 @@ /// single primary output, at least in terms of controlling the /// compilation. Actions can produce auxiliary files, but can only /// produce a single output to feed into subsequent actions. +/// +/// Actions are usually owned by a Compilation, which creates new +/// actions via MakeAction(). class Action { public: typedef ActionList::size_type size_type; @@ -70,27 +73,20 @@ ActionList Inputs; - unsigned OwnsInputs : 1; - protected: - Action(ActionClass Kind, types::ID Type) - : Kind(Kind), Type(Type), OwnsInputs(true) {} - Action(ActionClass Kind, std::unique_ptr Input, types::ID Type) - : Kind(Kind), Type(Type), Inputs(1, Input.release()), OwnsInputs(true) { - } - Action(ActionClass Kind, std::unique_ptr Input) - : Kind(Kind), Type(Input->getType()), Inputs(1, Input.release()), - OwnsInputs(true) {} + Action(ActionClass Kind, types::ID Type) : Action(Kind, ActionList(), Type) {} + Action(ActionClass Kind, Action *Input, types::ID Type) + : Action(Kind, ActionList({Input}), Type) {} + Action(ActionClass Kind, Action *Input) + : Action(Kind, ActionList({Input}), Input->getType()) {} Action(ActionClass Kind, const ActionList &Inputs, types::ID Type) - : Kind(Kind), Type(Type), Inputs(Inputs), OwnsInputs(true) {} + : Kind(Kind), Type(Type), Inputs(Inputs) {} + public: virtual ~Action(); const char *getClassName() const { return Action::getClassName(getKind()); } - bool getOwnsInputs() { return OwnsInputs; } - void setOwnsInputs(bool Value) { OwnsInputs = Value; } - ActionClass getKind() const { return Kind; } types::ID getType() const { return Type; } @@ -126,7 +122,7 @@ const char *ArchName; public: - BindArchAction(std::unique_ptr Input, const char *ArchName); + BindArchAction(Action *Input, const char *ArchName); const char *getArchName() const { return ArchName; } @@ -144,8 +140,7 @@ bool AtTopLevel; public: - CudaDeviceAction(std::unique_ptr Input, const char *ArchName, - bool AtTopLevel); + CudaDeviceAction(Action *Input, const char *ArchName, bool AtTopLevel); const char *getGpuArchName() const { return GpuArchName; } bool isAtTopLevel() const { return AtTopLevel; } @@ -160,9 +155,7 @@ ActionList DeviceActions; public: - CudaHostAction(std::unique_ptr Input, - const ActionList &DeviceActions); - ~CudaHostAction() override; + CudaHostAction(Action *Input, const ActionList &DeviceActions); const ActionList &getDeviceActions() const { return DeviceActions; } @@ -172,7 +165,7 @@ class JobAction : public Action { virtual void anchor(); protected: - JobAction(ActionClass Kind, std::unique_ptr Input, types::ID Type); + JobAction(ActionClass Kind, Action *Input, types::ID Type); JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type); public: @@ -185,7 +178,7 @@ class PreprocessJobAction : public JobAction { void anchor() override; public: - PreprocessJobAction(std::unique_ptr Input, types::ID OutputType); + PreprocessJobAction(Action *Input, types::ID OutputType); static bool classof(const Action *A) { return A->getKind() == PreprocessJobClass; @@ -195,7 +188,7 @@ class PrecompileJobAction : public JobAction { void anchor() override; public: - PrecompileJobAction(std::unique_ptr Input, types::ID OutputType); + PrecompileJobAction(Action *Input, types::ID OutputType); static bool classof(const Action *A) { return A->getKind() == PrecompileJobClass; @@ -205,7 +198,7 @@ class AnalyzeJobAction : public JobAction { void anchor() override; public: - AnalyzeJobAction(std::unique_ptr Input, types::ID OutputType); + AnalyzeJobAction(Action *Input, types::ID OutputType); static bool classof(const Action *A) { return A->getKind() == AnalyzeJobClass; @@ -215,7 +208,7 @@ class MigrateJobAction : public JobAction { void anchor() override; public: - MigrateJobAction(std::unique_ptr Input, types::ID OutputType); + MigrateJobAction(Action *Input, types::ID OutputType); static bool classof(const Action *A) { return A->getKind() == MigrateJobClass; @@ -225,7 +218,7 @@ class CompileJobAction : public JobAction { void anchor() override; public: - CompileJobAction(std::unique_ptr Input, types::ID OutputType); + CompileJobAction(Action *Input, types::ID OutputType); static bool classof(const Action *A) { return A->getKind() == CompileJobClass; @@ -235,7 +228,7 @@ class BackendJobAction : public JobAction { void anchor() override; public: - BackendJobAction(std::unique_ptr Input, types::ID OutputType); + BackendJobAction(Action *Input, types::ID OutputType); static bool classof(const Action *A) { return A->getKind() == BackendJobClass; @@ -245,7 +238,7 @@ class AssembleJobAction : public JobAction { void anchor() override; public: - AssembleJobAction(std::unique_ptr Input, types::ID OutputType); + AssembleJobAction(Action *Input, types::ID OutputType); static bool classof(const Action *A) { return A->getKind() == AssembleJobClass; @@ -285,8 +278,7 @@ class VerifyJobAction : public JobAction { void anchor() override; public: - VerifyJobAction(ActionClass Kind, std::unique_ptr Input, - types::ID Type); + VerifyJobAction(ActionClass Kind, Action *Input, types::ID Type); static bool classof(const Action *A) { return A->getKind() == VerifyDebugInfoJobClass || A->getKind() == VerifyPCHJobClass; @@ -296,7 +288,7 @@ class VerifyDebugInfoJobAction : public VerifyJobAction { void anchor() override; public: - VerifyDebugInfoJobAction(std::unique_ptr Input, types::ID Type); + VerifyDebugInfoJobAction(Action *Input, types::ID Type); static bool classof(const Action *A) { return A->getKind() == VerifyDebugInfoJobClass; } @@ -305,7 +297,7 @@ class VerifyPCHJobAction : public VerifyJobAction { void anchor() override; public: - VerifyPCHJobAction(std::unique_ptr Input, types::ID Type); + VerifyPCHJobAction(Action *Input, types::ID Type); static bool classof(const Action *A) { return A->getKind() == VerifyPCHJobClass; } Index: cfe/trunk/include/clang/Driver/Compilation.h =================================================================== --- cfe/trunk/include/clang/Driver/Compilation.h +++ cfe/trunk/include/clang/Driver/Compilation.h @@ -48,7 +48,12 @@ /// own argument translation. llvm::opt::DerivedArgList *TranslatedArgs; - /// The list of actions. + /// The list of actions we've created via MakeAction. This is not accessible + /// to consumers; it's here just to manage ownership. + std::vector> AllActions; + + /// The list of actions. This is maintained and modified by consumers, via + /// getActions(). ActionList Actions; /// The root list of jobs. @@ -105,6 +110,15 @@ ActionList &getActions() { return Actions; } const ActionList &getActions() const { return Actions; } + /// Creates a new Action owned by this Compilation. + /// + /// The new Action is *not* added to the list returned by getActions(). + template T *MakeAction(Args &&... Arg) { + T *RawPtr = new T(std::forward(Arg)...); + AllActions.push_back(std::unique_ptr(RawPtr)); + return RawPtr; + } + JobList &getJobs() { return Jobs; } const JobList &getJobs() const { return Jobs; } Index: cfe/trunk/include/clang/Driver/Driver.h =================================================================== --- cfe/trunk/include/clang/Driver/Driver.h +++ cfe/trunk/include/clang/Driver/Driver.h @@ -375,9 +375,9 @@ /// ConstructAction - Construct the appropriate action to do for /// \p Phase on the \p Input, taking in to account arguments /// like -fsyntax-only or --analyze. - std::unique_ptr - ConstructPhaseAction(const ToolChain &TC, const llvm::opt::ArgList &Args, - phases::ID Phase, std::unique_ptr Input) const; + Action *ConstructPhaseAction(Compilation &C, const ToolChain &TC, + const llvm::opt::ArgList &Args, phases::ID Phase, + Action *Input) const; /// BuildJobsForAction - Construct the jobs to perform for the /// action \p A. Index: cfe/trunk/lib/Driver/Action.cpp =================================================================== --- cfe/trunk/lib/Driver/Action.cpp +++ cfe/trunk/lib/Driver/Action.cpp @@ -13,12 +13,7 @@ using namespace clang::driver; using namespace llvm::opt; -Action::~Action() { - if (OwnsInputs) { - for (iterator it = begin(), ie = end(); it != ie; ++it) - delete *it; - } -} +Action::~Action() {} const char *Action::getClassName(ActionClass AC) { switch (AC) { @@ -51,33 +46,25 @@ void BindArchAction::anchor() {} -BindArchAction::BindArchAction(std::unique_ptr Input, - const char *_ArchName) - : Action(BindArchClass, std::move(Input)), ArchName(_ArchName) {} +BindArchAction::BindArchAction(Action *Input, const char *_ArchName) + : Action(BindArchClass, Input), ArchName(_ArchName) {} void CudaDeviceAction::anchor() {} -CudaDeviceAction::CudaDeviceAction(std::unique_ptr Input, - const char *ArchName, bool AtTopLevel) - : Action(CudaDeviceClass, std::move(Input)), GpuArchName(ArchName), +CudaDeviceAction::CudaDeviceAction(Action *Input, const char *ArchName, + bool AtTopLevel) + : Action(CudaDeviceClass, Input), GpuArchName(ArchName), AtTopLevel(AtTopLevel) {} void CudaHostAction::anchor() {} -CudaHostAction::CudaHostAction(std::unique_ptr Input, - const ActionList &DeviceActions) - : Action(CudaHostClass, std::move(Input)), DeviceActions(DeviceActions) {} - -CudaHostAction::~CudaHostAction() { - for (auto &DA : DeviceActions) - delete DA; -} +CudaHostAction::CudaHostAction(Action *Input, const ActionList &DeviceActions) + : Action(CudaHostClass, Input), DeviceActions(DeviceActions) {} void JobAction::anchor() {} -JobAction::JobAction(ActionClass Kind, std::unique_ptr Input, - types::ID Type) - : Action(Kind, std::move(Input), Type) {} +JobAction::JobAction(ActionClass Kind, Action *Input, types::ID Type) + : Action(Kind, Input, Type) {} JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type) : Action(Kind, Inputs, Type) { @@ -85,45 +72,38 @@ void PreprocessJobAction::anchor() {} -PreprocessJobAction::PreprocessJobAction(std::unique_ptr Input, - types::ID OutputType) - : JobAction(PreprocessJobClass, std::move(Input), OutputType) {} +PreprocessJobAction::PreprocessJobAction(Action *Input, types::ID OutputType) + : JobAction(PreprocessJobClass, Input, OutputType) {} void PrecompileJobAction::anchor() {} -PrecompileJobAction::PrecompileJobAction(std::unique_ptr Input, - types::ID OutputType) - : JobAction(PrecompileJobClass, std::move(Input), OutputType) {} +PrecompileJobAction::PrecompileJobAction(Action *Input, types::ID OutputType) + : JobAction(PrecompileJobClass, Input, OutputType) {} void AnalyzeJobAction::anchor() {} -AnalyzeJobAction::AnalyzeJobAction(std::unique_ptr Input, - types::ID OutputType) - : JobAction(AnalyzeJobClass, std::move(Input), OutputType) {} +AnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType) + : JobAction(AnalyzeJobClass, Input, OutputType) {} void MigrateJobAction::anchor() {} -MigrateJobAction::MigrateJobAction(std::unique_ptr Input, - types::ID OutputType) - : JobAction(MigrateJobClass, std::move(Input), OutputType) {} +MigrateJobAction::MigrateJobAction(Action *Input, types::ID OutputType) + : JobAction(MigrateJobClass, Input, OutputType) {} void CompileJobAction::anchor() {} -CompileJobAction::CompileJobAction(std::unique_ptr Input, - types::ID OutputType) - : JobAction(CompileJobClass, std::move(Input), OutputType) {} +CompileJobAction::CompileJobAction(Action *Input, types::ID OutputType) + : JobAction(CompileJobClass, Input, OutputType) {} void BackendJobAction::anchor() {} -BackendJobAction::BackendJobAction(std::unique_ptr Input, - types::ID OutputType) - : JobAction(BackendJobClass, std::move(Input), OutputType) {} +BackendJobAction::BackendJobAction(Action *Input, types::ID OutputType) + : JobAction(BackendJobClass, Input, OutputType) {} void AssembleJobAction::anchor() {} -AssembleJobAction::AssembleJobAction(std::unique_ptr Input, - types::ID OutputType) - : JobAction(AssembleJobClass, std::move(Input), OutputType) {} +AssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType) + : JobAction(AssembleJobClass, Input, OutputType) {} void LinkJobAction::anchor() {} @@ -145,21 +125,20 @@ void VerifyJobAction::anchor() {} -VerifyJobAction::VerifyJobAction(ActionClass Kind, - std::unique_ptr Input, types::ID Type) - : JobAction(Kind, std::move(Input), Type) { +VerifyJobAction::VerifyJobAction(ActionClass Kind, Action *Input, + types::ID Type) + : JobAction(Kind, Input, Type) { assert((Kind == VerifyDebugInfoJobClass || Kind == VerifyPCHJobClass) && "ActionClass is not a valid VerifyJobAction"); } void VerifyDebugInfoJobAction::anchor() {} -VerifyDebugInfoJobAction::VerifyDebugInfoJobAction( - std::unique_ptr Input, types::ID Type) - : VerifyJobAction(VerifyDebugInfoJobClass, std::move(Input), Type) {} +VerifyDebugInfoJobAction::VerifyDebugInfoJobAction(Action *Input, + types::ID Type) + : VerifyJobAction(VerifyDebugInfoJobClass, Input, Type) {} void VerifyPCHJobAction::anchor() {} -VerifyPCHJobAction::VerifyPCHJobAction(std::unique_ptr Input, - types::ID Type) - : VerifyJobAction(VerifyPCHJobClass, std::move(Input), Type) {} +VerifyPCHJobAction::VerifyPCHJobAction(Action *Input, types::ID Type) + : VerifyJobAction(VerifyPCHJobClass, Input, Type) {} Index: cfe/trunk/lib/Driver/Compilation.cpp =================================================================== --- cfe/trunk/lib/Driver/Compilation.cpp +++ cfe/trunk/lib/Driver/Compilation.cpp @@ -40,11 +40,6 @@ if (it->second != TranslatedArgs) delete it->second; - // Free the actions, if built. - for (ActionList::iterator it = Actions.begin(), ie = Actions.end(); - it != ie; ++it) - delete *it; - // Free redirections of stdout/stderr. if (Redirects) { delete Redirects[1]; @@ -208,7 +203,8 @@ ForDiagnostics = true; // Free actions and jobs. - DeleteContainerPointers(Actions); + Actions.clear(); + AllActions.clear(); Jobs.clear(); // Clear temporary/results file lists. Index: cfe/trunk/lib/Driver/Driver.cpp =================================================================== --- cfe/trunk/lib/Driver/Driver.cpp +++ cfe/trunk/lib/Driver/Driver.cpp @@ -1049,19 +1049,15 @@ << types::getTypeName(Act->getType()); ActionList Inputs; - for (unsigned i = 0, e = Archs.size(); i != e; ++i) { - Inputs.push_back( - new BindArchAction(std::unique_ptr(Act), Archs[i])); - if (i != 0) - Inputs.back()->setOwnsInputs(false); - } + for (unsigned i = 0, e = Archs.size(); i != e; ++i) + Inputs.push_back(C.MakeAction(Act, Archs[i])); // Lipo if necessary, we do it this way because we need to set the arch flag // so that -Xarch_ gets overwritten. if (Inputs.size() == 1 || Act->getType() == types::TY_Nothing) Actions.append(Inputs.begin(), Inputs.end()); else - Actions.push_back(new LipoJobAction(Inputs, Act->getType())); + Actions.push_back(C.MakeAction(Inputs, Act->getType())); // Handle debug info queries. Arg *A = Args.getLastArg(options::OPT_g_Group); @@ -1077,15 +1073,16 @@ ActionList Inputs; Inputs.push_back(Actions.back()); Actions.pop_back(); - Actions.push_back(new DsymutilJobAction(Inputs, types::TY_dSYM)); + Actions.push_back( + C.MakeAction(Inputs, types::TY_dSYM)); } // Verify the debug info output. if (Args.hasArg(options::OPT_verify_debug_info)) { - std::unique_ptr VerifyInput(Actions.back()); + Action* LastAction = Actions.back(); Actions.pop_back(); - Actions.push_back(new VerifyDebugInfoJobAction(std::move(VerifyInput), - types::TY_Nothing)); + Actions.push_back(C.MakeAction( + LastAction, types::TY_Nothing)); } } } @@ -1283,16 +1280,15 @@ // Actions and /p Current is released. Otherwise the function creates // and returns a new CudaHostAction which wraps /p Current and device // side actions. -static std::unique_ptr -buildCudaActions(Compilation &C, DerivedArgList &Args, const Arg *InputArg, - std::unique_ptr HostAction, ActionList &Actions) { +static Action *buildCudaActions(Compilation &C, DerivedArgList &Args, + const Arg *InputArg, Action *HostAction, + ActionList &Actions) { Arg *PartialCompilationArg = Args.getLastArg(options::OPT_cuda_host_only, options::OPT_cuda_device_only); // Host-only compilation case. if (PartialCompilationArg && PartialCompilationArg->getOption().matches(options::OPT_cuda_host_only)) - return std::unique_ptr( - new CudaHostAction(std::move(HostAction), {})); + return C.MakeAction(HostAction, ActionList()); // Collect all cuda_gpu_arch parameters, removing duplicates. SmallVector GpuArchList; @@ -1347,12 +1343,12 @@ } for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) - Actions.push_back(new CudaDeviceAction( - std::unique_ptr(CudaDeviceActions[I]), GpuArchList[I], - /* AtTopLevel */ true)); + Actions.push_back(C.MakeAction(CudaDeviceActions[I], + GpuArchList[I], + /* AtTopLevel */ true)); // Kill host action in case of device-only compilation. if (DeviceOnlyCompilation) - HostAction.reset(nullptr); + return nullptr; return HostAction; } @@ -1360,13 +1356,12 @@ // with AtTopLevel=false and become inputs for the host action. ActionList DeviceActions; for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I) - DeviceActions.push_back(new CudaDeviceAction( - std::unique_ptr(CudaDeviceActions[I]), GpuArchList[I], - /* AtTopLevel */ false)); + DeviceActions.push_back( + C.MakeAction(CudaDeviceActions[I], GpuArchList[I], + /* AtTopLevel */ false)); // Return a new host action that incorporates original host action and all // device actions. - return std::unique_ptr( - new CudaHostAction(std::move(HostAction), DeviceActions)); + return C.MakeAction(HostAction, DeviceActions); } void Driver::BuildActions(Compilation &C, const ToolChain &TC, @@ -1474,7 +1469,7 @@ : FinalPhase; // Build the pipeline for this file. - std::unique_ptr Current(new InputAction(*InputArg, InputType)); + Action *Current = C.MakeAction(*InputArg, InputType); for (SmallVectorImpl::iterator i = PL.begin(), e = PL.end(); i != e; ++i) { phases::ID Phase = *i; @@ -1486,7 +1481,8 @@ // Queue linker inputs. if (Phase == phases::Link) { assert((i + 1) == e && "linking must be final compilation step."); - LinkerInputs.push_back(Current.release()); + LinkerInputs.push_back(Current); + Current = nullptr; break; } @@ -1497,11 +1493,10 @@ continue; // Otherwise construct the appropriate action. - Current = ConstructPhaseAction(TC, Args, Phase, std::move(Current)); + Current = ConstructPhaseAction(C, TC, Args, Phase, Current); if (InputType == types::TY_CUDA && Phase == CudaInjectionPhase) { - Current = - buildCudaActions(C, Args, InputArg, std::move(Current), Actions); + Current = buildCudaActions(C, Args, InputArg, Current, Actions); if (!Current) break; } @@ -1512,12 +1507,13 @@ // If we ended with something, add to the output list. if (Current) - Actions.push_back(Current.release()); + Actions.push_back(Current); } // Add a link action if necessary. if (!LinkerInputs.empty()) - Actions.push_back(new LinkJobAction(LinkerInputs, types::TY_Image)); + Actions.push_back( + C.MakeAction(LinkerInputs, types::TY_Image)); // If we are linking, claim any options which are obviously only used for // compilation. @@ -1534,10 +1530,9 @@ Args.ClaimAllArgs(options::OPT_cuda_host_only); } -std::unique_ptr -Driver::ConstructPhaseAction(const ToolChain &TC, const ArgList &Args, - phases::ID Phase, - std::unique_ptr Input) const { +Action *Driver::ConstructPhaseAction(Compilation &C, const ToolChain &TC, + const ArgList &Args, phases::ID Phase, + Action *Input) const { llvm::PrettyStackTraceString CrashInfo("Constructing phase actions"); // Build the appropriate action. switch (Phase) { @@ -1557,7 +1552,7 @@ assert(OutputTy != types::TY_INVALID && "Cannot preprocess this input type!"); } - return llvm::make_unique(std::move(Input), OutputTy); + return C.MakeAction(Input, OutputTy); } case phases::Precompile: { types::ID OutputTy = types::TY_PCH; @@ -1565,53 +1560,43 @@ // Syntax checks should not emit a PCH file OutputTy = types::TY_Nothing; } - return llvm::make_unique(std::move(Input), OutputTy); + return C.MakeAction(Input, OutputTy); } case phases::Compile: { if (Args.hasArg(options::OPT_fsyntax_only)) - return llvm::make_unique(std::move(Input), - types::TY_Nothing); + return C.MakeAction(Input, types::TY_Nothing); if (Args.hasArg(options::OPT_rewrite_objc)) - return llvm::make_unique(std::move(Input), - types::TY_RewrittenObjC); + return C.MakeAction(Input, types::TY_RewrittenObjC); if (Args.hasArg(options::OPT_rewrite_legacy_objc)) - return llvm::make_unique(std::move(Input), - types::TY_RewrittenLegacyObjC); + return C.MakeAction(Input, + types::TY_RewrittenLegacyObjC); if (Args.hasArg(options::OPT__analyze, options::OPT__analyze_auto)) - return llvm::make_unique(std::move(Input), - types::TY_Plist); + return C.MakeAction(Input, types::TY_Plist); if (Args.hasArg(options::OPT__migrate)) - return llvm::make_unique(std::move(Input), - types::TY_Remap); + return C.MakeAction(Input, types::TY_Remap); if (Args.hasArg(options::OPT_emit_ast)) - return llvm::make_unique(std::move(Input), - types::TY_AST); + return C.MakeAction(Input, types::TY_AST); if (Args.hasArg(options::OPT_module_file_info)) - return llvm::make_unique(std::move(Input), - types::TY_ModuleFile); + return C.MakeAction(Input, types::TY_ModuleFile); if (Args.hasArg(options::OPT_verify_pch)) - return llvm::make_unique(std::move(Input), - types::TY_Nothing); - return llvm::make_unique(std::move(Input), - types::TY_LLVM_BC); + return C.MakeAction(Input, types::TY_Nothing); + return C.MakeAction(Input, types::TY_LLVM_BC); } case phases::Backend: { if (isUsingLTO()) { types::ID Output = Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC; - return llvm::make_unique(std::move(Input), Output); + return C.MakeAction(Input, Output); } if (Args.hasArg(options::OPT_emit_llvm)) { types::ID Output = Args.hasArg(options::OPT_S) ? types::TY_LLVM_IR : types::TY_LLVM_BC; - return llvm::make_unique(std::move(Input), Output); + return C.MakeAction(Input, Output); } - return llvm::make_unique(std::move(Input), - types::TY_PP_Asm); + return C.MakeAction(Input, types::TY_PP_Asm); } case phases::Assemble: - return llvm::make_unique(std::move(Input), - types::TY_Object); + return C.MakeAction(Input, types::TY_Object); } llvm_unreachable("invalid phase in ConstructPhaseAction");