r299982 - Modular Codegen: Add/use a bit in serialized function definitions to track whether they are the subject of modular codegen
David Blaikie via cfe-commits
cfe-commits at lists.llvm.org
Tue Apr 11 13:46:35 PDT 2017
Author: dblaikie
Date: Tue Apr 11 15:46:34 2017
New Revision: 299982
URL: http://llvm.org/viewvc/llvm-project?rev=299982&view=rev
Log:
Modular Codegen: Add/use a bit in serialized function definitions to track whether they are the subject of modular codegen
Some decls are created not where they are written, but in other module
files/users (implicit special members and function template implicit
specializations). To correctly identify them, use a bit next to the definition
to track the modular codegen property.
Discussed whether the module file bit could be omitted in favor of
reconstituting from the modular codegen decls list - best guess today is that
the efficiency improvement of not having to deserialize the whole list whenever
any function is queried by a module user is worth it for the small size
increase of this redundant (list + bit-on-def) representation.
Reviewers: rsmith
Differential Revision: https://reviews.llvm.org/D29901
Added:
cfe/trunk/test/Modules/Inputs/codegen-nodep/
cfe/trunk/test/Modules/Inputs/codegen-nodep/foo.h
cfe/trunk/test/Modules/Inputs/codegen-nodep/foo.modulemap
cfe/trunk/test/Modules/Inputs/codegen/use.cpp
cfe/trunk/test/Modules/codegen-nodep.test
Modified:
cfe/trunk/include/clang/AST/ASTContext.h
cfe/trunk/include/clang/AST/ExternalASTSource.h
cfe/trunk/include/clang/Basic/Module.h
cfe/trunk/include/clang/Sema/MultiplexExternalSemaSource.h
cfe/trunk/include/clang/Serialization/ASTReader.h
cfe/trunk/lib/AST/ASTContext.cpp
cfe/trunk/lib/AST/ExternalASTSource.cpp
cfe/trunk/lib/Basic/Module.cpp
cfe/trunk/lib/Sema/MultiplexExternalSemaSource.cpp
cfe/trunk/lib/Serialization/ASTReader.cpp
cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
cfe/trunk/lib/Serialization/ASTWriter.cpp
cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
cfe/trunk/test/Modules/Inputs/codegen/foo.h
cfe/trunk/test/Modules/codegen.test
Modified: cfe/trunk/include/clang/AST/ASTContext.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTContext.h?rev=299982&r1=299981&r2=299982&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ASTContext.h (original)
+++ cfe/trunk/include/clang/AST/ASTContext.h Tue Apr 11 15:46:34 2017
@@ -2510,7 +2510,7 @@ public:
///
/// \returns true if the function/var must be CodeGen'ed/deserialized even if
/// it is not used.
- bool DeclMustBeEmitted(const Decl *D, bool ForModularCodegen = false);
+ bool DeclMustBeEmitted(const Decl *D);
const CXXConstructorDecl *
getCopyConstructorForExceptionObject(CXXRecordDecl *RD);
Modified: cfe/trunk/include/clang/AST/ExternalASTSource.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ExternalASTSource.h?rev=299982&r1=299981&r2=299982&view=diff
==============================================================================
--- cfe/trunk/include/clang/AST/ExternalASTSource.h (original)
+++ cfe/trunk/include/clang/AST/ExternalASTSource.h Tue Apr 11 15:46:34 2017
@@ -172,7 +172,7 @@ public:
enum ExtKind { EK_Always, EK_Never, EK_ReplyHazy };
- virtual ExtKind hasExternalDefinitions(unsigned ID);
+ virtual ExtKind hasExternalDefinitions(const FunctionDecl *FD);
/// \brief Finds all declarations lexically contained within the given
/// DeclContext, after applying an optional filter predicate.
Modified: cfe/trunk/include/clang/Basic/Module.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Module.h?rev=299982&r1=299981&r2=299982&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Module.h (original)
+++ cfe/trunk/include/clang/Basic/Module.h Tue Apr 11 15:46:34 2017
@@ -215,8 +215,6 @@ public:
/// and headers from used modules.
unsigned NoUndeclaredIncludes : 1;
- unsigned WithCodegen : 1;
-
/// \brief Describes the visibility of the various names within a
/// particular module.
enum NameVisibilityKind {
Modified: cfe/trunk/include/clang/Sema/MultiplexExternalSemaSource.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/MultiplexExternalSemaSource.h?rev=299982&r1=299981&r2=299982&view=diff
==============================================================================
--- cfe/trunk/include/clang/Sema/MultiplexExternalSemaSource.h (original)
+++ cfe/trunk/include/clang/Sema/MultiplexExternalSemaSource.h Tue Apr 11 15:46:34 2017
@@ -90,7 +90,7 @@ public:
/// initializers themselves.
CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset) override;
- ExtKind hasExternalDefinitions(unsigned ID) override;
+ ExtKind hasExternalDefinitions(const FunctionDecl *FD) override;
/// \brief Find all declarations with the given name in the
/// given context.
Modified: cfe/trunk/include/clang/Serialization/ASTReader.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Serialization/ASTReader.h?rev=299982&r1=299981&r2=299982&view=diff
==============================================================================
--- cfe/trunk/include/clang/Serialization/ASTReader.h (original)
+++ cfe/trunk/include/clang/Serialization/ASTReader.h Tue Apr 11 15:46:34 2017
@@ -1115,6 +1115,8 @@ private:
/// predefines buffer may contain additional definitions.
std::string SuggestedPredefines;
+ llvm::DenseMap<const FunctionDecl *, bool> BodySource;
+
/// \brief Reads a statement from the specified cursor.
Stmt *ReadStmtFromStream(ModuleFile &F);
@@ -1997,7 +1999,7 @@ public:
/// \brief Return a descriptor for the corresponding module.
llvm::Optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID) override;
- ExtKind hasExternalDefinitions(unsigned ID) override;
+ ExtKind hasExternalDefinitions(const FunctionDecl *FD) override;
/// \brief Retrieve a selector from the given module with its local ID
/// number.
Modified: cfe/trunk/lib/AST/ASTContext.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTContext.cpp?rev=299982&r1=299981&r2=299982&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTContext.cpp (original)
+++ cfe/trunk/lib/AST/ASTContext.cpp Tue Apr 11 15:46:34 2017
@@ -8897,7 +8897,7 @@ GVALinkage ASTContext::GetGVALinkageForF
*this, basicGVALinkageForFunction(*this, FD), FD);
auto EK = ExternalASTSource::EK_ReplyHazy;
if (auto *Ext = getExternalSource())
- EK = Ext->hasExternalDefinitions(FD->getOwningModuleID());
+ EK = Ext->hasExternalDefinitions(FD);
switch (EK) {
case ExternalASTSource::EK_Never:
if (L == GVA_DiscardableODR)
@@ -8993,7 +8993,7 @@ GVALinkage ASTContext::GetGVALinkageForV
*this, basicGVALinkageForVariable(*this, VD), VD);
}
-bool ASTContext::DeclMustBeEmitted(const Decl *D, bool ForModularCodegen) {
+bool ASTContext::DeclMustBeEmitted(const Decl *D) {
if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
if (!VD->isFileVarDecl())
return false;
@@ -9059,9 +9059,6 @@ bool ASTContext::DeclMustBeEmitted(const
GVALinkage Linkage = GetGVALinkageForFunction(FD);
- if (Linkage == GVA_DiscardableODR && ForModularCodegen)
- return true;
-
// static, static inline, always_inline, and extern inline functions can
// always be deferred. Normal inline functions can be deferred in C99/C++.
// Implicit template instantiations can also be deferred in C++.
Modified: cfe/trunk/lib/AST/ExternalASTSource.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExternalASTSource.cpp?rev=299982&r1=299981&r2=299982&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ExternalASTSource.cpp (original)
+++ cfe/trunk/lib/AST/ExternalASTSource.cpp Tue Apr 11 15:46:34 2017
@@ -29,7 +29,7 @@ ExternalASTSource::getSourceDescriptor(u
}
ExternalASTSource::ExtKind
-ExternalASTSource::hasExternalDefinitions(unsigned ID) {
+ExternalASTSource::hasExternalDefinitions(const FunctionDecl *FD) {
return EK_ReplyHazy;
}
Modified: cfe/trunk/lib/Basic/Module.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Module.cpp?rev=299982&r1=299981&r2=299982&view=diff
==============================================================================
--- cfe/trunk/lib/Basic/Module.cpp (original)
+++ cfe/trunk/lib/Basic/Module.cpp Tue Apr 11 15:46:34 2017
@@ -33,7 +33,7 @@ Module::Module(StringRef Name, SourceLoc
IsExplicit(IsExplicit), IsSystem(false), IsExternC(false),
IsInferred(false), InferSubmodules(false), InferExplicitSubmodules(false),
InferExportWildcard(false), ConfigMacrosExhaustive(false),
- NoUndeclaredIncludes(false), WithCodegen(false), NameVisibility(Hidden) {
+ NoUndeclaredIncludes(false), NameVisibility(Hidden) {
if (Parent) {
if (!Parent->isAvailable())
IsAvailable = false;
Modified: cfe/trunk/lib/Sema/MultiplexExternalSemaSource.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/MultiplexExternalSemaSource.cpp?rev=299982&r1=299981&r2=299982&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/MultiplexExternalSemaSource.cpp (original)
+++ cfe/trunk/lib/Sema/MultiplexExternalSemaSource.cpp Tue Apr 11 15:46:34 2017
@@ -95,9 +95,9 @@ MultiplexExternalSemaSource::GetExternal
}
ExternalASTSource::ExtKind
-MultiplexExternalSemaSource::hasExternalDefinitions(unsigned int ID) {
+MultiplexExternalSemaSource::hasExternalDefinitions(const FunctionDecl *FD) {
for (const auto &S : Sources)
- if (auto EK = S->hasExternalDefinitions(ID))
+ if (auto EK = S->hasExternalDefinitions(FD))
if (EK != EK_ReplyHazy)
return EK;
return EK_ReplyHazy;
Modified: cfe/trunk/lib/Serialization/ASTReader.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReader.cpp?rev=299982&r1=299981&r2=299982&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReader.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReader.cpp Tue Apr 11 15:46:34 2017
@@ -4834,7 +4834,6 @@ ASTReader::ReadSubmoduleBlock(ModuleFile
bool InferExplicitSubmodules = Record[Idx++];
bool InferExportWildcard = Record[Idx++];
bool ConfigMacrosExhaustive = Record[Idx++];
- bool WithCodegen = Record[Idx++];
Module *ParentModule = nullptr;
if (Parent)
@@ -4880,7 +4879,6 @@ ASTReader::ReadSubmoduleBlock(ModuleFile
CurrentModule->InferExplicitSubmodules = InferExplicitSubmodules;
CurrentModule->InferExportWildcard = InferExportWildcard;
CurrentModule->ConfigMacrosExhaustive = ConfigMacrosExhaustive;
- CurrentModule->WithCodegen = WithCodegen;
if (DeserializationListener)
DeserializationListener->ModuleRead(GlobalID, CurrentModule);
@@ -8149,16 +8147,12 @@ ASTReader::getSourceDescriptor(unsigned
return None;
}
-ExternalASTSource::ExtKind ASTReader::hasExternalDefinitions(unsigned ID) {
- const Module *M = getSubmodule(ID);
- if (!M || !M->WithCodegen)
+ExternalASTSource::ExtKind
+ASTReader::hasExternalDefinitions(const FunctionDecl *FD) {
+ auto I = BodySource.find(FD);
+ if (I == BodySource.end())
return EK_ReplyHazy;
-
- ModuleFile *MF = ModuleMgr.lookup(M->getASTFile());
- assert(MF); // ?
- if (MF->Kind == ModuleKind::MK_MainFile)
- return EK_Never;
- return EK_Always;
+ return I->second ? EK_Never : EK_Always;
}
Selector ASTReader::getLocalSelector(ModuleFile &M, unsigned LocalID) {
@@ -8992,9 +8986,9 @@ void ASTReader::finishPendingActions() {
// FIXME: Check for =delete/=default?
// FIXME: Complain about ODR violations here?
const FunctionDecl *Defn = nullptr;
- if (!getContext().getLangOpts().Modules || !FD->hasBody(Defn))
+ if (!getContext().getLangOpts().Modules || !FD->hasBody(Defn)) {
FD->setLazyBody(PB->second);
- else
+ } else
mergeDefinitionVisibility(const_cast<FunctionDecl*>(Defn), FD);
continue;
}
Modified: cfe/trunk/lib/Serialization/ASTReaderDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTReaderDecl.cpp?rev=299982&r1=299981&r2=299982&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTReaderDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTReaderDecl.cpp Tue Apr 11 15:46:34 2017
@@ -424,6 +424,8 @@ uint64_t ASTDeclReader::GetCurrentCursor
}
void ASTDeclReader::ReadFunctionDefinition(FunctionDecl *FD) {
+ if (Record.readInt())
+ Reader.BodySource[FD] = Loc.F->Kind == ModuleKind::MK_MainFile;
if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) {
CD->NumCtorInitializers = Record.readInt();
if (CD->NumCtorInitializers)
Modified: cfe/trunk/lib/Serialization/ASTWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriter.cpp?rev=299982&r1=299981&r2=299982&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriter.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriter.cpp Tue Apr 11 15:46:34 2017
@@ -2627,7 +2627,6 @@ void ASTWriter::WriteSubmodules(Module *
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExplicit...
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InferExportWild...
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ConfigMacrosExh...
- Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // WithCodegen
Abbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // Name
unsigned DefinitionAbbrev = Stream.EmitAbbrev(std::move(Abbrev));
@@ -2726,8 +2725,7 @@ void ASTWriter::WriteSubmodules(Module *
Mod->InferSubmodules,
Mod->InferExplicitSubmodules,
Mod->InferExportWildcard,
- Mod->ConfigMacrosExhaustive,
- Context->getLangOpts().ModularCodegen && WritingModule};
+ Mod->ConfigMacrosExhaustive};
Stream.EmitRecordWithBlob(DefinitionAbbrev, Record, Mod->Name);
}
Modified: cfe/trunk/lib/Serialization/ASTWriterDecl.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Serialization/ASTWriterDecl.cpp?rev=299982&r1=299981&r2=299982&view=diff
==============================================================================
--- cfe/trunk/lib/Serialization/ASTWriterDecl.cpp (original)
+++ cfe/trunk/lib/Serialization/ASTWriterDecl.cpp Tue Apr 11 15:46:34 2017
@@ -2159,7 +2159,7 @@ void ASTWriter::WriteDeclAbbrevs() {
/// relatively painless since they would presumably only do it for top-level
/// decls.
static bool isRequiredDecl(const Decl *D, ASTContext &Context,
- bool WritingModule, bool ModularCode) {
+ bool WritingModule) {
// An ObjCMethodDecl is never considered as "required" because its
// implementation container always is.
@@ -2175,7 +2175,7 @@ static bool isRequiredDecl(const Decl *D
return false;
}
- return Context.DeclMustBeEmitted(D, ModularCode);
+ return Context.DeclMustBeEmitted(D);
}
void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) {
@@ -2219,11 +2219,8 @@ void ASTWriter::WriteDecl(ASTContext &Co
// Note declarations that should be deserialized eagerly so that we can add
// them to a record in the AST file later.
- if (isRequiredDecl(D, Context, WritingModule, false))
+ if (isRequiredDecl(D, Context, WritingModule))
EagerlyDeserializedDecls.push_back(ID);
- else if (Context.getLangOpts().ModularCodegen && WritingModule &&
- isRequiredDecl(D, Context, true, true))
- ModularCodegenDecls.push_back(ID);
}
void ASTRecordWriter::AddFunctionDefinition(const FunctionDecl *FD) {
@@ -2231,6 +2228,11 @@ void ASTRecordWriter::AddFunctionDefinit
Writer->ClearSwitchCaseIDs();
assert(FD->doesThisDeclarationHaveABody());
+ bool ModularCodegen = Writer->Context->getLangOpts().ModularCodegen &&
+ Writer->WritingModule && !FD->isDependentContext();
+ Record->push_back(ModularCodegen);
+ if (ModularCodegen)
+ Writer->ModularCodegenDecls.push_back(Writer->GetDeclRef(FD));
if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) {
Record->push_back(CD->getNumCtorInitializers());
if (CD->getNumCtorInitializers())
Added: cfe/trunk/test/Modules/Inputs/codegen-nodep/foo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/codegen-nodep/foo.h?rev=299982&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/codegen-nodep/foo.h (added)
+++ cfe/trunk/test/Modules/Inputs/codegen-nodep/foo.h Tue Apr 11 15:46:34 2017
@@ -0,0 +1,5 @@
+template <typename T>
+void ftempl() {
+}
+inline void f() {
+}
Added: cfe/trunk/test/Modules/Inputs/codegen-nodep/foo.modulemap
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/codegen-nodep/foo.modulemap?rev=299982&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/codegen-nodep/foo.modulemap (added)
+++ cfe/trunk/test/Modules/Inputs/codegen-nodep/foo.modulemap Tue Apr 11 15:46:34 2017
@@ -0,0 +1 @@
+module foo { header "foo.h" }
Modified: cfe/trunk/test/Modules/Inputs/codegen/foo.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/codegen/foo.h?rev=299982&r1=299981&r2=299982&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/codegen/foo.h (original)
+++ cfe/trunk/test/Modules/Inputs/codegen/foo.h Tue Apr 11 15:46:34 2017
@@ -2,3 +2,29 @@ inline void f1(const char* fmt, ...) {
__builtin_va_list args;
__builtin_va_start(args, fmt);
}
+
+struct non_trivial_dtor {
+ ~non_trivial_dtor();
+};
+
+struct implicit_dtor {
+ non_trivial_dtor d;
+};
+
+struct uninst_implicit_dtor {
+ non_trivial_dtor d;
+};
+
+inline void use_implicit_dtor() {
+ implicit_dtor d;
+}
+
+template <typename T>
+void inst() {
+}
+
+inline void inst_decl() {
+ // cause inst<int>'s declaration to be instantiated, without a definition.
+ (void)sizeof(&inst<int>);
+ inst<float>();
+}
Added: cfe/trunk/test/Modules/Inputs/codegen/use.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/codegen/use.cpp?rev=299982&view=auto
==============================================================================
--- cfe/trunk/test/Modules/Inputs/codegen/use.cpp (added)
+++ cfe/trunk/test/Modules/Inputs/codegen/use.cpp Tue Apr 11 15:46:34 2017
@@ -0,0 +1,8 @@
+#include "foo.h"
+void non_modular_use_of_implicit_dtor() {
+ implicit_dtor d1;
+ uninst_implicit_dtor d2;
+}
+void use_of_instantiated_declaration_without_definition() {
+ inst<int>();
+}
Added: cfe/trunk/test/Modules/codegen-nodep.test
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/codegen-nodep.test?rev=299982&view=auto
==============================================================================
--- cfe/trunk/test/Modules/codegen-nodep.test (added)
+++ cfe/trunk/test/Modules/codegen-nodep.test Tue Apr 11 15:46:34 2017
@@ -0,0 +1,13 @@
+RUN: rm -rf %t
+REQUIRES: x86-registered-target
+
+RUN: %clang_cc1 -triple=x86_64-linux-gnu -fmodules-codegen -x c++ -fmodules \
+RUN: -emit-module -fmodule-name=foo \
+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.
+
+CHECK: <MODULAR_CODEGEN_DECLS op0={{[0-9]+}}/>
Modified: cfe/trunk/test/Modules/codegen.test
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/codegen.test?rev=299982&r1=299981&r2=299982&view=diff
==============================================================================
--- cfe/trunk/test/Modules/codegen.test (original)
+++ cfe/trunk/test/Modules/codegen.test Tue Apr 11 15:46:34 2017
@@ -3,8 +3,25 @@ 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 %s
+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
-CHECK: $_Z2f1PKcz = comdat any
-CHECK: define weak_odr void @_Z2f1PKcz(i8* %fmt, ...) #{{[0-9]+}} comdat
-CHECK: call void @llvm.va_start(i8* %{{[a-zA-Z0-9]*}})
+FOO: $_Z2f1PKcz = comdat any
+FOO: $_ZN13implicit_dtorD1Ev = comdat any
+USE: $_Z4instIiEvv = comdat any
+FOO: $_ZN13implicit_dtorD2Ev = comdat any
+FOO: define weak_odr void @_Z2f1PKcz(i8* %fmt, ...) #{{[0-9]+}} comdat
+FOO: call void @llvm.va_start(i8* %{{[a-zA-Z0-9]*}})
+
+Test that implicit special members are emitted into the FOO module if they're
+ODR used there, otherwise emit them linkonce_odr as usual in the use.
+
+FIXME: Proactively instantiate any valid implicit special members to emit them into the module object.
+
+FOO: define weak_odr void @_ZN13implicit_dtorD1Ev
+FOO: define weak_odr void @_Z4instIfEvv
+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
More information about the cfe-commits
mailing list