]> granicus.if.org Git - graphviz/commitdiff
compiler annotations to explain calling convention of agerr and friends
authorMatthew Fernandez <matthew.fernandez@gmail.com>
Wed, 29 Jul 2020 02:38:55 +0000 (19:38 -0700)
committerMatthew Fernandez <matthew.fernandez@gmail.com>
Mon, 3 Aug 2020 13:53:57 +0000 (06:53 -0700)
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

index 4e269d9b5a22ba059c0f50fb20948fe9b5d529c2..c6a3f86e28c63000ef43f13c84fb294d03f280d3 100644 (file)
@@ -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)