Skip to content

Commit 07c5311

Browse files
Generate itype string from AST when extracting from source fails (#693)
Fixes an assertion failure (#594) when attempting to extract the string representation of an itype expression from the original source code if the itype expression is inside a macro. The string representation for itypes in macros is now re-generated from the AST. The fix in its current form leads to some unnecessary expansion of macros. This is discussed in #694.
1 parent fd4d8af commit 07c5311

File tree

3 files changed

+47
-7
lines changed

3 files changed

+47
-7
lines changed

clang/lib/3C/ConstraintVariables.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,16 @@ PointerVariableConstraint::PointerVariableConstraint(
280280
SourceRange R = ITE->getSourceRange();
281281
if (R.isValid()) {
282282
ItypeStr = getSourceText(R, C);
283-
assert(ItypeStr.size() > 0);
283+
}
284+
285+
// ITE->isCompilerGenerated will be true when an itype expression is
286+
// implied by a bounds expression on the declaration. When the itype
287+
// expression is not generated by the compiler, but we failed to extract
288+
// its string representation from the source, build the itype string
289+
// from the AST.
290+
if (!ITE->isCompilerGenerated() && ItypeStr.empty()) {
291+
assert(!InteropType.getAsString().empty());
292+
ItypeStr = "itype(" + InteropType.getAsString() + ")";
284293
}
285294
}
286295
}

clang/test/3C/macro_itype.c

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// RUN: rm -rf %t*
2+
// RUN: 3c -base-dir=%S -alltypes -addcr %s -- | FileCheck -match-full-lines -check-prefixes="CHECK_ALL","CHECK" %s
3+
// RUN: 3c -base-dir=%S -addcr %s -- | FileCheck -match-full-lines -check-prefixes="CHECK_NOALL","CHECK" %s
4+
// RUN: 3c -base-dir=%S -alltypes -addcr %s -- | %clang -c -fcheckedc-extension -x c -o /dev/null -
5+
// RUN: 3c -base-dir=%S -alltypes -output-dir=%t.checked %s --
6+
// RUN: 3c -base-dir=%t.checked -alltypes %t.checked/macro_itype.c -- | diff %t.checked/macro_itype.c -
7+
8+
// Example encountered while converting libjpeg. This triggered an assertion
9+
// fail because the ItypeStr extracted from the source was empty.
10+
#define macro0 int *a : itype(_Ptr<int>);
11+
struct s { macro0 };
12+
//CHECK: struct s { macro0 };
13+
14+
// Example from issue correctcomputation/checkedc-clang#594.
15+
#define PARAM_DECL_WITH_ITYPE int *p : itype(_Ptr<int>)
16+
void foo(PARAM_DECL_WITH_ITYPE);
17+
//CHECK: void foo(PARAM_DECL_WITH_ITYPE);
18+
19+
// Just removing the assertion that failed on the above example caused this to
20+
// rewrite incorrectly. The ItypeStr would be left empty, so first parameter
21+
// would be rewritten to `int *b` even though the rewriter intended to give it
22+
// an itype. If the parameter was then passed a checked pointer, there would be
23+
// a Checked C compiler error. Ideally, 3C wouldn't need to change the
24+
// declaration of `b` at all (see issue correctcomputation/checkedc-clang#694).
25+
#define macro1 : itype(_Ptr<int>)
26+
void fn(int *b macro1, int *c) {
27+
//CHECK: void fn(int *b : itype(_Ptr<int>), _Ptr<int> c) {
28+
b = 1;
29+
}
30+
void caller() {
31+
int *e;
32+
//CHECK: _Ptr<int> e = ((void *)0);
33+
fn(e, 0);
34+
}

clang/test/3C/params_in_macro.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,11 @@
1111

1212
typedef double mydouble;
1313

14-
// TODO: FunctionDeclBuilder::buildDeclVar should be able to handle an itype
15-
// here, but currently the PointerConstraintVariable constructor asserts when it
16-
// fails to retrieve the original source of the itype declaration.
1714
#define parms1 volatile mydouble d, void (*f)(void)
18-
#define parms2 int *const y : count(7), _Ptr<char> z
15+
#define parms2 int *const y : count(7), _Ptr<char> z, int *zz : itype(_Ptr<int>)
1916

2017
void test(parms1, int *x, parms2) {}
21-
// CHECK: void test(volatile mydouble d, void (*f)(void), _Ptr<int> x, int *const y : count(7), _Ptr<char> z) {}
18+
// CHECK: void test(volatile mydouble d, void (*f)(void), _Ptr<int> x, int *const y : count(7), _Ptr<char> z, int *zz : itype(_Ptr<int>)) {}
2219

2320
// Before the bug fix, we got:
24-
// void test(, , _Ptr<int> x, , ) {}
21+
// void test(, , _Ptr<int> x, , , ) {}

0 commit comments

Comments
 (0)