================ @@ -435,6 +435,86 @@ bool Sema::ConstantFoldAttrArgs(const AttributeCommonInfo &CI, return true; } +// Warn if parent function does not have builtin function format attribute. +void Sema::DiagnoseMissingFormatAttributes(NamedDecl *FDecl, + SourceLocation Loc) { + if (!FDecl) + return; + + auto *FD = dyn_cast_or_null<FunctionDecl>(FDecl); + if (!FD) + return; + + unsigned BuiltinID = FD->getBuiltinID(/*ConsiderWrappers=*/true); + + // Function is not builtin if it's builtin ID is 0. + if (!BuiltinID) + return; + + // Check if function is one with format attribute. + switch (BuiltinID) { + case Builtin::BIprintf: + case Builtin::BIfprintf: + case Builtin::BIsprintf: + case Builtin::BIscanf: + case Builtin::BIfscanf: + case Builtin::BIsscanf: + case Builtin::BIvprintf: + case Builtin::BIvfprintf: + case Builtin::BIvsprintf: + break; + default: { + // In C99 mode check functions below. + if (!getLangOpts().C99) + return; + switch (BuiltinID) { + case Builtin::BIsnprintf: + case Builtin::BIvsnprintf: + case Builtin::BIvscanf: + case Builtin::BIvfscanf: + case Builtin::BIvsscanf: + break; + default: + return; + } + } + } + + Scope *ParentScope = getCurScope() ? getCurScope()->getFnParent() : nullptr; + if (!ParentScope) + return; + + DeclContext *ParentScopeEntity = ParentScope->getEntity(); + if (!ParentScopeEntity) + return; + if (ParentScopeEntity->getDeclKind() != Decl::Kind::Function) + return; + + FunctionDecl *ParentFuncDecl = static_cast<FunctionDecl *>(ParentScopeEntity); + if (!ParentFuncDecl) + return; + if (!ParentFuncDecl->isVariadic()) + return; + + // Iterate through builtin function format attributes. Then check + // if parent function has these attributes. If parent function does + // not have builtin function format attribut, emit warning. + for (const FormatAttr *Attr : FD->specific_attrs<FormatAttr>()) { + bool hasFormatAttr = false; + for (const FormatAttr *ParentAttr : + ParentFuncDecl->specific_attrs<FormatAttr>()) { + if (ParentAttr->getType() == Attr->getType()) { + hasFormatAttr = true; + break; + } + } + if (!hasFormatAttr) { + Diag(Loc, diag::warn_missing_format_attribute) + << ParentFuncDecl << Attr->getType(); ---------------- aaronpuchert wrote:
Would be cool if we could add a fix-it. There are even ways to find macros that wrap the attribute, see the implementation for `-Wimplicit-fallthrough`. https://github.com/llvm/llvm-project/pull/70024 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits