Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
5722d2d
Target error message at assignments
dopelsunce Jul 29, 2020
021e928
Target subexpressions to blame on error messages for unknown inferred…
dopelsunce Aug 1, 2020
354a859
Update tests to reflect fine-grained error messages
dopelsunce Aug 1, 2020
2a82843
Update comments
dopelsunce Aug 3, 2020
af5f9c3
Remove unused variable
dopelsunce Aug 3, 2020
f6f3af5
* Also add (V, E) to BlameAssignments if E modifies the bounds of V
dopelsunce Aug 3, 2020
7296d8b
Update tests to reflect the missing case
dopelsunce Aug 3, 2020
70aa057
Restore whitespace
dopelsunce Aug 4, 2020
3abacfd
Restore whitespace
dopelsunce Aug 4, 2020
b22bd1a
Restore whitespace
dopelsunce Aug 4, 2020
29926f2
Restore whitespace
dopelsunce Aug 4, 2020
3317bce
Refactor and address the missing case; fix tests
dopelsunce Aug 5, 2020
ff01d32
Clarify the logic in BlameAssignmentWithinStmt
dopelsunce Aug 6, 2020
d321731
Reorder BoundsDeclarationCheck enum and update comments
dopelsunce Aug 10, 2020
6b84507
Gather proof failure cause and new error message
dopelsunce Aug 11, 2020
729e959
Update diagnostic messages
dopelsunce Aug 12, 2020
a22825d
Convert offset constant to count
Aug 12, 2020
edb3309
Simplify error messages
dopelsunce Aug 13, 2020
3df3205
New error message
dopelsunce Aug 13, 2020
62c2af8
Find free variables; use const modifier for some parameters
dopelsunce Aug 14, 2020
13ecbba
Clean up and small fix
dopelsunce Aug 17, 2020
5c5729f
Check equal variable
Aug 17, 2020
aba5112
Traverse ImplicitCastExpr instead of DeclRefExpr
dopelsunce Aug 17, 2020
84781f7
Revert changes
dopelsunce Aug 18, 2020
69c8870
Remove extra changes
dopelsunce Aug 18, 2020
a1e0ebb
Add wrapper for ProofBoundsDeclValidity
dopelsunce Aug 18, 2020
f5be4c2
Add comments
dopelsunce Aug 18, 2020
cfa45ef
More comments
Aug 18, 2020
07f9d30
Fix CollectVariableSet Helper
Aug 24, 2020
caf29d3
Exclude variables that equal to a constant from free variables; consi…
dopelsunce Aug 24, 2020
3960544
Code refactoring
dopelsunce Aug 25, 2020
cf5c27d
Detect free variables in bases and offsets separately
dopelsunce Aug 27, 2020
2476209
Consider member accesses and filter out indirect accesses
dopelsunce Aug 28, 2020
1362645
Merge branch master
dopelsunce Aug 28, 2020
7199da9
Handle expected argument bounds
dopelsunce Aug 30, 2020
65476a1
Fix tests
dopelsunce Aug 30, 2020
9682a24
Add comments
dopelsunce Aug 31, 2020
c425694
Reformatting and fixing constant checking
dopelsunce Sep 2, 2020
7a65d59
Update comments and reformat
Sep 2, 2020
97b4556
fix test
Sep 2, 2020
842cc89
Do not check free variables in static cast
dopelsunce Sep 4, 2020
389e118
No free variable detection for static pointer casts and other cleanup
dopelsunce Sep 5, 2020
7a0c884
Clean up
dopelsunce Sep 5, 2020
b20f1e4
Minor fix
dopelsunce Sep 5, 2020
6dba79a
Add expected errors where the compiler is able to create a base range…
kkjeer Sep 15, 2020
867cf58
Free variables: fix #909 and #911 by ignoring casts in EquivExprs (#919)
dopelsunce Oct 10, 2020
555a93c
Detect indirect relationships between variables (#940)
kkjeer Jan 14, 2021
7db553c
Add free-variables.c test to CheckedC/static-checking
Jan 21, 2021
c934e70
Update InRangeWithFreeVars comment
Jan 22, 2021
7352252
Update more InRangeWithFreeVars comments
Jan 22, 2021
d46fc90
Update EqualExprsContainsExpr comment
Jan 22, 2021
323e8ee
Add TODO for quadratic algorithm in CollectVariableSetHelper
Jan 22, 2021
ab80d34
Merge branch 'master' of https://github.com/Microsoft/checkedc-clang …
Jan 22, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -10172,6 +10172,23 @@ def err_bounds_type_annotation_lost_checking : Error<
"%select{assignment|decrement|increment|initialization|statement}0">,
InGroup<CheckBoundsDeclsChecked>;

def error_bounds_declaration_unprovable : Error<
"it is not possible to prove that the inferred bounds of %1 "
"imply the declared bounds of %1 after "
"%select{assignment|decrement|increment|initialization|statement}0">;

def note_free_variable_decl_or_inferred : Note<
"the %select{declared|inferred}0 %select{lower |upper |}1bounds use the "
"variable '%2' and there is no relational information involving '%2' "
"and any of the expressions used by the %select{inferred|declared}0 "
"%select{lower |upper |}1bounds">;

def note_free_variable_in_expected_args : Note<
"the %select{expected argument|inferred}0 %select{lower |upper |}1bounds use the "
"variable '%2' and there is no relational information involving '%2' "
"and any of the expressions used by the %select{inferred|expected argument}0 "
"%select{lower |upper |}1bounds">;

def error_bounds_declaration_invalid : Error<
"declared bounds for %1 are invalid after "
"%select{assignment|decrement|increment|initialization|statement}0">;
Expand Down Expand Up @@ -10203,6 +10220,9 @@ def err_bounds_type_annotation_lost_checking : Error<
"argument must be a non-modifying expression because %ordinal0 parameter "
"is used in a bounds expression">;

def error_argument_bounds_unprovable : Error<
"it is not possible to prove argument meets declared bounds for %ordinal0 parameter">;

def warn_argument_bounds_invalid : Warning<
"cannot prove argument meets declared bounds for %ordinal0 parameter">,
InGroup<CheckBoundsDeclsUnchecked>;
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/CanonBounds.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ Result Lexicographic::CompareExpr(const Expr *Arg1, const Expr *Arg2) {
#include "clang/AST/StmtNodes.inc"
llvm_unreachable("cannot compare a statement");
case Expr::PredefinedExprClass: Cmp = Compare<PredefinedExpr>(E1, E2); break;
case Expr::DeclRefExprClass: return Compare<DeclRefExpr>(E1, E2);
case Expr::DeclRefExprClass: Cmp = Compare<DeclRefExpr>(E1, E2); break;
case Expr::IntegerLiteralClass: return Compare<IntegerLiteral>(E1, E2);
case Expr::FloatingLiteralClass: return Compare<FloatingLiteral>(E1, E2);
case Expr::ImaginaryLiteralClass: break;
Expand Down
622 changes: 551 additions & 71 deletions clang/lib/Sema/SemaBounds.cpp

Large diffs are not rendered by default.

8 changes: 5 additions & 3 deletions clang/test/CheckedC/inferred-bounds/bounds-context.c
Original file line number Diff line number Diff line change
Expand Up @@ -616,9 +616,11 @@ void assign7(
// Observed bounds context before assignment: { a => bounds(a, a + 1), b => bounds(a, a + 1), c => bounds(a, a + 1) }
// Original value of a: b
// Observed bounds context after assignment: { a => bounds(b, b + 1), b => bounds(b, b + 1), c => bounds(b, b + 1) }
a = c; // expected-warning {{cannot prove declared bounds for 'a' are valid after assignment}} \
// expected-warning {{cannot prove declared bounds for 'b' are valid after assignment}} \
// expected-warning {{cannot prove declared bounds for 'c' are valid after assignment}} \
a = c; // expected-error {{it is not possible to prove that the inferred bounds of 'a' imply the declared bounds of 'a' after assignment}} \
// expected-error {{it is not possible to prove that the inferred bounds of 'b' imply the declared bounds of 'b' after assignment}} \
// expected-error {{it is not possible to prove that the inferred bounds of 'c' imply the declared bounds of 'c' after assignment}} \
// expected-note 3 {{the declared bounds use the variable 'a' and there is no relational information involving 'a' and any of the expressions used by the inferred bounds}} \
// expected-note 3 {{the inferred bounds use the variable 'b' and there is no relational information involving 'b' and any of the expressions used by the declared bounds}} \
// expected-note 3 {{(expanded) inferred bounds are 'bounds(b, b + 1)'}}
// CHECK: Statement S:
// CHECK-NEXT: BinaryOperator {{.*}} '='
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CheckedC/inferred-bounds/compound-literals.c
Original file line number Diff line number Diff line change
Expand Up @@ -140,4 +140,4 @@ void f2(_Array_ptr<struct S> arr : count(1), struct S s) {
// CHECK: |-UnaryOperator {{0x[0-9a-f]+}} '_Array_ptr<struct S>' prefix '&' cannot overflow
// CHECK: | `-BoundsValueExpr {{0x[0-9a-f]+}} 'struct S':'struct S' lvalue _BoundTemporary
// CHECK: `-IntegerLiteral {{0x[0-9a-f]+}} 'int' 1
}
}
11 changes: 5 additions & 6 deletions clang/test/CheckedC/inferred-bounds/member-reference.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@
//
// This line is for the clang test infrastructure:
// RUN: %clang_cc1 -fcheckedc-extension -fdump-inferred-bounds -verify -verify-ignore-unexpected=warning -verify-ignore-unexpected=note -fdump-inferred-bounds %s | FileCheck %s
// expected-no-diagnostics


struct S1 {
_Array_ptr<int> p : count(len);
int len;
Expand Down Expand Up @@ -101,7 +100,7 @@ void f1(struct S1 a1, struct S2 b2) {
int global_arr1[5];
void f2(struct S1 a3) {
// TODO: need bundled block.
a3.p = global_arr1;
a3.p = global_arr1; // expected-error {{it is not possible to prove that the inferred bounds of a3.p imply the declared bounds of a3.p after assignment}}
a3.len = 5;

// CHECK: BinaryOperator {{0x[0-9a-f]+}} '_Array_ptr<int>' '='
Expand Down Expand Up @@ -265,7 +264,7 @@ void f10(struct Interop_S1 a1, struct Interop_S2 b2,
_Checked void f11(struct Interop_S1 a1, struct Interop_S2 b2,
struct Interop_S4 c3) {
_Array_ptr<int> ap : count(a1.len) = a1.p;

// CHECK: VarDecl {{.*}} '_Array_ptr<int>' cinit
// CHECK: |-CountBoundsExpr {{0x[0-9a-f]+}} <col:24, col:36> 'NULL TYPE' Element
// CHECK: | `-ImplicitCastExpr {{0x[0-9a-f]+}} <col:30, col:33> 'int' <LValueToRValue>
Expand Down Expand Up @@ -348,7 +347,7 @@ int global_arr2 _Checked[5];

void f12(struct Interop_S1 a1) {
// TODO: need bundled block.
a1.p = global_arr2;
a1.p = global_arr2; // expected-error {{it is not possible to prove that the inferred bounds of a1.p imply the declared bounds of a1.p after assignment}}
a1.len = 5;
}

Expand Down Expand Up @@ -381,7 +380,7 @@ void f12(struct Interop_S1 a1) {

_Checked void f13(struct Interop_S1 a1) {
// TODO: need bundled block.
a1.p = global_arr2;
a1.p = global_arr2; // expected-error {{it is not possible to prove that the inferred bounds of a1.p imply the declared bounds of a1.p after assignment}}
a1.len = 5;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
// Tests for bounds widening of _Nt_array_ptr's using function to semantically
// compare two expressions.
//
// RUN: %clang_cc1 -fdump-widened-bounds -verify -verify-ignore-unexpected=note -verify-ignore-unexpected=warning %s 2>&1 | FileCheck %s

// expected-no-diagnostics
// RUN: %clang_cc1 -fdump-widened-bounds -verify -verify-ignore-unexpected=note -verify-ignore-unexpected=warning %s | FileCheck %s

void f1(int i) {
_Nt_array_ptr<char> p : bounds(p, p + i) = "a";
_Nt_array_ptr<char> p : bounds(p, p + i) = "a"; // expected-error {{it is not possible to prove that the inferred bounds of 'p' imply the declared bounds of 'p' after initialization}}

if (*(i + p)) {}

Expand All @@ -16,7 +14,7 @@ void f1(int i) {
}

void f2(int i, int j) {
_Nt_array_ptr<char> p : bounds(p, p + (i + j)) = "a";
_Nt_array_ptr<char> p : bounds(p, p + (i + j)) = "a"; // expected-error {{it is not possible to prove that the inferred bounds of 'p' imply the declared bounds of 'p' after initialization}}

if (*(p + (j + i))) {}

Expand All @@ -26,7 +24,7 @@ void f2(int i, int j) {
}

void f3(int i, int j) {
_Nt_array_ptr<char> p : bounds(p, p + (i * j)) = "a";
_Nt_array_ptr<char> p : bounds(p, p + (i * j)) = "a"; // expected-error {{it is not possible to prove that the inferred bounds of 'p' imply the declared bounds of 'p' after initialization}}

if (*(p + (j * i))) {}

Expand Down Expand Up @@ -66,7 +64,7 @@ void f6(int i, int j) {
}

void f7(int i, int j) {
_Nt_array_ptr<char> p : bounds(p, p + i * j) = "a";
_Nt_array_ptr<char> p : bounds(p, p + i * j) = "a"; // expected-error {{it is not possible to prove that the inferred bounds of 'p' imply the declared bounds of 'p' after initialization}}

if (*(p + i + j)) {}

Expand Down
14 changes: 7 additions & 7 deletions clang/test/CheckedC/inferred-bounds/widened-bounds.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ void f8() {
}

void f9(int i) {
_Nt_array_ptr<char> p : bounds(p, p + i) = "a";
_Nt_array_ptr<char> p : bounds(p, p + i) = "a"; // expected-error {{it is not possible to prove that the inferred bounds of 'p' imply the declared bounds of 'p' after initialization}}

if (*p)
if (*(p + i))
Expand Down Expand Up @@ -209,7 +209,7 @@ void f10(int i) {
}

void f11(int i, int j) {
_Nt_array_ptr<char> p : bounds(p + i, p + j) = "a";
_Nt_array_ptr<char> p : bounds(p + i, p + j) = "a"; // expected-error {{it is not possible to prove that the inferred bounds of 'p' imply the declared bounds of 'p' after initialization}}

if (*(p + j)) {
i = 0; // expected-error {{inferred bounds for 'p' are unknown after assignment}}
Expand Down Expand Up @@ -307,7 +307,7 @@ void f14(int i) {
}

void f15(int i) {
_Nt_array_ptr<char> p : bounds(p, p - i) = "a";
_Nt_array_ptr<char> p : bounds(p, p - i) = "a"; // expected-error {{it is not possible to prove that the inferred bounds of 'p' imply the declared bounds of 'p' after initialization}}
if (*(p - i)) {}

// CHECK: In function: f15
Expand Down Expand Up @@ -349,8 +349,8 @@ void f15(int i) {
}

void f16(_Nt_array_ptr<char> p : bounds(p, p)) {
_Nt_array_ptr<char> q : bounds(p, p) = "a";
_Nt_array_ptr<char> r : bounds(p, p + 1) = "a";
_Nt_array_ptr<char> q : bounds(p, p) = "a"; // expected-error {{it is not possible to prove that the inferred bounds of 'q' imply the declared bounds of 'q' after initialization}}
_Nt_array_ptr<char> r : bounds(p, p + 1) = "a"; // expected-error {{it is not possible to prove that the inferred bounds of 'r' imply the declared bounds of 'r' after initialization}}

if (*(p))
if (*(p + 1))
Expand All @@ -370,8 +370,8 @@ void f16(_Nt_array_ptr<char> p : bounds(p, p)) {
}

void f17(char p _Nt_checked[] : count(1)) {
_Nt_array_ptr<char> q : bounds(p, p + 1) = "a";
_Nt_array_ptr<char> r : bounds(p, p) = "a";
_Nt_array_ptr<char> q : bounds(p, p + 1) = "a"; // expected-error {{it is not possible to prove that the inferred bounds of 'q' imply the declared bounds of 'q' after initialization}}
_Nt_array_ptr<char> r : bounds(p, p) = "a"; // expected-error {{it is not possible to prove that the inferred bounds of 'r' imply the declared bounds of 'r' after initialization}}

if (*(p))
if (*(p + 1))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//
// These is a regression test case for
// These is a regression test case for
// https://github.com/Microsoft/checkedc-clang/issues/457
//
// This test checks that bounds declaration checking does not
Expand All @@ -20,9 +20,10 @@ static void myfunc2(_Array_ptr<int> data : count(len), int len) {

int main(void) {
int a _Checked[5];
myfunc1(a, 0); // expected-warning {{cannot prove argument meets declared bounds}} \
// expected-note {{expected argument bounds}} \
// expected-note {{inferred bounds}}
myfunc1(a, 0); // expected-error {{it is not possible to prove argument meets declared bounds for 1st parameter}} \
// expected-note {{the inferred bounds use the variable 'a' and there is no relational information involving 'a' and any of the expressions used by the expected argument bounds}} \
// expected-note {{(expanded) expected argument bounds are 'bounds((_Array_ptr<char>)0, (_Array_ptr<char>)0 + 5)'}} \
// expected-note {{(expanded) inferred bounds are 'bounds(a, a + 5)'}}
myfunc2(0, 0);
return 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ _Array_ptr<int> f11(unsigned num) {
}

_Array_ptr<int> f12(unsigned num1, unsigned num2){
_Array_ptr<int> p : count(num1) = test_f10(num2); // expected-warning {{cannot prove declared bounds for 'p' are valid after initialization}} \
_Array_ptr<int> p : count(num1) = test_f10(num2); // expected-error {{it is not possible to prove that the inferred bounds of 'p' imply the declared bounds of 'p' after initialization}} \
// expected-note {{the declared upper bounds use the variable 'num1' and there is no relational information involving 'num1' and any of the expressions used by the inferred upper bounds}} \
// expected-note {{the inferred upper bounds use the variable 'num2' and there is no relational information involving 'num2' and any of the expressions used by the declared upper bounds}} \
// expected-note {{(expanded) declared bounds are 'bounds(p, p + num1)'}} \
// expected-note {{(expanded) inferred bounds are 'bounds(value of test_f10(num2), value of test_f10(num2) + num2)'}}
return p;
Expand All @@ -64,7 +66,9 @@ _Array_ptr<int> f14(unsigned num) {
}

_Array_ptr<int> f15(unsigned num1, unsigned num2){
_Array_ptr<int> p : byte_count(num1) = test_f13(num2); // expected-warning {{cannot prove declared bounds for 'p' are valid after initialization}} \
_Array_ptr<int> p : byte_count(num1) = test_f13(num2); // expected-error {{it is not possible to prove that the inferred bounds of 'p' imply the declared bounds of 'p' after initialization}} \
// expected-note {{the declared upper bounds use the variable 'num1' and there is no relational information involving 'num1' and any of the expressions used by the inferred upper bounds}} \
// expected-note {{the inferred upper bounds use the variable 'num2' and there is no relational information involving 'num2' and any of the expressions used by the declared upper bounds}} \
// expected-note {{(expanded) declared bounds are 'bounds((_Array_ptr<char>)p, (_Array_ptr<char>)p + num1)'}} \
// expected-note {{inferred bounds are 'bounds((_Array_ptr<char>)value of test_f13(num2), (_Array_ptr<char>)value of test_f13(num2) + num2)'}}
return p;
Expand Down
Loading