================
@@ -7001,6 +7005,85 @@ bool Sema::CheckFormatString(const FormatMatchesAttr
*Format,
return false;
}
+static void CheckMissingFormatAttributes(Sema *S, FormatStringType FormatType,
+ unsigned FormatIdx, unsigned FirstArg,
+ ArrayRef<const Expr *> Args,
+ Sema::FormatArgumentPassingKind APK,
+ unsigned CallerParamIdx,
+ SourceLocation Loc) {
+ const FunctionDecl *Caller = S->getCurFunctionDecl();
+ if (!Caller)
+ return;
+
+ // Find the offset to convert between attribute and parameter indexes.
+ unsigned CallerArgumentIndexOffset =
+ hasImplicitObjectParameter(Caller) ? 2 : 1;
+
+ unsigned FirstArgumentIndex = -1;
+ switch (APK) {
+ case Sema::FormatArgumentPassingKind::FAPK_Fixed:
+ case Sema::FormatArgumentPassingKind::FAPK_Variadic: {
+ // As an extension, clang allows the format attribute on non-variadic
+ // functions.
+ // Caller must have fixed arguments to pass them to a fixed or variadic
+ // function. Try to match caller and callee arguments. If successful, then
+ // emit a diag with the caller idx, otherwise we can't determine the callee
+ // arguments.
+ unsigned NumCalleeArgs = Args.size() - FirstArg;
+ if (NumCalleeArgs == 0 || Caller->getNumParams() < NumCalleeArgs) {
+ // There aren't enough arugments in the caller to pass to callee.
+ return;
+ }
+ for (unsigned CalleeIdx = Args.size() - 1,
+ CallerIdx = Caller->getNumParams() - 1;
+ CalleeIdx >= FirstArg; --CalleeIdx, --CallerIdx) {
+ const auto *Arg =
+ dyn_cast<DeclRefExpr>(Args[CalleeIdx]->IgnoreParenCasts());
+ if (!Arg)
+ return;
+ const auto *Param = dyn_cast<ParmVarDecl>(Arg->getDecl());
+ if (!Param || Param->getFunctionScopeIndex() != CallerIdx)
+ return;
+ }
+ FirstArgumentIndex =
+ Caller->getNumParams() + CallerArgumentIndexOffset - NumCalleeArgs;
+ break;
+ }
+ case Sema::FormatArgumentPassingKind::FAPK_VAList:
+ // Caller arguments are either variadic or a va_list.
+ FirstArgumentIndex =
+ Caller->isVariadic()
+ ? (Caller->getNumParams() + CallerArgumentIndexOffset)
+ : 0;
+ break;
+ case Sema::FormatArgumentPassingKind::FAPK_Elsewhere:
+ // Args are not passed to the callee.
+ return;
+ }
+
+ // Emit the diagnostic and fixit.
+ unsigned FormatStringIndex = CallerParamIdx + CallerArgumentIndexOffset;
+ StringRef FormatTypeName = S->GetFormatStringTypeName(FormatType);
+ StringRef AttrPrefix, AttrSuffix;
+ if (S->getLangOpts().C23 || S->getLangOpts().CPlusPlus11) {
+ AttrPrefix = "[[gnu::format(";
+ AttrSuffix = ")]] ";
+ } else {
+ AttrPrefix = "__attribute__((format(";
+ AttrSuffix = "))) ";
+ }
+ S->Diag(Loc, diag::warn_missing_format_attribute)
+ << FormatTypeName << Caller
+ << FixItHint::CreateInsertion(Caller->getFirstDecl()->getBeginLoc(),
+ (AttrPrefix + FormatTypeName + ", " +
+ llvm::Twine(FormatStringIndex) + ", " +
+ llvm::Twine(FirstArgumentIndex) +
+ AttrSuffix)
+ .str());
+ S->Diag(Caller->getFirstDecl()->getLocation(), diag::note_callee_decl)
+ << Caller;
----------------
apple-fcloutier wrote:
note_callee_decl pointing to the Caller?
https://github.com/llvm/llvm-project/pull/166738
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits