Copyright (C) 2016, 2017, 2018, 2019, 2020, 2021  Stefan Vargyas

This file is part of Json-Type.

Json-Type is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Json-Type is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Json-Type.  If not, see <http://www.gnu.org/licenses/>.

--------------------------------------------------------------------------------

Building Json-Type with Clang
=============================

Although Clang compiler aims to be a drop-in replacement of GCC, Json-Type would
not compile out of the box with a command line like:

  $ make GCC=clang

The many warnings to be seen produced by Clang can be dealt with easily passing
a couple of `-Wno-...' command line options to the compiler.

However, there are two GCC C constructs which Clang rejects categorically. One
is the 'error' function attribute used by the macro 'STATIC' defined in both
files 'lib/common.h' and 'src/common.h'. The macro is a kind of '_Static_assert'
of C11 -- but with a little bit of extra power.

To work around the issue of 'error' function attribute, an immediate solution is
to redefine the macro 'STATIC' without using that attribute (see the patch file
'doc/clang-build.path'). A more involved solution would be to find something
similar to 'error' attribute in Clang's documentation [2]. Unfortunately, none
seems to be available for older versions of the compiler (I needed using v3.4).

Note that the solution in 'doc/clang-build.patch' looses important functionality
provided by the original 'STATIC' macro: the user wouldn't see on Clang's stderr
output line the text of the expression which makes a static assertion fail, but
will get a somehow evasive diagnostic message like the one below:

  FILE:LINE:COL: error: 'static_assertion_failed_COUNTER' declared as an array
  with a negative size.

GCC's diagnostic message would however look clear-cut:

  FILE:LINE:COL: error: call to ‘static_assert’ declared with attribute error:
  assertion failed: 'EXPRESSION'.

As a matter of fact, this is the very reason I implemented the macro 'STATIC' as
did: get better diagnostic messages out of GCC.

The other rejected GCC construct is the one in macro 'BIT_SET_DECL_AUTO' defined
in file 'lib/bit-set.h', which is used in file 'lib/json-type.c' in the function
'json_type_check_error_bit_arg_print_error_desc'. There is to be found something
like the struct below:

  $ cat auto-struct.c
  #include <stddef.h>

  void f(size_t n)
  {
      struct
      {
          char x[n];
      } a;
  }

Clang complains peremptorily about such code:

  $ clang -Wall -Wextra -std=gnu99 -c auto-struct.c -o /dev/null
  auto-struct.c:7:14: error: fields must have a constant size: 'variable length
  array in structure' extension will never be supported
          char x[n];
               ^
  1 error generated.

Fixing 'BIT_SET_DECL_AUTO' should go along the lines of the one below:

  $ cat auto-struct.c
  #include <stddef.h>
  #include <alloca.h>

  void f(size_t n)
  {
      struct
      {
          char* x;
      } a;
      a.x = n
          ? alloca(n)
          : NULL;
  }

The change makes Clang to stop complaining:

  $ clang -Wall -Wextra -std=gnu99 -c auto-struct.c -o /dev/null && echo OK
  OK

Given the above remarks, being at the top of a fresh Json-Type source tree,
first patch the tree with:

  $ patch -p0 -i doc/clang-build.patch

Then building Json-Type should succeed cleanly (i.e. without warnings):

  $ make GCC=clang

Finally, testing Json-Type should also succeed (i.e. none of the tests fails):

  $ (cd test && ./test.sh -q)
  test cases passed: ...
  test cases failed: 0

If one needs using the optional component Json-Litex, then building it should
also succeed cleanly:

  $ make litex PCRE2_HOME=... GCC=clang

Running Json-Litex's test-suite should also yield no failed test cases:

  $ (cd test && JSON_LITEX_TEST_PCRE2_LIB=... ./test-litex.sh -q)
  test cases passed: ...
  test cases failed: 0


References
----------

[1] The 'error' Function Attribute:

    GCC 4.3.0 Docs: 5.27 Declaring Attributes of Functions
    https://gcc.gnu.org/onlinedocs/gcc-4.3.0/gcc/Function-Attributes.html

    GCC 7.2.0 Docs: 6.31.1 Common Function Attributes
    https://gcc.gnu.org/onlinedocs/gcc-7.2.0/gcc/Common-Function-Attributes.html

    Note that documents prior to v4.3.0 are not mentioning the existence of this
    attribute.

[2] Clang 6 Docs: Attributes in Clang
    https://clang.llvm.org/docs/AttributeReference.html


