Skip to content

Commit 8c66180

Browse files
Work around Stmt::getID assertion failure on long string literals. (#552)
Fixes #544.
1 parent e0fb426 commit 8c66180

File tree

4 files changed

+140
-1
lines changed

4 files changed

+140
-1
lines changed

clang/include/clang/3C/Utils.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,4 +223,9 @@ void getPrintfStringArgIndices(const clang::CallExpr *CE,
223223
const clang::ASTContext &Context,
224224
std::set<unsigned> &StringArgIndices);
225225

226+
// Use instead of Stmt::getID since Stmt::getID fails an assertion on long
227+
// string literals (https://bugs.llvm.org/show_bug.cgi?id=49926).
228+
int64_t getStmtIdWorkaround(const clang::Stmt *St,
229+
const clang::ASTContext &Context);
230+
226231
#endif

clang/lib/3C/ProgramInfo.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -812,7 +812,7 @@ ProgramInfo::getExprKey(Expr *E, ASTContext *C) const {
812812
// is compiled multiple times with different defines
813813
std::string Name = C->getSourceManager().getFileEntryForID(
814814
C->getSourceManager().getMainFileID())->getName().str();
815-
return std::make_pair(E->getID(*C), Name);
815+
return std::make_pair(getStmtIdWorkaround(E, *C), Name);
816816
}
817817

818818
bool ProgramInfo::hasPersistentConstraints(Expr *E, ASTContext *C) const {

clang/lib/3C/Utils.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,3 +563,29 @@ void getPrintfStringArgIndices(const CallExpr *CE, const FunctionDecl *Callee,
563563
Context.getTargetInfo(), false);
564564
}
565565
}
566+
567+
int64_t getStmtIdWorkaround(const Stmt *St, const ASTContext &Context) {
568+
// Stmt::getID uses Context.getAllocator().identifyKnownAlignedObject(St) to
569+
// derive a unique ID for St from its pointer in a way that should be
570+
// reproducible if the exact same source file is loaded in the exact same
571+
// environment, since if AST building is deterministic, the sequence of memory
572+
// allocations should be identical.
573+
// Context.getAllocator().identifyKnownObject(St) generates an ID that is
574+
// normally the offset of the Stmt object within the allocator's memory slabs,
575+
// so it is divisible by alignof(Stmt). identifyKnownAlignedObject wraps
576+
// identifyKnownObject to divide the ID by alignof(Stmt) (after asserting that
577+
// it is divisible), probably in an effort to produce smaller IDs to make some
578+
// data structures more efficient. However, if the Stmt is allocated in a
579+
// custom-size slab because it exceeds the default slab size of 4096, then
580+
// identifyKnownObject returns -1 minus the offset, which is _not_ divisible
581+
// by alignof(Stmt) because of the -1. Unfortunately,
582+
// identifyKnownAlignedObject doesn't account for this rare case, and its
583+
// assertion fails (https://bugs.llvm.org/show_bug.cgi?id=49926).
584+
//
585+
// Since 3C doesn't currently use the ID in a data structure that benefits
586+
// from smaller IDs, we may as well just use identifyKnownObject. If we wanted
587+
// smaller IDs, the solution would probably be to have
588+
// identifyKnownAlignedObject fix the alignment of negative IDs by subtracting
589+
// (alignof(Stmt) - 1) before dividing.
590+
return Context.getAllocator().identifyKnownObject(St);
591+
}

clang/test/3C/long_string_literal.c

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
// Test that 3C doesn't crash on long string literals
2+
// (https://github.com/correctcomputation/checkedc-clang/issues/544).
3+
4+
// We only care that this doesn't crash.
5+
// RUN: 3c -base-dir=%S %s --
6+
7+
// 100 lines * 50 characters, to make sure we exceed the default slab size of
8+
// 4096.
9+
char x[] = "01234567890123456789012345678901234567890123456789"
10+
"01234567890123456789012345678901234567890123456789"
11+
"01234567890123456789012345678901234567890123456789"
12+
"01234567890123456789012345678901234567890123456789"
13+
"01234567890123456789012345678901234567890123456789"
14+
"01234567890123456789012345678901234567890123456789"
15+
"01234567890123456789012345678901234567890123456789"
16+
"01234567890123456789012345678901234567890123456789"
17+
"01234567890123456789012345678901234567890123456789"
18+
"01234567890123456789012345678901234567890123456789"
19+
"01234567890123456789012345678901234567890123456789"
20+
"01234567890123456789012345678901234567890123456789"
21+
"01234567890123456789012345678901234567890123456789"
22+
"01234567890123456789012345678901234567890123456789"
23+
"01234567890123456789012345678901234567890123456789"
24+
"01234567890123456789012345678901234567890123456789"
25+
"01234567890123456789012345678901234567890123456789"
26+
"01234567890123456789012345678901234567890123456789"
27+
"01234567890123456789012345678901234567890123456789"
28+
"01234567890123456789012345678901234567890123456789"
29+
"01234567890123456789012345678901234567890123456789"
30+
"01234567890123456789012345678901234567890123456789"
31+
"01234567890123456789012345678901234567890123456789"
32+
"01234567890123456789012345678901234567890123456789"
33+
"01234567890123456789012345678901234567890123456789"
34+
"01234567890123456789012345678901234567890123456789"
35+
"01234567890123456789012345678901234567890123456789"
36+
"01234567890123456789012345678901234567890123456789"
37+
"01234567890123456789012345678901234567890123456789"
38+
"01234567890123456789012345678901234567890123456789"
39+
"01234567890123456789012345678901234567890123456789"
40+
"01234567890123456789012345678901234567890123456789"
41+
"01234567890123456789012345678901234567890123456789"
42+
"01234567890123456789012345678901234567890123456789"
43+
"01234567890123456789012345678901234567890123456789"
44+
"01234567890123456789012345678901234567890123456789"
45+
"01234567890123456789012345678901234567890123456789"
46+
"01234567890123456789012345678901234567890123456789"
47+
"01234567890123456789012345678901234567890123456789"
48+
"01234567890123456789012345678901234567890123456789"
49+
"01234567890123456789012345678901234567890123456789"
50+
"01234567890123456789012345678901234567890123456789"
51+
"01234567890123456789012345678901234567890123456789"
52+
"01234567890123456789012345678901234567890123456789"
53+
"01234567890123456789012345678901234567890123456789"
54+
"01234567890123456789012345678901234567890123456789"
55+
"01234567890123456789012345678901234567890123456789"
56+
"01234567890123456789012345678901234567890123456789"
57+
"01234567890123456789012345678901234567890123456789"
58+
"01234567890123456789012345678901234567890123456789"
59+
"01234567890123456789012345678901234567890123456789"
60+
"01234567890123456789012345678901234567890123456789"
61+
"01234567890123456789012345678901234567890123456789"
62+
"01234567890123456789012345678901234567890123456789"
63+
"01234567890123456789012345678901234567890123456789"
64+
"01234567890123456789012345678901234567890123456789"
65+
"01234567890123456789012345678901234567890123456789"
66+
"01234567890123456789012345678901234567890123456789"
67+
"01234567890123456789012345678901234567890123456789"
68+
"01234567890123456789012345678901234567890123456789"
69+
"01234567890123456789012345678901234567890123456789"
70+
"01234567890123456789012345678901234567890123456789"
71+
"01234567890123456789012345678901234567890123456789"
72+
"01234567890123456789012345678901234567890123456789"
73+
"01234567890123456789012345678901234567890123456789"
74+
"01234567890123456789012345678901234567890123456789"
75+
"01234567890123456789012345678901234567890123456789"
76+
"01234567890123456789012345678901234567890123456789"
77+
"01234567890123456789012345678901234567890123456789"
78+
"01234567890123456789012345678901234567890123456789"
79+
"01234567890123456789012345678901234567890123456789"
80+
"01234567890123456789012345678901234567890123456789"
81+
"01234567890123456789012345678901234567890123456789"
82+
"01234567890123456789012345678901234567890123456789"
83+
"01234567890123456789012345678901234567890123456789"
84+
"01234567890123456789012345678901234567890123456789"
85+
"01234567890123456789012345678901234567890123456789"
86+
"01234567890123456789012345678901234567890123456789"
87+
"01234567890123456789012345678901234567890123456789"
88+
"01234567890123456789012345678901234567890123456789"
89+
"01234567890123456789012345678901234567890123456789"
90+
"01234567890123456789012345678901234567890123456789"
91+
"01234567890123456789012345678901234567890123456789"
92+
"01234567890123456789012345678901234567890123456789"
93+
"01234567890123456789012345678901234567890123456789"
94+
"01234567890123456789012345678901234567890123456789"
95+
"01234567890123456789012345678901234567890123456789"
96+
"01234567890123456789012345678901234567890123456789"
97+
"01234567890123456789012345678901234567890123456789"
98+
"01234567890123456789012345678901234567890123456789"
99+
"01234567890123456789012345678901234567890123456789"
100+
"01234567890123456789012345678901234567890123456789"
101+
"01234567890123456789012345678901234567890123456789"
102+
"01234567890123456789012345678901234567890123456789"
103+
"01234567890123456789012345678901234567890123456789"
104+
"01234567890123456789012345678901234567890123456789"
105+
"01234567890123456789012345678901234567890123456789"
106+
"01234567890123456789012345678901234567890123456789"
107+
"01234567890123456789012345678901234567890123456789"
108+
"01234567890123456789012345678901234567890123456789";

0 commit comments

Comments
 (0)