diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Basic/CMakeLists.txt | 1 | ||||
-rw-r--r-- | clang/lib/Basic/Warnings.cpp (renamed from clang/lib/Frontend/Warnings.cpp) | 5 | ||||
-rw-r--r-- | clang/lib/Frontend/CMakeLists.txt | 1 | ||||
-rw-r--r-- | clang/lib/Frontend/FrontendActions.cpp | 19 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReader.cpp | 131 |
5 files changed, 144 insertions, 13 deletions
diff --git a/clang/lib/Basic/CMakeLists.txt b/clang/lib/Basic/CMakeLists.txt index 0448fdb0d41..0df82b3bc90 100644 --- a/clang/lib/Basic/CMakeLists.txt +++ b/clang/lib/Basic/CMakeLists.txt @@ -25,6 +25,7 @@ add_clang_library(clangBasic Version.cpp VersionTuple.cpp VirtualFileSystem.cpp + Warnings.cpp ) # Determine Subversion revision. diff --git a/clang/lib/Frontend/Warnings.cpp b/clang/lib/Basic/Warnings.cpp index 767096a1c99..b09e69aeca6 100644 --- a/clang/lib/Frontend/Warnings.cpp +++ b/clang/lib/Basic/Warnings.cpp @@ -20,12 +20,9 @@ // Given a warning option 'foo', the following are valid: // -Wfoo, -Wno-foo, -Werror=foo, -Wfatal-errors=foo // -#include "clang/Frontend/Utils.h" +#include "clang/Basic/AllDiagnostics.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticOptions.h" -#include "clang/Frontend/FrontendDiagnostic.h" -#include "clang/Lex/LexDiagnostic.h" -#include "clang/Sema/SemaDiagnostic.h" #include <algorithm> #include <cstring> #include <utility> diff --git a/clang/lib/Frontend/CMakeLists.txt b/clang/lib/Frontend/CMakeLists.txt index f1c789778f1..b67e0aed24c 100644 --- a/clang/lib/Frontend/CMakeLists.txt +++ b/clang/lib/Frontend/CMakeLists.txt @@ -32,7 +32,6 @@ add_clang_library(clangFrontend TextDiagnosticBuffer.cpp TextDiagnosticPrinter.cpp VerifyDiagnosticConsumer.cpp - Warnings.cpp DEPENDS ClangDriverOptions diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index 3d65ae32c01..a8df7fd1cb8 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -459,6 +459,25 @@ namespace { return false; } + virtual bool + ReadDiagnosticOptions(IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, + bool Complain) override { + Out.indent(2) << "Diagnostic options:\n"; +#define DIAGOPT(Name, Bits, Default) DUMP_BOOLEAN(DiagOpts->Name, #Name); +#define ENUM_DIAGOPT(Name, Type, Bits, Default) \ + Out.indent(4) << #Name << ": " << DiagOpts->get##Name() << "\n"; +#define VALUE_DIAGOPT(Name, Bits, Default) \ + Out.indent(4) << #Name << ": " << DiagOpts->Name << "\n"; +#include "clang/Basic/DiagnosticOptions.def" + + Out.indent(4) << "Warning options:\n"; + for (const std::string &Warning : DiagOpts->Warnings) { + Out.indent(6) << "-W" << Warning << "\n"; + } + + return false; + } + bool ReadHeaderSearchOptions(const HeaderSearchOptions &HSOpts, bool Complain) override { Out.indent(2) << "Header search options:\n"; diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 834917de1d4..c6aec4592ba 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -29,6 +29,7 @@ #include "clang/Basic/TargetOptions.h" #include "clang/Basic/Version.h" #include "clang/Basic/VersionTuple.h" +#include "clang/Frontend/Utils.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/HeaderSearchOptions.h" #include "clang/Lex/MacroInfo.h" @@ -90,7 +91,7 @@ ChainedASTReaderListener::ReadTargetOptions(const TargetOptions &TargetOpts, Second->ReadTargetOptions(TargetOpts, Complain); } bool ChainedASTReaderListener::ReadDiagnosticOptions( - const DiagnosticOptions &DiagOpts, bool Complain) { + IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, bool Complain) { return First->ReadDiagnosticOptions(DiagOpts, Complain) || Second->ReadDiagnosticOptions(DiagOpts, Complain); } @@ -291,6 +292,120 @@ namespace { DeclsMap; } +static bool checkDiagnosticGroupMappings(DiagnosticsEngine &StoredDiags, + DiagnosticsEngine &Diags, + bool Complain) { + typedef DiagnosticsEngine::Level Level; + + // Check current mappings for new -Werror mappings, and the stored mappings + // for cases that were explicitly mapped to *not* be errors that are now + // errors because of options like -Werror. + DiagnosticsEngine *MappingSources[] = { &Diags, &StoredDiags }; + + for (DiagnosticsEngine *MappingSource : MappingSources) { + for (auto DiagIDMappingPair : MappingSource->getDiagnosticMappings()) { + diag::kind DiagID = DiagIDMappingPair.first; + Level CurLevel = Diags.getDiagnosticLevel(DiagID, SourceLocation()); + if (CurLevel < DiagnosticsEngine::Error) + continue; // not significant + Level StoredLevel = + StoredDiags.getDiagnosticLevel(DiagID, SourceLocation()); + if (StoredLevel < DiagnosticsEngine::Error) { + if (Complain) + Diags.Report(diag::err_pch_diagopt_mismatch) << "-Werror=" + + Diags.getDiagnosticIDs()->getWarningOptionForDiag(DiagID).str(); + return true; + } + } + } + + return false; +} + +static DiagnosticsEngine::ExtensionHandling +isExtHandlingFromDiagsError(DiagnosticsEngine &Diags) { + DiagnosticsEngine::ExtensionHandling Ext = + Diags.getExtensionHandlingBehavior(); + if (Ext == DiagnosticsEngine::Ext_Warn && Diags.getWarningsAsErrors()) + Ext = DiagnosticsEngine::Ext_Error; + return Ext; +} + +static bool checkDiagnosticMappings(DiagnosticsEngine &StoredDiags, + DiagnosticsEngine &Diags, + bool IsSystem, bool Complain) { + // Top-level options + if (IsSystem) { + if (Diags.getSuppressSystemWarnings()) + return false; + // If -Wsystem-headers was not enabled before, be conservative + if (StoredDiags.getSuppressSystemWarnings()) { + if (Complain) + Diags.Report(diag::err_pch_diagopt_mismatch) << "-Wsystem-headers"; + return true; + } + } + + if (Diags.getWarningsAsErrors() && !StoredDiags.getWarningsAsErrors()) { + if (Complain) + Diags.Report(diag::err_pch_diagopt_mismatch) << "-Werror"; + return true; + } + + if (Diags.getWarningsAsErrors() && Diags.getEnableAllWarnings() && + !StoredDiags.getEnableAllWarnings()) { + if (Complain) + Diags.Report(diag::err_pch_diagopt_mismatch) << "-Weverything -Werror"; + return true; + } + + if (isExtHandlingFromDiagsError(Diags) && + !isExtHandlingFromDiagsError(StoredDiags)) { + if (Complain) + Diags.Report(diag::err_pch_diagopt_mismatch) << "-pedantic-errors"; + return true; + } + + return checkDiagnosticGroupMappings(StoredDiags, Diags, Complain); +} + +bool PCHValidator::ReadDiagnosticOptions( + IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, bool Complain) { + DiagnosticsEngine &ExistingDiags = PP.getDiagnostics(); + IntrusiveRefCntPtr<DiagnosticIDs> DiagIDs(ExistingDiags.getDiagnosticIDs()); + IntrusiveRefCntPtr<DiagnosticsEngine> Diags( + new DiagnosticsEngine(DiagIDs, DiagOpts.getPtr())); + // This should never fail, because we would have processed these options + // before writing them to an ASTFile. + ProcessWarningOptions(*Diags, *DiagOpts, /*Report*/false); + + ModuleManager &ModuleMgr = Reader.getModuleManager(); + assert(ModuleMgr.size() >= 1 && "what ASTFile is this then"); + + // If the original import came from a file explicitly generated by the user, + // don't check the diagnostic mappings. + // FIXME: currently this is approximated by checking whether this is not a + // module import. + // Note: ModuleMgr.rbegin() may not be the current module, but it must be in + // the transitive closure of its imports, since unrelated modules cannot be + // imported until after this module finishes validation. + ModuleFile *TopImport = *ModuleMgr.rbegin(); + while (!TopImport->ImportedBy.empty()) + TopImport = TopImport->ImportedBy[0]; + if (TopImport->Kind != MK_Module) + return false; + + StringRef ModuleName = TopImport->ModuleName; + assert(!ModuleName.empty() && "diagnostic options read before module name"); + + Module *M = PP.getHeaderSearchInfo().lookupModule(ModuleName); + assert(M && "missing module"); + + // FIXME: if the diagnostics are incompatible, save a DiagnosticOptions that + // contains the union of their flags. + return checkDiagnosticMappings(*Diags, ExistingDiags, M->IsSystem, Complain); +} + /// \brief Collect the macro definitions provided by the given preprocessor /// options. static void collectMacroDefinitions(const PreprocessorOptions &PPOpts, @@ -2268,11 +2383,11 @@ ASTReader::ReadControlBlock(ModuleFile &F, } case DIAGNOSTIC_OPTIONS: { - bool Complain = (ClientLoadCapabilities & ARR_ConfigurationMismatch)==0; + bool Complain = (ClientLoadCapabilities & ARR_OutOfDate)==0; if (Listener && &F == *ModuleMgr.begin() && ParseDiagnosticOptions(Record, Complain, *Listener) && - !DisableValidation && !AllowConfigurationMismatch) - return ConfigurationMismatch; + !DisableValidation) + return OutOfDate; break; } @@ -4481,15 +4596,15 @@ bool ASTReader::ParseTargetOptions(const RecordData &Record, bool ASTReader::ParseDiagnosticOptions(const RecordData &Record, bool Complain, ASTReaderListener &Listener) { - DiagnosticOptions DiagOpts; + IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts(new DiagnosticOptions); unsigned Idx = 0; -#define DIAGOPT(Name, Bits, Default) DiagOpts.Name = Record[Idx++]; +#define DIAGOPT(Name, Bits, Default) DiagOpts->Name = Record[Idx++]; #define ENUM_DIAGOPT(Name, Type, Bits, Default) \ - DiagOpts.set##Name(static_cast<Type>(Record[Idx++])); + DiagOpts->set##Name(static_cast<Type>(Record[Idx++])); #include "clang/Basic/DiagnosticOptions.def" for (unsigned N = Record[Idx++]; N; --N) { - DiagOpts.Warnings.push_back(ReadString(Record, Idx)); + DiagOpts->Warnings.push_back(ReadString(Record, Idx)); } return Listener.ReadDiagnosticOptions(DiagOpts, Complain); |