[clang] [clang] Catch missing format attributes (PR #70024)
Aaron Puchert via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 24 18:31:19 PDT 2023
================
@@ -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
More information about the cfe-commits
mailing list