aganea updated this revision to Diff 244055.
aganea marked 3 inline comments as done.
aganea added a comment.

As suggested by Reid.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D74447/new/

https://reviews.llvm.org/D74447

Files:
  clang/include/clang/Driver/Job.h
  clang/lib/Driver/Driver.cpp
  clang/lib/Driver/Job.cpp
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/Driver/cc1-spawnprocess.c
  clang/tools/driver/cc1_main.cpp

Index: clang/tools/driver/cc1_main.cpp
===================================================================
--- clang/tools/driver/cc1_main.cpp
+++ clang/tools/driver/cc1_main.cpp
@@ -259,6 +259,7 @@
       // FIXME(ibiryukov): make profilerOutput flush in destructor instead.
       profilerOutput->flush();
       llvm::timeTraceProfilerCleanup();
+      Clang->clearOutputFiles(false);
     }
   }
 
Index: clang/test/Driver/cc1-spawnprocess.c
===================================================================
--- clang/test/Driver/cc1-spawnprocess.c
+++ clang/test/Driver/cc1-spawnprocess.c
@@ -20,3 +20,48 @@
 
 // YES: (in-process)
 // NO-NOT: (in-process)
+
+// The following tests ensure that only the last integrated-cc1 has -disable-free
+
+// RUN: echo 'int main() { return f() + g(); }' > %t1.cpp
+// RUN: echo 'int f() { return 1; }' > %t2.cpp
+// RUN: echo 'int g() { return 2; }' > %t3.cpp
+
+// Only one TU, one job, thus no cleanup is needed.
+// RUN: %clang -fintegrated-cc1 -c %t1.cpp -### 2>&1 | FileCheck %s --check-prefix=CLEAN
+// CLEAN: cc1
+// CLEAN-SAME: -disable-free
+
+// Three jobs, only the last invocation will skip clean up.
+// RUN: %clang -fintegrated-cc1 -c %t1.cpp %t2.cpp %t3.cpp -### 2>&1 | FileCheck %s --check-prefix=NOCLEAN-LAST
+// NOCLEAN-LAST: cc1
+// NOCLEAN-LAST-NOT: -disable-free
+// NOCLEAN-LAST-SAME: {{.*}}1.cpp
+// NOCLEAN-LAST: cc1
+// NOCLEAN-LAST-NOT: -disable-free
+// NOCLEAN-LAST-SAME: {{.*}}2.cpp
+// NOCLEAN-LAST: cc1
+// NOCLEAN-LAST-SAME: -disable-free
+// NOCLEAN-LAST-SAME: {{.*}}3.cpp
+
+// Four jobs, no invocation will skip clean up because the last job is linking.
+// RUN: %clang -fintegrated-cc1 %t1.cpp %t2.cpp %t3.cpp -### 2>&1 | FileCheck %s --check-prefix=ALL
+// ALL-NOT: -disable-free
+
+// In no-integrated-cc1 mode, no cleanup is needed, because we're running the
+// CC1 tool in a secondary process and the process' heap will be released
+// anyway when the process ends.
+// RUN: %clang -fno-integrated-cc1 -c %t1.cpp -### 2>&1 | FileCheck %s --check-prefix=CLEAN
+
+// RUN: %clang -fno-integrated-cc1 -c %t1.cpp %t2.cpp %t3.cpp -### 2>&1 | FileCheck %s --check-prefix=CLEANALL
+// CLEANALL: cc1
+// CLEANALL-SAME: -disable-free
+// CLEANALL-SAME: {{.*}}1.cpp
+// CLEANALL: cc1
+// CLEANALL-SAME: -disable-free
+// CLEANALL-SAME: {{.*}}2.cpp
+// CLEANALL: cc1
+// CLEANALL-SAME: -disable-free
+// CLEANALL-SAME: {{.*}}3.cpp
+
+// RUN: %clang -fno-integrated-cc1 %t1.cpp %t2.cpp %t3.cpp -### 2>&1 | FileCheck %s --check-prefix=CLEANALL
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -6143,7 +6143,7 @@
   if (Output.getType() == types::TY_Object &&
       Args.hasFlag(options::OPT__SLASH_showFilenames,
                    options::OPT__SLASH_showFilenames_, false)) {
-    C.getJobs().getJobs().back()->setPrintInputFilenames(true);
+    C.getJobs().getJobs().back()->PrintInputFilenames = true;
   }
 
   if (Arg *A = Args.getLastArg(options::OPT_pg))
Index: clang/lib/Driver/Job.cpp
===================================================================
--- clang/lib/Driver/Job.cpp
+++ clang/lib/Driver/Job.cpp
@@ -40,7 +40,7 @@
                  const llvm::opt::ArgStringList &Arguments,
                  ArrayRef<InputInfo> Inputs)
     : Source(Source), Creator(Creator), Executable(Executable),
-      Arguments(Arguments) {
+      Arguments(Arguments), PrintInputFilenames(false), InProcess(false) {
   for (const auto &II : Inputs)
     if (II.isFilename())
       InputFilenames.push_back(II.getFilename());
@@ -315,6 +315,15 @@
   Environment.push_back(nullptr);
 }
 
+// In some cases when running the calling process, we need to clean up if there
+// are other Commands being executed after us, to prevent bloating the heap.
+void Command::forceCleanUp() {
+  auto RemoveDisableFree = [](const char *A) {
+    return StringRef(A).equals("-disable-free");
+  };
+  llvm::erase_if(Arguments, RemoveDisableFree);
+}
+
 void Command::PrintFileNames() const {
   if (PrintInputFilenames) {
     for (const char *Arg : InputFilenames)
@@ -371,6 +380,14 @@
                                    /*memoryLimit*/ 0, ErrMsg, ExecutionFailed);
 }
 
+CC1Command::CC1Command(const Action &Source, const Tool &Creator,
+                       const char *Executable,
+                       const llvm::opt::ArgStringList &Arguments,
+                       ArrayRef<InputInfo> Inputs)
+    : Command(Source, Creator, Executable, Arguments, Inputs) {
+  InProcess = true;
+}
+
 void CC1Command::Print(raw_ostream &OS, const char *Terminator, bool Quote,
                        CrashReportInfo *CrashInfo) const {
   OS << " (in-process)\n";
Index: clang/lib/Driver/Driver.cpp
===================================================================
--- clang/lib/Driver/Driver.cpp
+++ clang/lib/Driver/Driver.cpp
@@ -3753,6 +3753,18 @@
                        /*TargetDeviceOffloadKind*/ Action::OFK_None);
   }
 
+  // Make sure we clean up after in-process jobs.
+  JobList &Jobs = C.getJobs();
+  if (!Jobs.empty()) {
+    Command &Last = *Jobs.getJobs().back();
+    for (auto &Job : Jobs) {
+      // If this is a in-process job, and there are other jobs coming after,
+      // then make sure we clean up once the job is done.
+      if (Job.InProcess && &Job != &Last)
+        Job.forceCleanUp();
+    }
+  }
+
   // If the user passed -Qunused-arguments or there were errors, don't warn
   // about any unused arguments.
   if (Diags.hasErrorOccurred() ||
Index: clang/include/clang/Driver/Job.h
===================================================================
--- clang/include/clang/Driver/Job.h
+++ clang/include/clang/Driver/Job.h
@@ -55,9 +55,6 @@
   /// The list of program arguments which are inputs.
   llvm::opt::ArgStringList InputFilenames;
 
-  /// Whether to print the input filenames when executing.
-  bool PrintInputFilenames = false;
-
   /// Response file name, if this command is set to use one, or nullptr
   /// otherwise
   const char *ResponseFile = nullptr;
@@ -86,6 +83,12 @@
   void writeResponseFile(raw_ostream &OS) const;
 
 public:
+  /// Whether to print the input filenames when executing.
+  bool PrintInputFilenames : 1;
+
+  /// Whether the command will be executed in this process or not.
+  bool InProcess : 1;
+
   Command(const Action &Source, const Tool &Creator, const char *Executable,
           const llvm::opt::ArgStringList &Arguments,
           ArrayRef<InputInfo> Inputs);
@@ -128,8 +131,8 @@
   /// Print a command argument, and optionally quote it.
   static void printArg(llvm::raw_ostream &OS, StringRef Arg, bool Quote);
 
-  /// Set whether to print the input filenames when executing.
-  void setPrintInputFilenames(bool P) { PrintInputFilenames = P; }
+  /// Prevent burying pointers, and ensure we free everything after execution.
+  void forceCleanUp();
 
 protected:
   /// Optionally print the filenames to be compiled
@@ -139,7 +142,9 @@
 /// Use the CC1 tool callback when available, to avoid creating a new process
 class CC1Command : public Command {
 public:
-  using Command::Command;
+  CC1Command(const Action &Source, const Tool &Creator, const char *Executable,
+             const llvm::opt::ArgStringList &Arguments,
+             ArrayRef<InputInfo> Inputs);
 
   void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote,
              CrashReportInfo *CrashInfo = nullptr) const override;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to