/// \brief Receives the preprocessor options.
///
+ /// \param SuggestedPredefines Can be filled in with the set of predefines
+ /// that are suggested by the preprocessor options. Typically only used when
+ /// loading a precompiled header.
+ ///
/// \returns true to indicate the preprocessor options are invalid, or false
/// otherwise.
virtual bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
- bool Complain) {
+ bool Complain,
+ std::string &SuggestedPredefines) {
return false;
}
virtual bool ReadTargetOptions(const TargetOptions &TargetOpts,
bool Complain);
virtual bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
- bool Complain);
+ bool Complain,
+ std::string &SuggestedPredefines);
virtual bool ReadPredefinesBuffer(const PCHPredefinesBlocks &Buffers,
StringRef OriginalFileName,
std::string &SuggestedPredefines,
static bool ParseHeaderSearchOptions(const RecordData &Record, bool Complain,
ASTReaderListener &Listener);
static bool ParsePreprocessorOptions(const RecordData &Record, bool Complain,
- ASTReaderListener &Listener);
+ ASTReaderListener &Listener,
+ std::string &SuggestedPredefines);
struct RecordLocation {
RecordLocation(ModuleFile *M, uint64_t O)
/// \param Diags If non-null, produce diagnostics for any mismatches incurred.
static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts,
const PreprocessorOptions &ExistingPPOpts,
- DiagnosticsEngine *Diags) {
+ DiagnosticsEngine *Diags,
+ FileManager &FileMgr,
+ std::string &SuggestedPredefines) {
// Check macro definitions.
MacroDefinitionsMap ASTFileMacros;
collectMacroDefinitions(PPOpts, ASTFileMacros);
// FIXME: Check whether this identifier was referenced anywhere in the
// AST file. If so, we should reject the AST file. Unfortunately, this
// information isn't in the control block. What shall we do about it?
+
+ if (Existing.second) {
+ SuggestedPredefines += "#undef ";
+ SuggestedPredefines += MacroName.str();
+ SuggestedPredefines += '\n';
+ } else {
+ SuggestedPredefines += "#define ";
+ SuggestedPredefines += MacroName.str();
+ SuggestedPredefines += Existing.first.str();
+ SuggestedPredefines += '\n';
+ }
continue;
}
return true;
}
+ // Compute the #include and #include_macros lines we need.
+ for (unsigned I = 0, N = ExistingPPOpts.Includes.size(); I != N; ++I) {
+ StringRef File = ExistingPPOpts.Includes[I];
+ if (File == ExistingPPOpts.ImplicitPCHInclude)
+ continue;
+
+ if (std::find(PPOpts.Includes.begin(), PPOpts.Includes.end(), File)
+ != PPOpts.Includes.end())
+ continue;
+
+ SuggestedPredefines += "#include \"";
+ SuggestedPredefines +=
+ HeaderSearch::NormalizeDashIncludePath(File, FileMgr);
+ SuggestedPredefines += "\"\n";
+ }
+
+ for (unsigned I = 0, N = ExistingPPOpts.MacroIncludes.size(); I != N; ++I) {
+ StringRef File = ExistingPPOpts.MacroIncludes[I];
+ if (std::find(PPOpts.MacroIncludes.begin(), PPOpts.MacroIncludes.end(),
+ File)
+ != PPOpts.MacroIncludes.end())
+ continue;
+
+ SuggestedPredefines += "#__include_macros \"";
+ SuggestedPredefines +=
+ HeaderSearch::NormalizeDashIncludePath(File, FileMgr);
+ SuggestedPredefines += "\"\n##\n";
+ }
+
return false;
}
bool PCHValidator::ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
- bool Complain) {
+ bool Complain,
+ std::string &SuggestedPredefines) {
const PreprocessorOptions &ExistingPPOpts = PP.getPreprocessorOpts();
return checkPreprocessorOptions(PPOpts, ExistingPPOpts,
- Complain? &Reader.Diags : 0);
+ Complain? &Reader.Diags : 0,
+ PP.getFileManager(),
+ SuggestedPredefines);
}
namespace {
if (Listener) {
// We only care about the primary module.
ModuleFile &M = ModuleMgr.getPrimaryModule();
+ SuggestedPredefines.clear();
return Listener->ReadPredefinesBuffer(PCHPredefinesBuffers,
M.ActualOriginalSourceFileName,
SuggestedPredefines,
case PREPROCESSOR_OPTIONS: {
bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0;
if (Listener && &F == *ModuleMgr.begin() &&
- ParsePreprocessorOptions(Record, Complain, *Listener) &&
+ ParsePreprocessorOptions(Record, Complain, *Listener,
+ SuggestedPredefines) &&
!DisableValidation)
return ConfigurationMismatch;
break;
const LangOptions &ExistingLangOpts;
const TargetOptions &ExistingTargetOpts;
const PreprocessorOptions &ExistingPPOpts;
-
+ FileManager &FileMgr;
+
public:
SimplePCHValidator(const LangOptions &ExistingLangOpts,
const TargetOptions &ExistingTargetOpts,
- const PreprocessorOptions &ExistingPPOpts)
+ const PreprocessorOptions &ExistingPPOpts,
+ FileManager &FileMgr)
: ExistingLangOpts(ExistingLangOpts),
ExistingTargetOpts(ExistingTargetOpts),
- ExistingPPOpts(ExistingPPOpts)
+ ExistingPPOpts(ExistingPPOpts),
+ FileMgr(FileMgr)
{
}
return checkTargetOptions(ExistingTargetOpts, TargetOpts, 0);
}
virtual bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts,
- bool Complain) {
- return checkPreprocessorOptions(ExistingPPOpts, PPOpts, 0);
+ bool Complain,
+ std::string &SuggestedPredefines) {
+ return checkPreprocessorOptions(ExistingPPOpts, PPOpts, 0, FileMgr,
+ SuggestedPredefines);
}
};
}
return false;
}
- SimplePCHValidator Validator(LangOpts, TargetOpts, PPOpts);
+ SimplePCHValidator Validator(LangOpts, TargetOpts, PPOpts, FileMgr);
RecordData Record;
bool InControlBlock = false;
while (!Stream.AtEndOfStream()) {
return false;
break;
- case PREPROCESSOR_OPTIONS:
- if (ParsePreprocessorOptions(Record, false, Validator))
+ case PREPROCESSOR_OPTIONS: {
+ std::string IgnoredSuggestedPredefines;
+ if (ParsePreprocessorOptions(Record, false, Validator,
+ IgnoredSuggestedPredefines))
return false;
break;
+ }
default:
// No other validation to perform.
bool ASTReader::ParsePreprocessorOptions(const RecordData &Record,
bool Complain,
- ASTReaderListener &Listener) {
+ ASTReaderListener &Listener,
+ std::string &SuggestedPredefines) {
PreprocessorOptions PPOpts;
unsigned Idx = 0;
PPOpts.ImplicitPTHInclude = ReadString(Record, Idx);
PPOpts.ObjCXXARCStandardLibrary =
static_cast<ObjCXXARCStandardLibraryKind>(Record[Idx++]);
- return Listener.ReadPreprocessorOptions(PPOpts, Complain);
+ SuggestedPredefines.clear();
+ return Listener.ReadPreprocessorOptions(PPOpts, Complain,
+ SuggestedPredefines);
}
std::pair<ModuleFile *, unsigned>