summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
authorDuncan P. N. Exon Smith <dexonsmith@apple.com>2017-04-12 03:58:58 +0000
committerDuncan P. N. Exon Smith <dexonsmith@apple.com>2017-04-12 03:58:58 +0000
commit900f817591d0f6871b324aef655cbda926d26052 (patch)
treeab7f49a6b2f01e9d7a5c2ee8d38f105c3a0450fa /clang/lib
parenta351c10df3b843acaa2ecb48a1bdb61afd10ff01 (diff)
downloadbcm5719-llvm-900f817591d0f6871b324aef655cbda926d26052.tar.gz
bcm5719-llvm-900f817591d0f6871b324aef655cbda926d26052.zip
Serialization: Simulate -Werror settings in implicit modules
r293123 started serializing diagnostic pragma state for modules. This makes the serialization work properly for implicit modules. An implicit module build (using Clang's internal build system) uses the same PCM file location for different `-Werror` levels. E.g., if a TU has `-Werror=format` and tries to load a PCM built without `-Werror=format`, a new PCM will be built in its place (and the new PCM should have the same signature, since r297655). In the other direction, if a TU does not have `-Werror=format` and tries to load a PCM built with `-Werror=format`, it should "just work". The idea is to evolve the PCM toward the strictest -Werror flags that anyone tries. r293123 started serializing the diagnostic pragma state for each PCM. Since this encodes the -Werror settings at module-build time, it breaks the implicit build model. This commit filters the diagnostic state in order to simulate the current compilation's diagnostic settings. Firstly, it ignores the module's serialized first diagnostic state, replacing it with the state from this compilation's command-line. Secondly, if a pragma warning was upgraded to error/fatal when generating the PCM (e.g., due to `-Werror` on the command-line), it checks whether it should still be upgraded in its current context. llvm-svn: 300025
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Basic/Diagnostic.cpp6
-rw-r--r--clang/lib/Serialization/ASTReader.cpp50
-rw-r--r--clang/lib/Serialization/ASTWriter.cpp7
3 files changed, 54 insertions, 9 deletions
diff --git a/clang/lib/Basic/Diagnostic.cpp b/clang/lib/Basic/Diagnostic.cpp
index 0c27ae4638d..350d5477751 100644
--- a/clang/lib/Basic/Diagnostic.cpp
+++ b/clang/lib/Basic/Diagnostic.cpp
@@ -258,13 +258,17 @@ void DiagnosticsEngine::setSeverity(diag::kind Diag, diag::Severity Map,
assert((L.isInvalid() || SourceMgr) && "No SourceMgr for valid location");
// Don't allow a mapping to a warning override an error/fatal mapping.
+ bool WasUpgradedFromWarning = false;
if (Map == diag::Severity::Warning) {
DiagnosticMapping &Info = GetCurDiagState()->getOrAddMapping(Diag);
if (Info.getSeverity() == diag::Severity::Error ||
- Info.getSeverity() == diag::Severity::Fatal)
+ Info.getSeverity() == diag::Severity::Fatal) {
Map = Info.getSeverity();
+ WasUpgradedFromWarning = true;
+ }
}
DiagnosticMapping Mapping = makeUserMapping(Map, L);
+ Mapping.setUpgradedFromWarning(WasUpgradedFromWarning);
// Common case; setting all the diagnostics of a group in one place.
if ((L.isInvalid() || L == DiagStatesByLoc.getCurDiagStateLoc()) &&
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index e09af28059b..d6bacfe3e09 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -5525,18 +5525,54 @@ void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) {
"Invalid data, not enough diag/map pairs");
while (Size--) {
unsigned DiagID = Record[Idx++];
- diag::Severity Map = (diag::Severity)Record[Idx++];
- DiagnosticMapping Mapping = Diag.makeUserMapping(Map, Loc);
- if (Mapping.isPragma() || IncludeNonPragmaStates)
- NewState->setMapping(DiagID, Mapping);
+ unsigned SeverityAndUpgradedFromWarning = Record[Idx++];
+ bool WasUpgradedFromWarning =
+ DiagnosticMapping::deserializeUpgradedFromWarning(
+ SeverityAndUpgradedFromWarning);
+ DiagnosticMapping NewMapping =
+ Diag.makeUserMapping(DiagnosticMapping::deserializeSeverity(
+ SeverityAndUpgradedFromWarning),
+ Loc);
+ if (!NewMapping.isPragma() && !IncludeNonPragmaStates)
+ continue;
+
+ DiagnosticMapping &Mapping = NewState->getOrAddMapping(DiagID);
+
+ // If this mapping was specified as a warning but the severity was
+ // upgraded due to diagnostic settings, simulate the current diagnostic
+ // settings (and use a warning).
+ if (WasUpgradedFromWarning && !Mapping.isErrorOrFatal()) {
+ Mapping = Diag.makeUserMapping(diag::Severity::Warning, Loc);
+ continue;
+ }
+
+ // Use the deserialized mapping verbatim.
+ Mapping = NewMapping;
+ Mapping.setUpgradedFromWarning(WasUpgradedFromWarning);
}
return NewState;
};
// Read the first state.
- auto *FirstState = ReadDiagState(
- F.isModule() ? DiagState() : *Diag.DiagStatesByLoc.CurDiagState,
- SourceLocation(), F.isModule());
+ DiagState *FirstState;
+ if (F.Kind == MK_ImplicitModule) {
+ // Implicitly-built modules are reused with different diagnostic
+ // settings. Use the initial diagnostic state from Diag to simulate this
+ // compilation's diagnostic settings.
+ FirstState = Diag.DiagStatesByLoc.FirstDiagState;
+ DiagStates.push_back(FirstState);
+
+ // Skip the initial diagnostic state from the serialized module.
+ assert(Record[0] == 0 &&
+ "Invalid data, unexpected backref in initial state");
+ Idx = 2 + Record[1] * 2;
+ assert(Idx < Record.size() &&
+ "Invalid data, not enough state change pairs in initial state");
+ } else {
+ FirstState = ReadDiagState(
+ F.isModule() ? DiagState() : *Diag.DiagStatesByLoc.CurDiagState,
+ SourceLocation(), F.isModule());
+ }
// Read the state transitions.
unsigned NumLocations = Record[Idx++];
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index ffcad78f295..7dd2ca302ca 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -2879,7 +2879,7 @@ void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag,
for (const auto &I : *State) {
if (I.second.isPragma() || IncludeNonPragmaStates) {
Record.push_back(I.first);
- Record.push_back((unsigned)I.second.getSeverity());
+ Record.push_back(I.second.serializeBits());
}
}
// Update the placeholder.
@@ -2913,6 +2913,11 @@ void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag,
Record[NumLocationsIdx] = NumLocations;
// Emit CurDiagStateLoc. Do it last in order to match source order.
+ //
+ // This also protects against a hypothetical corner case with simulating
+ // -Werror settings for implicit modules in the ASTReader, where reading
+ // CurDiagState out of context could change whether warning pragmas are
+ // treated as errors.
AddSourceLocation(Diag.DiagStatesByLoc.CurDiagStateLoc, Record);
AddDiagState(Diag.DiagStatesByLoc.CurDiagState, false);
OpenPOWER on IntegriCloud