@@ -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,217 @@ 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 || !ChildFunction->hasAttr <FormatAttr>())
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 child function is format function and format arguments are not
5438
+ // relevant to emit diagnostic, save only information about format type
5439
+ // (format index and first-to-check argument index are set to -1).
5440
+ // Information about format type is later used to determine if there are
5441
+ // more than one format type found.
5442
+
5443
+ // Check if function has format attribute with forwarded format string.
5444
+ IdentifierInfo *AttrType;
5445
+ const ParmVarDecl *FormatArg;
5446
+ if (!llvm::any_of (ChildFunction->specific_attrs <FormatAttr>(),
5447
+ [&](const FormatAttr *Attr) {
5448
+ AttrType = Attr->getType ();
5449
+
5450
+ int OffsetFormatIndex =
5451
+ Attr->getFormatIdx () -
5452
+ ChildFunctionFormatArgumentIndexOffset;
5453
+ if (OffsetFormatIndex < 0 ||
5454
+ (unsigned )OffsetFormatIndex >= NumArgs)
5455
+ return false ;
5456
+
5457
+ const auto *FormatArgExpr = dyn_cast<DeclRefExpr>(
5458
+ Args[OffsetFormatIndex]->IgnoreParenCasts ());
5459
+ if (!FormatArgExpr)
5460
+ return false ;
5461
+
5462
+ FormatArg = dyn_cast_or_null<ParmVarDecl>(
5463
+ FormatArgExpr->getReferencedDeclOfCallee ());
5464
+ if (!FormatArg)
5465
+ return false ;
5466
+
5467
+ return true ;
5468
+ })) {
5469
+ MissingAttributes.push_back (
5470
+ FormatAttr::CreateImplicit (getASTContext (), AttrType, -1 , -1 ));
5471
+ continue ;
5472
+ }
5473
+
5474
+ // Do not add in a vector format attributes whose type is different than
5475
+ // parent function attribute type.
5476
+ if (llvm::any_of (FDecl->specific_attrs <FormatAttr>(),
5477
+ [&](const FormatAttr *FunctionAttr) {
5478
+ return AttrType != FunctionAttr->getType ();
5479
+ }))
5480
+ continue ;
5481
+
5482
+ // Check if format string argument is parent function parameter.
5483
+ int StringIndex = 0 ;
5484
+ if (!llvm::any_of (FDecl->parameters (), [&](const ParmVarDecl *Param) {
5485
+ if (Param != FormatArg)
5486
+ return false ;
5487
+
5488
+ StringIndex = Param->getFunctionScopeIndex () +
5489
+ FunctionFormatArgumentIndexOffset;
5490
+
5491
+ return true ;
5492
+ })) {
5493
+ MissingAttributes.push_back (
5494
+ FormatAttr::CreateImplicit (getASTContext (), AttrType, -1 , -1 ));
5495
+ continue ;
5496
+ }
5497
+
5498
+ unsigned NumOfParentFunctionParams = FDecl->getNumParams ();
5499
+
5500
+ // Compare parent and calling function format attribute arguments (archetype
5501
+ // and format string).
5502
+ if (llvm::any_of (
5503
+ FDecl->specific_attrs <FormatAttr>(), [&](const FormatAttr *Attr) {
5504
+ if (Attr->getType () != AttrType)
5505
+ return false ;
5506
+ int OffsetFormatIndex =
5507
+ Attr->getFormatIdx () - FunctionFormatArgumentIndexOffset;
5508
+
5509
+ if (OffsetFormatIndex < 0 ||
5510
+ (unsigned )OffsetFormatIndex >= NumOfParentFunctionParams)
5511
+ return false ;
5512
+
5513
+ if (FDecl->parameters ()[OffsetFormatIndex] != FormatArg)
5514
+ return false ;
5515
+
5516
+ return true ;
5517
+ })) {
5518
+ MissingAttributes.push_back (
5519
+ FormatAttr::CreateImplicit (getASTContext (), AttrType, -1 , -1 ));
5520
+ continue ;
5521
+ }
5522
+
5523
+ // Get first argument index
5524
+ int FirstToCheck = [&]() -> unsigned {
5525
+ if (!FDecl->isVariadic ())
5526
+ return 0 ;
5527
+ const auto *FirstToCheckArg = Args[NumArgs - 1 ]->IgnoreParenCasts ();
5528
+ if (FirstToCheckArg->getType ().getCanonicalType () !=
5529
+ Context.getBuiltinVaListType ().getCanonicalType ())
5530
+ return 0 ;
5531
+ return NumOfParentFunctionParams + FunctionFormatArgumentIndexOffset;
5532
+ }();
5533
+
5534
+ // If there are already attributes which arguments matches arguments
5535
+ // detected in this iteration, do not add new attribute as it would be
5536
+ // duplicate.
5537
+ if (!llvm::any_of (MissingAttributes, [&](const FormatAttr *Attr) {
5538
+ return Attr->getType () == AttrType &&
5539
+ Attr->getFormatIdx () == StringIndex &&
5540
+ Attr->getFirstArg () == FirstToCheck;
5541
+ }))
5542
+ MissingAttributes.push_back (FormatAttr::CreateImplicit (
5543
+ getASTContext (), AttrType, StringIndex, FirstToCheck));
5544
+ }
5545
+
5546
+ return MissingAttributes;
5547
+ }
5548
+
5338
5549
// ===----------------------------------------------------------------------===//
5339
5550
// Microsoft specific attribute handlers.
5340
5551
// ===----------------------------------------------------------------------===//
0 commit comments