clang 24.0.0git
SemaBoundsSafety.cpp
Go to the documentation of this file.
1//===-- SemaBoundsSafety.cpp - Bounds Safety specific routines-*- C++ -*---===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// This file declares semantic analysis functions specific to `-fbounds-safety`
10/// (Bounds Safety) and also its attributes when used without `-fbounds-safety`
11/// (e.g. `counted_by`)
12///
13//===----------------------------------------------------------------------===//
14#include "clang/Lex/Lexer.h"
16#include "clang/Sema/Sema.h"
17
18namespace clang {
19
21 bool OrNull) {
22 if (CountInBytes)
27}
28
31 // Clang does not yet implement __ended_by (see BoundsSafety.md).
32 assert(!Flags.IsEndedBy && "ended_by is not implemented");
33 return getCountAttrKind(Flags.CountInBytes, Flags.OrNull);
34}
35
37 BoundsAttrFlags Flags;
38 switch (K) {
39 case ParsedAttr::AT_SizedBy:
40 Flags.CountInBytes = true;
41 break;
42 case ParsedAttr::AT_SizedByOrNull:
43 Flags.CountInBytes = true;
44 Flags.OrNull = true;
45 break;
46 case ParsedAttr::AT_CountedBy:
47 break;
48 case ParsedAttr::AT_CountedByOrNull:
49 Flags.OrNull = true;
50 break;
51 default:
52 llvm_unreachable("unexpected bounds attribute kind");
53 }
54 return Flags;
55}
56
58 const auto *RD = FD->getParent();
59 // An unnamed struct is treated as anonymous struct at this point.
60 // A struct may not be fully processed yet to determine
61 // whether it's anonymous or not. In that case, this function treats it as
62 // an anonymous struct and tries to find a named parent.
63 while (RD && (RD->isAnonymousStructOrUnion() || RD->getName().empty())) {
64 const auto *Parent = dyn_cast<RecordDecl>(RD->getParent());
65 if (!Parent)
66 break;
67 RD = Parent;
68 }
69 return RD;
70}
71
79
80/// Check type conflicts under the -fbounds-safety attribute model.
81/// Return std::nullopt if validation should continue with the shared checks.
82static std::optional<bool> checkBoundsAttrTypeConflictsAndMisc(
83 Sema &S, QualType Ty, SourceLocation AttrLoc,
84 const Sema::BoundsAttrFlags &Flags, StringRef AttrSpelling,
85 bool AllowRedecl, Expr *AttrArg) {
86 // The -fbounds-safety model's checks for conflicting attributes, atomic
87 // pointers and array shapes are not upstream yet.
88 return std::nullopt;
89}
90
92 SourceRange AttrRange,
93 BoundsAttrFlags &Flags,
94 StringRef AttrSpelling, bool AllowRedecl,
95 Expr *AttrArg, bool UpdateFlags) {
96 if (getLangOpts().hasBoundsSafetyAttributes())
97 if (std::optional<bool> Result = checkBoundsAttrTypeConflictsAndMisc(
98 *this, Ty, AttrLoc, Flags, AttrSpelling, AllowRedecl, AttrArg))
99 return *Result;
100
102
103 // counted_by and sized_by require a pointer or array.
104 if (!Ty->isPointerType() && !Ty->isArrayType()) {
105 Diag(AttrLoc, diag::err_count_attr_not_on_ptr_or_flexible_array_member)
106 << Kind << 0;
107 return false;
108 }
109
110 // Arrays only support counted_by outside the -fbounds-safety attribute model.
111 if (!getLangOpts().hasBoundsSafetyAttributes() && Ty->isArrayType() &&
112 (Flags.CountInBytes || Flags.OrNull)) {
113 Diag(AttrLoc, diag::err_count_attr_not_on_ptr_or_flexible_array_member)
114 << Kind << /*suggest counted_by*/ 1;
115 return false;
116 }
117
118 // Check the pointee or element type.
119 QualType PointeeTy;
120 int SelectPtrOrArr;
121 if (Ty->isPointerType()) {
122 PointeeTy = Ty->getPointeeType();
123 SelectPtrOrArr = 0;
124 } else {
125 const ArrayType *AT = getASTContext().getAsArrayType(Ty);
126 PointeeTy = AT->getElementType();
127 SelectPtrOrArr = 1;
128 }
129
130 auto InvalidTypeKind = CountedByInvalidPointeeTypeKind::VALID;
131 bool ShouldWarn = false;
132 if (!Flags.CountInBytes && PointeeTy->isAlwaysIncompleteType()) {
133 // In general using `counted_by` or `counted_by_or_null` on
134 // pointers where the pointee is an incomplete type are problematic. This
135 // is because it isn't possible to compute the pointer's bounds without
136 // knowing the pointee type size. At the same time it is common to forward
137 // declare types in header files.
138 //
139 // E.g.:
140 //
141 // struct Handle;
142 // struct Wrapper {
143 // size_t count;
144 // struct Handle* __counted_by(count) handles;
145 // }
146 //
147 // To allow the above code pattern but still prevent the pointee type from
148 // being incomplete in places where bounds checks are needed the following
149 // scheme is used:
150 //
151 // * When the pointee type might not always be an incomplete type (i.e.
152 // a type that is currently incomplete but might be completed later
153 // on in the translation unit) the attribute is allowed by this method
154 // but later uses of the FieldDecl are checked that the pointee type
155 // is complete see `BoundsSafetyCheckAssignmentToCountAttrPtr`,
156 // `BoundsSafetyCheckInitialization`, and
157 // `BoundsSafetyCheckUseOfCountAttrPtr`
158 //
159 // * When the pointee type is always an incomplete type (e.g.
160 // `void` in strict C mode) the attribute is disallowed by this method
161 // because we know the type can never be completed so there's no reason
162 // to allow it.
163 //
164 // Exception: void has an implicit size of 1 byte for pointer arithmetic
165 // (following GNU convention). Therefore, counted_by on void* is allowed
166 // and behaves equivalently to sized_by (treating the count as bytes).
167 if (PointeeTy->isVoidType() && !getLangOpts().hasBoundsSafetyAttributes()) {
168 // Emit a warning that this is a GNU extension.
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");
172 if (UpdateFlags)
173 Flags.CountInBytes = true;
174 return true;
175 }
177 } else if (PointeeTy->isSizelessType()) {
179 } else if (PointeeTy->isFunctionType()) {
181 } else if (!Flags.CountInBytes &&
183 if (Ty->isArrayType()) {
184 // This is a workaround for the Linux kernel that has already adopted
185 // `counted_by` on a FAM where the pointee is a struct with a FAM. This
186 // should be an error because computing the bounds of the array cannot
187 // be done correctly without manually traversing every struct object in
188 // the array at runtime. To allow the code to be built this error is
189 // downgraded to a warning.
190 ShouldWarn = true;
191 }
193 }
194
195 if (InvalidTypeKind != CountedByInvalidPointeeTypeKind::VALID) {
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;
201 if (ShouldWarn)
202 return true;
203 if (getLangOpts().hasBoundsSafetyAttributes() && !Ty->isArrayType()) {
204 // Under BoundsSafety, recover by switching to byte count so that
205 // type construction can proceed and emit follow-up diagnostics.
206 // We don't do this for arrays because `__sized_by` is not allowed.
207 Flags.CountInBytes = true;
208 return true;
209 }
210 return false;
211 }
212
213 return true;
214}
215
218 SourceRange AttrRange, unsigned PointerNestLevel, BoundsAttrFlags &Flags) {
219 Flags = BoundsAttrFlags::get(AttrKind);
220
221 if (!ValidateBoundsAttrTypeShape(Ty, AttrLoc, AttrRange, Flags,
222 /*AttrSpelling=*/{}, /*AllowRedecl=*/false,
223 /*AttrArg=*/nullptr, /*UpdateFlags=*/false))
224 return false;
225
226 // Currently, only attributes at the outermost level of the declared type
227 // are supported.
228 //
229 // FIXME: Support indirect parameters such as:
230 // void f(int *__counted_by(*len) *buf, int *len);
231 // See https://github.com/llvm/llvm-project/issues/166411.
232 if (PointerNestLevel > 0) {
233 Diag(AttrLoc, diag::err_counted_by_on_nested_pointer)
234 << getBoundsAttrKind(Flags);
235 return false;
236 }
237
238 return true;
239}
240
241bool Sema::CheckCountedByAttrOnField(FieldDecl *FD, Expr *E, bool CountInBytes,
242 bool OrNull) {
243 // Check the context the attribute is used in
244
245 unsigned Kind = getCountAttrKind(CountInBytes, OrNull);
246
247 if (FD->getParent()->isUnion()) {
248 Diag(FD->getBeginLoc(), diag::err_count_attr_in_union)
249 << Kind << FD->getSourceRange();
250 return true;
251 }
252
253 const auto FieldTy = FD->getType();
254 if (FieldTy->isArrayType() && (CountInBytes || OrNull)) {
255 Diag(FD->getBeginLoc(),
256 diag::err_count_attr_not_on_ptr_or_flexible_array_member)
257 << Kind << FD->getLocation() << /* suggest counted_by */ 1;
258 return true;
259 }
260 if (!FieldTy->isArrayType() && !FieldTy->isPointerType()) {
261 Diag(FD->getBeginLoc(),
262 diag::err_count_attr_not_on_ptr_or_flexible_array_member)
263 << Kind << FD->getLocation() << /* do not suggest counted_by */ 0;
264 return true;
265 }
266
267 LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel =
269 if (FieldTy->isArrayType() &&
271 StrictFlexArraysLevel, true)) {
272 Diag(FD->getBeginLoc(),
273 diag::err_counted_by_attr_on_array_not_flexible_array_member)
274 << Kind << FD->getLocation();
275 return true;
276 }
277
278 CountedByInvalidPointeeTypeKind InvalidTypeKind =
280 QualType PointeeTy;
281 int SelectPtrOrArr = 0;
282 if (FieldTy->isPointerType()) {
283 PointeeTy = FieldTy->getPointeeType();
284 SelectPtrOrArr = 0;
285 } else {
286 assert(FieldTy->isArrayType());
287 const ArrayType *AT = getASTContext().getAsArrayType(FieldTy);
288 PointeeTy = AT->getElementType();
289 SelectPtrOrArr = 1;
290 }
291 // Note: The `Decl::isFlexibleArrayMemberLike` check earlier on means
292 // only `PointeeTy->isStructureTypeWithFlexibleArrayMember()` is reachable
293 // when `FieldTy->isArrayType()`.
294 bool ShouldWarn = false;
295 if (!CountInBytes && PointeeTy->isAlwaysIncompleteType()) {
296 // In general using `counted_by` or `counted_by_or_null` on
297 // pointers where the pointee is an incomplete type are problematic. This is
298 // because it isn't possible to compute the pointer's bounds without knowing
299 // the pointee type size. At the same time it is common to forward declare
300 // types in header files.
301 //
302 // E.g.:
303 //
304 // struct Handle;
305 // struct Wrapper {
306 // size_t count;
307 // struct Handle* __counted_by(count) handles;
308 // }
309 //
310 // To allow the above code pattern but still prevent the pointee type from
311 // being incomplete in places where bounds checks are needed the following
312 // scheme is used:
313 //
314 // * When the pointee type might not always be an incomplete type (i.e.
315 // a type that is currently incomplete but might be completed later
316 // on in the translation unit) the attribute is allowed by this method
317 // but later uses of the FieldDecl are checked that the pointee type
318 // is complete see `BoundsSafetyCheckAssignmentToCountAttrPtr`,
319 // `BoundsSafetyCheckInitialization`, and
320 // `BoundsSafetyCheckUseOfCountAttrPtr`
321 //
322 // * When the pointee type is always an incomplete type (e.g.
323 // `void` in strict C mode) the attribute is disallowed by this method
324 // because we know the type can never be completed so there's no reason
325 // to allow it.
326 //
327 // Exception: void has an implicit size of 1 byte for pointer arithmetic
328 // (following GNU convention). Therefore, counted_by on void* is allowed
329 // and behaves equivalently to sized_by (treating the count as bytes).
330 bool IsVoidPtr = PointeeTy->isVoidType();
331 if (IsVoidPtr) {
332 // Emit a warning that this is a GNU extension.
333 Diag(FD->getBeginLoc(), diag::ext_gnu_counted_by_void_ptr) << Kind;
334 Diag(FD->getBeginLoc(), diag::note_gnu_counted_by_void_ptr_use_sized_by)
335 << Kind;
336 assert(InvalidTypeKind == CountedByInvalidPointeeTypeKind::VALID);
337 } else {
339 }
340 } else if (PointeeTy->isSizelessType()) {
342 } else if (PointeeTy->isFunctionType()) {
344 } else if (!CountInBytes &&
346 if (FieldTy->isArrayType() && !getLangOpts().BoundsSafety) {
347 // This is a workaround for the Linux kernel that has already adopted
348 // `counted_by` on a FAM where the pointee is a struct with a FAM. This
349 // should be an error because computing the bounds of the array cannot be
350 // done correctly without manually traversing every struct object in the
351 // array at runtime. To allow the code to be built this error is
352 // downgraded to a warning.
353 ShouldWarn = true;
354 }
356 }
357
358 if (InvalidTypeKind != CountedByInvalidPointeeTypeKind::VALID) {
359 unsigned DiagID = ShouldWarn
360 ? diag::warn_counted_by_attr_elt_type_unknown_size
361 : diag::err_counted_by_attr_pointee_unknown_size;
362 Diag(FD->getBeginLoc(), DiagID)
363 << SelectPtrOrArr << PointeeTy << (int)InvalidTypeKind
364 << (ShouldWarn ? 1 : 0) << Kind << FD->getSourceRange();
365 return true;
366 }
367
368 // Check the expression
369
370 if (!E->getType()->isIntegerType() || E->getType()->isBooleanType()) {
371 Diag(E->getBeginLoc(), diag::err_count_attr_argument_not_integer)
372 << Kind << E->getSourceRange();
373 return true;
374 }
375
376 auto *DRE = dyn_cast<DeclRefExpr>(E);
377 if (!DRE) {
378 Diag(E->getBeginLoc(),
379 diag::err_count_attr_only_support_simple_decl_reference)
380 << Kind << E->getSourceRange();
381 return true;
382 }
383
384 auto *CountDecl = DRE->getDecl();
385 FieldDecl *CountFD = dyn_cast<FieldDecl>(CountDecl);
386 if (auto *IFD = dyn_cast<IndirectFieldDecl>(CountDecl)) {
387 CountFD = IFD->getAnonField();
388 }
389 if (!CountFD) {
390 Diag(E->getBeginLoc(), diag::err_count_attr_must_be_in_structure)
391 << CountDecl << Kind << E->getSourceRange();
392
393 Diag(CountDecl->getBeginLoc(),
394 diag::note_flexible_array_counted_by_attr_field)
395 << CountDecl << CountDecl->getSourceRange();
396 return true;
397 }
398
399 if (FD->getParent() != CountFD->getParent()) {
400 if (CountFD->getParent()->isUnion()) {
401 Diag(CountFD->getBeginLoc(), diag::err_count_attr_refer_to_union)
402 << Kind << CountFD->getSourceRange();
403 return true;
404 }
405 // Whether CountRD is an anonymous struct is not determined at this
406 // point. Thus, an additional diagnostic in case it's not anonymous struct
407 // is done later in `Parser::ParseStructDeclaration`.
409 auto *CountRD = GetEnclosingNamedOrTopAnonRecord(CountFD);
410
411 if (RD != CountRD) {
412 Diag(E->getBeginLoc(), diag::err_count_attr_param_not_in_same_struct)
413 << CountFD << Kind << FieldTy->isArrayType() << E->getSourceRange();
414 Diag(CountFD->getBeginLoc(),
415 diag::note_flexible_array_counted_by_attr_field)
416 << CountFD << CountFD->getSourceRange();
417 return true;
418 }
419 }
420 return false;
421}
422
424 const CountAttributedType *CATy,
425 NamedDecl *IncompleteTyDecl) {
426 assert(IncompleteTyDecl == nullptr || isa<TypeDecl>(IncompleteTyDecl));
427
428 if (IncompleteTyDecl) {
429 // Suggest completing the pointee type if its a named typed (i.e.
430 // IncompleteTyDecl isn't nullptr). Suggest this first as it is more likely
431 // to be the correct fix.
432 //
433 // Note the `IncompleteTyDecl` type is the underlying type which might not
434 // be the same as `CATy->getPointeeType()` which could be a typedef.
435 //
436 // The diagnostic printed will be at the location of the underlying type but
437 // the diagnostic text will print the type of `CATy->getPointeeType()` which
438 // could be a typedef name rather than the underlying type. This is ok
439 // though because the diagnostic will print the underlying type name too.
440 S.Diag(IncompleteTyDecl->getBeginLoc(),
441 diag::note_counted_by_consider_completing_pointee_ty)
442 << CATy->getPointeeType();
443 }
444
445 // Suggest using __sized_by(_or_null) instead of __counted_by(_or_null) as
446 // __sized_by(_or_null) doesn't have the complete type restriction.
447 //
448 // We use the source range of the expression on the CountAttributedType as an
449 // approximation for the source range of the attribute. This isn't quite right
450 // but isn't easy to fix right now.
451 //
452 // TODO: Implement logic to find the relevant TypeLoc for the attribute and
453 // get the SourceRange from that (#113582).
454 //
455 // TODO: We should emit a fix-it here.
456 SourceRange AttrSrcRange = CATy->getCountExpr()->getSourceRange();
457 S.Diag(AttrSrcRange.getBegin(), diag::note_counted_by_consider_using_sized_by)
458 << CATy->isOrNull() << AttrSrcRange;
459}
460
461static std::tuple<const CountAttributedType *, QualType>
463 auto *CATy = Ty->getAs<CountAttributedType>();
464 // Incomplete pointee type is only a problem for
465 // counted_by/counted_by_or_null
466 if (!CATy || CATy->isCountInBytes())
467 return {};
468
469 auto PointeeTy = CATy->getPointeeType();
470 if (PointeeTy.isNull()) {
471 // Reachable if `CountAttributedType` wraps an IncompleteArrayType
472 return {};
473 }
474
475 if (!PointeeTy->isIncompleteType(ND))
476 return {};
477
478 if (PointeeTy->isVoidType())
479 return {};
480
481 return {CATy, PointeeTy};
482}
483
484/// Perform Checks for assigning to a `__counted_by` or
485/// `__counted_by_or_null` pointer type \param LHSTy where the pointee type
486/// is incomplete which is invalid.
487///
488/// \param S The Sema instance.
489/// \param LHSTy The type being assigned to. Checks will only be performed if
490/// the type is a `counted_by` or `counted_by_or_null ` pointer.
491/// \param RHSExpr The expression being assigned from.
492/// \param Action The type assignment being performed
493/// \param Loc The SourceLocation to use for error diagnostics
494/// \param Assignee The ValueDecl being assigned. This is used to compute
495/// the name of the assignee. If the assignee isn't known this can
496/// be set to nullptr.
497/// \param ShowFullyQualifiedAssigneeName If set to true when using \p
498/// Assignee to compute the name of the assignee use the fully
499/// qualified name, otherwise use the unqualified name.
500///
501/// \returns True iff no diagnostic where emitted, false otherwise.
503 Sema &S, QualType LHSTy, Expr *RHSExpr, AssignmentAction Action,
504 SourceLocation Loc, const ValueDecl *Assignee,
505 bool ShowFullyQualifiedAssigneeName) {
506 NamedDecl *IncompleteTyDecl = nullptr;
507 auto [CATy, PointeeTy] =
508 GetCountedByAttrOnIncompletePointee(LHSTy, &IncompleteTyDecl);
509 if (!CATy)
510 return true;
511
512 std::string AssigneeStr;
513 if (Assignee) {
514 if (ShowFullyQualifiedAssigneeName) {
515 AssigneeStr = Assignee->getQualifiedNameAsString();
516 } else {
517 AssigneeStr = Assignee->getNameAsString();
518 }
519 }
520
521 S.Diag(Loc, diag::err_counted_by_on_incomplete_type_on_assign)
522 << static_cast<int>(Action) << AssigneeStr << (AssigneeStr.size() > 0)
523 << isa<ImplicitValueInitExpr>(RHSExpr) << LHSTy
524 << CATy->getAttributeName(/*WithMacroPrefix=*/true) << PointeeTy
525 << CATy->isOrNull() << RHSExpr->getSourceRange();
526
527 EmitIncompleteCountedByPointeeNotes(S, CATy, IncompleteTyDecl);
528 return false; // check failed
529}
530
532 QualType LHSTy, Expr *RHSExpr, AssignmentAction Action, SourceLocation Loc,
533 const ValueDecl *Assignee, bool ShowFullyQualifiedAssigneeName) {
535 *this, LHSTy, RHSExpr, Action, Loc, Assignee,
536 ShowFullyQualifiedAssigneeName);
537}
538
540 const InitializationKind &Kind,
541 AssignmentAction Action,
542 QualType LHSType, Expr *RHSExpr) {
543 auto SL = Kind.getLocation();
544
545 // Note: We don't call `BoundsSafetyCheckAssignmentToCountAttrPtr` here
546 // because we need conditionalize what is checked. In downstream
547 // Clang `counted_by` is supported on variable definitions and in that
548 // implementation an error diagnostic will be emitted on the variable
549 // definition if the pointee is an incomplete type. To avoid warning about the
550 // same problem twice (once when the variable is defined, once when Sema
551 // checks the initializer) we skip checking the initializer if it's a
552 // variable.
553 if (Action == AssignmentAction::Initializing &&
555
557 *this, LHSType, RHSExpr, Action, SL,
558 dyn_cast_or_null<ValueDecl>(Entity.getDecl()),
559 /*ShowFullQualifiedAssigneeName=*/true)) {
560 return false;
561 }
562 }
563
564 return true;
565}
566
568 QualType T = E->getType();
569 if (!T->isPointerType())
570 return true;
571
572 NamedDecl *IncompleteTyDecl = nullptr;
573 auto [CATy, PointeeTy] =
574 GetCountedByAttrOnIncompletePointee(T, &IncompleteTyDecl);
575 if (!CATy)
576 return true;
577
578 // Generate a string for the diagnostic that describes the "use".
579 // The string is specialized for direct calls to produce a better
580 // diagnostic.
581 SmallString<64> UseStr;
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();
586 IsDirectCall = true;
587 }
588 }
589
590 if (!IsDirectCall) {
591 llvm::raw_svector_ostream SS(UseStr);
592 E->printPretty(SS, nullptr, getPrintingPolicy());
593 }
594
595 Diag(E->getBeginLoc(), diag::err_counted_by_on_incomplete_type_on_use)
596 << IsDirectCall << UseStr << T << PointeeTy
597 << CATy->getAttributeName(/*WithMacroPrefix=*/true) << CATy->isOrNull()
598 << E->getSourceRange();
599
600 EmitIncompleteCountedByPointeeNotes(*this, CATy, IncompleteTyDecl);
601 return false;
602}
603
604} // namespace clang
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3820
QualType getElementType() const
Definition TypeBase.h:3832
Represents a sugar type with __counted_by or __sized_by annotations, including their _or_null variant...
Definition TypeBase.h:3509
Expr * getCountExpr() const
Definition TypeBase.h:3544
static bool isFlexibleArrayMemberLike(const ASTContext &Context, const Decl *D, QualType Ty, LangOptions::StrictFlexArraysLevelKind StrictFlexArraysLevel, bool IgnoreTemplateOrMacroSubstitution)
Whether it resembles a flexible array member.
Definition DeclBase.cpp:463
SourceLocation getLocation() const
Definition DeclBase.h:447
SourceLocation getBeginLoc() const LLVM_READONLY
Definition DeclBase.h:439
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Decl.h:832
This represents one expression.
Definition Expr.h:113
Expr * IgnoreParens() LLVM_READONLY
Skip past any parentheses which might surround this expression until reaching a fixed point.
Definition Expr.cpp:3125
QualType getType() const
Definition Expr.h:145
Represents a member of a struct/union/class.
Definition Decl.h:3299
SourceRange getSourceRange() const override LLVM_READONLY
Source range that this declaration covers.
Definition Decl.cpp:4901
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Definition Decl.h:3535
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.
@ IncompleteOnly
Any trailing array member of undefined size is a FAM.
This represents a decl that may have a name.
Definition Decl.h:275
std::string getQualifiedNameAsString() const
Definition Decl.cpp:1682
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...
Definition Decl.h:318
A (possibly-)qualified type.
Definition TypeBase.h:938
Represents a struct/union/class.
Definition Decl.h:4464
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID)
Emit a diagnostic.
Definition SemaBase.cpp:61
Sema - This implements semantic analysis and AST building for C.
Definition Sema.h:863
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
Definition Sema.h:935
PrintingPolicy getPrintingPolicy() const
Retrieve a suitable printing policy for diagnostics.
Definition Sema.h:1236
const LangOptions & getLangOpts() const
Definition Sema.h:928
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...
Definition Stmt.cpp:343
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:355
bool isUnion() const
Definition Decl.h:4067
bool isSizelessType() const
As an extension, we classify types as one of "sized" or "sizeless"; every type is one or the other.
Definition Type.cpp:2789
bool isVoidType() const
Definition TypeBase.h:9068
bool isBooleanType() const
Definition TypeBase.h:9209
bool isAlwaysIncompleteType() const
Definition Type.cpp:2735
bool isArrayType() const
Definition TypeBase.h:8782
bool isPointerType() const
Definition TypeBase.h:8683
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:9116
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:885
bool isFunctionType() const
Definition TypeBase.h:8679
bool isStructureTypeWithFlexibleArrayMember() const
Definition Type.cpp:817
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9299
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:713
QualType getType() const
Definition Decl.h:724
Top level wrappers for InstallAPI frontend operations.
bool isa(CodeGen::Address addr)
Definition Address.h:330
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.
Definition TypeBase.h:906
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)
AssignmentAction
Definition Sema.h:217
static BoundsAttrFlags get(AttributeCommonInfo::Kind K)
Return the flags for a bounds attribute of kind K.