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