From cd98cb731288722bf44204feb2f570caaec6617c Mon Sep 17 00:00:00 2001 From: Ben Langmuir Date: Tue, 23 Jun 2015 18:20:18 +0000 Subject: [PATCH] [Modules] Consider -fmodule-feature in module hash and when loading Any extra features from -fmodule-feature are part of the module hash and need to get validated on load. Also print them with -module-file-info. llvm-svn: 240433 --- clang/include/clang/Basic/LangOptions.h | 2 ++ clang/lib/Frontend/CompilerInvocation.cpp | 4 ++++ clang/lib/Frontend/FrontendActions.cpp | 7 +++++++ clang/lib/Serialization/ASTReader.cpp | 9 +++++++++ clang/lib/Serialization/ASTWriter.cpp | 4 ++++ clang/test/Modules/module-feature.m | 14 ++++++++++++++ clang/test/Modules/module_file_info.m | 4 +++- 7 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 clang/test/Modules/module-feature.m diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index 84836eb..3c9d23e 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -102,6 +102,8 @@ public: /// \brief The names of any features to enable in module 'requires' decls /// in addition to the hard-coded list in Module.cpp and the target features. + /// + /// This list is sorted. std::vector ModuleFeatures; /// \brief Options for parsing comments. diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 250c992..dd664ca 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1588,6 +1588,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.ImplementationOfModule = Args.getLastArgValue(OPT_fmodule_implementation_of); Opts.ModuleFeatures = Args.getAllArgValues(OPT_fmodule_feature); + std::sort(Opts.ModuleFeatures.begin(), Opts.ModuleFeatures.end()); Opts.NativeHalfType |= Args.hasArg(OPT_fnative_half_type); Opts.HalfArgsAndReturns = Args.hasArg(OPT_fallow_half_arguments_and_returns); Opts.GNUAsm = !Args.hasArg(OPT_fno_gnu_inline_asm); @@ -1967,6 +1968,9 @@ std::string CompilerInvocation::getModuleHash() const { #define BENIGN_LANGOPT(Name, Bits, Default, Description) #define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) #include "clang/Basic/LangOptions.def" + + for (StringRef Feature : LangOpts->ModuleFeatures) + code = hash_combine(code, Feature); // Extend the signature with the target options. code = hash_combine(code, TargetOpts->Triple, TargetOpts->CPU, diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index 6f202a15..4997764 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -470,6 +470,13 @@ namespace { #define BENIGN_LANGOPT(Name, Bits, Default, Description) #define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) #include "clang/Basic/LangOptions.def" + + if (!LangOpts.ModuleFeatures.empty()) { + Out.indent(4) << "Module features:\n"; + for (StringRef Feature : LangOpts.ModuleFeatures) + Out.indent(6) << Feature << "\n"; + } + return false; } diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 7242793..6bdca05 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -209,6 +209,12 @@ static bool checkLanguageOptions(const LangOptions &LangOpts, #define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) #include "clang/Basic/LangOptions.def" + if (ExistingLangOpts.ModuleFeatures != LangOpts.ModuleFeatures) { + if (Diags) + Diags->Report(diag::err_pch_langopt_value_mismatch) << "module features"; + return true; + } + if (ExistingLangOpts.ObjCRuntime != LangOpts.ObjCRuntime) { if (Diags) Diags->Report(diag::err_pch_langopt_value_mismatch) @@ -4437,6 +4443,9 @@ bool ASTReader::ParseLanguageOptions(const RecordData &Record, LangOpts.Sanitize.set(SanitizerKind::ID, Record[Idx++]); #include "clang/Basic/Sanitizers.def" + for (unsigned N = Record[Idx++]; N; --N) + LangOpts.ModuleFeatures.push_back(ReadString(Record, Idx)); + ObjCRuntime::Kind runtimeKind = (ObjCRuntime::Kind) Record[Idx++]; VersionTuple runtimeVersion = ReadVersionTuple(Record, Idx); LangOpts.ObjCRuntime = ObjCRuntime(runtimeKind, runtimeVersion); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index 5bb0bec..d626776 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -1266,6 +1266,10 @@ void ASTWriter::WriteControlBlock(Preprocessor &PP, ASTContext &Context, Record.push_back(LangOpts.Sanitize.has(SanitizerKind::ID)); #include "clang/Basic/Sanitizers.def" + Record.push_back(LangOpts.ModuleFeatures.size()); + for (StringRef Feature : LangOpts.ModuleFeatures) + AddString(Feature, Record); + Record.push_back((unsigned) LangOpts.ObjCRuntime.getKind()); AddVersionTuple(LangOpts.ObjCRuntime.getVersion(), Record); diff --git a/clang/test/Modules/module-feature.m b/clang/test/Modules/module-feature.m new file mode 100644 index 0000000..4926d26 --- /dev/null +++ b/clang/test/Modules/module-feature.m @@ -0,0 +1,14 @@ +// RUN: rm -rf %t %t.nohash + +// Each set of features gets its own cache. +// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fimplicit-module-maps -fmodule-feature f1 -fmodule-feature f2 -F %S/Inputs %s -verify -Rmodule-build +// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fimplicit-module-maps -fmodule-feature f2 -F %S/Inputs %s -verify -Rmodule-build +// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t -fimplicit-module-maps -fmodule-feature f2 -fmodule-feature f1 -F %S/Inputs %s -Rmodule-build 2>&1 | FileCheck %s -allow-empty -check-prefix=ALREADY_BUILT +// ALREADY_BUILT-NOT: building module + +// Errors if we try to force the load. +// RUN: %clang_cc1 -fmodules -fmodules-cache-path=%t.nohash -fimplicit-module-maps -fdisable-module-hash -fmodule-feature f1 -fmodule-feature f2 -F %S/Inputs %s -verify -Rmodule-build +// RUN: not %clang_cc1 -fmodules -fmodules-cache-path=%t.nohash -fimplicit-module-maps -fdisable-module-hash -fmodule-feature f2 -F %S/Inputs %s 2>&1 | FileCheck %s -check-prefix=DIFFERS +// DIFFERS: error: module features differs + +@import Module; // expected-remark {{building module 'Module'}} expected-remark {{finished}} diff --git a/clang/test/Modules/module_file_info.m b/clang/test/Modules/module_file_info.m index 01d5073..8693d2b 100644 --- a/clang/test/Modules/module_file_info.m +++ b/clang/test/Modules/module_file_info.m @@ -2,7 +2,7 @@ @import DependsOnModule; // RUN: rm -rf %t -// RUN: %clang_cc1 -w -Wunused -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t -F %S/Inputs -DBLARG -DWIBBLE=WOBBLE %s +// RUN: %clang_cc1 -w -Wunused -fmodules -fimplicit-module-maps -fdisable-module-hash -fmodules-cache-path=%t -F %S/Inputs -DBLARG -DWIBBLE=WOBBLE -fmodule-feature myfeature %s // RUN: %clang_cc1 -module-file-info %t/DependsOnModule.pcm | FileCheck %s // CHECK: Generated by this Clang: @@ -14,6 +14,8 @@ // CHECK: C99: Yes // CHECK: Objective-C 1: Yes // CHECK: modules extension to C: Yes +// CHECK: Module features: +// CHECK: myfeature // CHECK: Target options: // CHECK: Triple: -- 2.7.4