Skip to content

Commit ddf2cc9

Browse files
Merge pull request #7779 from jkorous-apple/cxx-safe-buffers-cherry-picks
[-Wunsafe-buffer-usage] cherry-picks
2 parents 0307797 + 2c8d696 commit ddf2cc9

28 files changed

+1923
-673
lines changed

clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,46 @@
1616

1717
#include "clang/AST/Decl.h"
1818
#include "clang/AST/Stmt.h"
19+
#include "llvm/Support/Debug.h"
1920

2021
namespace clang {
2122

22-
using DefMapTy = llvm::DenseMap<const VarDecl *, std::vector<const VarDecl *>>;
23+
using VarGrpTy = std::vector<const VarDecl *>;
24+
using VarGrpRef = ArrayRef<const VarDecl *>;
25+
26+
class VariableGroupsManager {
27+
public:
28+
VariableGroupsManager() = default;
29+
virtual ~VariableGroupsManager() = default;
30+
/// Returns the set of variables (including `Var`) that need to be fixed
31+
/// together in one step.
32+
///
33+
/// `Var` must be a variable that needs fix (so it must be in a group).
34+
/// `HasParm` is an optional argument that will be set to true if the set of
35+
/// variables, where `Var` is in, contains parameters.
36+
virtual VarGrpRef getGroupOfVar(const VarDecl *Var,
37+
bool *HasParm = nullptr) const = 0;
38+
39+
/// Returns the non-empty group of variables that include parameters of the
40+
/// analyzing function, if such a group exists. An empty group, otherwise.
41+
virtual VarGrpRef getGroupOfParms() const = 0;
42+
};
2343

2444
/// The interface that lets the caller handle unsafe buffer usage analysis
2545
/// results by overriding this class's handle... methods.
2646
class UnsafeBufferUsageHandler {
47+
#ifndef NDEBUG
48+
public:
49+
// A self-debugging facility that you can use to notify the user when
50+
// suggestions or fixits are incomplete.
51+
// Uses std::function to avoid computing the message when it won't
52+
// actually be displayed.
53+
using DebugNote = std::pair<SourceLocation, std::string>;
54+
using DebugNoteList = std::vector<DebugNote>;
55+
using DebugNoteByVar = std::map<const VarDecl *, DebugNoteList>;
56+
DebugNoteByVar DebugNotesByVar;
57+
#endif
58+
2759
public:
2860
UnsafeBufferUsageHandler() = default;
2961
virtual ~UnsafeBufferUsageHandler() = default;
@@ -37,12 +69,35 @@ class UnsafeBufferUsageHandler {
3769
bool IsRelatedToDecl) = 0;
3870

3971
/// Invoked when a fix is suggested against a variable. This function groups
40-
/// all variables that must be fixed together (i.e their types must be changed to the
41-
/// same target type to prevent type mismatches) into a single fixit.
72+
/// all variables that must be fixed together (i.e their types must be changed
73+
/// to the same target type to prevent type mismatches) into a single fixit.
74+
///
75+
/// `D` is the declaration of the callable under analysis that owns `Variable`
76+
/// and all of its group mates.
4277
virtual void handleUnsafeVariableGroup(const VarDecl *Variable,
43-
const DefMapTy &VarGrpMap,
44-
FixItList &&Fixes) = 0;
78+
const VariableGroupsManager &VarGrpMgr,
79+
FixItList &&Fixes, const Decl *D) = 0;
4580

81+
#ifndef NDEBUG
82+
public:
83+
bool areDebugNotesRequested() {
84+
DEBUG_WITH_TYPE("SafeBuffers", return true);
85+
return false;
86+
}
87+
88+
void addDebugNoteForVar(const VarDecl *VD, SourceLocation Loc,
89+
std::string Text) {
90+
if (areDebugNotesRequested())
91+
DebugNotesByVar[VD].push_back(std::make_pair(Loc, Text));
92+
}
93+
94+
void clearDebugNotes() {
95+
if (areDebugNotesRequested())
96+
DebugNotesByVar.clear();
97+
}
98+
#endif
99+
100+
public:
46101
/// Returns a reference to the `Preprocessor`:
47102
virtual bool isSafeBufferOptOut(const SourceLocation &Loc) const = 0;
48103

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11965,8 +11965,17 @@ def note_unsafe_buffer_operation : Note<
1196511965
"used%select{| in pointer arithmetic| in buffer access}0 here">;
1196611966
def note_unsafe_buffer_variable_fixit_group : Note<
1196711967
"change type of %0 to '%select{std::span|std::array|std::span::iterator}1' to preserve bounds information%select{|, and change %2 to '%select{std::span|std::array|std::span::iterator}1' to propagate bounds information between them}3">;
11968+
def note_unsafe_buffer_variable_fixit_together : Note<
11969+
"change type of %0 to '%select{std::span|std::array|std::span::iterator}1' to preserve bounds information"
11970+
"%select{|, and change %2 to safe types to make function %4 bounds-safe}3">;
1196811971
def note_safe_buffer_usage_suggestions_disabled : Note<
1196911972
"pass -fsafe-buffer-usage-suggestions to receive code hardening suggestions">;
11973+
#ifndef NDEBUG
11974+
// Not a user-facing diagnostic. Useful for debugging false negatives in
11975+
// -fsafe-buffer-usage-suggestions (i.e. lack of -Wunsafe-buffer-usage fixits).
11976+
def note_safe_buffer_debug_mode : Note<"safe buffers debug: %0">;
11977+
#endif
11978+
1197011979
def err_loongarch_builtin_requires_la32 : Error<
1197111980
"this builtin requires target: loongarch32">;
1197211981

0 commit comments

Comments
 (0)