@@ -3508,7 +3508,7 @@ static void handleFormatAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
3508
3508
3509
3509
// In C++ the implicit 'this' function parameter also counts, and they are
3510
3510
// counted from one.
3511
- bool HasImplicitThisParam = isInstanceMethod (D);
3511
+ bool HasImplicitThisParam = checkIfMethodHasImplicitObjectParameter (D);
3512
3512
unsigned NumArgs = getFunctionOrMethodNumParams(D) + HasImplicitThisParam;
3513
3513
3514
3514
IdentifierInfo *II = AL.getArgAsIdent(0)->Ident;
@@ -3621,7 +3621,7 @@ static void handleCallbackAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
3621
3621
return;
3622
3622
}
3623
3623
3624
- bool HasImplicitThisParam = isInstanceMethod (D);
3624
+ bool HasImplicitThisParam = checkIfMethodHasImplicitObjectParameter (D);
3625
3625
int32_t NumArgs = getFunctionOrMethodNumParams(D);
3626
3626
3627
3627
FunctionDecl *FD = D->getAsFunction();
@@ -5320,6 +5320,221 @@ static void handlePreferredTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
5320
5320
D->addAttr(::new (S.Context) PreferredTypeAttr(S.Context, AL, ParmTSI));
5321
5321
}
5322
5322
5323
+ // This function is called only if function call is not inside template body.
5324
+ // TODO: Add call for function calls inside template body.
5325
+ // Emit warnings if parent function misses format attributes.
5326
+ void Sema::DiagnoseMissingFormatAttributes(Stmt *Body,
5327
+ const FunctionDecl *FDecl) {
5328
+ assert(FDecl);
5329
+
5330
+ // If there are no function body, exit.
5331
+ if (!Body)
5332
+ return;
5333
+
5334
+ // Get missing format attributes
5335
+ std::vector<FormatAttr *> MissingFormatAttributes =
5336
+ GetMissingFormatAttributes(Body, FDecl);
5337
+ if (MissingFormatAttributes.empty())
5338
+ return;
5339
+
5340
+ // Check if there are more than one format type found. In that case do not
5341
+ // emit diagnostic.
5342
+ const FormatAttr *FirstAttr = MissingFormatAttributes[0];
5343
+ if (llvm::any_of(MissingFormatAttributes, [&](const FormatAttr *Attr) {
5344
+ return FirstAttr->getType() != Attr->getType();
5345
+ }))
5346
+ return;
5347
+
5348
+ for (const FormatAttr *FA : MissingFormatAttributes) {
5349
+ // If format index and first-to-check argument index are negative, it means
5350
+ // that this attribute is only saved for multiple format types checking.
5351
+ if (FA->getFormatIdx() < 0 || FA->getFirstArg() < 0)
5352
+ continue;
5353
+
5354
+ // Emit diagnostic
5355
+ SourceLocation Loc = FDecl->getLocation();
5356
+ Diag(Loc, diag::warn_missing_format_attribute)
5357
+ << FA->getType() << FDecl
5358
+ << FixItHint::CreateInsertion(Loc,
5359
+ (llvm::Twine("__attribute__((format(") +
5360
+ FA->getType()->getName() + ", " +
5361
+ llvm::Twine(FA->getFormatIdx()) + ", " +
5362
+ llvm::Twine(FA->getFirstArg()) + ")))")
5363
+ .str());
5364
+ }
5365
+ }
5366
+
5367
+ // Returns vector of format attributes. There are no two attributes with same
5368
+ // arguments in returning vector. There can be attributes that effectivelly only
5369
+ // store information about format type.
5370
+ std::vector<FormatAttr *>
5371
+ Sema::GetMissingFormatAttributes(Stmt *Body, const FunctionDecl *FDecl) {
5372
+ unsigned int FunctionFormatArgumentIndexOffset =
5373
+ checkIfMethodHasImplicitObjectParameter(FDecl) ? 2 : 1;
5374
+
5375
+ std::vector<FormatAttr *> MissingAttributes;
5376
+
5377
+ // Iterate over body statements.
5378
+ for (auto *Child : Body->children()) {
5379
+ // If child statement is compound statement, recursively get missing
5380
+ // attributes.
5381
+ if (dyn_cast_or_null<CompoundStmt>(Child)) {
5382
+ std::vector<FormatAttr *> CompoundStmtMissingAttributes =
5383
+ GetMissingFormatAttributes(Child, FDecl);
5384
+
5385
+ // If there are already missing attributes with same arguments, do not add
5386
+ // duplicates.
5387
+ for (FormatAttr *FA : CompoundStmtMissingAttributes) {
5388
+ if (!llvm::any_of(MissingAttributes, [&](const FormatAttr *Attr) {
5389
+ return FA->getType() == Attr->getType() &&
5390
+ FA->getFormatIdx() == Attr->getFormatIdx() &&
5391
+ FA->getFirstArg() == Attr->getFirstArg();
5392
+ }))
5393
+ MissingAttributes.push_back(FA);
5394
+ }
5395
+
5396
+ continue;
5397
+ }
5398
+
5399
+ ValueStmt *VS = dyn_cast_or_null<ValueStmt>(Child);
5400
+ if (!VS)
5401
+ continue;
5402
+ Expr *TheExpr = VS->getExprStmt();
5403
+ if (!TheExpr)
5404
+ continue;
5405
+ CallExpr *TheCall = dyn_cast_or_null<CallExpr>(TheExpr);
5406
+ if (!TheCall)
5407
+ continue;
5408
+ const FunctionDecl *ChildFunction =
5409
+ dyn_cast_or_null<FunctionDecl>(TheCall->getCalleeDecl());
5410
+ if (!ChildFunction)
5411
+ continue;
5412
+
5413
+ Expr **Args = TheCall->getArgs();
5414
+ unsigned int NumArgs = TheCall->getNumArgs();
5415
+
5416
+ // If child expression is function, check if it is format function.
5417
+ // If it is, check if parent function misses format attributes.
5418
+
5419
+ // If child function is format function and format arguments are not
5420
+ // relevant to emit diagnostic, save only information about format type
5421
+ // (format index and first-to-check argument index are set to -1).
5422
+ // Information about format type is later used to determine if there are
5423
+ // more than one format type found.
5424
+
5425
+ unsigned int ChildFunctionFormatArgumentIndexOffset =
5426
+ checkIfMethodHasImplicitObjectParameter(ChildFunction) ? 2 : 1;
5427
+
5428
+ // Check if function has format attribute with forwarded format string.
5429
+ IdentifierInfo *AttrType;
5430
+ const ParmVarDecl *FormatArg;
5431
+ if (!llvm::any_of(ChildFunction->specific_attrs<FormatAttr>(),
5432
+ [&](const FormatAttr *Attr) {
5433
+ AttrType = Attr->getType();
5434
+
5435
+ int OffsetFormatIndex =
5436
+ Attr->getFormatIdx() -
5437
+ ChildFunctionFormatArgumentIndexOffset;
5438
+ if (OffsetFormatIndex < 0 ||
5439
+ (unsigned)OffsetFormatIndex >= NumArgs)
5440
+ return false;
5441
+
5442
+ const auto *FormatArgExpr = dyn_cast<DeclRefExpr>(
5443
+ Args[OffsetFormatIndex]->IgnoreParenCasts());
5444
+ if (!FormatArgExpr)
5445
+ return false;
5446
+
5447
+ FormatArg = dyn_cast_or_null<ParmVarDecl>(
5448
+ FormatArgExpr->getReferencedDeclOfCallee());
5449
+ if (!FormatArg)
5450
+ return false;
5451
+
5452
+ return true;
5453
+ })) {
5454
+ MissingAttributes.push_back(
5455
+ FormatAttr::CreateImplicit(getASTContext(), AttrType, -1, -1));
5456
+ continue;
5457
+ }
5458
+
5459
+ // Do not add in a vector format attributes whose type is different than
5460
+ // parent function attribute type.
5461
+ if (llvm::any_of(FDecl->specific_attrs<FormatAttr>(),
5462
+ [&](const FormatAttr *FunctionAttr) {
5463
+ return AttrType != FunctionAttr->getType();
5464
+ }))
5465
+ continue;
5466
+
5467
+ // Check if format string argument is parent function parameter.
5468
+ unsigned int StringIndex = 0;
5469
+ if (!llvm::any_of(FDecl->parameters(), [&](const ParmVarDecl *Param) {
5470
+ if (Param != FormatArg)
5471
+ return false;
5472
+
5473
+ StringIndex = Param->getFunctionScopeIndex() +
5474
+ FunctionFormatArgumentIndexOffset;
5475
+
5476
+ return true;
5477
+ })) {
5478
+ MissingAttributes.push_back(
5479
+ FormatAttr::CreateImplicit(getASTContext(), AttrType, -1, -1));
5480
+ continue;
5481
+ }
5482
+
5483
+ unsigned NumOfParentFunctionParams = FDecl->getNumParams();
5484
+
5485
+ // Compare parent and calling function format attribute arguments (archetype
5486
+ // and format string).
5487
+ if (llvm::any_of(
5488
+ FDecl->specific_attrs<FormatAttr>(), [&](const FormatAttr *Attr) {
5489
+ if (Attr->getType() != AttrType)
5490
+ return false;
5491
+ int OffsetFormatIndex =
5492
+ Attr->getFormatIdx() - FunctionFormatArgumentIndexOffset;
5493
+
5494
+ if (OffsetFormatIndex < 0 ||
5495
+ (unsigned)OffsetFormatIndex >= NumOfParentFunctionParams)
5496
+ return false;
5497
+
5498
+ if (FDecl->parameters()[OffsetFormatIndex] != FormatArg)
5499
+ return false;
5500
+
5501
+ return true;
5502
+ })) {
5503
+ MissingAttributes.push_back(
5504
+ FormatAttr::CreateImplicit(getASTContext(), AttrType, -1, -1));
5505
+ continue;
5506
+ }
5507
+
5508
+ // Get first argument index
5509
+ unsigned FirstToCheck = [&]() -> unsigned {
5510
+ if (!FDecl->isVariadic())
5511
+ return 0;
5512
+ const auto *FirstToCheckArg =
5513
+ dyn_cast<DeclRefExpr>(Args[NumArgs - 1]->IgnoreParenCasts());
5514
+ if (!FirstToCheckArg)
5515
+ return 0;
5516
+
5517
+ if (FirstToCheckArg->getType().getCanonicalType() !=
5518
+ Context.getBuiltinVaListType().getCanonicalType())
5519
+ return 0;
5520
+ return NumOfParentFunctionParams + FunctionFormatArgumentIndexOffset;
5521
+ }();
5522
+
5523
+ // If there are already attributes which arguments matches arguments
5524
+ // detected in this iteration, do not add new attribute as it would be
5525
+ // duplicate.
5526
+ if (!llvm::any_of(MissingAttributes, [&](const FormatAttr *Attr) {
5527
+ return Attr->getType() == AttrType &&
5528
+ Attr->getFormatIdx() == StringIndex &&
5529
+ Attr->getFirstArg() == FirstToCheck;
5530
+ }))
5531
+ MissingAttributes.push_back(FormatAttr::CreateImplicit(
5532
+ getASTContext(), AttrType, StringIndex, FirstToCheck));
5533
+ }
5534
+
5535
+ return MissingAttributes;
5536
+ }
5537
+
5323
5538
//===----------------------------------------------------------------------===//
5324
5539
// Microsoft specific attribute handlers.
5325
5540
//===----------------------------------------------------------------------===//
0 commit comments