]> granicus.if.org Git - clang/commitdiff
Module debugging: Support submodules in the PCM/PCH debug info.
authorAdrian Prantl <aprantl@apple.com>
Sun, 20 Sep 2015 16:51:35 +0000 (16:51 +0000)
committerAdrian Prantl <aprantl@apple.com>
Sun, 20 Sep 2015 16:51:35 +0000 (16:51 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@248127 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGDebugInfo.cpp
lib/CodeGen/CGDebugInfo.h
lib/CodeGen/ObjectFilePCHContainerOperations.cpp
test/Modules/DebugInfoSubmodules.c [new file with mode: 0644]
test/Modules/Inputs/DebugSubmoduleA.h [new file with mode: 0644]
test/Modules/Inputs/DebugSubmoduleB.h [new file with mode: 0644]
test/Modules/Inputs/module.map

index c0a3db4d61b7288573b7fe69b592ea84e8d3caa5..6af8d6626b43b12e72e66525e862689f1bd18640 100644 (file)
@@ -28,6 +28,7 @@
 #include "clang/Basic/Version.h"
 #include "clang/Frontend/CodeGenOptions.h"
 #include "clang/Lex/HeaderSearchOptions.h"
+#include "clang/Lex/ModuleMap.h"
 #include "clang/Lex/PreprocessorOptions.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringExtras.h"
@@ -2159,17 +2160,34 @@ ObjCInterfaceDecl *CGDebugInfo::getObjCInterfaceDecl(QualType Ty) {
 }
 
 llvm::DIModule *CGDebugInfo::getParentModuleOrNull(const Decl *D) {
-  if (!DebugTypeExtRefs || !D->isFromASTFile())
-    return nullptr;
+  ExternalASTSource::ASTSourceDescriptor Info;
+  if (ClangModuleMap) {
+    // We are building a clang module or a precompiled header.
+    //
+    // TODO: When D is a CXXRecordDecl or a C++ Enum, the ODR applies
+    // and it wouldn't be necessary to specify the parent scope
+    // because the type is already unique by definition (it would look
+    // like the output of -fno-standalone-debug). On the other hand,
+    // the parent scope helps a consumer to quickly locate the object
+    // file where the type's definition is located, so it might be
+    // best to make this behavior a command line or debugger tuning
+    // option.
+    FullSourceLoc Loc(D->getLocation(), CGM.getContext().getSourceManager());
+    if (Module *M = ClangModuleMap->inferModuleFromLocation(Loc)) {
+      auto Info = ExternalASTSource::ASTSourceDescriptor(*M);
+      return getOrCreateModuleRef(Info, /*SkeletonCU=*/false);
+    }
+  }
 
-  // Record a reference to an imported clang module or precompiled header.
-  llvm::DIModule *ModuleRef = nullptr;
-  auto *Reader = CGM.getContext().getExternalSource();
-  auto Idx = D->getOwningModuleID();
-  auto Info = Reader->getSourceDescriptor(Idx);
-  if (Info)
-    ModuleRef = getOrCreateModuleRef(*Info, true);
-  return ModuleRef;
+  if (DebugTypeExtRefs && D->isFromASTFile()) {
+    // Record a reference to an imported clang module or precompiled header.
+    auto *Reader = CGM.getContext().getExternalSource();
+    auto Idx = D->getOwningModuleID();
+    auto Info = Reader->getSourceDescriptor(Idx);
+    if (Info)
+      return getOrCreateModuleRef(*Info, /*SkeletonCU=*/true);
+  }
+  return nullptr;
 }
 
 llvm::DIType *CGDebugInfo::CreateTypeNode(QualType Ty, llvm::DIFile *Unit) {
index 8d42f57a3ecbaa17a1a5202563e1c0c97689de37..8cad0c16b764e6b316139add013d7a16de8dc885 100644 (file)
@@ -32,12 +32,13 @@ class MDNode;
 
 namespace clang {
 class CXXMethodDecl;
-class VarDecl;
-class ObjCInterfaceDecl;
-class ObjCIvarDecl;
 class ClassTemplateSpecializationDecl;
 class GlobalDecl;
+class ModuleMap;
+class ObjCInterfaceDecl;
+class ObjCIvarDecl;
 class UsingDecl;
+class VarDecl;
 
 namespace CodeGen {
 class CodeGenModule;
@@ -55,6 +56,7 @@ class CGDebugInfo {
   bool DebugTypeExtRefs;
   llvm::DIBuilder DBuilder;
   llvm::DICompileUnit *TheCU = nullptr;
+  ModuleMap *ClangModuleMap = nullptr;
   SourceLocation CurLoc;
   llvm::DIType *VTablePtrType = nullptr;
   llvm::DIType *ClassTy = nullptr;
@@ -274,6 +276,11 @@ public:
 
   void finalize();
 
+  /// When generating debug information for a clang module or
+  /// precompiled header, this module map will be used to determine
+  /// the module of origin of each Decl.
+  void setModuleMap(ModuleMap &MMap) { ClangModuleMap = &MMap; }
+
   /// Update the current source location. If \arg loc is invalid it is
   /// ignored.
   void setLocation(SourceLocation Loc);
index 147d198d9b8f9a9e82c1b3f6c9327a4b02bb7042..1673340a495cb801df4410ab4095301bcc383900 100644 (file)
@@ -19,6 +19,8 @@
 #include "clang/CodeGen/BackendUtil.h"
 #include "clang/Frontend/CodeGenOptions.h"
 #include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Preprocessor.h"
+#include "clang/Lex/HeaderSearch.h"
 #include "clang/Serialization/ASTWriter.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Bitcode/BitstreamReader.h"
@@ -41,6 +43,7 @@ class PCHContainerGenerator : public ASTConsumer {
   DiagnosticsEngine &Diags;
   const std::string MainFileName;
   ASTContext *Ctx;
+  ModuleMap &MMap;
   const HeaderSearchOptions &HeaderSearchOpts;
   const PreprocessorOptions &PreprocessorOpts;
   CodeGenOptions CodeGenOpts;
@@ -121,6 +124,7 @@ public:
                         raw_pwrite_stream *OS,
                         std::shared_ptr<PCHBuffer> Buffer)
       : Diags(CI.getDiagnostics()), Ctx(nullptr),
+        MMap(CI.getPreprocessor().getHeaderSearchInfo().getModuleMap()),
         HeaderSearchOpts(CI.getHeaderSearchOpts()),
         PreprocessorOpts(CI.getPreprocessorOpts()),
         TargetOpts(CI.getTargetOpts()), LangOpts(CI.getLangOpts()), OS(OS),
@@ -145,6 +149,7 @@ public:
     M->setDataLayout(Ctx->getTargetInfo().getDataLayoutString());
     Builder.reset(new CodeGen::CodeGenModule(
         *Ctx, HeaderSearchOpts, PreprocessorOpts, CodeGenOpts, *M, Diags));
+    Builder->getModuleDebugInfo()->setModuleMap(MMap);
   }
 
   bool HandleTopLevelDecl(DeclGroupRef D) override {
diff --git a/test/Modules/DebugInfoSubmodules.c b/test/Modules/DebugInfoSubmodules.c
new file mode 100644 (file)
index 0000000..1cba00d
--- /dev/null
@@ -0,0 +1,15 @@
+// RUN: rm -rf %t
+// RUN: %clang_cc1 -fmodules -fmodule-format=obj -g -dwarf-ext-refs \
+// RUN:     -fimplicit-module-maps -x c -fmodules-cache-path=%t -I %S/Inputs \
+// RUN:     %s -mllvm -debug-only=pchcontainer 2>&1 | FileCheck %s
+#include "DebugSubmoduleA.h"
+
+// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "A",
+// CHECK-SAME:             scope: ![[SUBMODULEA:[0-9]+]]
+// CHECK: ![[SUBMODULEA]] = !DIModule(
+// CHECK-SAME:                        name: "DebugSubmodules.DebugSubmoduleA",
+
+// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "B",
+// CHECK-SAME:             scope: ![[SUBMODULEB:[0-9]+]]
+// CHECK: ![[SUBMODULEB]] = !DIModule(
+// CHECK-SAME:                        name: "DebugSubmodules.DebugSubmoduleB",
diff --git a/test/Modules/Inputs/DebugSubmoduleA.h b/test/Modules/Inputs/DebugSubmoduleA.h
new file mode 100644 (file)
index 0000000..1403a7d
--- /dev/null
@@ -0,0 +1,3 @@
+struct A {
+  int a;
+};
diff --git a/test/Modules/Inputs/DebugSubmoduleB.h b/test/Modules/Inputs/DebugSubmoduleB.h
new file mode 100644 (file)
index 0000000..b06ae6a
--- /dev/null
@@ -0,0 +1,3 @@
+struct B {
+  int b;
+};
index 79a9a47e5847a0ca25dcca1637941e02b752c0b4..27751d8fd51fb07be56b18a12ae5862c9d0a187a 100644 (file)
@@ -364,3 +364,14 @@ module TargetFeatures {
     module x86_64 { requires x86_64 }
   }
 }
+
+module DebugSubmodules {
+  module DebugSubmoduleA {
+    header "DebugSubmoduleA.h"
+    export *
+  }
+  module DebugSubmoduleB {
+    header "DebugSubmoduleB.h"
+    export *
+  }
+}