[modules] When a .pcm file is explicitly built separately from the translation
unit, allow the -O settings of the two compilations to differ. llvm-svn: 220943
This commit is contained in:
parent
d5e7ff856c
commit
1e2cf0dd4b
|
@ -9,26 +9,40 @@
|
|||
//
|
||||
// This file defines the language options. Users of this file must
|
||||
// define the LANGOPT macro to make use of this information.
|
||||
// Optionally, the user may also define BENIGN_LANGOPT
|
||||
// (for options that don't affect the construction of the AST in an
|
||||
// incompatible way), ENUM_LANGOPT (for options that have enumeration,
|
||||
// rather than unsigned, type), BENIGN_ENUM_LANGOPT (for benign
|
||||
// options that have enumeration type), and VALUE_LANGOPT is a language option
|
||||
// that describes a value rather than a flag.
|
||||
//
|
||||
// Optionally, the user may also define:
|
||||
//
|
||||
// BENIGN_LANGOPT: for options that don't affect the construction of the AST in
|
||||
// any way (that is, the value can be different between an implicit module
|
||||
// and the user of that module).
|
||||
//
|
||||
// COMPATIBLE_LANGOPT: for options that affect the construction of the AST in
|
||||
// a way that doesn't prevent interoperability (that is, the value can be
|
||||
// different between an explicit module and the user of that module).
|
||||
//
|
||||
// ENUM_LANGOPT: for options that have enumeration, rather than unsigned, type.
|
||||
//
|
||||
// VALUE_LANGOPT: for options that describe a value rather than a flag.
|
||||
//
|
||||
// BENIGN_ENUM_LANGOPT, COMPATIBLE_ENUM_LANGOPT: combinations of the above.
|
||||
//
|
||||
// FIXME: Clients should be able to more easily select whether they want
|
||||
// different levels of compatibility versus how to handle different kinds
|
||||
// of option.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LANGOPT
|
||||
# error Define the LANGOPT macro to handle language options
|
||||
#endif
|
||||
|
||||
#ifndef VALUE_LANGOPT
|
||||
# define VALUE_LANGOPT(Name, Bits, Default, Description) \
|
||||
#ifndef COMPATIBLE_LANGOPT
|
||||
# define COMPATIBLE_LANGOPT(Name, Bits, Default, Description) \
|
||||
LANGOPT(Name, Bits, Default, Description)
|
||||
#endif
|
||||
|
||||
#ifndef BENIGN_LANGOPT
|
||||
# define BENIGN_LANGOPT(Name, Bits, Default, Description) \
|
||||
LANGOPT(Name, Bits, Default, Description)
|
||||
COMPATIBLE_LANGOPT(Name, Bits, Default, Description)
|
||||
#endif
|
||||
|
||||
#ifndef ENUM_LANGOPT
|
||||
|
@ -36,11 +50,22 @@
|
|||
LANGOPT(Name, Bits, Default, Description)
|
||||
#endif
|
||||
|
||||
#ifndef BENIGN_ENUM_LANGOPT
|
||||
# define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
|
||||
#ifndef COMPATIBLE_ENUM_LANGOPT
|
||||
# define COMPATIBLE_ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
|
||||
ENUM_LANGOPT(Name, Type, Bits, Default, Description)
|
||||
#endif
|
||||
|
||||
#ifndef BENIGN_ENUM_LANGOPT
|
||||
# define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) \
|
||||
COMPATIBLE_ENUM_LANGOPT(Name, Type, Bits, Default, Description)
|
||||
#endif
|
||||
|
||||
#ifndef VALUE_LANGOPT
|
||||
# define VALUE_LANGOPT(Name, Bits, Default, Description) \
|
||||
LANGOPT(Name, Bits, Default, Description)
|
||||
#endif
|
||||
|
||||
// FIXME: A lot of the BENIGN_ options should be COMPATIBLE_ instead.
|
||||
LANGOPT(C99 , 1, 0, "C99")
|
||||
LANGOPT(C11 , 1, 0, "C11")
|
||||
LANGOPT(MSVCCompat , 1, 0, "Microsoft Visual C++ full compatibility mode")
|
||||
|
@ -102,8 +127,8 @@ LANGOPT(ModulesDeclUse , 1, 0, "require declaration of module uses")
|
|||
LANGOPT(ModulesSearchAll , 1, 1, "search even non-imported modules to find unresolved references")
|
||||
LANGOPT(ModulesStrictDeclUse, 1, 0, "require declaration of module uses and all headers to be in modules")
|
||||
LANGOPT(ModulesErrorRecovery, 1, 1, "automatically import modules as needed when performing error recovery")
|
||||
LANGOPT(Optimize , 1, 0, "__OPTIMIZE__ predefined macro")
|
||||
LANGOPT(OptimizeSize , 1, 0, "__OPTIMIZE_SIZE__ predefined macro")
|
||||
COMPATIBLE_LANGOPT(Optimize , 1, 0, "__OPTIMIZE__ predefined macro")
|
||||
COMPATIBLE_LANGOPT(OptimizeSize , 1, 0, "__OPTIMIZE_SIZE__ predefined macro")
|
||||
LANGOPT(Static , 1, 0, "__STATIC__ predefined macro (as opposed to __DYNAMIC__)")
|
||||
VALUE_LANGOPT(PackStruct , 32, 0,
|
||||
"default struct packing maximum alignment")
|
||||
|
@ -112,8 +137,8 @@ VALUE_LANGOPT(MaxTypeAlign , 32, 0,
|
|||
VALUE_LANGOPT(PICLevel , 2, 0, "__PIC__ level")
|
||||
VALUE_LANGOPT(PIELevel , 2, 0, "__PIE__ level")
|
||||
LANGOPT(GNUInline , 1, 0, "GNU inline semantics")
|
||||
LANGOPT(NoInlineDefine , 1, 0, "__NO_INLINE__ predefined macro")
|
||||
LANGOPT(Deprecated , 1, 0, "__DEPRECATED predefined macro")
|
||||
COMPATIBLE_LANGOPT(NoInlineDefine , 1, 0, "__NO_INLINE__ predefined macro")
|
||||
COMPATIBLE_LANGOPT(Deprecated , 1, 0, "__DEPRECATED predefined macro")
|
||||
LANGOPT(FastMath , 1, 0, "__FAST_MATH__ predefined macro")
|
||||
LANGOPT(FiniteMathOnly , 1, 0, "__FINITE_MATH_ONLY__ predefined macro")
|
||||
|
||||
|
@ -192,8 +217,10 @@ LANGOPT(ApplePragmaPack, 1, 0, "Apple gcc-compatible #pragma pack handling")
|
|||
LANGOPT(RetainCommentsFromSystemHeaders, 1, 0, "retain documentation comments from system headers in the AST")
|
||||
|
||||
#undef LANGOPT
|
||||
#undef VALUE_LANGOPT
|
||||
#undef COMPATIBLE_LANGOPT
|
||||
#undef BENIGN_LANGOPT
|
||||
#undef ENUM_LANGOPT
|
||||
#undef COMPATIBLE_ENUM_LANGOPT
|
||||
#undef BENIGN_ENUM_LANGOPT
|
||||
#undef VALUE_LANGOPT
|
||||
|
||||
|
|
|
@ -115,7 +115,8 @@ public:
|
|||
///
|
||||
/// \returns true to indicate the options are invalid or false otherwise.
|
||||
virtual bool ReadLanguageOptions(const LangOptions &LangOpts,
|
||||
bool Complain) {
|
||||
bool Complain,
|
||||
bool AllowCompatibleDifferences) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -219,7 +220,8 @@ public:
|
|||
bool ReadFullVersionInformation(StringRef FullVersion) override;
|
||||
void ReadModuleName(StringRef ModuleName) override;
|
||||
void ReadModuleMapFile(StringRef ModuleMapPath) override;
|
||||
bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain) override;
|
||||
bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain,
|
||||
bool AllowCompatibleDifferences) override;
|
||||
bool ReadTargetOptions(const TargetOptions &TargetOpts,
|
||||
bool Complain) override;
|
||||
bool ReadDiagnosticOptions(IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts,
|
||||
|
@ -251,8 +253,8 @@ public:
|
|||
PCHValidator(Preprocessor &PP, ASTReader &Reader)
|
||||
: PP(PP), Reader(Reader) {}
|
||||
|
||||
bool ReadLanguageOptions(const LangOptions &LangOpts,
|
||||
bool Complain) override;
|
||||
bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain,
|
||||
bool AllowCompatibleDifferences) override;
|
||||
bool ReadTargetOptions(const TargetOptions &TargetOpts,
|
||||
bool Complain) override;
|
||||
bool ReadDiagnosticOptions(IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts,
|
||||
|
@ -1149,7 +1151,8 @@ private:
|
|||
ASTReadResult ReadSubmoduleBlock(ModuleFile &F,
|
||||
unsigned ClientLoadCapabilities);
|
||||
static bool ParseLanguageOptions(const RecordData &Record, bool Complain,
|
||||
ASTReaderListener &Listener);
|
||||
ASTReaderListener &Listener,
|
||||
bool AllowCompatibleDifferences);
|
||||
static bool ParseTargetOptions(const RecordData &Record, bool Complain,
|
||||
ASTReaderListener &Listener);
|
||||
static bool ParseDiagnosticOptions(const RecordData &Record, bool Complain,
|
||||
|
|
|
@ -508,8 +508,8 @@ public:
|
|||
: PP(PP), Context(Context), LangOpt(LangOpt), TargetOpts(TargetOpts),
|
||||
Target(Target), Counter(Counter), InitializedLanguage(false) {}
|
||||
|
||||
bool ReadLanguageOptions(const LangOptions &LangOpts,
|
||||
bool Complain) override {
|
||||
bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain,
|
||||
bool AllowCompatibleDifferences) override {
|
||||
if (InitializedLanguage)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -431,8 +431,8 @@ namespace {
|
|||
Out.indent(2) << "Module map file: " << ModuleMapPath << "\n";
|
||||
}
|
||||
|
||||
bool ReadLanguageOptions(const LangOptions &LangOpts,
|
||||
bool Complain) override {
|
||||
bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain,
|
||||
bool AllowCompatibleDifferences) override {
|
||||
Out.indent(2) << "Language options:\n";
|
||||
#define LANGOPT(Name, Bits, Default, Description) \
|
||||
DUMP_BOOLEAN(LangOpts.Name, Description);
|
||||
|
|
|
@ -80,10 +80,14 @@ void ChainedASTReaderListener::ReadModuleMapFile(StringRef ModuleMapPath) {
|
|||
First->ReadModuleMapFile(ModuleMapPath);
|
||||
Second->ReadModuleMapFile(ModuleMapPath);
|
||||
}
|
||||
bool ChainedASTReaderListener::ReadLanguageOptions(const LangOptions &LangOpts,
|
||||
bool Complain) {
|
||||
return First->ReadLanguageOptions(LangOpts, Complain) ||
|
||||
Second->ReadLanguageOptions(LangOpts, Complain);
|
||||
bool
|
||||
ChainedASTReaderListener::ReadLanguageOptions(const LangOptions &LangOpts,
|
||||
bool Complain,
|
||||
bool AllowCompatibleDifferences) {
|
||||
return First->ReadLanguageOptions(LangOpts, Complain,
|
||||
AllowCompatibleDifferences) ||
|
||||
Second->ReadLanguageOptions(LangOpts, Complain,
|
||||
AllowCompatibleDifferences);
|
||||
}
|
||||
bool
|
||||
ChainedASTReaderListener::ReadTargetOptions(const TargetOptions &TargetOpts,
|
||||
|
@ -155,11 +159,14 @@ ASTReaderListener::~ASTReaderListener() {}
|
|||
/// language options.
|
||||
///
|
||||
/// \param Diags If non-NULL, diagnostics will be emitted via this engine.
|
||||
/// \param AllowCompatibleDifferences If true, differences between compatible
|
||||
/// language options will be permitted.
|
||||
///
|
||||
/// \returns true if the languagae options mis-match, false otherwise.
|
||||
static bool checkLanguageOptions(const LangOptions &LangOpts,
|
||||
const LangOptions &ExistingLangOpts,
|
||||
DiagnosticsEngine *Diags) {
|
||||
DiagnosticsEngine *Diags,
|
||||
bool AllowCompatibleDifferences = true) {
|
||||
#define LANGOPT(Name, Bits, Default, Description) \
|
||||
if (ExistingLangOpts.Name != LangOpts.Name) { \
|
||||
if (Diags) \
|
||||
|
@ -184,6 +191,14 @@ static bool checkLanguageOptions(const LangOptions &LangOpts,
|
|||
return true; \
|
||||
}
|
||||
|
||||
#define COMPATIBLE_LANGOPT(Name, Bits, Default, Description) \
|
||||
if (!AllowCompatibleDifferences) \
|
||||
LANGOPT(Name, Bits, Default, Description)
|
||||
|
||||
#define COMPATIBLE_ENUM_LANGOPT(Name, Bits, Default, Description) \
|
||||
if (!AllowCompatibleDifferences) \
|
||||
ENUM_LANGOPT(Name, Bits, Default, Description)
|
||||
|
||||
#define BENIGN_LANGOPT(Name, Bits, Default, Description)
|
||||
#define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description)
|
||||
#include "clang/Basic/LangOptions.def"
|
||||
|
@ -278,10 +293,12 @@ static bool checkTargetOptions(const TargetOptions &TargetOpts,
|
|||
|
||||
bool
|
||||
PCHValidator::ReadLanguageOptions(const LangOptions &LangOpts,
|
||||
bool Complain) {
|
||||
bool Complain,
|
||||
bool AllowCompatibleDifferences) {
|
||||
const LangOptions &ExistingLangOpts = PP.getLangOpts();
|
||||
return checkLanguageOptions(LangOpts, ExistingLangOpts,
|
||||
Complain? &Reader.Diags : nullptr);
|
||||
Complain ? &Reader.Diags : nullptr,
|
||||
AllowCompatibleDifferences);
|
||||
}
|
||||
|
||||
bool PCHValidator::ReadTargetOptions(const TargetOptions &TargetOpts,
|
||||
|
@ -2261,6 +2278,12 @@ ASTReader::ReadControlBlock(ModuleFile &F,
|
|||
return Failure;
|
||||
}
|
||||
|
||||
// Should we allow the configuration of the module file to differ from the
|
||||
// configuration of the current translation unit in a compatible way?
|
||||
//
|
||||
// FIXME: Allow this for files explicitly specified with -include-pch too.
|
||||
bool AllowCompatibleConfigurationMismatch = F.Kind == MK_ExplicitModule;
|
||||
|
||||
// Read all of the records and blocks in the control block.
|
||||
RecordData Record;
|
||||
unsigned NumInputs = 0;
|
||||
|
@ -2415,8 +2438,10 @@ ASTReader::ReadControlBlock(ModuleFile &F,
|
|||
|
||||
case LANGUAGE_OPTIONS: {
|
||||
bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch) == 0;
|
||||
// FIXME: The &F == *ModuleMgr.begin() check is wrong for modules.
|
||||
if (Listener && &F == *ModuleMgr.begin() &&
|
||||
ParseLanguageOptions(Record, Complain, *Listener) &&
|
||||
ParseLanguageOptions(Record, Complain, *Listener,
|
||||
AllowCompatibleConfigurationMismatch) &&
|
||||
!DisableValidation && !AllowConfigurationMismatch)
|
||||
return ConfigurationMismatch;
|
||||
break;
|
||||
|
@ -2434,7 +2459,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
|
|||
case DIAGNOSTIC_OPTIONS: {
|
||||
bool Complain = (ClientLoadCapabilities & ARR_OutOfDate)==0;
|
||||
if (Listener && &F == *ModuleMgr.begin() &&
|
||||
F.Kind != MK_ExplicitModule &&
|
||||
!AllowCompatibleConfigurationMismatch &&
|
||||
ParseDiagnosticOptions(Record, Complain, *Listener) &&
|
||||
!DisableValidation)
|
||||
return OutOfDate;
|
||||
|
@ -2444,7 +2469,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
|
|||
case FILE_SYSTEM_OPTIONS: {
|
||||
bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
|
||||
if (Listener && &F == *ModuleMgr.begin() &&
|
||||
F.Kind != MK_ExplicitModule &&
|
||||
!AllowCompatibleConfigurationMismatch &&
|
||||
ParseFileSystemOptions(Record, Complain, *Listener) &&
|
||||
!DisableValidation && !AllowConfigurationMismatch)
|
||||
return ConfigurationMismatch;
|
||||
|
@ -2454,7 +2479,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
|
|||
case HEADER_SEARCH_OPTIONS: {
|
||||
bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
|
||||
if (Listener && &F == *ModuleMgr.begin() &&
|
||||
F.Kind != MK_ExplicitModule &&
|
||||
!AllowCompatibleConfigurationMismatch &&
|
||||
ParseHeaderSearchOptions(Record, Complain, *Listener) &&
|
||||
!DisableValidation && !AllowConfigurationMismatch)
|
||||
return ConfigurationMismatch;
|
||||
|
@ -2464,7 +2489,7 @@ ASTReader::ReadControlBlock(ModuleFile &F,
|
|||
case PREPROCESSOR_OPTIONS: {
|
||||
bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
|
||||
if (Listener && &F == *ModuleMgr.begin() &&
|
||||
F.Kind != MK_ExplicitModule &&
|
||||
!AllowCompatibleConfigurationMismatch &&
|
||||
ParsePreprocessorOptions(Record, Complain, *Listener,
|
||||
SuggestedPredefines) &&
|
||||
!DisableValidation && !AllowConfigurationMismatch)
|
||||
|
@ -4156,9 +4181,10 @@ namespace {
|
|||
{
|
||||
}
|
||||
|
||||
bool ReadLanguageOptions(const LangOptions &LangOpts,
|
||||
bool Complain) override {
|
||||
return checkLanguageOptions(ExistingLangOpts, LangOpts, nullptr);
|
||||
bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain,
|
||||
bool AllowCompatibleDifferences) override {
|
||||
return checkLanguageOptions(ExistingLangOpts, LangOpts, nullptr,
|
||||
AllowCompatibleDifferences);
|
||||
}
|
||||
bool ReadTargetOptions(const TargetOptions &TargetOpts,
|
||||
bool Complain) override {
|
||||
|
@ -4256,7 +4282,8 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename,
|
|||
break;
|
||||
}
|
||||
case LANGUAGE_OPTIONS:
|
||||
if (ParseLanguageOptions(Record, false, Listener))
|
||||
if (ParseLanguageOptions(Record, false, Listener,
|
||||
/*AllowCompatibleConfigurationMismatch*/false))
|
||||
return true;
|
||||
break;
|
||||
|
||||
|
@ -4612,7 +4639,8 @@ ASTReader::ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities) {
|
|||
/// \returns true if the listener deems the file unacceptable, false otherwise.
|
||||
bool ASTReader::ParseLanguageOptions(const RecordData &Record,
|
||||
bool Complain,
|
||||
ASTReaderListener &Listener) {
|
||||
ASTReaderListener &Listener,
|
||||
bool AllowCompatibleDifferences) {
|
||||
LangOptions LangOpts;
|
||||
unsigned Idx = 0;
|
||||
#define LANGOPT(Name, Bits, Default, Description) \
|
||||
|
@ -4640,7 +4668,8 @@ bool ASTReader::ParseLanguageOptions(const RecordData &Record,
|
|||
}
|
||||
LangOpts.CommentOpts.ParseAllComments = Record[Idx++];
|
||||
|
||||
return Listener.ReadLanguageOptions(LangOpts, Complain);
|
||||
return Listener.ReadLanguageOptions(LangOpts, Complain,
|
||||
AllowCompatibleDifferences);
|
||||
}
|
||||
|
||||
bool ASTReader::ParseTargetOptions(const RecordData &Record,
|
||||
|
|
|
@ -25,6 +25,13 @@
|
|||
// Can use the module if -I flags change.
|
||||
// RUN: %clang_cc1 -fmodules -DBAR=2 -I. -x c++ -fmodule-map-file=%t/map -fmodule-file=%t/tmp.pcm -verify -I%t %s
|
||||
|
||||
// Can use the module if -O flags change.
|
||||
// RUN: %clang_cc1 -fmodules -DBAR=2 -Os -x c++ -fmodule-map-file=%t/map -fmodule-file=%t/tmp.pcm -verify -I%t %s
|
||||
//
|
||||
// RUN: %clang_cc1 -fmodules -DFOO=1 -O2 -x c++ -fmodule-name=tmp %t/map -emit-module -o %t/tmp-O2.pcm
|
||||
// RUN: %clang_cc1 -fmodules -DBAR=2 -O0 -x c++ -fmodule-map-file=%t/map -fmodule-file=%t/tmp-O2.pcm -verify -I%t %s
|
||||
// RUN: %clang_cc1 -fmodules -DBAR=2 -Os -x c++ -fmodule-map-file=%t/map -fmodule-file=%t/tmp-O2.pcm -verify -I%t %s
|
||||
|
||||
#include "tmp.h" // expected-no-diagnostics
|
||||
|
||||
#ifndef BAR
|
||||
|
|
Loading…
Reference in New Issue