]> granicus.if.org Git - clang/commitdiff
Fix memory leak after r312467. The ModuleMap is the owner of the global module object...
authorRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 5 Sep 2017 21:46:22 +0000 (21:46 +0000)
committerRichard Smith <richard-llvm@metafoo.co.uk>
Tue, 5 Sep 2017 21:46:22 +0000 (21:46 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@312580 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Lex/ModuleMap.h
lib/Lex/ModuleMap.cpp

index 9cca0167518aac1700a24a3194327ef2a144ef01..4e600ce855eefc910b2107ce92584c48fad086fe 100644 (file)
@@ -82,22 +82,26 @@ class ModuleMap {
   
   /// \brief The directory used for Clang-supplied, builtin include headers,
   /// such as "stdint.h".
-  const DirectoryEntry *BuiltinIncludeDir;
+  const DirectoryEntry *BuiltinIncludeDir = nullptr;
   
   /// \brief Language options used to parse the module map itself.
   ///
   /// These are always simple C language options.
   LangOptions MMapLangOpts;
 
-  // The module that the main source file is associated with (the module
-  // named LangOpts::CurrentModule, if we've loaded it).
-  Module *SourceModule;
+  /// The module that the main source file is associated with (the module
+  /// named LangOpts::CurrentModule, if we've loaded it).
+  Module *SourceModule = nullptr;
+
+  /// The global module for the current TU, if we still own it. (Ownership is
+  /// transferred if/when we create an enclosing module.
+  std::unique_ptr<Module> PendingGlobalModule;
 
   /// \brief The top-level modules that are known.
   llvm::StringMap<Module *> Modules;
 
   /// \brief The number of modules we have created in total.
-  unsigned NumCreatedModules;
+  unsigned NumCreatedModules = 0;
 
 public:
   /// \brief Flags describing the role of a module header.
index db2f952e3c9df6e29355058bfab9a5117b582979..b01080e55a533f8e8bd444d5bf94eedf92561db1 100644 (file)
@@ -256,8 +256,7 @@ ModuleMap::ModuleMap(SourceManager &SourceMgr, DiagnosticsEngine &Diags,
                      const LangOptions &LangOpts, const TargetInfo *Target,
                      HeaderSearch &HeaderInfo)
     : SourceMgr(SourceMgr), Diags(Diags), LangOpts(LangOpts), Target(Target),
-      HeaderInfo(HeaderInfo), BuiltinIncludeDir(nullptr),
-      SourceModule(nullptr), NumCreatedModules(0) {
+      HeaderInfo(HeaderInfo) {
   MMapLangOpts.LineComment = true;
 }
 
@@ -747,10 +746,12 @@ std::pair<Module *, bool> ModuleMap::findOrCreateModule(StringRef Name,
 }
 
 Module *ModuleMap::createGlobalModuleForInterfaceUnit(SourceLocation Loc) {
-  auto *Result = new Module("<global>", Loc, nullptr, /*IsFramework*/ false,
-                            /*IsExplicit*/ true, NumCreatedModules++);
-  Result->Kind = Module::GlobalModuleFragment;
-  return Result;
+  assert(!PendingGlobalModule && "created multiple global modules");
+  PendingGlobalModule.reset(
+      new Module("<global>", Loc, nullptr, /*IsFramework*/ false,
+                 /*IsExplicit*/ true, NumCreatedModules++));
+  PendingGlobalModule->Kind = Module::GlobalModuleFragment;
+  return PendingGlobalModule.get();
 }
 
 Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
@@ -766,7 +767,10 @@ Module *ModuleMap::createModuleForInterfaceUnit(SourceLocation Loc,
   Modules[Name] = SourceModule = Result;
 
   // Reparent the current global module fragment as a submodule of this module.
+  assert(GlobalModule == PendingGlobalModule.get() &&
+         "unexpected global module");
   GlobalModule->setParent(Result);
+  PendingGlobalModule.release(); // now owned by parent
 
   // Mark the main source file as being within the newly-created module so that
   // declarations and macros are properly visibility-restricted to it.