jlebar created this revision.
jlebar added a reviewer: echristo.
jlebar added a subscriber: cfe-commits.
jlebar added a dependency: D15910: Make isa, cast, dyn_cast, etc. work with 
std::unique_ptr and std::shared_ptr..
Herald added a subscriber: klimek.

This makes constructing Action graphs which are DAGs much simpler.  It
also just simplifies in general the ownership semantics of Actions.

Depends on D15910.

http://reviews.llvm.org/D15911

Files:
  include/clang/Driver/Action.h
  include/clang/Driver/Driver.h
  include/clang/Driver/Util.h
  lib/Driver/Action.cpp
  lib/Driver/Compilation.cpp
  lib/Driver/Driver.cpp
  lib/Driver/Tools.cpp
  lib/Tooling/CompilationDatabase.cpp

Index: lib/Tooling/CompilationDatabase.cpp
===================================================================
--- lib/Tooling/CompilationDatabase.cpp
+++ lib/Tooling/CompilationDatabase.cpp
@@ -141,7 +141,7 @@
 
     for (driver::ActionList::const_iterator I = A->begin(), E = A->end();
          I != E; ++I)
-      runImpl(*I, CollectChildren);
+      runImpl(I->get(), CollectChildren);
   }
 };
 
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp
+++ lib/Driver/Tools.cpp
@@ -2455,7 +2455,7 @@
     return true;
 
   for (const auto &Act : *A)
-    if (ContainsCompileAction(Act))
+    if (ContainsCompileAction(Act.get()))
       return true;
 
   return false;
@@ -2472,7 +2472,7 @@
   if (RelaxDefault) {
     RelaxDefault = false;
     for (const auto &Act : C.getActions()) {
-      if (ContainsCompileAction(Act)) {
+      if (ContainsCompileAction(Act.get())) {
         RelaxDefault = true;
         break;
       }
@@ -5922,7 +5922,7 @@
   const Action *SourceAction = &JA;
   while (SourceAction->getKind() != Action::InputClass) {
     assert(!SourceAction->getInputs().empty() && "unexpected root action!");
-    SourceAction = SourceAction->getInputs()[0];
+    SourceAction = SourceAction->getInputs()[0].get();
   }
 
   // Forward -g and handle debug info related flags, assuming we are dealing
@@ -6833,7 +6833,7 @@
   const Action *SourceAction = &JA;
   while (SourceAction->getKind() != Action::InputClass) {
     assert(!SourceAction->getInputs().empty() && "unexpected root action!");
-    SourceAction = SourceAction->getInputs()[0];
+    SourceAction = SourceAction->getInputs()[0].get();
   }
 
   // If -fno-integrated-as is used add -Q to the darwin assember driver to make
Index: lib/Driver/Driver.cpp
===================================================================
--- lib/Driver/Driver.cpp
+++ lib/Driver/Driver.cpp
@@ -934,36 +934,36 @@
 // Display an action graph human-readably.  Action A is the "sink" node
 // and latest-occuring action. Traversal is in pre-order, visiting the
 // inputs to each action before printing the action itself.
-static unsigned PrintActions1(const Compilation &C, Action *A,
-                              std::map<Action *, unsigned> &Ids) {
+static unsigned PrintActions1(const Compilation &C, const Action *A,
+                              std::map<const Action *, unsigned> &Ids) {
   if (Ids.count(A)) // A was already visited.
     return Ids[A];
 
   std::string str;
   llvm::raw_string_ostream os(str);
 
   os << Action::getClassName(A->getKind()) << ", ";
-  if (InputAction *IA = dyn_cast<InputAction>(A)) {
+  if (const InputAction *IA = dyn_cast<InputAction>(A)) {
     os << "\"" << IA->getInputArg().getValue() << "\"";
-  } else if (BindArchAction *BIA = dyn_cast<BindArchAction>(A)) {
+  } else if (const BindArchAction *BIA = dyn_cast<BindArchAction>(A)) {
     os << '"' << BIA->getArchName() << '"' << ", {"
-       << PrintActions1(C, *BIA->begin(), Ids) << "}";
-  } else if (CudaDeviceAction *CDA = dyn_cast<CudaDeviceAction>(A)) {
+       << PrintActions1(C, BIA->begin()->get(), Ids) << "}";
+  } else if (const CudaDeviceAction *CDA = dyn_cast<CudaDeviceAction>(A)) {
     os << '"' << CDA->getGpuArchName() << '"' << ", {"
-       << PrintActions1(C, *CDA->begin(), Ids) << "}";
+       << PrintActions1(C, CDA->begin()->get(), Ids) << "}";
   } else {
     const ActionList *AL;
-    if (CudaHostAction *CHA = dyn_cast<CudaHostAction>(A)) {
-      os << "{" << PrintActions1(C, *CHA->begin(), Ids) << "}"
+    if (const CudaHostAction *CHA = dyn_cast<CudaHostAction>(A)) {
+      os << "{" << PrintActions1(C, CHA->begin()->get(), Ids) << "}"
          << ", gpu binaries ";
       AL = &CHA->getDeviceActions();
     } else
       AL = &A->getInputs();
 
     if (AL->size()) {
       const char *Prefix = "{";
-      for (Action *PreRequisite : *AL) {
-        os << Prefix << PrintActions1(C, PreRequisite, Ids);
+      for (const std::shared_ptr<Action> &PreRequisite : *AL) {
+        os << Prefix << PrintActions1(C, PreRequisite.get(), Ids);
         Prefix = ", ";
       }
       os << "}";
@@ -982,9 +982,9 @@
 // Print the action graphs in a compilation C.
 // For example "clang -c file1.c file2.c" is composed of two subgraphs.
 void Driver::PrintActions(const Compilation &C) const {
-  std::map<Action *, unsigned> Ids;
-  for (Action *A : C.getActions())
-    PrintActions1(C, A, Ids);
+  std::map<const Action *, unsigned> Ids;
+  for (const std::shared_ptr<Action> &A : C.getActions())
+    PrintActions1(C, A.get(), Ids);
 }
 
 /// \brief Check whether the given input tree contains any compilation or
@@ -994,8 +994,8 @@
       isa<AssembleJobAction>(A))
     return true;
 
-  for (const Action *Input : *A)
-    if (ContainsCompileOrAssembleAction(Input))
+  for (const std::shared_ptr<Action> Input : *A)
+    if (ContainsCompileOrAssembleAction(Input.get()))
       return true;
 
   return false;
@@ -1037,7 +1037,7 @@
 
   // Add in arch bindings for every top level action, as well as lipo and
   // dsymutil steps if needed.
-  for (Action* Act : SingleActions) {
+  for (const std::shared_ptr<Action> &Act : SingleActions) {
     // Make sure we can lipo this kind of output. If not (and it is an actual
     // output) then we disallow, since we can't create an output file with the
     // right name without overwriting it. We could remove this oddity by just
@@ -1050,24 +1050,22 @@
 
     ActionList Inputs;
     for (unsigned i = 0, e = Archs.size(); i != e; ++i) {
-      Inputs.push_back(
-          new BindArchAction(std::unique_ptr<Action>(Act), Archs[i]));
-      if (i != 0)
-        Inputs.back()->setOwnsInputs(false);
+      Inputs.push_back(std::make_shared<BindArchAction>(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(
+          std::make_shared<LipoJobAction>(Inputs, Act->getType()));
 
     // Handle debug info queries.
     Arg *A = Args.getLastArg(options::OPT_g_Group);
     if (A && !A->getOption().matches(options::OPT_g0) &&
         !A->getOption().matches(options::OPT_gstabs) &&
-        ContainsCompileOrAssembleAction(Actions.back())) {
+        ContainsCompileOrAssembleAction(Actions.back().get())) {
 
       // Add a 'dsymutil' step if necessary, when debug info is enabled and we
       // have a compile input. We need to run 'dsymutil' ourselves in such cases
@@ -1077,15 +1075,16 @@
         ActionList Inputs;
         Inputs.push_back(Actions.back());
         Actions.pop_back();
-        Actions.push_back(new DsymutilJobAction(Inputs, types::TY_dSYM));
+        Actions.push_back(
+            std::make_shared<DsymutilJobAction>(Inputs, types::TY_dSYM));
       }
 
       // Verify the debug info output.
       if (Args.hasArg(options::OPT_verify_debug_info)) {
-        std::unique_ptr<Action> VerifyInput(Actions.back());
+        std::shared_ptr<Action> LastAction = Actions.back();
         Actions.pop_back();
-        Actions.push_back(new VerifyDebugInfoJobAction(std::move(VerifyInput),
-                                                       types::TY_Nothing));
+        Actions.push_back(std::make_shared<VerifyDebugInfoJobAction>(
+            LastAction, types::TY_Nothing));
       }
     }
   }
@@ -1283,16 +1282,16 @@
 // 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<Action>
+static std::shared_ptr<Action>
 buildCudaActions(Compilation &C, DerivedArgList &Args, const Arg *InputArg,
-                 std::unique_ptr<Action> HostAction, ActionList &Actions) {
+                 std::shared_ptr<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<Action>(
-        new CudaHostAction(std::move(HostAction), {}));
+    return std::make_shared<CudaHostAction>(std::move(HostAction),
+                                            ActionList());
 
   // Collect all cuda_gpu_arch parameters, removing duplicates.
   SmallVector<const char *, 4> GpuArchList;
@@ -1350,26 +1349,25 @@
     }
 
     for (unsigned I = 0, E = GpuArchList.size(); I != E; ++I)
-      Actions.push_back(new CudaDeviceAction(
-          std::unique_ptr<Action>(CudaDeviceActions[I]), GpuArchList[I],
+      Actions.push_back(std::make_shared<CudaDeviceAction>(
+          CudaDeviceActions[I], GpuArchList[I],
           /* AtTopLevel */ true));
     // Kill host action in case of device-only compilation.
     if (DeviceOnlyCompilation)
-      HostAction.reset(nullptr);
+      return nullptr;
     return HostAction;
   }
 
   // Outputs of device actions during complete CUDA compilation get created
   // 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<Action>(CudaDeviceActions[I]), GpuArchList[I],
-        /* AtTopLevel */ false));
+    DeviceActions.push_back(
+        std::make_shared<CudaDeviceAction>(CudaDeviceActions[I], GpuArchList[I],
+                                           /* AtTopLevel */ false));
   // Return a new host action that incorporates original host action and all
   // device actions.
-  return std::unique_ptr<Action>(
-      new CudaHostAction(std::move(HostAction), DeviceActions));
+  return std::make_shared<CudaHostAction>(std::move(HostAction), DeviceActions);
 }
 
 void Driver::BuildActions(Compilation &C, const ToolChain &TC,
@@ -1478,7 +1476,8 @@
       }
 
     // Build the pipeline for this file.
-    std::unique_ptr<Action> Current(new InputAction(*InputArg, InputType));
+    std::shared_ptr<Action> Current =
+        std::make_shared<InputAction>(*InputArg, InputType);
     for (SmallVectorImpl<phases::ID>::iterator i = PL.begin(), e = PL.end();
          i != e; ++i) {
       phases::ID Phase = *i;
@@ -1490,7 +1489,7 @@
       // 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(std::move(Current));
         break;
       }
 
@@ -1516,12 +1515,13 @@
 
     // If we ended with something, add to the output list.
     if (Current)
-      Actions.push_back(Current.release());
+      Actions.push_back(std::move(Current));
   }
 
   // Add a link action if necessary.
   if (!LinkerInputs.empty())
-    Actions.push_back(new LinkJobAction(LinkerInputs, types::TY_Image));
+    Actions.push_back(
+        std::make_shared<LinkJobAction>(LinkerInputs, types::TY_Image));
 
   // If we are linking, claim any options which are obviously only used for
   // compilation.
@@ -1538,10 +1538,10 @@
   Args.ClaimAllArgs(options::OPT_cuda_host_only);
 }
 
-std::unique_ptr<Action>
+std::shared_ptr<Action>
 Driver::ConstructPhaseAction(const ToolChain &TC, const ArgList &Args,
                              phases::ID Phase,
-                             std::unique_ptr<Action> Input) const {
+                             std::shared_ptr<Action> Input) const {
   llvm::PrettyStackTraceString CrashInfo("Constructing phase actions");
   // Build the appropriate action.
   switch (Phase) {
@@ -1630,7 +1630,7 @@
   // files.
   if (FinalOutput) {
     unsigned NumOutputs = 0;
-    for (const Action *A : C.getActions())
+    for (const std::shared_ptr<Action> &A : C.getActions())
       if (A->getType() != types::TY_Nothing)
         ++NumOutputs;
 
@@ -1647,7 +1647,7 @@
       if (A->getOption().matches(options::OPT_arch))
         ArchNames.insert(A->getValue());
 
-  for (Action *A : C.getActions()) {
+  for (const std::shared_ptr<Action>& A : C.getActions()) {
     // If we are linking an image for multiple archs then the linker wants
     // -arch_multiple and -final_output <final image name>. Unfortunately, this
     // doesn't fit in cleanly because we have to pass this information down.
@@ -1663,7 +1663,7 @@
     }
 
     InputInfo II;
-    BuildJobsForAction(C, A, &C.getDefaultToolChain(),
+    BuildJobsForAction(C, A.get(), &C.getDefaultToolChain(),
                        /*BoundArch*/ nullptr,
                        /*AtTopLevel*/ true,
                        /*MultipleArchs*/ ArchNames.size() > 1,
@@ -1806,14 +1806,14 @@
   if (const CudaHostAction *CHA = dyn_cast<CudaHostAction>(A)) {
     InputInfo II;
     // Append outputs of device jobs to the input list.
-    for (const Action *DA : CHA->getDeviceActions()) {
-      BuildJobsForAction(C, DA, TC, nullptr, AtTopLevel,
+    for (const std::shared_ptr<Action> &DA : CHA->getDeviceActions()) {
+      BuildJobsForAction(C, DA.get(), TC, nullptr, AtTopLevel,
                          /*MultipleArchs*/ false, LinkingOutput, II);
       CudaDeviceInputInfos.push_back(II);
     }
     // Override current action with a real host compile action and continue
     // processing it.
-    A = *CHA->begin();
+    A = CHA->begin()->get();
   }
 
   if (const InputAction *IA = dyn_cast<InputAction>(A)) {
@@ -1841,16 +1841,16 @@
     else
       TC = &C.getDefaultToolChain();
 
-    BuildJobsForAction(C, *BAA->begin(), TC, ArchName, AtTopLevel,
+    BuildJobsForAction(C, BAA->begin()->get(), TC, ArchName, AtTopLevel,
                        MultipleArchs, LinkingOutput, Result);
     return;
   }
 
   if (const CudaDeviceAction *CDA = dyn_cast<CudaDeviceAction>(A)) {
     // Initial processing of CudaDeviceAction carries host params.
     // Call BuildJobsForAction() again, now with correct device parameters.
     assert(CDA->getGpuArchName() && "No GPU name in device action.");
-    BuildJobsForAction(C, *CDA->begin(), C.getCudaDeviceToolChain(),
+    BuildJobsForAction(C, CDA->begin()->get(), C.getCudaDeviceToolChain(),
                        CDA->getGpuArchName(), CDA->isAtTopLevel(),
                        /*MultipleArchs*/ true, LinkingOutput, Result);
     return;
@@ -1869,26 +1869,26 @@
   // need to build jobs for device-side inputs it may have held.
   if (CollapsedCHA) {
     InputInfo II;
-    for (const Action *DA : CollapsedCHA->getDeviceActions()) {
-      BuildJobsForAction(C, DA, TC, "", AtTopLevel,
+    for (const std::shared_ptr<Action> &DA : CollapsedCHA->getDeviceActions()) {
+      BuildJobsForAction(C, DA.get(), TC, "", AtTopLevel,
                          /*MultipleArchs*/ false, LinkingOutput, II);
       CudaDeviceInputInfos.push_back(II);
     }
   }
 
   // Only use pipes when there is exactly one input.
   InputInfoList InputInfos;
-  for (const Action *Input : *Inputs) {
+  for (const std::shared_ptr<Action> &Input : *Inputs) {
     // Treat dsymutil and verify sub-jobs as being at the top-level too, they
     // shouldn't get temporary output names.
     // FIXME: Clean this up.
     bool SubJobAtTopLevel = false;
     if (AtTopLevel && (isa<DsymutilJobAction>(A) || isa<VerifyJobAction>(A)))
       SubJobAtTopLevel = true;
 
     InputInfo II;
-    BuildJobsForAction(C, Input, TC, BoundArch, SubJobAtTopLevel, MultipleArchs,
-                       LinkingOutput, II);
+    BuildJobsForAction(C, Input.get(), TC, BoundArch, SubJobAtTopLevel,
+                       MultipleArchs, LinkingOutput, II);
     InputInfos.push_back(II);
   }
 
Index: lib/Driver/Compilation.cpp
===================================================================
--- lib/Driver/Compilation.cpp
+++ 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];
@@ -182,7 +177,7 @@
       return true;
 
   for (Action::const_iterator AI = A->begin(), AE = A->end(); AI != AE; ++AI)
-    if (ActionFailed(*AI, FailingCommands))
+    if (ActionFailed(AI->get(), FailingCommands))
       return true;
 
   return false;
@@ -208,7 +203,7 @@
   ForDiagnostics = true;
 
   // Free actions and jobs.
-  DeleteContainerPointers(Actions);
+  Actions.clear();
   Jobs.clear();
 
   // Clear temporary/results file lists.
Index: lib/Driver/Action.cpp
===================================================================
--- lib/Driver/Action.cpp
+++ 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,31 +46,28 @@
 
 void BindArchAction::anchor() {}
 
-BindArchAction::BindArchAction(std::unique_ptr<Action> Input,
+BindArchAction::BindArchAction(std::shared_ptr<Action> Input,
                                const char *_ArchName)
     : Action(BindArchClass, std::move(Input)), ArchName(_ArchName) {}
 
 void CudaDeviceAction::anchor() {}
 
-CudaDeviceAction::CudaDeviceAction(std::unique_ptr<Action> Input,
+CudaDeviceAction::CudaDeviceAction(std::shared_ptr<Action> Input,
                                    const char *ArchName, bool AtTopLevel)
     : Action(CudaDeviceClass, std::move(Input)), GpuArchName(ArchName),
       AtTopLevel(AtTopLevel) {}
 
 void CudaHostAction::anchor() {}
 
-CudaHostAction::CudaHostAction(std::unique_ptr<Action> Input,
+CudaHostAction::CudaHostAction(std::shared_ptr<Action> Input,
                                const ActionList &DeviceActions)
     : Action(CudaHostClass, std::move(Input)), DeviceActions(DeviceActions) {}
 
-CudaHostAction::~CudaHostAction() {
-  for (auto &DA : DeviceActions)
-    delete DA;
-}
+CudaHostAction::~CudaHostAction() {}
 
 void JobAction::anchor() {}
 
-JobAction::JobAction(ActionClass Kind, std::unique_ptr<Action> Input,
+JobAction::JobAction(ActionClass Kind, std::shared_ptr<Action> Input,
                      types::ID Type)
     : Action(Kind, std::move(Input), Type) {}
 
@@ -85,43 +77,43 @@
 
 void PreprocessJobAction::anchor() {}
 
-PreprocessJobAction::PreprocessJobAction(std::unique_ptr<Action> Input,
+PreprocessJobAction::PreprocessJobAction(std::shared_ptr<Action> Input,
                                          types::ID OutputType)
     : JobAction(PreprocessJobClass, std::move(Input), OutputType) {}
 
 void PrecompileJobAction::anchor() {}
 
-PrecompileJobAction::PrecompileJobAction(std::unique_ptr<Action> Input,
+PrecompileJobAction::PrecompileJobAction(std::shared_ptr<Action> Input,
                                          types::ID OutputType)
     : JobAction(PrecompileJobClass, std::move(Input), OutputType) {}
 
 void AnalyzeJobAction::anchor() {}
 
-AnalyzeJobAction::AnalyzeJobAction(std::unique_ptr<Action> Input,
+AnalyzeJobAction::AnalyzeJobAction(std::shared_ptr<Action> Input,
                                    types::ID OutputType)
     : JobAction(AnalyzeJobClass, std::move(Input), OutputType) {}
 
 void MigrateJobAction::anchor() {}
 
-MigrateJobAction::MigrateJobAction(std::unique_ptr<Action> Input,
+MigrateJobAction::MigrateJobAction(std::shared_ptr<Action> Input,
                                    types::ID OutputType)
     : JobAction(MigrateJobClass, std::move(Input), OutputType) {}
 
 void CompileJobAction::anchor() {}
 
-CompileJobAction::CompileJobAction(std::unique_ptr<Action> Input,
+CompileJobAction::CompileJobAction(std::shared_ptr<Action> Input,
                                    types::ID OutputType)
     : JobAction(CompileJobClass, std::move(Input), OutputType) {}
 
 void BackendJobAction::anchor() {}
 
-BackendJobAction::BackendJobAction(std::unique_ptr<Action> Input,
+BackendJobAction::BackendJobAction(std::shared_ptr<Action> Input,
                                    types::ID OutputType)
     : JobAction(BackendJobClass, std::move(Input), OutputType) {}
 
 void AssembleJobAction::anchor() {}
 
-AssembleJobAction::AssembleJobAction(std::unique_ptr<Action> Input,
+AssembleJobAction::AssembleJobAction(std::shared_ptr<Action> Input,
                                      types::ID OutputType)
     : JobAction(AssembleJobClass, std::move(Input), OutputType) {}
 
@@ -146,20 +138,20 @@
 void VerifyJobAction::anchor() {}
 
 VerifyJobAction::VerifyJobAction(ActionClass Kind,
-                                 std::unique_ptr<Action> Input, types::ID Type)
+                                 std::shared_ptr<Action> Input, types::ID Type)
     : JobAction(Kind, std::move(Input), Type) {
   assert((Kind == VerifyDebugInfoJobClass || Kind == VerifyPCHJobClass) &&
          "ActionClass is not a valid VerifyJobAction");
 }
 
 void VerifyDebugInfoJobAction::anchor() {}
 
 VerifyDebugInfoJobAction::VerifyDebugInfoJobAction(
-    std::unique_ptr<Action> Input, types::ID Type)
+    std::shared_ptr<Action> Input, types::ID Type)
     : VerifyJobAction(VerifyDebugInfoJobClass, std::move(Input), Type) {}
 
 void VerifyPCHJobAction::anchor() {}
 
-VerifyPCHJobAction::VerifyPCHJobAction(std::unique_ptr<Action> Input,
+VerifyPCHJobAction::VerifyPCHJobAction(std::shared_ptr<Action> Input,
                                        types::ID Type)
     : VerifyJobAction(VerifyPCHJobClass, std::move(Input), Type) {}
Index: include/clang/Driver/Util.h
===================================================================
--- include/clang/Driver/Util.h
+++ include/clang/Driver/Util.h
@@ -24,7 +24,7 @@
   typedef llvm::DenseMap<const JobAction*, const char*> ArgStringMap;
 
   /// ActionList - Type used for lists of actions.
-  typedef SmallVector<Action*, 3> ActionList;
+  typedef SmallVector<std::shared_ptr<Action>, 3> ActionList;
 
 } // end namespace driver
 } // end namespace clang
Index: include/clang/Driver/Driver.h
===================================================================
--- include/clang/Driver/Driver.h
+++ 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<Action>
+  std::shared_ptr<Action>
   ConstructPhaseAction(const ToolChain &TC, const llvm::opt::ArgList &Args,
-                       phases::ID Phase, std::unique_ptr<Action> Input) const;
+                       phases::ID Phase, std::shared_ptr<Action> Input) const;
 
   /// BuildJobsForAction - Construct the jobs to perform for the
   /// action \p A.
Index: include/clang/Driver/Action.h
===================================================================
--- include/clang/Driver/Action.h
+++ include/clang/Driver/Action.h
@@ -32,6 +32,10 @@
 /// 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.
+///
+/// An Action keeps a std::shared_ptr to each of its inputs (in an
+/// ActionList). Using shared_ptrs lets us manage graphs of Actions that
+/// are DAGs.
 class Action {
 public:
   typedef ActionList::size_type size_type;
@@ -70,27 +74,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<Action> Input, types::ID Type)
-      : Kind(Kind), Type(Type), Inputs(1, Input.release()), OwnsInputs(true) {
-  }
-  Action(ActionClass Kind, std::unique_ptr<Action> 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, std::shared_ptr<Action> Input, types::ID Type)
+      : Action(Kind, ActionList({Input}), Type) {}
+  Action(ActionClass Kind, std::shared_ptr<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 +123,7 @@
   const char *ArchName;
 
 public:
-  BindArchAction(std::unique_ptr<Action> Input, const char *ArchName);
+  BindArchAction(std::shared_ptr<Action> Input, const char *ArchName);
 
   const char *getArchName() const { return ArchName; }
 
@@ -144,7 +141,7 @@
   bool AtTopLevel;
 
 public:
-  CudaDeviceAction(std::unique_ptr<Action> Input, const char *ArchName,
+  CudaDeviceAction(std::shared_ptr<Action> Input, const char *ArchName,
                    bool AtTopLevel);
 
   const char *getGpuArchName() const { return GpuArchName; }
@@ -160,7 +157,7 @@
   ActionList DeviceActions;
 
 public:
-  CudaHostAction(std::unique_ptr<Action> Input,
+  CudaHostAction(std::shared_ptr<Action> Input,
                  const ActionList &DeviceActions);
   ~CudaHostAction() override;
 
@@ -172,7 +169,7 @@
 class JobAction : public Action {
   virtual void anchor();
 protected:
-  JobAction(ActionClass Kind, std::unique_ptr<Action> Input, types::ID Type);
+  JobAction(ActionClass Kind, std::shared_ptr<Action> Input, types::ID Type);
   JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type);
 
 public:
@@ -185,7 +182,7 @@
 class PreprocessJobAction : public JobAction {
   void anchor() override;
 public:
-  PreprocessJobAction(std::unique_ptr<Action> Input, types::ID OutputType);
+  PreprocessJobAction(std::shared_ptr<Action> Input, types::ID OutputType);
 
   static bool classof(const Action *A) {
     return A->getKind() == PreprocessJobClass;
@@ -195,7 +192,7 @@
 class PrecompileJobAction : public JobAction {
   void anchor() override;
 public:
-  PrecompileJobAction(std::unique_ptr<Action> Input, types::ID OutputType);
+  PrecompileJobAction(std::shared_ptr<Action> Input, types::ID OutputType);
 
   static bool classof(const Action *A) {
     return A->getKind() == PrecompileJobClass;
@@ -205,7 +202,7 @@
 class AnalyzeJobAction : public JobAction {
   void anchor() override;
 public:
-  AnalyzeJobAction(std::unique_ptr<Action> Input, types::ID OutputType);
+  AnalyzeJobAction(std::shared_ptr<Action> Input, types::ID OutputType);
 
   static bool classof(const Action *A) {
     return A->getKind() == AnalyzeJobClass;
@@ -215,7 +212,7 @@
 class MigrateJobAction : public JobAction {
   void anchor() override;
 public:
-  MigrateJobAction(std::unique_ptr<Action> Input, types::ID OutputType);
+  MigrateJobAction(std::shared_ptr<Action> Input, types::ID OutputType);
 
   static bool classof(const Action *A) {
     return A->getKind() == MigrateJobClass;
@@ -225,7 +222,7 @@
 class CompileJobAction : public JobAction {
   void anchor() override;
 public:
-  CompileJobAction(std::unique_ptr<Action> Input, types::ID OutputType);
+  CompileJobAction(std::shared_ptr<Action> Input, types::ID OutputType);
 
   static bool classof(const Action *A) {
     return A->getKind() == CompileJobClass;
@@ -235,7 +232,7 @@
 class BackendJobAction : public JobAction {
   void anchor() override;
 public:
-  BackendJobAction(std::unique_ptr<Action> Input, types::ID OutputType);
+  BackendJobAction(std::shared_ptr<Action> Input, types::ID OutputType);
 
   static bool classof(const Action *A) {
     return A->getKind() == BackendJobClass;
@@ -245,7 +242,7 @@
 class AssembleJobAction : public JobAction {
   void anchor() override;
 public:
-  AssembleJobAction(std::unique_ptr<Action> Input, types::ID OutputType);
+  AssembleJobAction(std::shared_ptr<Action> Input, types::ID OutputType);
 
   static bool classof(const Action *A) {
     return A->getKind() == AssembleJobClass;
@@ -285,7 +282,7 @@
 class VerifyJobAction : public JobAction {
   void anchor() override;
 public:
-  VerifyJobAction(ActionClass Kind, std::unique_ptr<Action> Input,
+  VerifyJobAction(ActionClass Kind, std::shared_ptr<Action> Input,
                   types::ID Type);
   static bool classof(const Action *A) {
     return A->getKind() == VerifyDebugInfoJobClass ||
@@ -296,16 +293,16 @@
 class VerifyDebugInfoJobAction : public VerifyJobAction {
   void anchor() override;
 public:
-  VerifyDebugInfoJobAction(std::unique_ptr<Action> Input, types::ID Type);
+  VerifyDebugInfoJobAction(std::shared_ptr<Action> Input, types::ID Type);
   static bool classof(const Action *A) {
     return A->getKind() == VerifyDebugInfoJobClass;
   }
 };
 
 class VerifyPCHJobAction : public VerifyJobAction {
   void anchor() override;
 public:
-  VerifyPCHJobAction(std::unique_ptr<Action> Input, types::ID Type);
+  VerifyPCHJobAction(std::shared_ptr<Action> Input, types::ID Type);
   static bool classof(const Action *A) {
     return A->getKind() == VerifyPCHJobClass;
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to