aboutsummaryrefslogtreecommitdiff
path: root/lib/Frontend
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Frontend')
-rw-r--r--lib/Frontend/CompilerInstance.cpp99
1 files changed, 98 insertions, 1 deletions
diff --git a/lib/Frontend/CompilerInstance.cpp b/lib/Frontend/CompilerInstance.cpp
index d5c1a27ec8..a20e7d7ed0 100644
--- a/lib/Frontend/CompilerInstance.cpp
+++ b/lib/Frontend/CompilerInstance.cpp
@@ -905,6 +905,96 @@ static void compileModule(CompilerInstance &ImportingInstance,
}
}
+/// \brief Diagnose differences between the current definition of the given
+/// configuration macro and the definition provided on the command line.
+static void checkConfigMacro(Preprocessor &PP, StringRef ConfigMacro,
+ Module *Mod, SourceLocation ImportLoc) {
+ IdentifierInfo *Id = PP.getIdentifierInfo(ConfigMacro);
+ SourceManager &SourceMgr = PP.getSourceManager();
+
+ // If this identifier has never had a macro definition, then it could
+ // not have changed.
+ if (!Id->hadMacroDefinition())
+ return;
+
+ // If this identifier does not currently have a macro definition,
+ // check whether it had one on the command line.
+ if (!Id->hasMacroDefinition()) {
+ MacroDirective *UndefMD = PP.getMacroDirectiveHistory(Id);
+ for (MacroDirective *MD = UndefMD; MD; MD = MD->getPrevious()) {
+
+ FileID FID = SourceMgr.getFileID(MD->getLocation());
+ if (FID.isInvalid())
+ continue;
+
+ const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(FID);
+ if (!Buffer)
+ continue;
+
+ // We only care about the predefines buffer.
+ if (!StringRef(Buffer->getBufferIdentifier()).equals("<built-in>"))
+ continue;
+
+ // This macro was defined on the command line, then #undef'd later.
+ // Complain.
+ PP.Diag(ImportLoc, diag::warn_module_config_macro_undef)
+ << true << ConfigMacro << Mod->getFullModuleName();
+ if (UndefMD->getUndefLoc().isValid())
+ PP.Diag(UndefMD->getUndefLoc(), diag::note_module_def_undef_here)
+ << true;
+ return;
+ }
+
+ // Okay: no definition in the predefines buffer.
+ return;
+ }
+
+ // This identifier has a macro definition. Check whether we had a definition
+ // on the command line.
+ MacroDirective *DefMD = PP.getMacroDirective(Id);
+ MacroDirective *PredefinedMD = 0;
+ for (MacroDirective *MD = DefMD; MD; MD = MD->getPrevious()) {
+ FileID FID = SourceMgr.getFileID(MD->getLocation());
+ if (FID.isInvalid())
+ continue;
+
+ const llvm::MemoryBuffer *Buffer = SourceMgr.getBuffer(FID);
+ if (!Buffer)
+ continue;
+
+ // We only care about the predefines buffer.
+ if (!StringRef(Buffer->getBufferIdentifier()).equals("<built-in>"))
+ continue;
+
+ PredefinedMD = MD;
+ break;
+ }
+
+ // If there was no definition for this macro in the predefines buffer,
+ // complain.
+ if (!PredefinedMD ||
+ (!PredefinedMD->getLocation().isValid() &&
+ PredefinedMD->getUndefLoc().isValid())) {
+ PP.Diag(ImportLoc, diag::warn_module_config_macro_undef)
+ << false << ConfigMacro << Mod->getFullModuleName();
+ PP.Diag(DefMD->getLocation(), diag::note_module_def_undef_here)
+ << false;
+ return;
+ }
+
+ // If the current macro definition is the same as the predefined macro
+ // definition, it's okay.
+ if (DefMD == PredefinedMD ||
+ DefMD->getInfo()->isIdenticalTo(*PredefinedMD->getInfo(), PP))
+ return;
+
+ // The macro definitions differ.
+ PP.Diag(ImportLoc, diag::warn_module_config_macro_undef)
+ << false << ConfigMacro << Mod->getFullModuleName();
+ PP.Diag(DefMD->getLocation(), diag::note_module_def_undef_here)
+ << false;
+}
+
ModuleLoadResult
CompilerInstance::loadModule(SourceLocation ImportLoc,
ModuleIdPath Path,
@@ -1177,7 +1267,14 @@ CompilerInstance::loadModule(SourceLocation ImportLoc,
ModuleManager->makeModuleVisible(Module, Visibility, ImportLoc);
}
-
+
+ // Check for any configuration macros that have changed.
+ clang::Module *TopModule = Module->getTopLevelModule();
+ for (unsigned I = 0, N = TopModule->ConfigMacros.size(); I != N; ++I) {
+ checkConfigMacro(getPreprocessor(), TopModule->ConfigMacros[I],
+ Module, ImportLoc);
+ }
+
// If this module import was due to an inclusion directive, create an
// implicit import declaration to capture it in the AST.
if (IsInclusionDirective && hasASTContext()) {