From efaa54a5a8a1e33cb3124d8d9b458aeb08025ba1 Mon Sep 17 00:00:00 2001 From: Argyrios Kyrtzidis Date: Tue, 30 Oct 2012 00:27:21 +0000 Subject: [PATCH] [PCH] The diagnostic state points can refer to previously created diagnostic states; make sure the ASTReader sets the diagnostic state properly instead of always recreating it. Fixes rdar://12581618 & http://llvm.org/PR14181 llvm-svn: 166987 --- clang/lib/Serialization/ASTReader.cpp | 24 ++++++++++++++++++------ clang/lib/Serialization/ASTWriter.cpp | 27 +++++++++++++++++++-------- clang/test/PCH/pragma-diag-section.cpp | 21 ++++++++++++++++----- 3 files changed, 53 insertions(+), 19 deletions(-) diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 4ba0534..4857856 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -2512,11 +2512,6 @@ bool ASTReader::ReadASTBlock(ModuleFile &F) { } case DIAG_PRAGMA_MAPPINGS: - if (Record.size() % 2 != 0) { - Error("invalid DIAG_USER_MAPPINGS block in AST file"); - return true; - } - if (F.PragmaDiagMappings.empty()) F.PragmaDiagMappings.swap(Record); else @@ -4143,14 +4138,31 @@ HeaderFileInfo ASTReader::GetHeaderFileInfo(const FileEntry *FE) { } void ASTReader::ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag) { + // FIXME: Make it work properly with modules. + llvm::SmallVector DiagStates; for (ModuleIterator I = ModuleMgr.begin(), E = ModuleMgr.end(); I != E; ++I) { ModuleFile &F = *(*I); unsigned Idx = 0; + DiagStates.clear(); + assert(!Diag.DiagStates.empty()); + DiagStates.push_back(&Diag.DiagStates.front()); // the command-line one. while (Idx < F.PragmaDiagMappings.size()) { SourceLocation Loc = ReadSourceLocation(F, F.PragmaDiagMappings[Idx++]); + unsigned DiagStateID = F.PragmaDiagMappings[Idx++]; + if (DiagStateID != 0) { + Diag.DiagStatePoints.push_back( + DiagnosticsEngine::DiagStatePoint(DiagStates[DiagStateID-1], + FullSourceLoc(Loc, SourceMgr))); + continue; + } + + assert(DiagStateID == 0); + // A new DiagState was created here. Diag.DiagStates.push_back(*Diag.GetCurDiagState()); + DiagnosticsEngine::DiagState *NewState = &Diag.DiagStates.back(); + DiagStates.push_back(NewState); Diag.DiagStatePoints.push_back( - DiagnosticsEngine::DiagStatePoint(&Diag.DiagStates.back(), + DiagnosticsEngine::DiagStatePoint(NewState, FullSourceLoc(Loc, SourceMgr))); while (1) { assert(Idx < F.PragmaDiagMappings.size() && diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index ea10086..500351f 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -2272,24 +2272,35 @@ ASTWriter::inferSubmoduleIDFromLocation(SourceLocation Loc) { } void ASTWriter::WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag) { + // FIXME: Make it work properly with modules. + llvm::SmallDenseMap + DiagStateIDMap; + unsigned CurrID = 0; + DiagStateIDMap[&Diag.DiagStates.front()] = ++CurrID; // the command-line one. RecordData Record; for (DiagnosticsEngine::DiagStatePointsTy::const_iterator I = Diag.DiagStatePoints.begin(), E = Diag.DiagStatePoints.end(); I != E; ++I) { - const DiagnosticsEngine::DiagStatePoint &point = *I; + const DiagnosticsEngine::DiagStatePoint &point = *I; if (point.Loc.isInvalid()) continue; Record.push_back(point.Loc.getRawEncoding()); - for (DiagnosticsEngine::DiagState::const_iterator - I = point.State->begin(), E = point.State->end(); I != E; ++I) { - if (I->second.isPragma()) { - Record.push_back(I->first); - Record.push_back(I->second.getMapping()); + unsigned &DiagStateID = DiagStateIDMap[point.State]; + Record.push_back(DiagStateID); + + if (DiagStateID == 0) { + DiagStateID = ++CurrID; + for (DiagnosticsEngine::DiagState::const_iterator + I = point.State->begin(), E = point.State->end(); I != E; ++I) { + if (I->second.isPragma()) { + Record.push_back(I->first); + Record.push_back(I->second.getMapping()); + } } + Record.push_back(-1); // mark the end of the diag/map pairs for this + // location. } - Record.push_back(-1); // mark the end of the diag/map pairs for this - // location. } if (!Record.empty()) diff --git a/clang/test/PCH/pragma-diag-section.cpp b/clang/test/PCH/pragma-diag-section.cpp index 103b252..627156f 100644 --- a/clang/test/PCH/pragma-diag-section.cpp +++ b/clang/test/PCH/pragma-diag-section.cpp @@ -5,15 +5,13 @@ // RUN: %clang_cc1 %s -emit-pch -o %t // RUN: %clang_cc1 %s -include-pch %t -verify -fsyntax-only -// expected-no-diagnostics - #ifndef HEADER #define HEADER #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wtautological-compare" template -struct TS { +struct TS1 { void m() { T a = 0; T b = a==a; @@ -23,9 +21,22 @@ struct TS { #else + +template +struct TS2 { + void m() { + T a = 0; + T b = a==a; // expected-warning {{self-comparison always evaluates to true}} expected-note@39 {{in instantiation of member function}} + } +}; + void f() { - TS ts; - ts.m(); + TS1 ts1; + ts1.m(); + + + TS2 ts2; + ts2.m(); } #endif -- 2.7.4