summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ASTContext.cpp27
-rw-r--r--clang/lib/Driver/Driver.cpp2
-rw-r--r--clang/lib/Driver/ToolChains/Clang.cpp4
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp1
-rw-r--r--clang/lib/Frontend/FrontendActions.cpp8
-rw-r--r--clang/lib/Sema/MultiplexExternalSemaSource.cpp7
-rw-r--r--clang/lib/Serialization/ASTReader.cpp9
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp15
8 files changed, 62 insertions, 11 deletions
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 96b7b56c1c7..43577e8640a 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -9553,6 +9553,29 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
else
return false;
+ if (D->isFromASTFile() && !LangOpts.BuildingPCHWithObjectFile) {
+ assert(getExternalSource() && "It's from an AST file; must have a source.");
+ // On Windows, PCH files are built together with an object file. If this
+ // declaration comes from such a PCH and DeclMustBeEmitted would return
+ // true, it would have returned true and the decl would have been emitted
+ // into that object file, so it doesn't need to be emitted here.
+ // Note that decls are still emitted if they're referenced, as usual;
+ // DeclMustBeEmitted is used to decide whether a decl must be emitted even
+ // if it's not referenced.
+ //
+ // Explicit template instantiation definitions are tricky. If there was an
+ // explicit template instantiation decl in the PCH before, it will look like
+ // the definition comes from there, even if that was just the declaration.
+ // (Explicit instantiation defs of variable templates always get emitted.)
+ bool IsExpInstDef =
+ isa<FunctionDecl>(D) &&
+ cast<FunctionDecl>(D)->getTemplateSpecializationKind() ==
+ TSK_ExplicitInstantiationDefinition;
+
+ if (getExternalSource()->DeclIsFromPCHWithObjectFile(D) && !IsExpInstDef)
+ return false;
+ }
+
// If this is a member of a class template, we do not need to emit it.
if (D->getDeclContext()->isDependentContext())
return false;
@@ -9573,7 +9596,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
// Constructors and destructors are required.
if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>())
return true;
-
+
// The key function for a class is required. This rule only comes
// into play when inline functions can be key functions, though.
if (getTargetInfo().getCXXABI().canKeyFunctionBeInline()) {
@@ -9594,7 +9617,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) {
// Implicit template instantiations can also be deferred in C++.
return !isDiscardableGVALinkage(Linkage);
}
-
+
const auto *VD = cast<VarDecl>(D);
assert(VD->isFileVarDecl() && "Expected file scoped var");
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index 14d94c029d5..7b890d80f0a 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -3088,6 +3088,8 @@ void Driver::BuildActions(Compilation &C, DerivedArgList &Args,
// The driver currently exits after the first failed command. This
// relies on that behavior, to make sure if the pch generation fails,
// the main compilation won't run.
+ // FIXME: If the main compilation fails, the PCH generation should
+ // probably not be considered successful either.
}
}
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index bce2083051e..88e2f83f6da 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -1084,6 +1084,10 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA,
CmdArgs.push_back(Args.MakeArgString(Twine("-find-pch-source=") +
Inputs[0].second->getValue()));
}
+ if (YcIndex != -1 && JA.getKind() >= Action::PrecompileJobClass &&
+ JA.getKind() <= Action::AssembleJobClass) {
+ CmdArgs.push_back(Args.MakeArgString("-building-pch-with-obj"));
+ }
bool RenderedImplicitInclude = false;
int AI = -1;
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index 60ed5fdf708..26414f1a52c 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -2776,6 +2776,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
}
Opts.CompleteMemberPointers = Args.hasArg(OPT_fcomplete_member_pointers);
+ Opts.BuildingPCHWithObjectFile = Args.hasArg(OPT_building_pch_with_obj);
}
static bool isStrictlyPreprocessorAction(frontend::ActionKind Action) {
diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp
index 602fee1fdca..06db814f4b5 100644
--- a/clang/lib/Frontend/FrontendActions.cpp
+++ b/clang/lib/Frontend/FrontendActions.cpp
@@ -112,14 +112,14 @@ GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
if (!CI.getFrontendOpts().RelocatablePCH)
Sysroot.clear();
+ const auto &FrontendOpts = CI.getFrontendOpts();
auto Buffer = std::make_shared<PCHBuffer>();
std::vector<std::unique_ptr<ASTConsumer>> Consumers;
Consumers.push_back(llvm::make_unique<PCHGenerator>(
CI.getPreprocessor(), OutputFile, Sysroot,
- Buffer, CI.getFrontendOpts().ModuleFileExtensions,
- /*AllowASTWithErrors*/CI.getPreprocessorOpts().AllowPCHWithCompilerErrors,
- /*IncludeTimestamps*/
- +CI.getFrontendOpts().IncludeTimestamps));
+ Buffer, FrontendOpts.ModuleFileExtensions,
+ CI.getPreprocessorOpts().AllowPCHWithCompilerErrors,
+ FrontendOpts.IncludeTimestamps));
Consumers.push_back(CI.getPCHContainerWriter().CreatePCHContainerGenerator(
CI, InFile, OutputFile, std::move(OS), Buffer));
diff --git a/clang/lib/Sema/MultiplexExternalSemaSource.cpp b/clang/lib/Sema/MultiplexExternalSemaSource.cpp
index 9370cf27ef4..7e61ccbb106 100644
--- a/clang/lib/Sema/MultiplexExternalSemaSource.cpp
+++ b/clang/lib/Sema/MultiplexExternalSemaSource.cpp
@@ -171,6 +171,13 @@ Module *MultiplexExternalSemaSource::getModule(unsigned ID) {
return nullptr;
}
+bool MultiplexExternalSemaSource::DeclIsFromPCHWithObjectFile(const Decl *D) {
+ for (auto *S : Sources)
+ if (S->DeclIsFromPCHWithObjectFile(D))
+ return true;
+ return false;
+}
+
bool MultiplexExternalSemaSource::layoutRecordType(const RecordDecl *Record,
uint64_t &Size,
uint64_t &Alignment,
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 3dd233e449b..982c4cbee88 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -2482,7 +2482,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
return VersionMismatch;
}
- bool hasErrors = Record[6];
+ bool hasErrors = Record[7];
if (hasErrors && !DisableValidation && !AllowASTWithCompilerErrors) {
Diag(diag::err_pch_with_compiler_errors);
return HadErrors;
@@ -2500,6 +2500,8 @@ ASTReader::ReadControlBlock(ModuleFile &F,
F.HasTimestamps = Record[5];
+ F.PCHHasObjectFile = Record[6];
+
const std::string &CurBranch = getClangFullRepositoryVersion();
StringRef ASTBranch = Blob;
if (StringRef(CurBranch) != ASTBranch && !DisableValidation) {
@@ -8448,6 +8450,11 @@ Module *ASTReader::getModule(unsigned ID) {
return getSubmodule(ID);
}
+bool ASTReader::DeclIsFromPCHWithObjectFile(const Decl *D) {
+ ModuleFile *MF = getOwningModuleFile(D);
+ return MF && MF->PCHHasObjectFile;
+}
+
ModuleFile *ASTReader::getLocalModuleFile(ModuleFile &F, unsigned ID) {
if (ID & 1) {
// It's a module, look it up by submodule ID.
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 1e3a098b09e..7d5b521d4d9 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -1458,16 +1458,23 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context,
MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 16)); // Clang min.
MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Relocatable
MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Timestamps
+ MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // PCHHasObjectFile
MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Errors
MetadataAbbrev->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); // SVN branch/tag
unsigned MetadataAbbrevCode = Stream.EmitAbbrev(std::move(MetadataAbbrev));
assert((!WritingModule || isysroot.empty()) &&
"writing module as a relocatable PCH?");
{
- RecordData::value_type Record[] = {METADATA, VERSION_MAJOR, VERSION_MINOR,
- CLANG_VERSION_MAJOR, CLANG_VERSION_MINOR,
- !isysroot.empty(), IncludeTimestamps,
- ASTHasCompilerErrors};
+ RecordData::value_type Record[] = {
+ METADATA,
+ VERSION_MAJOR,
+ VERSION_MINOR,
+ CLANG_VERSION_MAJOR,
+ CLANG_VERSION_MINOR,
+ !isysroot.empty(),
+ IncludeTimestamps,
+ Context.getLangOpts().BuildingPCHWithObjectFile,
+ ASTHasCompilerErrors};
Stream.EmitRecordWithBlob(MetadataAbbrevCode, Record,
getClangFullRepositoryVersion());
}
OpenPOWER on IntegriCloud