From 0a982672e53868cb394743a03b4e7b68951c282b Mon Sep 17 00:00:00 2001 From: Matthew Fernandez Date: Tue, 28 Jul 2020 19:38:55 -0700 Subject: [PATCH] compiler annotations to explain calling convention of agerr and friends This change teaches suitably enlightened compilers (Clang and GCC) more about how these functions are intended to be called. When told to detect misuse of format strings (`-Wformat`), they can now detect incorrect calls like that fixed in 31ef5a3c31214d77137e4b36603a2a97576e851e. --- lib/cgraph/cgraph.h | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/cgraph/cgraph.h b/lib/cgraph/cgraph.h index 4e269d9b5..c6a3f86e2 100644 --- a/lib/cgraph/cgraph.h +++ b/lib/cgraph/cgraph.h @@ -384,18 +384,28 @@ CGRAPH_API void aginternalmapclearlocalnames(Agraph_t * g); #define agnew(g,t) ((t*)agalloc(g,sizeof(t))) #define agnnew(g,n,t) ((t*)agalloc(g,(n)*sizeof(t))) +/* support for extra API misuse warnings if available */ +#ifdef __GNUC__ + #define PRINTF_LIKE(index, first) __attribute__((format(printf, index, first))) +#else + #define PRINTF_LIKE(index, first) /* nothing */ +#endif + /* error handling */ typedef enum { AGWARN, AGERR, AGMAX, AGPREV } agerrlevel_t; typedef int (*agusererrf) (char*); CGRAPH_API agerrlevel_t agseterr(agerrlevel_t); CGRAPH_API char *aglasterr(void); -CGRAPH_API int agerr(agerrlevel_t level, const char *fmt, ...); -CGRAPH_API void agerrorf(const char *fmt, ...); -CGRAPH_API void agwarningf(const char *fmt, ...); +CGRAPH_API int agerr(agerrlevel_t level, const char *fmt, ...) + PRINTF_LIKE(2, 3); +CGRAPH_API void agerrorf(const char *fmt, ...) PRINTF_LIKE(1, 2); +CGRAPH_API void agwarningf(const char *fmt, ...) PRINTF_LIKE(1, 2); CGRAPH_API int agerrors(void); CGRAPH_API int agreseterrors(void); CGRAPH_API agusererrf agseterrf(agusererrf); +#undef PRINTF_LIKE + /* data access macros */ /* this assumes that e[0] is out and e[1] is inedge, see edgepair in edge.c */ #define AGIN2OUT(e) ((e)-1) -- 2.50.1