Skip to content

Commit b6c748b

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 (cherry picked from commit f5a8063)
1 parent f919c42 commit b6c748b

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
@@ -686,6 +686,11 @@ struct CompatibleCountExprVisitor
686686
}
687687
return false;
688688
}
689+
690+
bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *SelfDAE,
691+
const Expr *Other, bool hasBeenSubstituted) {
692+
return Visit(SelfDAE->getExpr(), Other, hasBeenSubstituted);
693+
}
689694
};
690695

691696
// TL'DR:
@@ -930,7 +935,10 @@ static bool isCountAttributedPointerArgumentSafeImpl(
930935
assert((CountedByExpr || !DependentValueMap) &&
931936
"If the __counted_by information is hardcoded, there is no "
932937
"dependent value map.");
938+
933939
const Expr *PtrArgNoImp = PtrArg->IgnoreParenImpCasts();
940+
if (const auto *DAE = dyn_cast<CXXDefaultArgExpr>(PtrArgNoImp))
941+
PtrArgNoImp = DAE->getExpr()->IgnoreParenImpCasts();
934942

935943
// check form 0:
936944
if (PtrArgNoImp->getType()->isNullPtrType()) {

clang/lib/Sema/AnalysisBasedWarnings.cpp

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

2579-
S.Diag(Arg->getBeginLoc(),
2580-
diag::warn_unsafe_count_attributed_pointer_argument);
2579+
SourceLocation DiagLoc =
2580+
Arg->isDefaultArgument() ? Call->getRParenLoc() : Arg->getBeginLoc();
2581+
S.Diag(DiagLoc, diag::warn_unsafe_count_attributed_pointer_argument);
25812582
S.Diag(PVD->getBeginLoc(),
25822583
diag::note_unsafe_count_attributed_pointer_argument)
25832584
<< 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)