summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Blaikie <dblaikie@gmail.com>2017-04-11 21:13:37 +0000
committerDavid Blaikie <dblaikie@gmail.com>2017-04-11 21:13:37 +0000
commita312d25909101f12a3b66a95aa0692676d3924fa (patch)
treebf881d7ef0890a6b5fb7bd5170aa089bd902ded0
parentfd6174d4ae513da6a0d2a26d61ce3af2a949533a (diff)
downloadclang-a312d25909101f12a3b66a95aa0692676d3924fa.tar.gz
Modular Codegen: Support homing debug info for types in modular objects
Matching the function-homing support for modular codegen. Any type implicitly (implicit template specializations) or explicitly defined in a module is attached to that module's object file and omitted elsewhere (only a declaration used if necessary for references). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@299987 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang/AST/ExternalASTSource.h2
-rw-r--r--include/clang/Sema/MultiplexExternalSemaSource.h2
-rw-r--r--include/clang/Serialization/ASTReader.h4
-rw-r--r--lib/AST/ExternalASTSource.cpp2
-rw-r--r--lib/CodeGen/CGDebugInfo.cpp14
-rw-r--r--lib/CodeGen/CGDebugInfo.h1
-rw-r--r--lib/CodeGen/CodeGenModule.cpp5
-rw-r--r--lib/Sema/MultiplexExternalSemaSource.cpp4
-rw-r--r--lib/Serialization/ASTReader.cpp3
-rw-r--r--lib/Serialization/ASTReaderDecl.cpp19
-rw-r--r--lib/Serialization/ASTWriter.cpp6
-rw-r--r--test/Modules/Inputs/codegen-nodep/foo.h10
-rw-r--r--test/Modules/codegen-nodep.test6
-rw-r--r--test/Modules/codegen.test12
14 files changed, 68 insertions, 22 deletions
diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h
index f2b29cd9a7..d8dd18ecb8 100644
--- a/include/clang/AST/ExternalASTSource.h
+++ b/include/clang/AST/ExternalASTSource.h
@@ -172,7 +172,7 @@ public:
enum ExtKind { EK_Always, EK_Never, EK_ReplyHazy };
- virtual ExtKind hasExternalDefinitions(const FunctionDecl *FD);
+ virtual ExtKind hasExternalDefinitions(const Decl *D);
/// \brief Finds all declarations lexically contained within the given
/// DeclContext, after applying an optional filter predicate.
diff --git a/include/clang/Sema/MultiplexExternalSemaSource.h b/include/clang/Sema/MultiplexExternalSemaSource.h
index 0386552dbe..1d681a0055 100644
--- a/include/clang/Sema/MultiplexExternalSemaSource.h
+++ b/include/clang/Sema/MultiplexExternalSemaSource.h
@@ -90,7 +90,7 @@ public:
/// initializers themselves.
CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset) override;
- ExtKind hasExternalDefinitions(const FunctionDecl *FD) override;
+ ExtKind hasExternalDefinitions(const Decl *D) override;
/// \brief Find all declarations with the given name in the
/// given context.
diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h
index 4e1c1cf57d..de122e63ba 100644
--- a/include/clang/Serialization/ASTReader.h
+++ b/include/clang/Serialization/ASTReader.h
@@ -1115,7 +1115,7 @@ private:
/// predefines buffer may contain additional definitions.
std::string SuggestedPredefines;
- llvm::DenseMap<const FunctionDecl *, bool> BodySource;
+ llvm::DenseMap<const Decl *, bool> BodySource;
/// \brief Reads a statement from the specified cursor.
Stmt *ReadStmtFromStream(ModuleFile &F);
@@ -1999,7 +1999,7 @@ public:
/// \brief Return a descriptor for the corresponding module.
llvm::Optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID) override;
- ExtKind hasExternalDefinitions(const FunctionDecl *FD) override;
+ ExtKind hasExternalDefinitions(const Decl *D) override;
/// \brief Retrieve a selector from the given module with its local ID
/// number.
diff --git a/lib/AST/ExternalASTSource.cpp b/lib/AST/ExternalASTSource.cpp
index 958a67843b..182d38242f 100644
--- a/lib/AST/ExternalASTSource.cpp
+++ b/lib/AST/ExternalASTSource.cpp
@@ -29,7 +29,7 @@ ExternalASTSource::getSourceDescriptor(unsigned ID) {
}
ExternalASTSource::ExtKind
-ExternalASTSource::hasExternalDefinitions(const FunctionDecl *FD) {
+ExternalASTSource::hasExternalDefinitions(const Decl *D) {
return EK_ReplyHazy;
}
diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp
index 05987be845..818b51543d 100644
--- a/lib/CodeGen/CGDebugInfo.cpp
+++ b/lib/CodeGen/CGDebugInfo.cpp
@@ -1820,6 +1820,10 @@ static bool shouldOmitDefinition(codegenoptions::DebugInfoKind DebugKind,
if (DebugTypeExtRefs && isDefinedInClangModule(RD->getDefinition()))
return true;
+ if (auto *ES = RD->getASTContext().getExternalSource())
+ if (ES->hasExternalDefinitions(RD) == ExternalASTSource::EK_Always)
+ return true;
+
if (DebugKind > codegenoptions::LimitedDebugInfo)
return false;
@@ -2552,11 +2556,17 @@ void CGDebugInfo::completeTemplateDefinition(
const ClassTemplateSpecializationDecl &SD) {
if (DebugKind <= codegenoptions::DebugLineTablesOnly)
return;
+ completeUnusedClass(SD);
+}
+
+void CGDebugInfo::completeUnusedClass(const CXXRecordDecl &D) {
+ if (DebugKind <= codegenoptions::DebugLineTablesOnly)
+ return;
- completeClassData(&SD);
+ completeClassData(&D);
// In case this type has no member function definitions being emitted, ensure
// it is retained
- RetainedTypes.push_back(CGM.getContext().getRecordType(&SD).getAsOpaquePtr());
+ RetainedTypes.push_back(CGM.getContext().getRecordType(&D).getAsOpaquePtr());
}
llvm::DIType *CGDebugInfo::getOrCreateType(QualType Ty, llvm::DIFile *Unit) {
diff --git a/lib/CodeGen/CGDebugInfo.h b/lib/CodeGen/CGDebugInfo.h
index c6d1c66e13..5050ca0ad3 100644
--- a/lib/CodeGen/CGDebugInfo.h
+++ b/lib/CodeGen/CGDebugInfo.h
@@ -438,6 +438,7 @@ public:
void completeClass(const RecordDecl *RD);
void completeTemplateDefinition(const ClassTemplateSpecializationDecl &SD);
+ void completeUnusedClass(const CXXRecordDecl &D);
/// Create debug info for a macro defined by a #define directive or a macro
/// undefined by a #undef directive.
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 96358bf611..7fe8bf0412 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -3820,6 +3820,11 @@ void CodeGenModule::EmitTopLevelDecl(Decl *D) {
EmitDeclContext(cast<NamespaceDecl>(D));
break;
case Decl::CXXRecord:
+ if (DebugInfo) {
+ if (auto *ES = D->getASTContext().getExternalSource())
+ if (ES->hasExternalDefinitions(D) == ExternalASTSource::EK_Never)
+ DebugInfo->completeUnusedClass(cast<CXXRecordDecl>(*D));
+ }
// Emit any static data members, they may be definitions.
for (auto *I : cast<CXXRecordDecl>(D)->decls())
if (isa<VarDecl>(I) || isa<CXXRecordDecl>(I))
diff --git a/lib/Sema/MultiplexExternalSemaSource.cpp b/lib/Sema/MultiplexExternalSemaSource.cpp
index f749b7d139..b7e343c647 100644
--- a/lib/Sema/MultiplexExternalSemaSource.cpp
+++ b/lib/Sema/MultiplexExternalSemaSource.cpp
@@ -95,9 +95,9 @@ MultiplexExternalSemaSource::GetExternalCXXCtorInitializers(uint64_t Offset) {
}
ExternalASTSource::ExtKind
-MultiplexExternalSemaSource::hasExternalDefinitions(const FunctionDecl *FD) {
+MultiplexExternalSemaSource::hasExternalDefinitions(const Decl *D) {
for (const auto &S : Sources)
- if (auto EK = S->hasExternalDefinitions(FD))
+ if (auto EK = S->hasExternalDefinitions(D))
if (EK != EK_ReplyHazy)
return EK;
return EK_ReplyHazy;
diff --git a/lib/Serialization/ASTReader.cpp b/lib/Serialization/ASTReader.cpp
index a51f144ae0..322fc863be 100644
--- a/lib/Serialization/ASTReader.cpp
+++ b/lib/Serialization/ASTReader.cpp
@@ -8147,8 +8147,7 @@ ASTReader::getSourceDescriptor(unsigned ID) {
return None;
}
-ExternalASTSource::ExtKind
-ASTReader::hasExternalDefinitions(const FunctionDecl *FD) {
+ExternalASTSource::ExtKind ASTReader::hasExternalDefinitions(const Decl *FD) {
auto I = BodySource.find(FD);
if (I == BodySource.end())
return EK_ReplyHazy;
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 9b9b41a104..db7d55ec0b 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -119,7 +119,8 @@ namespace clang {
}
void ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update);
- void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data);
+ void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data,
+ const CXXRecordDecl *D);
void MergeDefinitionData(CXXRecordDecl *D,
struct CXXRecordDecl::DefinitionData &&NewDD);
void ReadObjCDefinitionData(struct ObjCInterfaceDecl::DefinitionData &Data);
@@ -1490,7 +1491,7 @@ void ASTDeclReader::VisitUnresolvedUsingTypenameDecl(
}
void ASTDeclReader::ReadCXXDefinitionData(
- struct CXXRecordDecl::DefinitionData &Data) {
+ struct CXXRecordDecl::DefinitionData &Data, const CXXRecordDecl *D) {
// Note: the caller has deserialized the IsLambda bit already.
Data.UserDeclaredConstructor = Record.readInt();
Data.UserDeclaredSpecialMembers = Record.readInt();
@@ -1536,6 +1537,12 @@ void ASTDeclReader::ReadCXXDefinitionData(
Data.HasDeclaredCopyAssignmentWithConstParam = Record.readInt();
Data.ODRHash = Record.readInt();
+ if (Record.readInt()) {
+ Reader.BodySource[D] = Loc.F->Kind == ModuleKind::MK_MainFile
+ ? ExternalASTSource::EK_Never
+ : ExternalASTSource::EK_Always;
+ }
+
Data.NumBases = Record.readInt();
if (Data.NumBases)
Data.Bases = ReadGlobalOffset();
@@ -1707,7 +1714,7 @@ void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update) {
else
DD = new (C) struct CXXRecordDecl::DefinitionData(D);
- ReadCXXDefinitionData(*DD);
+ ReadCXXDefinitionData(*DD, D);
// We might already have a definition for this record. This can happen either
// because we're reading an update record, or because we've already done some
@@ -2553,7 +2560,11 @@ static bool isConsumerInterestedIn(ASTContext &Ctx, Decl *D, bool HasBody) {
Var->isThisDeclarationADefinition() == VarDecl::Definition;
if (FunctionDecl *Func = dyn_cast<FunctionDecl>(D))
return Func->doesThisDeclarationHaveABody() || HasBody;
-
+
+ if (auto *ES = D->getASTContext().getExternalSource())
+ if (ES->hasExternalDefinitions(D) == ExternalASTSource::EK_Never)
+ return true;
+
return false;
}
diff --git a/lib/Serialization/ASTWriter.cpp b/lib/Serialization/ASTWriter.cpp
index 23859c241d..ec59250e19 100644
--- a/lib/Serialization/ASTWriter.cpp
+++ b/lib/Serialization/ASTWriter.cpp
@@ -5770,6 +5770,12 @@ void ASTRecordWriter::AddCXXDefinitionData(const CXXRecordDecl *D) {
Record->push_back(Data.HasDeclaredCopyConstructorWithConstParam);
Record->push_back(Data.HasDeclaredCopyAssignmentWithConstParam);
Record->push_back(Data.ODRHash);
+ bool ModularCodegen = Writer->Context->getLangOpts().ModularCodegen &&
+ Writer->WritingModule && !D->isDependentType();
+ Record->push_back(ModularCodegen);
+ if (ModularCodegen)
+ Writer->ModularCodegenDecls.push_back(Writer->GetDeclRef(D));
+
// IsLambda bit is already saved.
Record->push_back(Data.NumBases);
diff --git a/test/Modules/Inputs/codegen-nodep/foo.h b/test/Modules/Inputs/codegen-nodep/foo.h
index af91e8d263..e7b20a512d 100644
--- a/test/Modules/Inputs/codegen-nodep/foo.h
+++ b/test/Modules/Inputs/codegen-nodep/foo.h
@@ -1,5 +1,11 @@
template <typename T>
-void ftempl() {
+void foot() {
}
-inline void f() {
+inline void foo() {
}
+
+template <typename T>
+struct bart {
+};
+struct bar {
+};
diff --git a/test/Modules/codegen-nodep.test b/test/Modules/codegen-nodep.test
index cb2b4e37e9..0c3eb47a1e 100644
--- a/test/Modules/codegen-nodep.test
+++ b/test/Modules/codegen-nodep.test
@@ -7,7 +7,7 @@ RUN: %S/Inputs/codegen-nodep/foo.modulemap -o - \
RUN: | llvm-bcanalyzer - -dump \
RUN: | FileCheck %s
-Ensure there's only one modular codegen decl - the sentinel plain inline
-function, not any for the function template.
+Ensure there are only two modular codegen decls (one for the class, one for the
+function - none for the class and function templates).
-CHECK: <MODULAR_CODEGEN_DECLS op0={{[0-9]+}}/>
+CHECK: <MODULAR_CODEGEN_DECLS op0={{[0-9]+}} op1={{[0-9]+}}/>
diff --git a/test/Modules/codegen.test b/test/Modules/codegen.test
index 6807640e60..ce252e89eb 100644
--- a/test/Modules/codegen.test
+++ b/test/Modules/codegen.test
@@ -3,8 +3,8 @@ REQUIRES: x86-registered-target
RUN: %clang_cc1 -triple=x86_64-linux-gnu -fmodules-codegen -x c++ -fmodules -emit-module -fmodule-name=foo %S/Inputs/codegen/foo.modulemap -o %t/foo.pcm
-RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %t/foo.pcm | FileCheck --check-prefix=FOO --check-prefix=BOTH %s
-RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - -fmodules -fmodule-file=%t/foo.pcm %S/Inputs/codegen/use.cpp | FileCheck --check-prefix=BOTH --check-prefix=USE %s
+RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -debug-info-kind=limited -o - %t/foo.pcm | FileCheck --check-prefix=FOO --check-prefix=BOTH %s
+RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -debug-info-kind=limited -o - -fmodules -fmodule-file=%t/foo.pcm %S/Inputs/codegen/use.cpp | FileCheck --check-prefix=BOTH --check-prefix=USE %s
FOO: $_Z2f1PKcz = comdat any
FOO: $_ZN13implicit_dtorD1Ev = comdat any
@@ -25,3 +25,11 @@ FOO: define weak_odr void @_ZN13implicit_dtorD2Ev
USE: define linkonce_odr void @_ZN20uninst_implicit_dtorD1Ev
USE: define linkonce_odr void @_Z4instIiEvv
USE: define linkonce_odr void @_ZN20uninst_implicit_dtorD2Ev
+
+Modular debug info puts the definition of a class defined in a module in that
+module's object. Users of the module only get a declaration.
+
+'distinct' is used for definition records (the flags field is empty/unspecified)
+FOO: = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "implicit_dtor"
+Declarations are non-distinct and include the 'DIFlagFwdDecl' flag.
+USE: = !DICompositeType(tag: DW_TAG_structure_type, name: "implicit_dtor", {{.*}}, flags: DIFlagFwdDecl