32 assert(!Flags.
IsEndedBy &&
"ended_by is not implemented");
39 case ParsedAttr::AT_SizedBy:
42 case ParsedAttr::AT_SizedByOrNull:
46 case ParsedAttr::AT_CountedBy:
48 case ParsedAttr::AT_CountedByOrNull:
52 llvm_unreachable(
"unexpected bounds attribute kind");
63 while (RD && (RD->isAnonymousStructOrUnion() || RD->getName().empty())) {
64 const auto *Parent = dyn_cast<RecordDecl>(RD->getParent());
85 bool AllowRedecl,
Expr *AttrArg) {
94 StringRef AttrSpelling,
bool AllowRedecl,
95 Expr *AttrArg,
bool UpdateFlags) {
98 *
this, Ty, AttrLoc, Flags, AttrSpelling, AllowRedecl, AttrArg))
105 Diag(AttrLoc, diag::err_count_attr_not_on_ptr_or_flexible_array_member)
113 Diag(AttrLoc, diag::err_count_attr_not_on_ptr_or_flexible_array_member)
131 bool ShouldWarn =
false;
169 Diag(AttrLoc, diag::ext_gnu_counted_by_void_ptr) << Kind;
170 Diag(AttrLoc, diag::note_gnu_counted_by_void_ptr_use_sized_by) << Kind;
171 assert(!Ty->
isArrayType() &&
"sized_by is not allowed on arrays");
196 unsigned DiagID = ShouldWarn
197 ? diag::warn_counted_by_attr_elt_type_unknown_size
198 : diag::err_counted_by_attr_pointee_unknown_size;
199 Diag(AttrLoc, DiagID) << SelectPtrOrArr << PointeeTy << (
int)InvalidTypeKind
200 << (ShouldWarn ? 1 : 0) << Kind << AttrRange;
232 if (PointerNestLevel > 0) {
233 Diag(AttrLoc, diag::err_counted_by_on_nested_pointer)
253 const auto FieldTy = FD->
getType();
254 if (FieldTy->isArrayType() && (CountInBytes || OrNull)) {
256 diag::err_count_attr_not_on_ptr_or_flexible_array_member)
260 if (!FieldTy->isArrayType() && !FieldTy->isPointerType()) {
262 diag::err_count_attr_not_on_ptr_or_flexible_array_member)
269 if (FieldTy->isArrayType() &&
271 StrictFlexArraysLevel,
true)) {
273 diag::err_counted_by_attr_on_array_not_flexible_array_member)
281 int SelectPtrOrArr = 0;
282 if (FieldTy->isPointerType()) {
286 assert(FieldTy->isArrayType());
294 bool ShouldWarn =
false;
334 Diag(FD->
getBeginLoc(), diag::note_gnu_counted_by_void_ptr_use_sized_by)
344 }
else if (!CountInBytes &&
346 if (FieldTy->isArrayType() && !
getLangOpts().BoundsSafety) {
359 unsigned DiagID = ShouldWarn
360 ? diag::warn_counted_by_attr_elt_type_unknown_size
361 : diag::err_counted_by_attr_pointee_unknown_size;
363 << SelectPtrOrArr << PointeeTy << (
int)InvalidTypeKind
376 auto *DRE = dyn_cast<DeclRefExpr>(E);
379 diag::err_count_attr_only_support_simple_decl_reference)
384 auto *CountDecl = DRE->getDecl();
385 FieldDecl *CountFD = dyn_cast<FieldDecl>(CountDecl);
386 if (
auto *IFD = dyn_cast<IndirectFieldDecl>(CountDecl)) {
387 CountFD = IFD->getAnonField();
393 Diag(CountDecl->getBeginLoc(),
394 diag::note_flexible_array_counted_by_attr_field)
395 << CountDecl << CountDecl->getSourceRange();
413 << CountFD << Kind << FieldTy->isArrayType() << E->
getSourceRange();
415 diag::note_flexible_array_counted_by_attr_field)
426 assert(IncompleteTyDecl ==
nullptr ||
isa<TypeDecl>(IncompleteTyDecl));
428 if (IncompleteTyDecl) {
441 diag::note_counted_by_consider_completing_pointee_ty)
457 S.
Diag(AttrSrcRange.
getBegin(), diag::note_counted_by_consider_using_sized_by)
458 << CATy->
isOrNull() << AttrSrcRange;
461static std::tuple<const CountAttributedType *, QualType>
466 if (!CATy || CATy->isCountInBytes())
470 if (PointeeTy.isNull()) {
475 if (!PointeeTy->isIncompleteType(ND))
478 if (PointeeTy->isVoidType())
481 return {CATy, PointeeTy};
505 bool ShowFullyQualifiedAssigneeName) {
507 auto [CATy, PointeeTy] =
512 std::string AssigneeStr;
514 if (ShowFullyQualifiedAssigneeName) {
521 S.
Diag(Loc, diag::err_counted_by_on_incomplete_type_on_assign)
522 <<
static_cast<int>(Action) << AssigneeStr << (AssigneeStr.size() > 0)
524 << CATy->getAttributeName(
true) << PointeeTy
533 const ValueDecl *Assignee,
bool ShowFullyQualifiedAssigneeName) {
535 *
this, LHSTy, RHSExpr, Action, Loc, Assignee,
536 ShowFullyQualifiedAssigneeName);
543 auto SL = Kind.getLocation();
557 *
this, LHSType, RHSExpr, Action, SL,
558 dyn_cast_or_null<ValueDecl>(Entity.
getDecl()),
569 if (!
T->isPointerType())
573 auto [CATy, PointeeTy] =
582 bool IsDirectCall =
false;
583 if (
const auto *CE = dyn_cast<CallExpr>(E->
IgnoreParens())) {
584 if (
const auto *FD = CE->getDirectCallee()) {
585 UseStr = FD->getName();
591 llvm::raw_svector_ostream SS(UseStr);
596 << IsDirectCall << UseStr <<
T << PointeeTy
597 << CATy->getAttributeName(
true) << CATy->isOrNull()
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
QualType getElementType() const
Represents a sugar type with __counted_by or __sized_by annotations, including their _or_null variant...
Expr * getCountExpr() const
static bool isFlexibleArrayMemberLike(const ASTContext &Context, const Decl *D, QualType Ty, LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel, bool IgnoreTemplateOrMacroSubstitution)
Whether it resembles a flexible array member.
SourceLocation getLocation() const
SourceLocation getBeginLoc() const LLVM_READONLY
SourceLocation getBeginLoc() const LLVM_READONLY
This represents one expression.
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Represents a member of a struct/union/class.
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Describes the kind of initialization being performed, along with location information for tokens rela...
Describes an entity that is being initialized.
EntityKind getKind() const
Determine the kind of initialization.
ValueDecl * getDecl() const
Retrieve the variable, parameter, or field being initialized.
@ EK_Variable
The entity being initialized is a variable.
StrictFlexArraysLevelKind
@ IncompleteOnly
Any trailing array member of undefined size is a FAM.
This represents a decl that may have a name.
std::string getQualifiedNameAsString() const
std::string getNameAsString() const
Get a human-readable name for the declaration, even if it is one of the special kinds of names (C++ c...
A (possibly-)qualified type.
Represents a struct/union/class.
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Sema - This implements semantic analysis and AST building for C.
bool BoundsSafetyCheckAssignmentToCountAttrPtr(QualType LHSTy, Expr *RHSExpr, AssignmentAction Action, SourceLocation Loc, const ValueDecl *Assignee, bool ShowFullyQualifiedAssigneeName)
Perform Bounds Safety Semantic checks for assigning to a __counted_by or __counted_by_or_null pointer...
bool BoundsSafetyCheckUseOfCountAttrPtr(const Expr *E)
Perform Bounds Safety semantic checks for uses of invalid uses counted_by or counted_by_or_null point...
ASTContext & getASTContext() const
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
const LangOptions & getLangOpts() const
bool CheckCountedByAttrOnField(FieldDecl *FD, Expr *E, bool CountInBytes, bool OrNull)
Check if applying the specified attribute variant from the "counted by" family of attributes to Field...
bool ValidateBoundsAttrTypeForTypePosition(QualType Ty, AttributeCommonInfo::Kind AttrKind, SourceLocation AttrLoc, SourceRange AttrRange, unsigned PointerNestLevel, BoundsAttrFlags &Flags)
Check a counted_by-family attribute in type position and initialize Flags from AttrKind.
bool BoundsSafetyCheckInitialization(const InitializedEntity &Entity, const InitializationKind &Kind, AssignmentAction Action, QualType LHSType, Expr *RHSExpr)
Perform Bounds Safety Semantic checks for initializing a Bounds Safety pointer.
static BoundsAttributedType::BoundsAttrKind getBoundsAttrKind(const BoundsAttrFlags &)
bool ValidateBoundsAttrTypeShape(QualType Ty, SourceLocation AttrLoc, SourceRange AttrRange, BoundsAttrFlags &Flags, StringRef AttrSpelling={}, bool AllowRedecl=false, Expr *AttrArg=nullptr, bool UpdateFlags=true)
Check the type shape for counted_by, sized_by and their _or_null variants.
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getBegin() const
void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation=0, StringRef NewlineSymbol="\n", const ASTContext *Context=nullptr) const
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
SourceLocation getBeginLoc() const LLVM_READONLY
bool isSizelessType() const
As an extension, we classify types as one of "sized" or "sizeless"; every type is one or the other.
bool isBooleanType() const
bool isAlwaysIncompleteType() const
bool isPointerType() const
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
bool isFunctionType() const
bool isStructureTypeWithFlexibleArrayMember() const
const T * getAs() const
Member-template getAs<specific type>'.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
CountedByInvalidPointeeTypeKind
static bool CheckAssignmentToCountAttrPtrWithIncompletePointeeTy(Sema &S, QualType LHSTy, Expr *RHSExpr, AssignmentAction Action, SourceLocation Loc, const ValueDecl *Assignee, bool ShowFullyQualifiedAssigneeName)
Perform Checks for assigning to a __counted_by or __counted_by_or_null pointer type.
static std::optional< bool > checkBoundsAttrTypeConflictsAndMisc(Sema &S, QualType Ty, SourceLocation AttrLoc, const Sema::BoundsAttrFlags &Flags, StringRef AttrSpelling, bool AllowRedecl, Expr *AttrArg)
Check type conflicts under the -fbounds-safety attribute model.
static const RecordDecl * GetEnclosingNamedOrTopAnonRecord(const FieldDecl *FD)
@ Result
The result type of a method or function.
static void EmitIncompleteCountedByPointeeNotes(Sema &S, const CountAttributedType *CATy, NamedDecl *IncompleteTyDecl)
static std::tuple< const CountAttributedType *, QualType > GetCountedByAttrOnIncompletePointee(QualType Ty, NamedDecl **ND)
const FunctionProtoType * T
static CountAttributedType::BoundsAttrKind getCountAttrKind(bool CountInBytes, bool OrNull)
static BoundsAttrFlags get(AttributeCommonInfo::Kind K)
Return the flags for a bounds attribute of kind K.