[PATCH] D112579: Allow non-variadic functions to be attributed with `__attribute__((format))`
Arthur O'Dwyer via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Thu Nov 4 08:03:14 PDT 2021
Quuxplusone added a comment.
> Agreed. This should be checking the instantiations, so by that point, the variadic template is really more like a fixed parameter list anyway.
FWIW, in my own mental model, there's a big semantic difference between (varargs functions, variadic templates) on the one hand and (non-template functions) on the other. In my experience, there's //nothing// you can do with a varargs ellipsis except forward it along as a `va_list`; and it's //uncommon// to do anything with a variadic parameter pack except forward it along via `std::forward`; but messing with fixed arguments is quite common. Technically, you can mess with a parameter pack too:
void apple(const char *fmt, int x, int y) __attribute__((format(printf, 1, 2))) {
printf(fmt, double(x), double(y));
}
void banana(const char *fmt, auto... args) __attribute__((format(printf, 1, 2))) {
printf(fmt, double(args)...);
}
int main() {
apple("%g %g", 17, 42); // well-defined; shall we warn anyway? (My gut feeling is that this is relatively common)
banana("%g %g", 17, 42); // well-defined; shall we warn anyway? (My gut feeling is that this is extremely rare)
}
This morning I am leaning in favor of this PR as written. If a programmer wants `apple`/`banana` to be callable like that, without any diagnostics, then their appropriate course of action is simply not to apply the `__attribute__((format(printf, 1, 2)))` annotation.
================
Comment at: clang/include/clang/Basic/DiagnosticSemaKinds.td:4051
+def warn_gcc_requires_variadic_function : Warning<
+ "GCC requires functions with %0 attribute to be variadic">,
+ InGroup<GccCompat>;
----------------
I'd say `with the %0 attribute` (add "the")
================
Comment at: clang/lib/AST/FormatString.cpp:325-329
+ // When using the format attribute with variadic templates in C++, you can
+ // receive an array that will necessarily decay to a pointer when passed to
+ // the final format consumer. Apply decay before type comparison.
+ if (C.getAsArrayType(argTy))
+ argTy = C.getArrayDecayedType(argTy);
----------------
Also, function references will decay to function pointers. I have no idea if you need to do anything special here to get the "right behavior" for function references. But please add a (compile-only?) test case for the function-pointer codepath, just to prove it doesn't crash or anything.
================
Comment at: clang/test/Sema/attr-format.cpp:5-7
+template<typename... Args>
+void format(const char *fmt, Args &&... args) // expected-warning{{GCC requires functions with 'format' attribute to be variadic}}
+ __attribute__((format(printf, 1, 2)));
----------------
Can we also do an example of a //member function// variadic template?
```
struct S {
template<class... Args>
void format(const char *fmt, Args&&... args)
__attribute__((format(printf, 2, 3)));
};
```
Also, I believe that this entire file should be removed from `Sema/` and combined into `SemaCXX/attr-format.cpp`.
I also notice that we have literally zero test coverage for cases where the format string is not the first argument to the function; but that can-and-should be addressed in a separate PR.
================
Comment at: clang/test/Sema/attr-format.cpp:14
+ format("bare string");
+ format("%s %s %u %d %i %p\n", "hello", s, 10u, x, y, &do_format);
+ format("bad format %s"); // expected-warning{{more '%' conversions than data arguments}}
----------------
Basically, add `, do_format` here.
(Aside: I'm surprised that Clang quietly lets you print a function pointer with `%p`. It'll work on sane architectures, but //in general// C and C++ don't require that function pointers even be the same size as `void*` — technically this should be UB or at least impl-defined behavior.)
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D112579/new/
https://reviews.llvm.org/D112579
More information about the cfe-commits
mailing list