@@ -3624,7 +3624,7 @@ static void handleFormatAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
36243624
36253625 // In C++ the implicit 'this' function parameter also counts, and they are
36263626 // counted from one.
3627- bool HasImplicitThisParam = isInstanceMethod (D);
3627+ bool HasImplicitThisParam = checkIfMethodHasImplicitObjectParameter (D);
36283628 unsigned NumArgs = getFunctionOrMethodNumParams (D) + HasImplicitThisParam;
36293629
36303630 IdentifierInfo *II = AL.getArgAsIdent (0 )->Ident ;
@@ -3737,7 +3737,7 @@ static void handleCallbackAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
37373737 return ;
37383738 }
37393739
3740- bool HasImplicitThisParam = isInstanceMethod (D);
3740+ bool HasImplicitThisParam = checkIfMethodHasImplicitObjectParameter (D);
37413741 int32_t NumArgs = getFunctionOrMethodNumParams (D);
37423742
37433743 FunctionDecl *FD = D->getAsFunction ();
@@ -5421,6 +5421,224 @@ static void handlePreferredTypeAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
54215421 D->addAttr (::new (S.Context ) PreferredTypeAttr (S.Context , AL, ParmTSI));
54225422}
54235423
5424+ // Returns vector of format attributes. There are no two attributes with same
5425+ // arguments in returning vector. There can be attributes that effectively only
5426+ // store information about format type.
5427+ static std::vector<FormatAttr *>
5428+ GetMissingFormatAttributes (Sema &S, Stmt *Body, const FunctionDecl *FDecl) {
5429+ unsigned int ArgumentIndexOffset =
5430+ checkIfMethodHasImplicitObjectParameter (FDecl) ? 2 : 1 ;
5431+
5432+ std::vector<FormatAttr *> MissingAttributes;
5433+
5434+ // Iterate over body statements.
5435+ for (auto *Child : Body->children ()) {
5436+ // If child statement is compound statement, recursively get missing
5437+ // attributes.
5438+ if (dyn_cast_or_null<CompoundStmt>(Child)) {
5439+ std::vector<FormatAttr *> CompoundStmtMissingAttributes =
5440+ GetMissingFormatAttributes (S, Child, FDecl);
5441+
5442+ // If there are already missing attributes with same arguments, do not add
5443+ // duplicates.
5444+ for (FormatAttr *FA : CompoundStmtMissingAttributes) {
5445+ if (!llvm::any_of (MissingAttributes, [&](const FormatAttr *Attr) {
5446+ return FA->getType () == Attr->getType () &&
5447+ FA->getFormatIdx () == Attr->getFormatIdx () &&
5448+ FA->getFirstArg () == Attr->getFirstArg ();
5449+ }))
5450+ MissingAttributes.push_back (FA);
5451+ }
5452+
5453+ continue ;
5454+ }
5455+
5456+ ValueStmt *VS = dyn_cast<ValueStmt>(Child);
5457+ if (!VS)
5458+ continue ;
5459+ CallExpr *TheCall = dyn_cast_or_null<CallExpr>(VS->getExprStmt ());
5460+ if (!TheCall)
5461+ continue ;
5462+
5463+ const FunctionDecl *CalleeFunction =
5464+ dyn_cast_or_null<FunctionDecl>(TheCall->getCalleeDecl ());
5465+ if (!CalleeFunction || !CalleeFunction->hasAttr <FormatAttr>())
5466+ continue ;
5467+
5468+ // va_list is not intended to be passed to variadic function.
5469+ if (CalleeFunction->isVariadic ())
5470+ continue ;
5471+
5472+ Expr **Args = TheCall->getArgs ();
5473+ unsigned int NumArgs = TheCall->getNumArgs ();
5474+
5475+ // Check if va_list is passed to callee function.
5476+ // If va_list is not passed, continue to the next iteration.
5477+ bool hasVaList = false ;
5478+ for (const auto *Param : CalleeFunction->parameters ()) {
5479+ if (Param->getOriginalType ().getCanonicalType () ==
5480+ S.getASTContext ().getBuiltinVaListType ().getCanonicalType ()) {
5481+ hasVaList = true ;
5482+ break ;
5483+ }
5484+ }
5485+ if (!hasVaList)
5486+ continue ;
5487+
5488+ // If callee expression is function, check if it is format function.
5489+ // If it is, check if caller function misses format attributes.
5490+
5491+ unsigned int CalleeFunctionFormatArgumentIndexOffset =
5492+ checkIfMethodHasImplicitObjectParameter (CalleeFunction) ? 2 : 1 ;
5493+
5494+ // If callee function is format function and format arguments are not
5495+ // relevant to emit diagnostic, save only information about format type
5496+ // (format index and first-to-check argument index are set to -1).
5497+ // Information about format type is later used to determine if there are
5498+ // more than one format type found.
5499+
5500+ // Check if function has format attribute with forwarded format string.
5501+ IdentifierInfo *AttrType;
5502+ const ParmVarDecl *FormatArg;
5503+ if (!llvm::any_of (CalleeFunction->specific_attrs <FormatAttr>(),
5504+ [&](const FormatAttr *Attr) {
5505+ AttrType = Attr->getType ();
5506+
5507+ int OffsetFormatIndex =
5508+ Attr->getFormatIdx () -
5509+ CalleeFunctionFormatArgumentIndexOffset;
5510+ if (OffsetFormatIndex < 0 ||
5511+ (unsigned )OffsetFormatIndex >= NumArgs)
5512+ return false ;
5513+
5514+ if (const auto *FormatArgExpr = dyn_cast<DeclRefExpr>(
5515+ Args[OffsetFormatIndex]->IgnoreParenCasts ()))
5516+ if (FormatArg = dyn_cast_or_null<ParmVarDecl>(
5517+ FormatArgExpr->getReferencedDeclOfCallee ()))
5518+ return true ;
5519+ return false ;
5520+ })) {
5521+ MissingAttributes.push_back (
5522+ FormatAttr::CreateImplicit (S.getASTContext (), AttrType, -1 , -1 ));
5523+ continue ;
5524+ }
5525+
5526+ // If format string argument is caller function parameter, get string index.
5527+ // Otherwise, save only attribute type and go to next iteration.
5528+ int StringIndex = [=]() -> int {
5529+ for (const ParmVarDecl *Param : FDecl->parameters ()) {
5530+ if (Param == FormatArg)
5531+ return Param->getFunctionScopeIndex () + ArgumentIndexOffset;
5532+ }
5533+ return 0 ;
5534+ }();
5535+
5536+ if (StringIndex == 0 ) {
5537+ MissingAttributes.push_back (
5538+ FormatAttr::CreateImplicit (S.getASTContext (), AttrType, -1 , -1 ));
5539+ continue ;
5540+ }
5541+
5542+ unsigned NumOfCallerFunctionParams = FDecl->getNumParams ();
5543+
5544+ // Compare caller and callee function format attribute arguments (archetype
5545+ // and format string).
5546+ if (llvm::any_of (
5547+ FDecl->specific_attrs <FormatAttr>(), [&](const FormatAttr *Attr) {
5548+ if (Attr->getType () != AttrType)
5549+ return false ;
5550+ int OffsetFormatIndex =
5551+ Attr->getFormatIdx () - ArgumentIndexOffset;
5552+
5553+ if (OffsetFormatIndex < 0 ||
5554+ (unsigned )OffsetFormatIndex >= NumOfCallerFunctionParams)
5555+ return false ;
5556+
5557+ if (FDecl->parameters ()[OffsetFormatIndex] != FormatArg)
5558+ return false ;
5559+
5560+ return true ;
5561+ })) {
5562+ MissingAttributes.push_back (
5563+ FormatAttr::CreateImplicit (S.getASTContext (), AttrType, -1 , -1 ));
5564+ continue ;
5565+ }
5566+
5567+ // Get first argument index
5568+ int FirstToCheck = FDecl->isVariadic ()
5569+ ? (NumOfCallerFunctionParams + ArgumentIndexOffset)
5570+ : 0 ;
5571+
5572+ // If there are already attributes which arguments matches arguments
5573+ // detected in this iteration, do not add new attribute as it would be
5574+ // duplicate.
5575+ if (!llvm::any_of (MissingAttributes, [&](const FormatAttr *Attr) {
5576+ return Attr->getType () == AttrType &&
5577+ Attr->getFormatIdx () == StringIndex &&
5578+ Attr->getFirstArg () == FirstToCheck;
5579+ }))
5580+ MissingAttributes.push_back (
5581+ FormatAttr::CreateImplicit (S.getASTContext (), AttrType, StringIndex,
5582+ FirstToCheck, TheCall->getBeginLoc ()));
5583+ }
5584+
5585+ return MissingAttributes;
5586+ }
5587+
5588+ // This function is called only if function call is not inside template body.
5589+ // TODO: Add call for function calls inside template body.
5590+ // Emit warnings if caller function misses format attributes.
5591+ void Sema::DiagnoseMissingFormatAttributes (Stmt *Body,
5592+ const FunctionDecl *FDecl) {
5593+ assert (FDecl);
5594+
5595+ // If there are no function body, exit.
5596+ if (!Body)
5597+ return ;
5598+
5599+ // Get missing format attributes
5600+ std::vector<FormatAttr *> MissingFormatAttributes =
5601+ GetMissingFormatAttributes (*this , Body, FDecl);
5602+ if (MissingFormatAttributes.empty ())
5603+ return ;
5604+
5605+ // Check if there are more than one format type found. In that case do not
5606+ // emit diagnostic.
5607+ const clang::IdentifierInfo *AttrType = MissingFormatAttributes[0 ]->getType ();
5608+ for (unsigned i = 1 ; i < MissingFormatAttributes.size (); ++i) {
5609+ if (AttrType != MissingFormatAttributes[i]->getType ())
5610+ return ;
5611+ }
5612+
5613+ for (const FormatAttr *FA : MissingFormatAttributes) {
5614+ // If format index and first-to-check argument index are negative, it means
5615+ // that this attribute is only saved for multiple format types checking.
5616+ if (FA->getFormatIdx () < 0 || FA->getFirstArg () < 0 )
5617+ continue ;
5618+
5619+ // If caller function has format attributes and callee format attribute type
5620+ // mismatches caller attribute type, do not emit diagnostic.
5621+ if (FDecl->hasAttr <FormatAttr>() &&
5622+ !llvm::any_of (FDecl->specific_attrs <FormatAttr>(),
5623+ [FA](const FormatAttr *FunctionAttr) {
5624+ return FA->getType () == FunctionAttr->getType ();
5625+ }))
5626+ continue ;
5627+
5628+ // Emit diagnostic
5629+ SourceLocation Loc = FDecl->getFirstDecl ()->getLocation ();
5630+ Diag (Loc, diag::warn_missing_format_attribute)
5631+ << FA->getType () << FDecl
5632+ << FixItHint::CreateInsertion (Loc,
5633+ (llvm::Twine (" __attribute__((format(" ) +
5634+ FA->getType ()->getName () + " , " +
5635+ llvm::Twine (FA->getFormatIdx ()) + " , " +
5636+ llvm::Twine (FA->getFirstArg ()) + " )))" )
5637+ .str ());
5638+ Diag (FA->getLocation (), diag::note_format_function) << FA->getType ();
5639+ }
5640+ }
5641+
54245642// ===----------------------------------------------------------------------===//
54255643// Microsoft specific attribute handlers.
54265644// ===----------------------------------------------------------------------===//
0 commit comments