The the preprocessor option validator to compute suggested

predefines. We're not quite ready to cut over to these suggested
predefines yet, however.

llvm-svn: 166648
This commit is contained in:
Douglas Gregor 2012-10-25 00:07:54 +00:00
parent 753c8782df
commit 55358ede64
2 changed files with 82 additions and 17 deletions

View File

@ -151,10 +151,15 @@ public:
/// \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;
}
@ -204,7 +209,8 @@ public:
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,
@ -960,7 +966,8 @@ private:
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)

View File

@ -247,7 +247,9 @@ static void collectMacroDefinitions(const PreprocessorOptions &PPOpts,
/// \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);
@ -267,6 +269,17 @@ static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts,
// 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;
}
@ -301,15 +314,47 @@ static bool checkPreprocessorOptions(const PreprocessorOptions &PPOpts,
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 {
@ -984,6 +1029,7 @@ bool ASTReader::CheckPredefinesBuffers(bool Complain) {
if (Listener) {
// We only care about the primary module.
ModuleFile &M = ModuleMgr.getPrimaryModule();
SuggestedPredefines.clear();
return Listener->ReadPredefinesBuffer(PCHPredefinesBuffers,
M.ActualOriginalSourceFileName,
SuggestedPredefines,
@ -2152,7 +2198,8 @@ ASTReader::ReadControlBlock(ModuleFile &F,
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;
@ -3503,14 +3550,17 @@ namespace {
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)
{
}
@ -3523,8 +3573,10 @@ namespace {
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);
}
};
}
@ -3557,7 +3609,7 @@ bool ASTReader::isAcceptableASTFile(StringRef Filename,
return false;
}
SimplePCHValidator Validator(LangOpts, TargetOpts, PPOpts);
SimplePCHValidator Validator(LangOpts, TargetOpts, PPOpts, FileMgr);
RecordData Record;
bool InControlBlock = false;
while (!Stream.AtEndOfStream()) {
@ -3640,10 +3692,13 @@ bool ASTReader::isAcceptableASTFile(StringRef Filename,
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.
@ -4052,7 +4107,8 @@ bool ASTReader::ParseHeaderSearchOptions(const RecordData &Record,
bool ASTReader::ParsePreprocessorOptions(const RecordData &Record,
bool Complain,
ASTReaderListener &Listener) {
ASTReaderListener &Listener,
std::string &SuggestedPredefines) {
PreprocessorOptions PPOpts;
unsigned Idx = 0;
@ -4078,7 +4134,9 @@ bool ASTReader::ParsePreprocessorOptions(const RecordData &Record,
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>