Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/clang/lib/Frontend/SerializedDiagnosticReader.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- SerializedDiagnosticReader.cpp - Reads diagnostics -----------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "clang/Frontend/SerializedDiagnosticReader.h"
10
#include "clang/Basic/FileManager.h"
11
#include "clang/Basic/FileSystemOptions.h"
12
#include "clang/Frontend/SerializedDiagnostics.h"
13
#include "llvm/ADT/Optional.h"
14
#include "llvm/ADT/SmallVector.h"
15
#include "llvm/ADT/StringRef.h"
16
#include "llvm/Bitstream/BitCodes.h"
17
#include "llvm/Bitstream/BitstreamReader.h"
18
#include "llvm/Support/Compiler.h"
19
#include "llvm/Support/ErrorHandling.h"
20
#include "llvm/Support/ErrorOr.h"
21
#include "llvm/Support/ManagedStatic.h"
22
#include <cstdint>
23
#include <system_error>
24
25
using namespace clang;
26
using namespace serialized_diags;
27
28
16
std::error_code SerializedDiagnosticReader::readDiagnostics(StringRef File) {
29
16
  // Open the diagnostics file.
30
16
  FileSystemOptions FO;
31
16
  FileManager FileMgr(FO);
32
16
33
16
  auto Buffer = FileMgr.getBufferForFile(File);
34
16
  if (!Buffer)
35
0
    return SDError::CouldNotLoad;
36
16
37
16
  llvm::BitstreamCursor Stream(**Buffer);
38
16
  Optional<llvm::BitstreamBlockInfo> BlockInfo;
39
16
40
16
  if (Stream.AtEndOfStream())
41
1
    return SDError::InvalidSignature;
42
15
43
15
  // Sniff for the signature.
44
60
  
for (unsigned char C : {'D', 'I', 'A', 'G'})15
{
45
60
    if (Expected<llvm::SimpleBitstreamCursor::word_t> Res = Stream.Read(8)) {
46
60
      if (Res.get() == C)
47
60
        continue;
48
0
    } else {
49
0
      // FIXME this drops the error on the floor.
50
0
      consumeError(Res.takeError());
51
0
    }
52
60
    
return SDError::InvalidSignature0
;
53
60
  }
54
15
55
15
  // Read the top level blocks.
56
84
  
while (15
!Stream.AtEndOfStream()) {
57
69
    if (Expected<unsigned> Res = Stream.ReadCode()) {
58
69
      if (Res.get() != llvm::bitc::ENTER_SUBBLOCK)
59
0
        return SDError::InvalidDiagnostics;
60
0
    } else {
61
0
      // FIXME this drops the error on the floor.
62
0
      consumeError(Res.takeError());
63
0
      return SDError::InvalidDiagnostics;
64
0
    }
65
69
66
69
    std::error_code EC;
67
69
    Expected<unsigned> MaybeSubBlockID = Stream.ReadSubBlockID();
68
69
    if (!MaybeSubBlockID) {
69
0
      // FIXME this drops the error on the floor.
70
0
      consumeError(MaybeSubBlockID.takeError());
71
0
      return SDError::InvalidDiagnostics;
72
0
    }
73
69
74
69
    switch (MaybeSubBlockID.get()) {
75
69
    case llvm::bitc::BLOCKINFO_BLOCK_ID: {
76
15
      Expected<Optional<llvm::BitstreamBlockInfo>> MaybeBlockInfo =
77
15
          Stream.ReadBlockInfoBlock();
78
15
      if (!MaybeBlockInfo) {
79
0
        // FIXME this drops the error on the floor.
80
0
        consumeError(MaybeBlockInfo.takeError());
81
0
        return SDError::InvalidDiagnostics;
82
0
      }
83
15
      BlockInfo = std::move(MaybeBlockInfo.get());
84
15
    }
85
15
      if (!BlockInfo)
86
0
        return SDError::MalformedBlockInfoBlock;
87
15
      Stream.setBlockInfo(&*BlockInfo);
88
15
      continue;
89
15
    case BLOCK_META:
90
15
      if ((EC = readMetaBlock(Stream)))
91
0
        return EC;
92
15
      continue;
93
39
    case BLOCK_DIAG:
94
39
      if ((EC = readDiagnosticBlock(Stream)))
95
0
        return EC;
96
39
      continue;
97
39
    default:
98
0
      if (llvm::Error Err = Stream.SkipBlock()) {
99
0
        // FIXME this drops the error on the floor.
100
0
        consumeError(std::move(Err));
101
0
        return SDError::MalformedTopLevelBlock;
102
0
      }
103
0
      continue;
104
69
    }
105
69
  }
106
15
  return {};
107
15
}
108
109
enum class SerializedDiagnosticReader::Cursor {
110
  Record = 1,
111
  BlockEnd,
112
  BlockBegin
113
};
114
115
llvm::ErrorOr<SerializedDiagnosticReader::Cursor>
116
SerializedDiagnosticReader::skipUntilRecordOrBlock(
117
328
    llvm::BitstreamCursor &Stream, unsigned &BlockOrRecordID) {
118
328
  BlockOrRecordID = 0;
119
328
120
328
  while (!Stream.AtEndOfStream()) {
121
328
    unsigned Code;
122
328
    if (Expected<unsigned> Res = Stream.ReadCode())
123
328
      Code = Res.get();
124
0
    else
125
0
      return llvm::errorToErrorCode(Res.takeError());
126
328
127
328
    if (Code >= static_cast<unsigned>(llvm::bitc::FIRST_APPLICATION_ABBREV)) {
128
206
      // We found a record.
129
206
      BlockOrRecordID = Code;
130
206
      return Cursor::Record;
131
206
    }
132
122
    switch (static_cast<llvm::bitc::FixedAbbrevIDs>(Code)) {
133
122
    case llvm::bitc::ENTER_SUBBLOCK:
134
34
      if (Expected<unsigned> Res = Stream.ReadSubBlockID())
135
34
        BlockOrRecordID = Res.get();
136
0
      else
137
0
        return llvm::errorToErrorCode(Res.takeError());
138
34
      return Cursor::BlockBegin;
139
34
140
88
    case llvm::bitc::END_BLOCK:
141
88
      if (Stream.ReadBlockEnd())
142
0
        return SDError::InvalidDiagnostics;
143
88
      return Cursor::BlockEnd;
144
88
145
88
    case llvm::bitc::DEFINE_ABBREV:
146
0
      if (llvm::Error Err = Stream.ReadAbbrevRecord())
147
0
        return llvm::errorToErrorCode(std::move(Err));
148
0
      continue;
149
0
150
0
    case llvm::bitc::UNABBREV_RECORD:
151
0
      return SDError::UnsupportedConstruct;
152
0
153
0
    case llvm::bitc::FIRST_APPLICATION_ABBREV:
154
0
      llvm_unreachable("Unexpected abbrev id.");
155
122
    }
156
122
  }
157
328
158
328
  
return SDError::InvalidDiagnostics0
;
159
328
}
160
161
std::error_code
162
15
SerializedDiagnosticReader::readMetaBlock(llvm::BitstreamCursor &Stream) {
163
15
  if (llvm::Error Err =
164
0
          Stream.EnterSubBlock(clang::serialized_diags::BLOCK_META)) {
165
0
    // FIXME this drops the error on the floor.
166
0
    consumeError(std::move(Err));
167
0
    return SDError::MalformedMetadataBlock;
168
0
  }
169
15
170
15
  bool VersionChecked = false;
171
15
172
30
  while (true) {
173
30
    unsigned BlockOrCode = 0;
174
30
    llvm::ErrorOr<Cursor> Res = skipUntilRecordOrBlock(Stream, BlockOrCode);
175
30
    if (!Res)
176
0
      Res.getError();
177
30
178
30
    switch (Res.get()) {
179
30
    case Cursor::Record:
180
15
      break;
181
30
    case Cursor::BlockBegin:
182
0
      if (llvm::Error Err = Stream.SkipBlock()) {
183
0
        // FIXME this drops the error on the floor.
184
0
        consumeError(std::move(Err));
185
0
        return SDError::MalformedMetadataBlock;
186
0
      }
187
0
      LLVM_FALLTHROUGH;
188
15
    case Cursor::BlockEnd:
189
15
      if (!VersionChecked)
190
0
        return SDError::MissingVersion;
191
15
      return {};
192
15
    }
193
15
194
15
    SmallVector<uint64_t, 1> Record;
195
15
    Expected<unsigned> MaybeRecordID = Stream.readRecord(BlockOrCode, Record);
196
15
    if (!MaybeRecordID)
197
0
      return errorToErrorCode(MaybeRecordID.takeError());
198
15
    unsigned RecordID = MaybeRecordID.get();
199
15
200
15
    if (RecordID == RECORD_VERSION) {
201
15
      if (Record.size() < 1)
202
0
        return SDError::MissingVersion;
203
15
      if (Record[0] > VersionNumber)
204
0
        return SDError::VersionMismatch;
205
15
      VersionChecked = true;
206
15
    }
207
15
  }
208
15
}
209
210
std::error_code
211
73
SerializedDiagnosticReader::readDiagnosticBlock(llvm::BitstreamCursor &Stream) {
212
73
  if (llvm::Error Err =
213
0
          Stream.EnterSubBlock(clang::serialized_diags::BLOCK_DIAG)) {
214
0
    // FIXME this drops the error on the floor.
215
0
    consumeError(std::move(Err));
216
0
    return SDError::MalformedDiagnosticBlock;
217
0
  }
218
73
219
73
  std::error_code EC;
220
73
  if ((EC = visitStartOfDiagnostic()))
221
0
    return EC;
222
73
223
73
  SmallVector<uint64_t, 16> Record;
224
298
  while (true) {
225
298
    unsigned BlockOrCode = 0;
226
298
    llvm::ErrorOr<Cursor> Res = skipUntilRecordOrBlock(Stream, BlockOrCode);
227
298
    if (!Res)
228
0
      Res.getError();
229
298
230
298
    switch (Res.get()) {
231
298
    case Cursor::BlockBegin:
232
34
      // The only blocks we care about are subdiagnostics.
233
34
      if (BlockOrCode == serialized_diags::BLOCK_DIAG) {
234
34
        if ((EC = readDiagnosticBlock(Stream)))
235
0
          return EC;
236
0
      } else if (llvm::Error Err = Stream.SkipBlock()) {
237
0
        // FIXME this drops the error on the floor.
238
0
        consumeError(std::move(Err));
239
0
        return SDError::MalformedSubBlock;
240
0
      }
241
34
      continue;
242
73
    case Cursor::BlockEnd:
243
73
      if ((EC = visitEndOfDiagnostic()))
244
0
        return EC;
245
73
      return {};
246
191
    case Cursor::Record:
247
191
      break;
248
191
    }
249
191
250
191
    // Read the record.
251
191
    Record.clear();
252
191
    StringRef Blob;
253
191
    Expected<unsigned> MaybeRecID =
254
191
        Stream.readRecord(BlockOrCode, Record, &Blob);
255
191
    if (!MaybeRecID)
256
0
      return errorToErrorCode(MaybeRecID.takeError());
257
191
    unsigned RecID = MaybeRecID.get();
258
191
259
191
    if (RecID < serialized_diags::RECORD_FIRST ||
260
191
        RecID > serialized_diags::RECORD_LAST)
261
0
      continue;
262
191
263
191
    switch ((RecordIDs)RecID) {
264
191
    case RECORD_CATEGORY:
265
28
      // A category has ID and name size.
266
28
      if (Record.size() != 2)
267
0
        return SDError::MalformedDiagnosticRecord;
268
28
      if ((EC = visitCategoryRecord(Record[0], Blob)))
269
0
        return EC;
270
28
      continue;
271
73
    case RECORD_DIAG:
272
73
      // A diagnostic has severity, location (4), category, flag, and message
273
73
      // size.
274
73
      if (Record.size() != 8)
275
0
        return SDError::MalformedDiagnosticRecord;
276
73
      if ((EC = visitDiagnosticRecord(
277
73
               Record[0], Location(Record[1], Record[2], Record[3], Record[4]),
278
73
               Record[5], Record[6], Blob)))
279
0
        return EC;
280
73
      continue;
281
73
    case RECORD_DIAG_FLAG:
282
16
      // A diagnostic flag has ID and name size.
283
16
      if (Record.size() != 2)
284
0
        return SDError::MalformedDiagnosticRecord;
285
16
      if ((EC = visitDiagFlagRecord(Record[0], Blob)))
286
0
        return EC;
287
16
      continue;
288
26
    case RECORD_FILENAME:
289
26
      // A filename has ID, size, timestamp, and name size. The size and
290
26
      // timestamp are legacy fields that are always zero these days.
291
26
      if (Record.size() != 4)
292
0
        return SDError::MalformedDiagnosticRecord;
293
26
      if ((EC = visitFilenameRecord(Record[0], Record[1], Record[2], Blob)))
294
0
        return EC;
295
26
      continue;
296
26
    case RECORD_FIXIT:
297
12
      // A fixit has two locations (4 each) and message size.
298
12
      if (Record.size() != 9)
299
0
        return SDError::MalformedDiagnosticRecord;
300
12
      if ((EC = visitFixitRecord(
301
12
               Location(Record[0], Record[1], Record[2], Record[3]),
302
12
               Location(Record[4], Record[5], Record[6], Record[7]), Blob)))
303
0
        return EC;
304
12
      continue;
305
36
    case RECORD_SOURCE_RANGE:
306
36
      // A source range is two locations (4 each).
307
36
      if (Record.size() != 8)
308
0
        return SDError::MalformedDiagnosticRecord;
309
36
      if ((EC = visitSourceRangeRecord(
310
36
               Location(Record[0], Record[1], Record[2], Record[3]),
311
36
               Location(Record[4], Record[5], Record[6], Record[7]))))
312
0
        return EC;
313
36
      continue;
314
36
    case RECORD_VERSION:
315
0
      // A version is just a number.
316
0
      if (Record.size() != 1)
317
0
        return SDError::MalformedDiagnosticRecord;
318
0
      if ((EC = visitVersionRecord(Record[0])))
319
0
        return EC;
320
0
      continue;
321
191
    }
322
191
  }
323
73
}
324
325
namespace {
326
327
class SDErrorCategoryType final : public std::error_category {
328
0
  const char *name() const noexcept override {
329
0
    return "clang.serialized_diags";
330
0
  }
331
332
1
  std::string message(int IE) const override {
333
1
    auto E = static_cast<SDError>(IE);
334
1
    switch (E) {
335
1
    case SDError::CouldNotLoad:
336
0
      return "Failed to open diagnostics file";
337
1
    case SDError::InvalidSignature:
338
1
      return "Invalid diagnostics signature";
339
1
    case SDError::InvalidDiagnostics:
340
0
      return "Parse error reading diagnostics";
341
1
    case SDError::MalformedTopLevelBlock:
342
0
      return "Malformed block at top-level of diagnostics";
343
1
    case SDError::MalformedSubBlock:
344
0
      return "Malformed sub-block in a diagnostic";
345
1
    case SDError::MalformedBlockInfoBlock:
346
0
      return "Malformed BlockInfo block";
347
1
    case SDError::MalformedMetadataBlock:
348
0
      return "Malformed Metadata block";
349
1
    case SDError::MalformedDiagnosticBlock:
350
0
      return "Malformed Diagnostic block";
351
1
    case SDError::MalformedDiagnosticRecord:
352
0
      return "Malformed Diagnostic record";
353
1
    case SDError::MissingVersion:
354
0
      return "No version provided in diagnostics";
355
1
    case SDError::VersionMismatch:
356
0
      return "Unsupported diagnostics version";
357
1
    case SDError::UnsupportedConstruct:
358
0
      return "Bitcode constructs that are not supported in diagnostics appear";
359
1
    case SDError::HandlerFailed:
360
0
      return "Generic error occurred while handling a record";
361
0
    }
362
0
    llvm_unreachable("Unknown error type!");
363
0
  }
364
};
365
366
} // namespace
367
368
static llvm::ManagedStatic<SDErrorCategoryType> ErrorCategory;
369
2
const std::error_category &clang::serialized_diags::SDErrorCategory() {
370
2
  return *ErrorCategory;
371
2
}