clang: lib/Sema/SemaBoundsSafety.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
17
19
28
31
32
33
34
35 while (RD && (RD->isAnonymousStructOrUnion() ||
36 (!RD->isCompleteDefinition() && RD->getName().empty()))) {
37 const auto *Parent = dyn_cast(RD->getParent());
38 if (!Parent)
39 break;
40 RD = Parent;
41 }
42 return RD;
43}
44
52
54 bool OrNull) {
55
56
58
62 return true;
63 }
64
65 const auto FieldTy = FD->getType();
66 if (FieldTy->isArrayType() && (CountInBytes || OrNull)) {
68 diag::err_count_attr_not_on_ptr_or_flexible_array_member)
69 << Kind << FD->getLocation() << 1;
70 return true;
71 }
72 if (!FieldTy->isArrayType() && !FieldTy->isPointerType()) {
74 diag::err_count_attr_not_on_ptr_or_flexible_array_member)
75 << Kind << FD->getLocation() << 0;
76 return true;
77 }
78
81 if (FieldTy->isArrayType() &&
83 StrictFlexArraysLevel, true)) {
85 diag::err_counted_by_attr_on_array_not_flexible_array_member)
87 return true;
88 }
89
93 int SelectPtrOrArr = 0;
94 if (FieldTy->isPointerType()) {
96 SelectPtrOrArr = 0;
97 } else {
98 assert(FieldTy->isArrayType());
101 SelectPtrOrArr = 1;
102 }
103
104
105
106 bool ShouldWarn = false;
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142 bool IsVoidPtr = PointeeTy->isVoidType();
143 if (IsVoidPtr) {
144
145 Diag(FD->getBeginLoc(), diag::ext_gnu_counted_by_void_ptr) << Kind;
146 Diag(FD->getBeginLoc(), diag::note_gnu_counted_by_void_ptr_use_sized_by)
147 << Kind;
149 } else {
151 }
157 if (FieldTy->isArrayType() && ().BoundsSafety) {
158
159
160
161
162
163
164 ShouldWarn = true;
165 }
167 }
168
170 unsigned DiagID = ShouldWarn
171 ? diag::warn_counted_by_attr_elt_type_unknown_size
172 : diag::err_counted_by_attr_pointee_unknown_size;
174 << SelectPtrOrArr << PointeeTy << (int)InvalidTypeKind
175 << (ShouldWarn ? 1 : 0) << Kind << FD->getSourceRange();
176 return true;
177 }
178
179
180
182 Diag(E->getBeginLoc(), diag::err_count_attr_argument_not_integer)
184 return true;
185 }
186
187 auto *DRE = dyn_cast(E);
188 if (!DRE) {
190 diag::err_count_attr_only_support_simple_decl_reference)
192 return true;
193 }
194
195 auto *CountDecl = DRE->getDecl();
196 FieldDecl *CountFD = dyn_cast(CountDecl);
197 if (auto *IFD = dyn_cast(CountDecl)) {
198 CountFD = IFD->getAnonField();
199 }
200 if (!CountFD) {
201 Diag(E->getBeginLoc(), diag::err_count_attr_must_be_in_structure)
203
204 Diag(CountDecl->getBeginLoc(),
205 diag::note_flexible_array_counted_by_attr_field)
206 << CountDecl << CountDecl->getSourceRange();
207 return true;
208 }
209
212 Diag(CountFD->getBeginLoc(), diag::err_count_attr_refer_to_union)
214 return true;
215 }
216
217
218
221
222 if (RD != CountRD) {
223 Diag(E->getBeginLoc(), diag::err_count_attr_param_not_in_same_struct)
224 << CountFD << Kind << FieldTy->isArrayType() << E->getSourceRange();
226 diag::note_flexible_array_counted_by_attr_field)
228 return true;
229 }
230 }
231 return false;
232}
233
237 assert(IncompleteTyDecl == nullptr || isa(IncompleteTyDecl));
238
239 if (IncompleteTyDecl) {
240
241
242
243
244
245
246
247
248
249
250
252 diag::note_counted_by_consider_completing_pointee_ty)
254 }
255
256
257
258
259
260
261
262
263
264
265
266
268 S.Diag(AttrSrcRange.getBegin(), diag::note_counted_by_consider_using_sized_by)
269 << CATy->isOrNull() << AttrSrcRange;
270}
271
272static std::tuple<const CountAttributedType *, QualType>
275
276
277 if (!CATy || CATy->isCountInBytes())
278 return {};
279
281 if (PointeeTy.isNull()) {
282
283 return {};
284 }
285
286 if (!PointeeTy->isIncompleteType(ND))
287 return {};
288
289 if (PointeeTy->isVoidType())
290 return {};
291
292 return {CATy, PointeeTy};
293}
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
316 bool ShowFullyQualifiedAssigneeName) {
317 NamedDecl *IncompleteTyDecl = nullptr;
318 auto [CATy, PointeeTy] =
320 if (!CATy)
321 return true;
322
323 std::string AssigneeStr;
324 if (Assignee) {
325 if (ShowFullyQualifiedAssigneeName) {
327 } else {
329 }
330 }
331
332 S.Diag(Loc, diag::err_counted_by_on_incomplete_type_on_assign)
333 << static_cast<int>(Action) << AssigneeStr << (AssigneeStr.size() > 0)
335 << CATy->getAttributeName(true) << PointeeTy
337
339 return false;
340}
341
344 const ValueDecl *Assignee, bool ShowFullyQualifiedAssigneeName) {
346 *this, LHSTy, RHSExpr, Action, Loc, Assignee,
347 ShowFullyQualifiedAssigneeName);
348}
349
354 auto SL = Kind.getLocation();
355
356
357
358
359
360
361
362
363
366
368 *this, LHSType, RHSExpr, Action, SL,
369 dyn_cast_or_null(Entity.getDecl()),
370 true)) {
371 return false;
372 }
373 }
374
375 return true;
376}
377
380 if (->isPointerType())
381 return true;
382
383 NamedDecl *IncompleteTyDecl = nullptr;
384 auto [CATy, PointeeTy] =
386 if (!CATy)
387 return true;
388
389
390
391
393 bool IsDirectCall = false;
394 if (const auto *CE = dyn_cast(E->IgnoreParens())) {
395 if (const auto *FD = CE->getDirectCallee()) {
396 UseStr = FD->getName();
397 IsDirectCall = true;
398 }
399 }
400
401 if (!IsDirectCall) {
402 llvm::raw_svector_ostream SS(UseStr);
404 }
405
406 Diag(E->getBeginLoc(), diag::err_counted_by_on_incomplete_type_on_use)
407 << IsDirectCall << UseStr << T << PointeeTy
408 << CATy->getAttributeName(true) << CATy->isOrNull()
410
412 return false;
413}
414
415}
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...
Definition SemaBoundsSafety.cpp:342
bool BoundsSafetyCheckUseOfCountAttrPtr(const Expr *E)
Perform Bounds Safety semantic checks for uses of invalid uses counted_by or counted_by_or_null point...
Definition SemaBoundsSafety.cpp:378
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...
Definition SemaBoundsSafety.cpp:53
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.
Definition SemaBoundsSafety.cpp:350
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 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'.
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
The JSON file list parser is used to communicate input to InstallAPI.
bool isa(CodeGen::Address addr)
static CountAttributedType::DynamicCountPointerKind getCountAttrKind(bool CountInBytes, bool OrNull)
Definition SemaBoundsSafety.cpp:21
CountedByInvalidPointeeTypeKind
Definition SemaBoundsSafety.cpp:45
@ INCOMPLETE
Definition SemaBoundsSafety.cpp:46
@ SIZELESS
Definition SemaBoundsSafety.cpp:47
@ FLEXIBLE_ARRAY_MEMBER
Definition SemaBoundsSafety.cpp:49
@ FUNCTION
Definition SemaBoundsSafety.cpp:48
@ VALID
Definition SemaBoundsSafety.cpp:50
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.
Definition SemaBoundsSafety.cpp:313
static const RecordDecl * GetEnclosingNamedOrTopAnonRecord(const FieldDecl *FD)
Definition SemaBoundsSafety.cpp:29
static void EmitIncompleteCountedByPointeeNotes(Sema &S, const CountAttributedType *CATy, NamedDecl *IncompleteTyDecl)
Definition SemaBoundsSafety.cpp:234
static std::tuple< const CountAttributedType *, QualType > GetCountedByAttrOnIncompletePointee(QualType Ty, NamedDecl **ND)
Definition SemaBoundsSafety.cpp:273
const FunctionProtoType * T