From bafa091fada7b3fdc663567abc0a7455bc3a77c9 Mon Sep 17 00:00:00 2001
From: David Robillard <d@drobilla.net>
Date: Tue, 10 Nov 2020 15:44:37 +0100
Subject: Add const, pure, and malloc function attributes

---
 include/serd/serd.h | 21 ++++++++++++++++-----
 src/attributes.h    | 26 ++++++++++++++++++++++++++
 src/base64.h        |  4 +++-
 src/env.c           |  2 +-
 src/reader.h        |  6 +++---
 src/serdi.c         |  2 +-
 src/system.h        |  4 +++-
 src/uri_utils.h     |  6 +++---
 wscript             |  3 ---
 9 files changed, 56 insertions(+), 18 deletions(-)
 create mode 100644 src/attributes.h

diff --git a/include/serd/serd.h b/include/serd/serd.h
index 55813ba9..c39414e0 100644
--- a/include/serd/serd.h
+++ b/include/serd/serd.h
@@ -37,6 +37,17 @@
 #    define SERD_API
 #endif
 
+#ifdef __GNUC__
+#    define SERD_PURE_FUNC __attribute__((pure))
+#    define SERD_CONST_FUNC __attribute__((const))
+#else
+#    define SERD_PURE_FUNC
+#    define SERD_CONST_FUNC
+#endif
+
+#define SERD_PURE_API SERD_API SERD_PURE_FUNC
+#define SERD_CONST_API SERD_API SERD_CONST_FUNC
+
 #ifdef __cplusplus
 extern "C" {
 #    if defined(__GNUC__)
@@ -289,7 +300,7 @@ serd_free(void* ptr);
 /**
    Return a string describing a status code.
 */
-SERD_API
+SERD_CONST_API
 const uint8_t*
 serd_strerror(SerdStatus status);
 
@@ -402,7 +413,7 @@ serd_file_uri_parse(const uint8_t* uri, uint8_t** hostname);
 /**
    Return true iff `utf8` starts with a valid URI scheme.
 */
-SERD_API
+SERD_PURE_API
 bool
 serd_uri_string_has_scheme(const uint8_t* utf8);
 
@@ -590,7 +601,7 @@ serd_node_copy(const SerdNode* node);
 /**
    Return true iff `a` is equal to `b`.
 */
-SERD_API
+SERD_PURE_API
 bool
 serd_node_equals(const SerdNode* a, const SerdNode* b);
 
@@ -801,7 +812,7 @@ serd_reader_set_error_sink(SerdReader*   reader,
 /**
    Return the `handle` passed to serd_reader_new().
 */
-SERD_API
+SERD_PURE_API
 void*
 serd_reader_get_handle(const SerdReader* reader);
 
@@ -951,7 +962,7 @@ serd_writer_free(SerdWriter* writer);
 /**
    Return the env used by `writer`.
 */
-SERD_API
+SERD_PURE_API
 SerdEnv*
 serd_writer_get_env(SerdWriter* writer);
 
diff --git a/src/attributes.h b/src/attributes.h
new file mode 100644
index 00000000..3ca797a4
--- /dev/null
+++ b/src/attributes.h
@@ -0,0 +1,26 @@
+/*
+  Copyright 2019-2020 David Robillard <http://drobilla.net>
+
+  Permission to use, copy, modify, and/or distribute this software for any
+  purpose with or without fee is hereby granted, provided that the above
+  copyright notice and this permission notice appear in all copies.
+
+  THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+*/
+
+#ifndef SERD_ATTRIBUTES_H
+#define SERD_ATTRIBUTES_H
+
+#ifdef __GNUC__
+#    define SERD_MALLOC_FUNC __attribute__((malloc))
+#else
+#    define SERD_MALLOC_FUNC
+#endif
+
+#endif // SERD_ATTRIBUTES_H
diff --git a/src/base64.h b/src/base64.h
index 11eb9db9..7fd29fef 100644
--- a/src/base64.h
+++ b/src/base64.h
@@ -17,6 +17,8 @@
 #ifndef SERD_BASE64_H
 #define SERD_BASE64_H
 
+#include "serd/serd.h"
+
 #include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
@@ -28,7 +30,7 @@
    @param wrap_lines Wrap lines at 76 characters to conform to RFC 2045.
    @return The length of the base64 encoding, excluding null terminator.
 */
-size_t
+SERD_CONST_FUNC size_t
 serd_base64_get_length(size_t size, bool wrap_lines);
 
 /**
diff --git a/src/env.c b/src/env.c
index e67b42c0..3813391c 100644
--- a/src/env.c
+++ b/src/env.c
@@ -93,7 +93,7 @@ serd_env_set_base_uri(SerdEnv*        env,
 	return SERD_ERR_BAD_ARG;
 }
 
-static inline SerdPrefix*
+static inline SERD_PURE_FUNC SerdPrefix*
 serd_env_find(const SerdEnv* env,
               const uint8_t* name,
               size_t         name_len)
diff --git a/src/reader.h b/src/reader.h
index 9de37f4c..166e2137 100644
--- a/src/reader.h
+++ b/src/reader.h
@@ -98,9 +98,9 @@ Ref push_node(SerdReader* reader,
               const char* str,
               size_t      n_bytes);
 
-size_t genid_size(SerdReader* reader);
-Ref    blank_id(SerdReader* reader);
-void   set_blank_id(SerdReader* reader, Ref ref, size_t buf_size);
+SERD_PURE_FUNC size_t genid_size(SerdReader* reader);
+Ref                   blank_id(SerdReader* reader);
+void                  set_blank_id(SerdReader* reader, Ref ref, size_t buf_size);
 
 SerdNode* deref(SerdReader* reader, Ref ref);
 
diff --git a/src/serdi.c b/src/serdi.c
index 5b3d4bbb..033a8c75 100644
--- a/src/serdi.c
+++ b/src/serdi.c
@@ -66,7 +66,7 @@ get_syntax(const char* name)
 	return (SerdSyntax)0;
 }
 
-static SerdSyntax
+static SERD_PURE_FUNC SerdSyntax
 guess_syntax(const char* filename)
 {
 	const char* ext = strrchr(filename, '.');
diff --git a/src/system.h b/src/system.h
index b1b84925..0f6a0e0b 100644
--- a/src/system.h
+++ b/src/system.h
@@ -17,12 +17,14 @@
 #ifndef SERD_SYSTEM_H
 #define SERD_SYSTEM_H
 
+#include "attributes.h"
+
 #include <stdio.h>
 
 FILE*
 serd_fopen(const char* path, const char* mode);
 
-void*
+SERD_MALLOC_FUNC void*
 serd_bufalloc(size_t size);
 
 #endif // SERD_SYSTEM_H
diff --git a/src/uri_utils.h b/src/uri_utils.h
index 4dbcdba5..896d9d8b 100644
--- a/src/uri_utils.h
+++ b/src/uri_utils.h
@@ -48,7 +48,7 @@ uri_path_at(const SerdURI* uri, size_t i)
    Return the index of the first differing character after the last root slash,
    or zero if `uri` is not under `root`.
 */
-static inline size_t
+static inline SERD_PURE_FUNC size_t
 uri_rooted_index(const SerdURI* uri, const SerdURI* root)
 {
 	if (!root || !root->scheme.len ||
@@ -78,14 +78,14 @@ uri_rooted_index(const SerdURI* uri, const SerdURI* root)
 }
 
 /** Return true iff `uri` shares path components with `root` */
-static inline bool
+static inline SERD_PURE_FUNC bool
 uri_is_related(const SerdURI* uri, const SerdURI* root)
 {
 	return uri_rooted_index(uri, root) > 0;
 }
 
 /** Return true iff `uri` is within the base of `root` */
-static inline bool
+static inline SERD_PURE_FUNC bool
 uri_is_under(const SerdURI* uri, const SerdURI* root)
 {
 	const size_t index = uri_rooted_index(uri, root);
diff --git a/wscript b/wscript
index 7be924be..f12503e9 100644
--- a/wscript
+++ b/wscript
@@ -71,8 +71,6 @@ def configure(conf):
                 '-Wno-inline',
                 '-Wno-padded',
                 '-Wno-sign-conversion',
-                '-Wno-suggest-attribute=const',
-                '-Wno-suggest-attribute=pure',
             ],
             'msvc': [
                 '/wd4061',  # enumerator in switch is not explicitly handled
@@ -91,7 +89,6 @@ def configure(conf):
             ],
             'gcc': [
                 '-Wno-bad-function-cast',
-                '-Wno-suggest-attribute=malloc'
             ],
             'msvc': [
                 '/wd4706',  # assignment within conditional expression
-- 
cgit v1.2.1