Skip to content

Commit 324d1bb

Browse files
[Clang] Report an error and crash on source location exhaustion in macros (#69908)
`createExpansionLocImpl` has an assert that checks if we ran out of source locations. We have observed this happening on real code and in release builds the assertion does not fire and the compiler just keeps running indefinitely without giving any indication that something went wrong. Diagnose this problem and reliably crash to make sure the problem is easy to detect. I have also tried: - returning invalid source locations, - reporting sloc address space usage on error. Both caused the compiler to run indefinitely. It would be nice to dig further why that happens, but until then crashing seems like a better alternative.
1 parent 89eeb4f commit 324d1bb

File tree

3 files changed

+14
-9
lines changed

3 files changed

+14
-9
lines changed

clang/include/clang/Basic/DiagnosticCommonKinds.td

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -356,9 +356,8 @@ def err_file_modified : Error<
356356
"file '%0' modified since it was first processed">, DefaultFatal;
357357
def err_file_too_large : Error<
358358
"sorry, unsupported: file '%0' is too large for Clang to process">;
359-
def err_include_too_large : Error<
360-
"sorry, this include generates a translation unit too large for"
361-
" Clang to process.">, DefaultFatal;
359+
def err_sloc_space_too_large : Error<
360+
"sorry, the translation unit is too large for Clang to process: ran out of source locations">, DefaultFatal;
362361
def err_unsupported_bom : Error<"%0 byte order mark detected in '%1', but "
363362
"encoding is not supported">, DefaultFatal;
364363
def err_unable_to_rename_temp : Error<

clang/lib/Basic/SourceManager.cpp

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,7 @@ FileID SourceManager::createFileIDImpl(ContentCache &File, StringRef Filename,
605605
unsigned FileSize = File.getSize();
606606
if (!(NextLocalOffset + FileSize + 1 > NextLocalOffset &&
607607
NextLocalOffset + FileSize + 1 <= CurrentLoadedOffset)) {
608-
Diag.Report(IncludePos, diag::err_include_too_large);
608+
Diag.Report(IncludePos, diag::err_sloc_space_too_large);
609609
noteSLocAddressSpaceUsage(Diag);
610610
return FileID();
611611
}
@@ -663,10 +663,16 @@ SourceManager::createExpansionLocImpl(const ExpansionInfo &Info,
663663
return SourceLocation::getMacroLoc(LoadedOffset);
664664
}
665665
LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset, Info));
666-
// FIXME: Produce a proper diagnostic for this case.
667-
assert(NextLocalOffset + Length + 1 > NextLocalOffset &&
668-
NextLocalOffset + Length + 1 <= CurrentLoadedOffset &&
669-
"Ran out of source locations!");
666+
if (NextLocalOffset + Length + 1 <= NextLocalOffset ||
667+
NextLocalOffset + Length + 1 > CurrentLoadedOffset) {
668+
Diag.Report(SourceLocation(), diag::err_sloc_space_too_large);
669+
// FIXME: call `noteSLocAddressSpaceUsage` to report details to users and
670+
// use a source location from `Info` to point at an error.
671+
// Currently, both cause Clang to run indefinitely, this needs to be fixed.
672+
// FIXME: return an error instead of crashing. Returning invalid source
673+
// locations causes compiler to run indefinitely.
674+
llvm::report_fatal_error("ran out of source locations");
675+
}
670676
// See createFileID for that +1.
671677
NextLocalOffset += Length + 1;
672678
return SourceLocation::getMacroLoc(NextLocalOffset - (Length + 1));

clang/test/Lexer/SourceLocationsOverflow.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: not %clang %s -S -o - 2>&1 | FileCheck %s
22
// CHECK: In file included from {{.*}}SourceLocationsOverflow.c
3-
// CHECK-NEXT: inc1.h{{.*}}: fatal error: sorry, this include generates a translation unit too large for Clang to process.
3+
// CHECK-NEXT: inc1.h{{.*}}: fatal error: sorry, the translation unit is too large for Clang to process: ran out of source locations
44
// CHECK-NEXT: #include "inc2.h"
55
// CHECK-NEXT: ^
66
// CHECK-NEXT: note: 214{{.......}}B in local locations, 0B in locations loaded from AST files, for a total of 214{{.......}}B (99% of available space)

0 commit comments

Comments
 (0)