mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-30 17:21:10 +00:00
[-Wunsafe-buffer-usage] Emit Fix-Its only for C++20 and later standards
The transformation strategy we are bringing up heavily relies on std::span which was introduced as part of C++20. Differential Revision: https://reviews.llvm.org/D143455
This commit is contained in:
parent
f71de259c3
commit
8b6ae9bd74
@ -53,7 +53,8 @@ public:
|
||||
|
||||
// This function invokes the analysis and allows the caller to react to it
|
||||
// through the handler class.
|
||||
void checkUnsafeBufferUsage(const Decl *D, UnsafeBufferUsageHandler &Handler);
|
||||
void checkUnsafeBufferUsage(const Decl *D, UnsafeBufferUsageHandler &Handler,
|
||||
bool EmitFixits);
|
||||
|
||||
namespace internal {
|
||||
// Tests if any two `FixItHint`s in `FixIts` conflict. Two `FixItHint`s
|
||||
|
@ -1008,7 +1008,8 @@ getNaiveStrategy(const llvm::SmallVectorImpl<const VarDecl *> &UnsafeVars) {
|
||||
}
|
||||
|
||||
void clang::checkUnsafeBufferUsage(const Decl *D,
|
||||
UnsafeBufferUsageHandler &Handler) {
|
||||
UnsafeBufferUsageHandler &Handler,
|
||||
bool EmitFixits) {
|
||||
assert(D && D->getBody());
|
||||
|
||||
WarningGadgetSets UnsafeOps;
|
||||
@ -1016,40 +1017,46 @@ void clang::checkUnsafeBufferUsage(const Decl *D,
|
||||
DeclUseTracker Tracker;
|
||||
|
||||
{
|
||||
// FIXME: We could skip even matching Fixables' matchers if EmitFixits ==
|
||||
// false.
|
||||
auto [FixableGadgets, WarningGadgets, TrackerRes] = findGadgets(D, Handler);
|
||||
UnsafeOps = groupWarningGadgetsByVar(std::move(WarningGadgets));
|
||||
FixablesForUnsafeVars = groupFixablesByVar(std::move(FixableGadgets));
|
||||
Tracker = std::move(TrackerRes);
|
||||
}
|
||||
|
||||
// Filter out non-local vars and vars with unclaimed DeclRefExpr-s.
|
||||
for (auto it = FixablesForUnsafeVars.byVar.cbegin();
|
||||
it != FixablesForUnsafeVars.byVar.cend();) {
|
||||
// FIXME: Support ParmVarDecl as well.
|
||||
if (!it->first->isLocalVarDecl() || Tracker.hasUnclaimedUses(it->first)) {
|
||||
it = FixablesForUnsafeVars.byVar.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
std::map<const VarDecl *, FixItList> FixItsForVariable;
|
||||
|
||||
if (EmitFixits) {
|
||||
// Filter out non-local vars and vars with unclaimed DeclRefExpr-s.
|
||||
for (auto it = FixablesForUnsafeVars.byVar.cbegin();
|
||||
it != FixablesForUnsafeVars.byVar.cend();) {
|
||||
// FIXME: Support ParmVarDecl as well.
|
||||
if (!it->first->isLocalVarDecl() || Tracker.hasUnclaimedUses(it->first)) {
|
||||
it = FixablesForUnsafeVars.byVar.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
|
||||
llvm::SmallVector<const VarDecl *, 16> UnsafeVars;
|
||||
for (const auto &[VD, ignore] : FixablesForUnsafeVars.byVar)
|
||||
UnsafeVars.push_back(VD);
|
||||
|
||||
Strategy NaiveStrategy = getNaiveStrategy(UnsafeVars);
|
||||
FixItsForVariable = getFixIts(FixablesForUnsafeVars, NaiveStrategy, Tracker,
|
||||
D->getASTContext(), Handler);
|
||||
|
||||
// FIXME Detect overlapping FixIts.
|
||||
}
|
||||
|
||||
llvm::SmallVector<const VarDecl *, 16> UnsafeVars;
|
||||
for (const auto &[VD, ignore] : FixablesForUnsafeVars.byVar)
|
||||
UnsafeVars.push_back(VD);
|
||||
|
||||
Strategy NaiveStrategy = getNaiveStrategy(UnsafeVars);
|
||||
std::map<const VarDecl *, FixItList> FixItsForVariable =
|
||||
getFixIts(FixablesForUnsafeVars, NaiveStrategy, Tracker,
|
||||
D->getASTContext(), Handler);
|
||||
|
||||
// FIXME Detect overlapping FixIts.
|
||||
|
||||
for (const auto &G : UnsafeOps.noVar) {
|
||||
Handler.handleUnsafeOperation(G->getBaseStmt(), /*IsRelatedToDecl=*/false);
|
||||
}
|
||||
|
||||
for (const auto &[VD, WarningGadgets] : UnsafeOps.byVar) {
|
||||
auto FixItsIt = FixItsForVariable.find(VD);
|
||||
auto FixItsIt =
|
||||
EmitFixits ? FixItsForVariable.find(VD) : FixItsForVariable.end();
|
||||
Handler.handleFixableVariable(VD, FixItsIt != FixItsForVariable.end()
|
||||
? std::move(FixItsIt->second)
|
||||
: FixItList{});
|
||||
|
@ -2516,7 +2516,9 @@ void clang::sema::AnalysisBasedWarnings::IssueWarnings(
|
||||
if (!Diags.isIgnored(diag::warn_unsafe_buffer_operation, D->getBeginLoc()) ||
|
||||
!Diags.isIgnored(diag::warn_unsafe_buffer_variable, D->getBeginLoc())) {
|
||||
UnsafeBufferUsageReporter R(S);
|
||||
checkUnsafeBufferUsage(D, R);
|
||||
checkUnsafeBufferUsage(
|
||||
D, R,
|
||||
/*EmitFixits=*/S.getLangOpts().CPlusPlus20);
|
||||
}
|
||||
|
||||
// If none of the previous checks caused a CFG build, trigger one here
|
||||
|
82
clang/test/SemaCXX/warn-unsafe-buffer-usage-no-fixits.cpp
Normal file
82
clang/test/SemaCXX/warn-unsafe-buffer-usage-no-fixits.cpp
Normal file
@ -0,0 +1,82 @@
|
||||
// RUN: %clang_cc1 -x c -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
|
||||
|
||||
// RUN: %clang_cc1 -x c -std=c89 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
|
||||
// RUN: %clang_cc1 -x c -std=gnu89 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
|
||||
// RUN: %clang_cc1 -x c -std=iso9899:1990 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
|
||||
|
||||
// RUN: %clang_cc1 -x c -std=c17 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
|
||||
// RUN: %clang_cc1 -x c -std=gnu17 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
|
||||
// RUN: %clang_cc1 -x c -std=iso9899:2017 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
|
||||
// RUN: %clang_cc1 -x c -std=c2x -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
|
||||
|
||||
// RUN: %clang_cc1 -x c++ -std=c++98 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
|
||||
// RUN: %clang_cc1 -x c++ -std=gnu++98 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
|
||||
// RUN: %clang_cc1 -x c++ -std=c++17 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
|
||||
// RUN: %clang_cc1 -x c++ -std=gnu++17 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
|
||||
|
||||
// RUN: %clang_cc1 -x objective-c++ -std=c++98 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
|
||||
// RUN: %clang_cc1 -x objective-c++ -std=gnu++98 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
|
||||
// RUN: %clang_cc1 -x objective-c++ -std=c++17 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
|
||||
// RUN: %clang_cc1 -x objective-c++ -std=gnu++17 -Wunsafe-buffer-usage -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s
|
||||
|
||||
// CHECK-NOT: fix-it:
|
||||
|
||||
typedef int * Int_ptr_t;
|
||||
typedef int Int_t;
|
||||
|
||||
void local_array_subscript_simple() {
|
||||
int tmp;
|
||||
int *p;
|
||||
const int *q;
|
||||
tmp = p[5];
|
||||
tmp = q[5];
|
||||
|
||||
Int_ptr_t x;
|
||||
Int_ptr_t y;
|
||||
Int_t * z;
|
||||
Int_t * w;
|
||||
|
||||
tmp = x[5];
|
||||
tmp = y[5];
|
||||
tmp = z[5];
|
||||
tmp = w[5];
|
||||
}
|
||||
|
||||
void local_ptr_to_array() {
|
||||
int tmp;
|
||||
int n = 10;
|
||||
int a[10];
|
||||
int b[n];
|
||||
int *p = a;
|
||||
int *q = b;
|
||||
tmp = p[5];
|
||||
tmp = q[5];
|
||||
}
|
||||
|
||||
void local_ptr_addrof_init() {
|
||||
int var;
|
||||
int * q = &var;
|
||||
var = q[5];
|
||||
}
|
||||
|
||||
void decl_without_init() {
|
||||
int tmp;
|
||||
int * p;
|
||||
Int_ptr_t q;
|
||||
tmp = p[5];
|
||||
tmp = q[5];
|
||||
}
|
||||
|
||||
void explict_cast() {
|
||||
int tmp;
|
||||
int * p;
|
||||
tmp = p[5];
|
||||
|
||||
int a;
|
||||
char * q = (char *)&a;
|
||||
tmp = (int) q[5];
|
||||
|
||||
void * r = &a;
|
||||
char * s = (char *) r;
|
||||
tmp = (int) s[5];
|
||||
}
|
Loading…
Reference in New Issue
Block a user