Skip to content

Commit f34c187

Browse files
committed
Create a separate checking function.
1 parent 90cdf04 commit f34c187

File tree

7 files changed

+70
-51
lines changed

7 files changed

+70
-51
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6670,14 +6670,15 @@ def warn_counted_by_attr_elt_type_unknown_size :
66706670
// __builtin_counted_by_ref diagnostics:
66716671
def err_builtin_counted_by_ref_must_be_flex_array_member : Error<
66726672
"'__builtin_counted_by_ref' argument must reference a flexible array member">;
6673+
def err_builtin_counted_by_ref_has_side_effects : Error<
6674+
"'__builtin_counted_by_ref' argument cannot have side-effects">;
6675+
66736676
def err_builtin_counted_by_ref_cannot_leak_reference : Error<
6674-
"value returned by '__builtin_counted_by_ref' cannot be assigned to a "
6675-
"variable, have its address taken, or passed into or returned from a function">;
6677+
"value returned by '__builtin_counted_by_ref' cannot be %select{assigned to a "
6678+
"variable|passed into a function|returned from a function}0">;
66766679
def err_builtin_counted_by_ref_invalid_use : Error<
66776680
"value returned by '__builtin_counted_by_ref' cannot be used in "
66786681
"%select{an array subscript|a binary}0 expression">;
6679-
def err_builtin_counted_by_ref_has_side_effects : Error<
6680-
"'__builtin_counted_by_ref' argument cannot have side-effects">;
66816682

66826683
let CategoryName = "ARC Semantic Issue" in {
66836684

clang/include/clang/Sema/Sema.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2518,11 +2518,17 @@ class Sema final : public SemaBase {
25182518

25192519
bool BuiltinNonDeterministicValue(CallExpr *TheCall);
25202520

2521-
bool IsBuiltinCountedByRef(const Expr *E) const {
2522-
const CallExpr *CE =
2523-
E ? dyn_cast<CallExpr>(E->IgnoreParenImpCasts()) : nullptr;
2524-
return CE && CE->getBuiltinCallee() == Builtin::BI__builtin_counted_by_ref;
2525-
}
2521+
enum BuiltinCountedByRefKind {
2522+
AssignmentKind,
2523+
InitializerKind,
2524+
FunctionArgKind,
2525+
ReturnArgKind,
2526+
ArraySubscriptKind,
2527+
BinaryExprKind,
2528+
};
2529+
2530+
bool CheckInvalidBuiltinCountedByRef(const Expr *E,
2531+
BuiltinCountedByRefKind K);
25262532
bool BuiltinCountedByRef(CallExpr *TheCall);
25272533

25282534
// Matrix builtin handling.

clang/lib/Sema/SemaChecking.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5621,6 +5621,45 @@ bool Sema::BuiltinCountedByRef(CallExpr *TheCall) {
56215621
return false;
56225622
}
56235623

5624+
/// The result of __builtin_counted_by_ref cannot be assigned to a variable.
5625+
/// It allows leaking and modification of bounds safety information.
5626+
bool Sema::CheckInvalidBuiltinCountedByRef(const Expr *E,
5627+
BuiltinCountedByRefKind K) {
5628+
const CallExpr *CE =
5629+
E ? dyn_cast<CallExpr>(E->IgnoreParenImpCasts()) : nullptr;
5630+
if (!CE || CE->getBuiltinCallee() != Builtin::BI__builtin_counted_by_ref)
5631+
return false;
5632+
5633+
switch (K) {
5634+
case AssignmentKind:
5635+
case InitializerKind:
5636+
Diag(E->getExprLoc(),
5637+
diag::err_builtin_counted_by_ref_cannot_leak_reference)
5638+
<< 0 << E->getSourceRange();
5639+
break;
5640+
case FunctionArgKind:
5641+
Diag(E->getExprLoc(),
5642+
diag::err_builtin_counted_by_ref_cannot_leak_reference)
5643+
<< 1 << E->getSourceRange();
5644+
break;
5645+
case ReturnArgKind:
5646+
Diag(E->getExprLoc(),
5647+
diag::err_builtin_counted_by_ref_cannot_leak_reference)
5648+
<< 2 << E->getSourceRange();
5649+
break;
5650+
case ArraySubscriptKind:
5651+
Diag(E->getExprLoc(), diag::err_builtin_counted_by_ref_invalid_use)
5652+
<< 0 << E->getSourceRange();
5653+
break;
5654+
case BinaryExprKind:
5655+
Diag(E->getExprLoc(), diag::err_builtin_counted_by_ref_invalid_use)
5656+
<< 1 << E->getSourceRange();
5657+
break;
5658+
}
5659+
5660+
return true;
5661+
}
5662+
56245663
namespace {
56255664

56265665
class UncoveredArgHandler {

clang/lib/Sema/SemaDecl.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14690,12 +14690,7 @@ void Sema::FinalizeDeclaration(Decl *ThisDecl) {
1469014690
}
1469114691
}
1469214692

14693-
// The result of __builtin_counted_by_ref cannot be assigned to a variable.
14694-
// It allows leaking and modification of bounds safety information.
14695-
if (IsBuiltinCountedByRef(VD->getInit()))
14696-
Diag(VD->getInit()->getExprLoc(),
14697-
diag::err_builtin_counted_by_ref_cannot_leak_reference)
14698-
<< VD->getInit()->getSourceRange();
14693+
CheckInvalidBuiltinCountedByRef(VD->getInit(), InitializerKind);
1469914694

1470014695
checkAttributesAfterMerging(*this, *VD);
1470114696

clang/lib/Sema/SemaExpr.cpp

Lines changed: 6 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -4894,11 +4894,7 @@ ExprResult Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base,
48944894
return ExprError();
48954895
}
48964896

4897-
// We cannot use __builtin_counted_by_ref in a binary expression. It's
4898-
// possible to leak the reference and violate bounds security.
4899-
if (IsBuiltinCountedByRef(base))
4900-
Diag(base->getExprLoc(), diag::err_builtin_counted_by_ref_invalid_use)
4901-
<< 0 << base->getSourceRange();
4897+
CheckInvalidBuiltinCountedByRef(base, ArraySubscriptKind);
49024898

49034899
// Handle any non-overload placeholder types in the base and index
49044900
// expressions. We can't handle overloads here because the other
@@ -6495,12 +6491,8 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
64956491
// The result of __builtin_counted_by_ref cannot be used as a function
64966492
// argument. It allows leaking and modification of bounds safety information.
64976493
for (const Expr *Arg : ArgExprs)
6498-
if (IsBuiltinCountedByRef(Arg)) {
6499-
Diag(Arg->getExprLoc(),
6500-
diag::err_builtin_counted_by_ref_cannot_leak_reference)
6501-
<< Arg->getSourceRange();
6494+
if (CheckInvalidBuiltinCountedByRef(Arg, FunctionArgKind))
65026495
return ExprError();
6503-
}
65046496

65056497
if (getLangOpts().CPlusPlus) {
65066498
// If this is a pseudo-destructor expression, build the call immediately.
@@ -15222,22 +15214,11 @@ ExprResult Sema::ActOnBinOp(Scope *S, SourceLocation TokLoc,
1522215214
if (Kind == tok::TokenKind::slash)
1522315215
DetectPrecisionLossInComplexDivision(*this, TokLoc, LHSExpr);
1522415216

15225-
// We cannot use __builtin_counted_by_ref in a binary expression. It's
15226-
// possible to leak the reference and violate bounds security.
15227-
auto CheckBuiltinCountedByRef = [&](const Expr *E) {
15228-
if (IsBuiltinCountedByRef(E)) {
15229-
if (BinaryOperator::isAssignmentOp(Opc))
15230-
Diag(E->getExprLoc(),
15231-
diag::err_builtin_counted_by_ref_cannot_leak_reference)
15232-
<< E->getSourceRange();
15233-
else
15234-
Diag(E->getExprLoc(), diag::err_builtin_counted_by_ref_invalid_use)
15235-
<< 1 << E->getSourceRange();
15236-
}
15237-
};
15217+
BuiltinCountedByRefKind K =
15218+
BinaryOperator::isAssignmentOp(Opc) ? AssignmentKind : BinaryExprKind;
1523815219

15239-
CheckBuiltinCountedByRef(LHSExpr);
15240-
CheckBuiltinCountedByRef(RHSExpr);
15220+
CheckInvalidBuiltinCountedByRef(LHSExpr, K);
15221+
CheckInvalidBuiltinCountedByRef(RHSExpr, K);
1524115222

1524215223
return BuildBinOp(S, TokLoc, Opc, LHSExpr, RHSExpr);
1524315224
}

clang/lib/Sema/SemaStmt.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3765,10 +3765,7 @@ Sema::ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp,
37653765
<< FSI->getFirstCoroutineStmtKeyword();
37663766
}
37673767

3768-
if (IsBuiltinCountedByRef(RetVal.get()))
3769-
Diag(RetVal.get()->getExprLoc(),
3770-
diag::err_builtin_counted_by_ref_cannot_leak_reference)
3771-
<< RetVal.get()->getSourceRange();
3768+
CheckInvalidBuiltinCountedByRef(RetVal.get(), ReturnArgKind);
37723769

37733770
StmtResult R =
37743771
BuildReturnStmt(ReturnLoc, RetVal.get(), /*AllowRecovery=*/true);

clang/test/Sema/builtin-counted-by-ref.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,21 +48,21 @@ void test4(struct fam_struct *ptr, int idx) {
4848
}
4949

5050
void *test5(struct fam_struct *ptr, int size, int idx) {
51-
char *ref = __builtin_counted_by_ref(ptr->array); // expected-error {{value returned by '__builtin_counted_by_ref' cannot be assigned to a variable, have its address taken, or passed into or returned from a function}}
51+
char *ref = __builtin_counted_by_ref(ptr->array); // expected-error {{value returned by '__builtin_counted_by_ref' cannot be assigned to a variable}}
5252
char *int_ptr;
5353
char *p;
5454

55-
ref = __builtin_counted_by_ref(ptr->array); // expected-error {{value returned by '__builtin_counted_by_ref' cannot be assigned to a variable, have its address taken, or passed into or returned from a function}}
56-
g(__builtin_counted_by_ref(ptr->array)); // expected-error {{value returned by '__builtin_counted_by_ref' cannot be assigned to a variable, have its address taken, or passed into or returned from a function}}
57-
g(ref = __builtin_counted_by_ref(ptr->array)); // expected-error {{value returned by '__builtin_counted_by_ref' cannot be assigned to a variable, have its address taken, or passed into or returned from a function}}
55+
ref = __builtin_counted_by_ref(ptr->array); // expected-error {{value returned by '__builtin_counted_by_ref' cannot be assigned to a variable}}
56+
g(__builtin_counted_by_ref(ptr->array)); // expected-error {{value returned by '__builtin_counted_by_ref' cannot be passed into a function}}
57+
g(ref = __builtin_counted_by_ref(ptr->array)); // expected-error {{value returned by '__builtin_counted_by_ref' cannot be assigned to a variable}}
5858

59-
if ((ref = __builtin_counted_by_ref(ptr->array))) // expected-error {{value returned by '__builtin_counted_by_ref' cannot be assigned to a variable, have its address taken, or passed into or returned from a function}}
59+
if ((ref = __builtin_counted_by_ref(ptr->array))) // expected-error {{value returned by '__builtin_counted_by_ref' cannot be assigned to a variable}}
6060
;
6161

62-
for (p = __builtin_counted_by_ref(ptr->array); p && *p; ++p) // expected-error {{value returned by '__builtin_counted_by_ref' cannot be assigned to a variable, have its address taken, or passed into or returned from a function}}
62+
for (p = __builtin_counted_by_ref(ptr->array); p && *p; ++p) // expected-error {{value returned by '__builtin_counted_by_ref' cannot be assigned to a variable}}
6363
;
6464

65-
return __builtin_counted_by_ref(ptr->array); // expected-error {{value returned by '__builtin_counted_by_ref' cannot be assigned to a variable, have its address taken, or passed into or returned from a function}}
65+
return __builtin_counted_by_ref(ptr->array); // expected-error {{value returned by '__builtin_counted_by_ref' cannot be returned from a function}}
6666
}
6767

6868
void test6(struct fam_struct *ptr, int size, int idx) {

0 commit comments

Comments
 (0)