Coverage Report

Created: 2021-01-23 06:44

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/tools/clang-format/ClangFormat.cpp
Line
Count
Source (jump to first uncovered line)
1
//===-- clang-format/ClangFormat.cpp - Clang format tool ------------------===//
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
/// \file
10
/// This file implements a clang-format tool that automatically formats
11
/// (fragments of) C++ code.
12
///
13
//===----------------------------------------------------------------------===//
14
15
#include "clang/Basic/Diagnostic.h"
16
#include "clang/Basic/DiagnosticOptions.h"
17
#include "clang/Basic/FileManager.h"
18
#include "clang/Basic/SourceManager.h"
19
#include "clang/Basic/Version.h"
20
#include "clang/Format/Format.h"
21
#include "clang/Rewrite/Core/Rewriter.h"
22
#include "llvm/Support/CommandLine.h"
23
#include "llvm/Support/FileSystem.h"
24
#include "llvm/Support/InitLLVM.h"
25
#include "llvm/Support/Process.h"
26
27
using namespace llvm;
28
using clang::tooling::Replacements;
29
30
static cl::opt<bool> Help("h", cl::desc("Alias for -help"), cl::Hidden);
31
32
// Mark all our options with this category, everything else (except for -version
33
// and -help) will be hidden.
34
static cl::OptionCategory ClangFormatCategory("Clang-format options");
35
36
static cl::list<unsigned>
37
    Offsets("offset",
38
            cl::desc("Format a range starting at this byte offset.\n"
39
                     "Multiple ranges can be formatted by specifying\n"
40
                     "several -offset and -length pairs.\n"
41
                     "Can only be used with one input file."),
42
            cl::cat(ClangFormatCategory));
43
static cl::list<unsigned>
44
    Lengths("length",
45
            cl::desc("Format a range of this length (in bytes).\n"
46
                     "Multiple ranges can be formatted by specifying\n"
47
                     "several -offset and -length pairs.\n"
48
                     "When only a single -offset is specified without\n"
49
                     "-length, clang-format will format up to the end\n"
50
                     "of the file.\n"
51
                     "Can only be used with one input file."),
52
            cl::cat(ClangFormatCategory));
53
static cl::list<std::string>
54
    LineRanges("lines",
55
               cl::desc("<start line>:<end line> - format a range of\n"
56
                        "lines (both 1-based).\n"
57
                        "Multiple ranges can be formatted by specifying\n"
58
                        "several -lines arguments.\n"
59
                        "Can't be used with -offset and -length.\n"
60
                        "Can only be used with one input file."),
61
               cl::cat(ClangFormatCategory));
62
static cl::opt<std::string>
63
    Style("style", cl::desc(clang::format::StyleOptionHelpDescription),
64
          cl::init(clang::format::DefaultFormatStyle),
65
          cl::cat(ClangFormatCategory));
66
static cl::opt<std::string>
67
    FallbackStyle("fallback-style",
68
                  cl::desc("The name of the predefined style used as a\n"
69
                           "fallback in case clang-format is invoked with\n"
70
                           "-style=file, but can not find the .clang-format\n"
71
                           "file to use.\n"
72
                           "Use -fallback-style=none to skip formatting."),
73
                  cl::init(clang::format::DefaultFallbackStyle),
74
                  cl::cat(ClangFormatCategory));
75
76
static cl::opt<std::string> AssumeFileName(
77
    "assume-filename",
78
    cl::desc("Override filename used to determine the language.\n"
79
             "When reading from stdin, clang-format assumes this\n"
80
             "filename to determine the language."),
81
    cl::init("<stdin>"), cl::cat(ClangFormatCategory));
82
83
static cl::opt<bool> Inplace("i",
84
                             cl::desc("Inplace edit <file>s, if specified."),
85
                             cl::cat(ClangFormatCategory));
86
87
static cl::opt<bool> OutputXML("output-replacements-xml",
88
                               cl::desc("Output replacements as XML."),
89
                               cl::cat(ClangFormatCategory));
90
static cl::opt<bool>
91
    DumpConfig("dump-config",
92
               cl::desc("Dump configuration options to stdout and exit.\n"
93
                        "Can be used with -style option."),
94
               cl::cat(ClangFormatCategory));
95
static cl::opt<unsigned>
96
    Cursor("cursor",
97
           cl::desc("The position of the cursor when invoking\n"
98
                    "clang-format from an editor integration"),
99
           cl::init(0), cl::cat(ClangFormatCategory));
100
101
static cl::opt<bool> SortIncludes(
102
    "sort-includes",
103
    cl::desc("If set, overrides the include sorting behavior determined by the "
104
             "SortIncludes style flag"),
105
    cl::cat(ClangFormatCategory));
106
107
static cl::opt<bool>
108
    Verbose("verbose", cl::desc("If set, shows the list of processed files"),
109
            cl::cat(ClangFormatCategory));
110
111
// Use --dry-run to match other LLVM tools when you mean do it but don't
112
// actually do it
113
static cl::opt<bool>
114
    DryRun("dry-run",
115
           cl::desc("If set, do not actually make the formatting changes"),
116
           cl::cat(ClangFormatCategory));
117
118
// Use -n as a common command as an alias for --dry-run. (git and make use -n)
119
static cl::alias DryRunShort("n", cl::desc("Alias for --dry-run"),
120
                             cl::cat(ClangFormatCategory), cl::aliasopt(DryRun),
121
                             cl::NotHidden);
122
123
// Emulate being able to turn on/off the warning.
124
static cl::opt<bool>
125
    WarnFormat("Wclang-format-violations",
126
               cl::desc("Warnings about individual formatting changes needed. "
127
                        "Used only with --dry-run or -n"),
128
               cl::init(true), cl::cat(ClangFormatCategory), cl::Hidden);
129
130
static cl::opt<bool>
131
    NoWarnFormat("Wno-clang-format-violations",
132
                 cl::desc("Do not warn about individual formatting changes "
133
                          "needed. Used only with --dry-run or -n"),
134
                 cl::init(false), cl::cat(ClangFormatCategory), cl::Hidden);
135
136
static cl::opt<unsigned> ErrorLimit(
137
    "ferror-limit",
138
    cl::desc("Set the maximum number of clang-format errors to emit before "
139
             "stopping (0 = no limit). Used only with --dry-run or -n"),
140
    cl::init(0), cl::cat(ClangFormatCategory));
141
142
static cl::opt<bool>
143
    WarningsAsErrors("Werror",
144
                     cl::desc("If set, changes formatting warnings to errors"),
145
                     cl::cat(ClangFormatCategory));
146
147
namespace {
148
enum class WNoError { Unknown };
149
}
150
151
static cl::bits<WNoError> WNoErrorList(
152
    "Wno-error",
153
    cl::desc("If set don't error out on the specified warning type."),
154
    cl::values(
155
        clEnumValN(WNoError::Unknown, "unknown",
156
                   "If set, unknown format options are only warned about.\n"
157
                   "This can be used to enable formatting, even if the\n"
158
                   "configuration contains unknown (newer) options.\n"
159
                   "Use with caution, as this might lead to dramatically\n"
160
                   "differing format depending on an option being\n"
161
                   "supported or not.")),
162
    cl::cat(ClangFormatCategory));
163
164
static cl::opt<bool>
165
    ShowColors("fcolor-diagnostics",
166
               cl::desc("If set, and on a color-capable terminal controls "
167
                        "whether or not to print diagnostics in color"),
168
               cl::init(true), cl::cat(ClangFormatCategory), cl::Hidden);
169
170
static cl::opt<bool>
171
    NoShowColors("fno-color-diagnostics",
172
                 cl::desc("If set, and on a color-capable terminal controls "
173
                          "whether or not to print diagnostics in color"),
174
                 cl::init(false), cl::cat(ClangFormatCategory), cl::Hidden);
175
176
static cl::list<std::string> FileNames(cl::Positional, cl::desc("[<file> ...]"),
177
                                       cl::cat(ClangFormatCategory));
178
179
namespace clang {
180
namespace format {
181
182
static FileID createInMemoryFile(StringRef FileName, MemoryBufferRef Source,
183
                                 SourceManager &Sources, FileManager &Files,
184
73
                                 llvm::vfs::InMemoryFileSystem *MemFS) {
185
73
  MemFS->addFileNoOwn(FileName, 0, Source);
186
73
  auto File = Files.getOptionalFileRef(FileName);
187
73
  assert(File && "File not added to MemFS?");
188
73
  return Sources.createFileID(*File, SourceLocation(), SrcMgr::C_User);
189
73
}
190
191
// Parses <start line>:<end line> input to a pair of line numbers.
192
// Returns true on error.
193
static bool parseLineRange(StringRef Input, unsigned &FromLine,
194
4
                           unsigned &ToLine) {
195
4
  std::pair<StringRef, StringRef> LineRange = Input.split(':');
196
4
  return LineRange.first.getAsInteger(0, FromLine) ||
197
4
         LineRange.second.getAsInteger(0, ToLine);
198
4
}
199
200
static bool fillRanges(MemoryBuffer *Code,
201
40
                       std::vector<tooling::Range> &Ranges) {
202
40
  IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
203
40
      new llvm::vfs::InMemoryFileSystem);
204
40
  FileManager Files(FileSystemOptions(), InMemoryFileSystem);
205
40
  DiagnosticsEngine Diagnostics(
206
40
      IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
207
40
      new DiagnosticOptions);
208
40
  SourceManager Sources(Diagnostics, Files);
209
40
  FileID ID = createInMemoryFile("<irrelevant>", *Code, Sources, Files,
210
40
                                 InMemoryFileSystem.get());
211
40
  if (!LineRanges.empty()) {
212
3
    if (!Offsets.empty() || !Lengths.empty()) {
213
0
      errs() << "error: cannot use -lines with -offset/-length\n";
214
0
      return true;
215
0
    }
216
217
7
    
for (unsigned i = 0, e = LineRanges.size(); 3
i < e;
++i4
) {
218
4
      unsigned FromLine, ToLine;
219
4
      if (parseLineRange(LineRanges[i], FromLine, ToLine)) {
220
0
        errs() << "error: invalid <start line>:<end line> pair\n";
221
0
        return true;
222
0
      }
223
4
      if (FromLine > ToLine) {
224
0
        errs() << "error: start line should be less than end line\n";
225
0
        return true;
226
0
      }
227
4
      SourceLocation Start = Sources.translateLineCol(ID, FromLine, 1);
228
4
      SourceLocation End = Sources.translateLineCol(ID, ToLine, UINT_MAX);
229
4
      if (Start.isInvalid() || End.isInvalid())
230
0
        return true;
231
4
      unsigned Offset = Sources.getFileOffset(Start);
232
4
      unsigned Length = Sources.getFileOffset(End) - Offset;
233
4
      Ranges.push_back(tooling::Range(Offset, Length));
234
4
    }
235
3
    return false;
236
37
  }
237
238
37
  if (Offsets.empty())
239
34
    Offsets.push_back(0);
240
37
  if (Offsets.size() != Lengths.size() &&
241
36
      !(Offsets.size() == 1 && Lengths.empty())) {
242
0
    errs() << "error: number of -offset and -length arguments must match.\n";
243
0
    return true;
244
0
  }
245
75
  
for (unsigned i = 0, e = Offsets.size(); 37
i != e;
++i38
) {
246
38
    if (Offsets[i] >= Code->getBufferSize()) {
247
0
      errs() << "error: offset " << Offsets[i] << " is outside the file\n";
248
0
      return true;
249
0
    }
250
38
    SourceLocation Start =
251
38
        Sources.getLocForStartOfFile(ID).getLocWithOffset(Offsets[i]);
252
38
    SourceLocation End;
253
38
    if (i < Lengths.size()) {
254
2
      if (Offsets[i] + Lengths[i] > Code->getBufferSize()) {
255
0
        errs() << "error: invalid length " << Lengths[i]
256
0
               << ", offset + length (" << Offsets[i] + Lengths[i]
257
0
               << ") is outside the file.\n";
258
0
        return true;
259
0
      }
260
2
      End = Start.getLocWithOffset(Lengths[i]);
261
36
    } else {
262
36
      End = Sources.getLocForEndOfFile(ID);
263
36
    }
264
38
    unsigned Offset = Sources.getFileOffset(Start);
265
38
    unsigned Length = Sources.getFileOffset(End) - Offset;
266
38
    Ranges.push_back(tooling::Range(Offset, Length));
267
38
  }
268
37
  return false;
269
37
}
270
271
3
static void outputReplacementXML(StringRef Text) {
272
  // FIXME: When we sort includes, we need to make sure the stream is correct
273
  // utf-8.
274
3
  size_t From = 0;
275
3
  size_t Index;
276
7
  while ((Index = Text.find_first_of("\n\r<&", From)) != StringRef::npos) {
277
4
    outs() << Text.substr(From, Index - From);
278
4
    switch (Text[Index]) {
279
2
    case '\n':
280
2
      outs() << "&#10;";
281
2
      break;
282
0
    case '\r':
283
0
      outs() << "&#13;";
284
0
      break;
285
2
    case '<':
286
2
      outs() << "&lt;";
287
2
      break;
288
0
    case '&':
289
0
      outs() << "&amp;";
290
0
      break;
291
0
    default:
292
0
      llvm_unreachable("Unexpected character encountered!");
293
4
    }
294
4
    From = Index + 1;
295
4
  }
296
3
  outs() << Text.substr(From);
297
3
}
298
299
1
static void outputReplacementsXML(const Replacements &Replaces) {
300
3
  for (const auto &R : Replaces) {
301
3
    outs() << "<replacement "
302
3
           << "offset='" << R.getOffset() << "' "
303
3
           << "length='" << R.getLength() << "'>";
304
3
    outputReplacementXML(R.getReplacementText());
305
3
    outs() << "</replacement>\n";
306
3
  }
307
1
}
308
309
static bool
310
emitReplacementWarnings(const Replacements &Replaces, StringRef AssumedFileName,
311
2
                        const std::unique_ptr<llvm::MemoryBuffer> &Code) {
312
2
  if (Replaces.empty())
313
0
    return false;
314
315
2
  unsigned Errors = 0;
316
2
  if (WarnFormat && !NoWarnFormat) {
317
2
    llvm::SourceMgr Mgr;
318
2
    const char *StartBuf = Code->getBufferStart();
319
320
2
    Mgr.AddNewSourceBuffer(
321
2
        MemoryBuffer::getMemBuffer(StartBuf, AssumedFileName), SMLoc());
322
2
    for (const auto &R : Replaces) {
323
2
      SMDiagnostic Diag = Mgr.GetMessage(
324
2
          SMLoc::getFromPointer(StartBuf + R.getOffset()),
325
0
          WarningsAsErrors ? SourceMgr::DiagKind::DK_Error
326
2
                           : SourceMgr::DiagKind::DK_Warning,
327
2
          "code should be clang-formatted [-Wclang-format-violations]");
328
329
2
      Diag.print(nullptr, llvm::errs(), (ShowColors && !NoShowColors));
330
2
      if (ErrorLimit && 
++Errors >= ErrorLimit0
)
331
0
        break;
332
2
    }
333
2
  }
334
2
  return WarningsAsErrors;
335
2
}
336
337
static void outputXML(const Replacements &Replaces,
338
                      const Replacements &FormatChanges,
339
                      const FormattingAttemptStatus &Status,
340
                      const cl::opt<unsigned> &Cursor,
341
1
                      unsigned CursorPosition) {
342
1
  outs() << "<?xml version='1.0'?>\n<replacements "
343
1
            "xml:space='preserve' incomplete_format='"
344
1
         << (Status.FormatComplete ? "false" : 
"true"0
) << "'";
345
1
  if (!Status.FormatComplete)
346
0
    outs() << " line='" << Status.Line << "'";
347
1
  outs() << ">\n";
348
1
  if (Cursor.getNumOccurrences() != 0)
349
0
    outs() << "<cursor>" << FormatChanges.getShiftedCodePosition(CursorPosition)
350
0
           << "</cursor>\n";
351
352
1
  outputReplacementsXML(Replaces);
353
1
  outs() << "</replacements>\n";
354
1
}
355
356
// Returns true on error.
357
40
static bool format(StringRef FileName) {
358
40
  if (!OutputXML && 
Inplace39
&&
FileName == "-"5
) {
359
0
    errs() << "error: cannot use -i when reading from stdin.\n";
360
0
    return false;
361
0
  }
362
  // On Windows, overwriting a file with an open file mapping doesn't work,
363
  // so read the whole file into memory when formatting in-place.
364
40
  ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
365
40
      !OutputXML && 
Inplace39
?
MemoryBuffer::getFileAsStream(FileName)5
366
35
                            : MemoryBuffer::getFileOrSTDIN(FileName);
367
40
  if (std::error_code EC = CodeOrErr.getError()) {
368
0
    errs() << EC.message() << "\n";
369
0
    return true;
370
0
  }
371
40
  std::unique_ptr<llvm::MemoryBuffer> Code = std::move(CodeOrErr.get());
372
40
  if (Code->getBufferSize() == 0)
373
0
    return false; // Empty files are formatted correctly.
374
375
40
  StringRef BufStr = Code->getBuffer();
376
377
40
  const char *InvalidBOM = SrcMgr::ContentCache::getInvalidBOM(BufStr);
378
379
40
  if (InvalidBOM) {
380
0
    errs() << "error: encoding with unsupported byte order mark \""
381
0
           << InvalidBOM << "\" detected";
382
0
    if (FileName != "-")
383
0
      errs() << " in file '" << FileName << "'";
384
0
    errs() << ".\n";
385
0
    return true;
386
0
  }
387
388
40
  std::vector<tooling::Range> Ranges;
389
40
  if (fillRanges(Code.get(), Ranges))
390
0
    return true;
391
40
  StringRef AssumedFileName = (FileName == "-") ? 
AssumeFileName14
:
FileName26
;
392
40
  if (AssumedFileName.empty()) {
393
0
    llvm::errs() << "error: empty filenames are not allowed\n";
394
0
    return true;
395
0
  }
396
397
40
  llvm::Expected<FormatStyle> FormatStyle =
398
40
      getStyle(Style, AssumedFileName, FallbackStyle, Code->getBuffer(),
399
40
               nullptr, WNoErrorList.isSet(WNoError::Unknown));
400
40
  if (!FormatStyle) {
401
4
    llvm::errs() << llvm::toString(FormatStyle.takeError()) << "\n";
402
4
    return true;
403
4
  }
404
405
36
  if (SortIncludes.getNumOccurrences() != 0)
406
3
    FormatStyle->SortIncludes = SortIncludes;
407
36
  unsigned CursorPosition = Cursor;
408
36
  Replacements Replaces = sortIncludes(*FormatStyle, Code->getBuffer(), Ranges,
409
36
                                       AssumedFileName, &CursorPosition);
410
36
  auto ChangedCode = tooling::applyAllReplacements(Code->getBuffer(), Replaces);
411
36
  if (!ChangedCode) {
412
0
    llvm::errs() << llvm::toString(ChangedCode.takeError()) << "\n";
413
0
    return true;
414
0
  }
415
  // Get new affected ranges after sorting `#includes`.
416
36
  Ranges = tooling::calculateRangesAfterReplacements(Replaces, Ranges);
417
36
  FormattingAttemptStatus Status;
418
36
  Replacements FormatChanges =
419
36
      reformat(*FormatStyle, *ChangedCode, Ranges, AssumedFileName, &Status);
420
36
  Replaces = Replaces.merge(FormatChanges);
421
36
  if (OutputXML || 
DryRun35
) {
422
3
    if (DryRun) {
423
2
      return emitReplacementWarnings(Replaces, AssumedFileName, Code);
424
1
    } else {
425
1
      outputXML(Replaces, FormatChanges, Status, Cursor, CursorPosition);
426
1
    }
427
33
  } else {
428
33
    IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
429
33
        new llvm::vfs::InMemoryFileSystem);
430
33
    FileManager Files(FileSystemOptions(), InMemoryFileSystem);
431
33
    DiagnosticsEngine Diagnostics(
432
33
        IntrusiveRefCntPtr<DiagnosticIDs>(new DiagnosticIDs),
433
33
        new DiagnosticOptions);
434
33
    SourceManager Sources(Diagnostics, Files);
435
33
    FileID ID = createInMemoryFile(AssumedFileName, *Code, Sources, Files,
436
33
                                   InMemoryFileSystem.get());
437
33
    Rewriter Rewrite(Sources, LangOptions());
438
33
    tooling::applyAllReplacements(Replaces, Rewrite);
439
33
    if (Inplace) {
440
3
      if (Rewrite.overwriteChangedFiles())
441
0
        return true;
442
30
    } else {
443
30
      if (Cursor.getNumOccurrences() != 0) {
444
2
        outs() << "{ \"Cursor\": "
445
2
               << FormatChanges.getShiftedCodePosition(CursorPosition)
446
2
               << ", \"IncompleteFormat\": "
447
1
               << (Status.FormatComplete ? "false" : "true");
448
2
        if (!Status.FormatComplete)
449
1
          outs() << ", \"Line\": " << Status.Line;
450
2
        outs() << " }\n";
451
2
      }
452
30
      Rewrite.getEditBuffer(ID).write(outs());
453
30
    }
454
33
  }
455
34
  return false;
456
36
}
457
458
} // namespace format
459
} // namespace clang
460
461
0
static void PrintVersion(raw_ostream &OS) {
462
0
  OS << clang::getClangToolFullVersion("clang-format") << '\n';
463
0
}
464
465
// Dump the configuration.
466
5
static int dumpConfig() {
467
5
  StringRef FileName;
468
5
  std::unique_ptr<llvm::MemoryBuffer> Code;
469
5
  if (FileNames.empty()) {
470
    // We can't read the code to detect the language if there's no
471
    // file name, so leave Code empty here.
472
0
    FileName = AssumeFileName;
473
5
  } else {
474
    // Read in the code in case the filename alone isn't enough to
475
    // detect the language.
476
5
    ErrorOr<std::unique_ptr<MemoryBuffer>> CodeOrErr =
477
5
        MemoryBuffer::getFileOrSTDIN(FileNames[0]);
478
5
    if (std::error_code EC = CodeOrErr.getError()) {
479
0
      llvm::errs() << EC.message() << "\n";
480
0
      return 1;
481
0
    }
482
5
    FileName = (FileNames[0] == "-") ? 
AssumeFileName0
: FileNames[0];
483
5
    Code = std::move(CodeOrErr.get());
484
5
  }
485
5
  llvm::Expected<clang::format::FormatStyle> FormatStyle =
486
5
      clang::format::getStyle(Style, FileName, FallbackStyle,
487
5
                              Code ? Code->getBuffer() : 
""0
);
488
5
  if (!FormatStyle) {
489
0
    llvm::errs() << llvm::toString(FormatStyle.takeError()) << "\n";
490
0
    return 1;
491
0
  }
492
5
  std::string Config = clang::format::configurationAsText(*FormatStyle);
493
5
  outs() << Config << "\n";
494
5
  return 0;
495
5
}
496
497
45
int main(int argc, const char **argv) {
498
45
  llvm::InitLLVM X(argc, argv);
499
500
45
  cl::HideUnrelatedOptions(ClangFormatCategory);
501
502
45
  cl::SetVersionPrinter(PrintVersion);
503
45
  cl::ParseCommandLineOptions(
504
45
      argc, argv,
505
45
      "A tool to format C/C++/Java/JavaScript/Objective-C/Protobuf/C# code.\n\n"
506
45
      "If no arguments are specified, it formats the code from standard input\n"
507
45
      "and writes the result to the standard output.\n"
508
45
      "If <file>s are given, it reformats the files. If -i is specified\n"
509
45
      "together with <file>s, the files are edited in-place. Otherwise, the\n"
510
45
      "result is written to the standard output.\n");
511
512
45
  if (Help) {
513
0
    cl::PrintHelpMessage();
514
0
    return 0;
515
0
  }
516
517
45
  if (DumpConfig) {
518
5
    return dumpConfig();
519
5
  }
520
521
40
  bool Error = false;
522
40
  if (FileNames.empty()) {
523
14
    Error = clang::format::format("-");
524
13
    return Error ? 
11
: 0;
525
14
  }
526
26
  if (FileNames.size() != 1 &&
527
4
      (!Offsets.empty() || 
!Lengths.empty()3
||
!LineRanges.empty()3
)) {
528
2
    errs() << "error: -offset, -length and -lines can only be used for "
529
2
              "single file.\n";
530
2
    return 1;
531
2
  }
532
26
  
for (const auto &FileName : FileNames)24
{
533
26
    if (Verbose)
534
2
      errs() << "Formatting " << FileName << "\n";
535
26
    Error |= clang::format::format(FileName);
536
26
  }
537
21
  return Error ? 
13
: 0;
538
24
}