Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions clang/include/clang/AST/Decl.h
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,10 @@ class ValueDecl : public NamedDecl {
bool isInitCapture() const;

/* TO_UPSTREAM(BoundsSafety) ON */
bool isDependentValue() const;
bool isDependentValueWithoutDeref() const;
bool isDependentValueWithDeref() const;
bool isDependentValueThatIsUsedInInoutPointer() const;
/// Whether this decl is a dependent parameter referred to by the return type
/// that is a bounds-attributed type.
bool isDependentParamOfReturnType(
Expand Down
1 change: 1 addition & 0 deletions clang/include/clang/AST/TypeBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -2651,6 +2651,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
bool isAnyVaListType(ASTContext &) const;
bool isDynamicRangePointerType() const;
bool isBoundsAttributedType() const;
bool isBoundsAttributedTypeDependingOnInoutValue() const;
bool isValueTerminatedType() const;
bool isImplicitlyNullTerminatedType(const ASTContext &) const;
/* TO_UPSTREAM(BoundsSafety) OFF */
Expand Down
51 changes: 50 additions & 1 deletion clang/include/clang/Analysis/Analyses/UnsafeBufferUsage.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "clang/AST/Expr.h"
#include "clang/AST/Stmt.h"
#include "clang/Basic/SourceLocation.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/Debug.h"
#include <set>

Expand Down Expand Up @@ -142,6 +143,53 @@ class UnsafeBufferUsageHandler {
ASTContext &Ctx) {
handleUnsafeOperation(Arg, IsRelatedToDecl, Ctx);
}

virtual void handleStandaloneAssign(const Expr *E, const ValueDecl *VD,
bool IsRelatedToDecl, ASTContext &Ctx) {
handleUnsafeOperation(E, IsRelatedToDecl, Ctx);
}

enum class AssignToImmutableObjectKind {
PointerToPointer,
PointerToDependentValue,
PointerDependingOnInoutValue,
DependentValueUsedInInoutPointer,
};

virtual void handleAssignToImmutableObject(const BinaryOperator *Assign,
const ValueDecl *VD,
AssignToImmutableObjectKind Kind,
bool IsRelatedToDecl,
ASTContext &Ctx) {
handleUnsafeOperation(Assign, IsRelatedToDecl, Ctx);
}

virtual void handleMissingAssignments(
const Expr *LastAssignInGroup,
const llvm::SmallPtrSetImpl<const ValueDecl *> &Required,
const llvm::SmallPtrSetImpl<const ValueDecl *> &Missing,
bool IsRelatedToDecl, ASTContext &Ctx) {
handleUnsafeOperation(LastAssignInGroup, IsRelatedToDecl, Ctx);
}

virtual void handleDuplicatedAssignment(const BinaryOperator *Assign,
const BinaryOperator *PrevAssign,
const ValueDecl *VD,
bool IsRelatedToDecl,
ASTContext &Ctx) {
handleUnsafeOperation(Assign, IsRelatedToDecl, Ctx);
}

virtual void handleAssignedAndUsed(const BinaryOperator *Assign,
const Expr *Use, const ValueDecl *VD,
bool IsRelatedToDecl, ASTContext &Ctx) {
handleUnsafeOperation(Assign, IsRelatedToDecl, Ctx);
}

virtual void handleUnsafeCountAttributedPointerAssignment(
const BinaryOperator *Assign, bool IsRelatedToDecl, ASTContext &Ctx) {
handleUnsafeOperation(Assign, IsRelatedToDecl, Ctx);
}
/* TO_UPSTREAM(BoundsSafety) OFF */

/// Invoked when a fix is suggested against a variable. This function groups
Expand Down Expand Up @@ -196,7 +244,8 @@ class UnsafeBufferUsageHandler {
// This function invokes the analysis and allows the caller to react to it
// through the handler class.
void checkUnsafeBufferUsage(const Decl *D, UnsafeBufferUsageHandler &Handler,
bool EmitSuggestions);
bool EmitSuggestions,
bool BoundsSafetyAttributes = false);

namespace internal {
// Tests if any two `FixItHint`s in `FixIts` conflict. Two `FixItHint`s
Expand Down
23 changes: 23 additions & 0 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -14236,6 +14236,29 @@ def note_unsafe_count_attributed_pointer_argument_null_to_nonnull : Note<
def warn_unsafe_single_pointer_argument : Warning<
"unsafe assignment to function parameter of __single pointer type">,
InGroup<UnsafeBufferUsage>, DefaultIgnore;
def warn_standalone_assign_to_bounds_attributed_object : Warning<
"assignment to %select{bounds-attributed pointer|dependent value}0 %1 "
"must be inside of a bounds-attributed group in a compound statement">,
InGroup<UnsafeBufferUsage>, DefaultIgnore;
def warn_cannot_assign_to_immutable_bounds_attributed_object : Warning<
"cannot assign to %select{variable|parameter|member}0 %1 because %select{"
"it points to a bounds-attributed pointer|"
"it points to a dependent value|"
"its type depends on an inout dependent value|"
"it's used as dependent value in an inout bounds-attributed pointer"
"}2">, InGroup<UnsafeBufferUsage>, DefaultIgnore;
def warn_missing_assignments_in_bounds_attributed_group : Warning<
"bounds-attributed group requires assigning '%0', assignments to '%1' missing">,
InGroup<UnsafeBufferUsage>, DefaultIgnore;
def warn_duplicated_assignment_in_bounds_attributed_group : Warning<
"duplicated assignment to %select{variable|parameter|member}0 %1 in "
"bounds-attributed group">, InGroup<UnsafeBufferUsage>, DefaultIgnore;
def warn_assigned_and_used_in_bounds_attributed_group : Warning<
"%select{variable|parameter|member}0 %1 is assigned and used in the same "
"bounds-attributed group">, InGroup<UnsafeBufferUsage>, DefaultIgnore;
def warn_unsafe_count_attributed_pointer_assignment : Warning<
"unsafe assignment to count-attributed pointer">,
InGroup<UnsafeBufferUsage>, DefaultIgnore;
#ifndef NDEBUG
// Not a user-facing diagnostic. Useful for debugging false negatives in
// -fsafe-buffer-usage-suggestions (i.e. lack of -Wunsafe-buffer-usage fixits).
Expand Down
21 changes: 21 additions & 0 deletions clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5502,6 +5502,27 @@ bool ValueDecl::isParameterPack() const {
}

/* TO_UPSTREAM(BoundsSafety) ON */
bool ValueDecl::isDependentValue() const {
return hasAttr<DependerDeclsAttr>();
}

bool ValueDecl::isDependentValueWithoutDeref() const {
const auto *Att = getAttr<DependerDeclsAttr>();
return Att && !Att->getIsDeref();
}

bool ValueDecl::isDependentValueWithDeref() const {
const auto *Att = getAttr<DependerDeclsAttr>();
return Att && Att->getIsDeref();
}

bool ValueDecl::isDependentValueThatIsUsedInInoutPointer() const {
const auto *Att = getAttr<DependerDeclsAttr>();
return Att &&
std::any_of(Att->dependerLevels_begin(), Att->dependerLevels_end(),
[](unsigned Level) { return Level > 0; });
}

bool ValueDecl::isDependentParamOfReturnType(
const BoundsAttributedType **RetType,
const TypeCoupledDeclRefInfo **Info) const {
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -829,6 +829,14 @@ bool Type::isBoundsAttributedType() const {
return getAs<BoundsAttributedType>();
}

bool Type::isBoundsAttributedTypeDependingOnInoutValue() const {
const auto *BAT = getAs<BoundsAttributedType>();
return BAT &&
std::any_of(
BAT->dependent_decl_begin(), BAT->dependent_decl_end(),
[](const TypeCoupledDeclRefInfo &Info) { return Info.isDeref(); });
}

bool Type::isValueTerminatedType() const {
return getAs<ValueTerminatedType>();
}
Expand Down
Loading