Skip to content

Commit f5a8063

Browse files
[-Wunsafe-buffer-usage] Add basic support for C++ default args
This commit changes two things: - Allows the count-attributed pointer analysis see through `CXXDefaultArgExpr` for both pointer and count arguments. - Fixes the diagnostic location. Since `CXXDefaultArgExpr` has no source representation, we emit the diagnostic at the right parenthesis of the call expression. rdar://156005108
1 parent e304fb1 commit f5a8063

File tree

3 files changed

+52
-2
lines changed

3 files changed

+52
-2
lines changed

clang/lib/Analysis/UnsafeBufferUsage.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,11 @@ struct CompatibleCountExprVisitor
691691
}
692692
return false;
693693
}
694+
695+
bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *SelfDAE,
696+
const Expr *Other, bool hasBeenSubstituted) {
697+
return Visit(SelfDAE->getExpr(), Other, hasBeenSubstituted);
698+
}
694699
};
695700

696701
// TL'DR:
@@ -935,7 +940,10 @@ static bool isCountAttributedPointerArgumentSafeImpl(
935940
assert((CountedByExpr || !DependentValueMap) &&
936941
"If the __counted_by information is hardcoded, there is no "
937942
"dependent value map.");
943+
938944
const Expr *PtrArgNoImp = PtrArg->IgnoreParenImpCasts();
945+
if (const auto *DAE = dyn_cast<CXXDefaultArgExpr>(PtrArgNoImp))
946+
PtrArgNoImp = DAE->getExpr()->IgnoreParenImpCasts();
939947

940948
// check form 0:
941949
if (PtrArgNoImp->getType()->isNullPtrType()) {

clang/lib/Sema/AnalysisBasedWarnings.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2587,8 +2587,9 @@ class UnsafeBufferUsageReporter : public UnsafeBufferUsageHandler {
25872587
IsSimpleCount ? CATy->dependent_decls().begin()->getDecl()->getName()
25882588
: "";
25892589

2590-
S.Diag(Arg->getBeginLoc(),
2591-
diag::warn_unsafe_count_attributed_pointer_argument);
2590+
SourceLocation DiagLoc =
2591+
Arg->isDefaultArgument() ? Call->getRParenLoc() : Arg->getBeginLoc();
2592+
S.Diag(DiagLoc, diag::warn_unsafe_count_attributed_pointer_argument);
25922593
S.Diag(PVD->getBeginLoc(),
25932594
diag::note_unsafe_count_attributed_pointer_argument)
25942595
<< IsSimpleCount << QualType(CATy, 0) << !PtrParamName.empty()

clang/test/SemaCXX/warn-unsafe-buffer-usage-count-attributed-pointer-argument.cpp

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -664,3 +664,44 @@ static void previous_infinite_loop3(int * __counted_by(n + n * m) p, size_t n,
664664
previous_infinite_loop3(p, n, q, r, m, o);
665665
previous_infinite_loop3(p, n, q, r, m, o + 1); // expected-warning 2{{unsafe assignment to function parameter of count-attributed type}}
666666
}
667+
668+
// Check default args.
669+
670+
void cb_def_arg_null_0(int *__counted_by(count) p = nullptr, size_t count = 0);
671+
672+
// expected-note@+1{{consider using a safe container and passing '.data()' to the parameter 'p' and '.size()' to its dependent parameter 'count' or 'std::span' and passing '.first(...).data()' to the parameter 'p'}}
673+
void cb_def_arg_0_null(size_t count = 0, int *__counted_by(count) p = nullptr);
674+
675+
// expected-note@+1 6{{consider using a safe container and passing '.data()' to the parameter 'p' and '.size()' to its dependent parameter 'count' or 'std::span' and passing '.first(...).data()' to the parameter 'p'}}
676+
void cb_def_arg_null_42(int *__counted_by(count) p = nullptr, size_t count = 42);
677+
678+
void default_arg(std::span<int> sp) {
679+
cb_def_arg_null_0();
680+
cb_def_arg_null_0(nullptr);
681+
cb_def_arg_null_0(nullptr, 0);
682+
cb_def_arg_null_0(sp.data(), sp.size());
683+
684+
cb_def_arg_0_null();
685+
cb_def_arg_0_null(0);
686+
cb_def_arg_0_null(0, nullptr);
687+
cb_def_arg_0_null(sp.size(), sp.data());
688+
cb_def_arg_0_null(42); // expected-warning{{unsafe assignment to function parameter of count-attributed type}}
689+
cb_def_arg_0_null(42, sp.first(42).data());
690+
691+
cb_def_arg_null_42(); // expected-warning{{unsafe assignment to function parameter of count-attributed type}}
692+
cb_def_arg_null_42(nullptr); // expected-warning{{unsafe assignment to function parameter of count-attributed type}}
693+
cb_def_arg_null_42(nullptr, 42); // expected-warning{{unsafe assignment to function parameter of count-attributed type}}
694+
cb_def_arg_null_42(nullptr, 0);
695+
cb_def_arg_null_42(sp.data()); // expected-warning{{unsafe assignment to function parameter of count-attributed type}}
696+
cb_def_arg_null_42(sp.data(), sp.size());
697+
cb_def_arg_null_42(sp.first(42).data());
698+
cb_def_arg_null_42(sp.first(42).data(), 42);
699+
cb_def_arg_null_42(sp.first(41).data()); // expected-warning{{unsafe assignment to function parameter of count-attributed type}}
700+
701+
// Check if the diagnostic is at the right paren.
702+
// clang-format off
703+
cb_def_arg_null_42
704+
(
705+
); // expected-warning{{unsafe assignment to function parameter of count-attributed type}}
706+
// clang-format on
707+
}

0 commit comments

Comments
 (0)