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() && getLangOpts().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 (T->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