After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 695235 - nil is a keyword in Objective-C++
nil is a keyword in Objective-C++
Status: RESOLVED FIXED
Product: libsigc++
Classification: Bindings
Component: general
2.3.x
Other All
: Normal normal
: ---
Assigned To: libsigc++ maintainer(s)
libsigc++ maintainer(s)
Depends on:
Blocks:
 
 
Reported: 2013-03-05 18:45 UTC by Kjell Ahlstedt
Modified: 2016-03-03 12:05 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
patch: Make it easier to use libsigc++ with Objective-C++. (16.07 KB, patch)
2013-03-13 08:22 UTC, Kjell Ahlstedt
none Details | Review
patch: Make it easier to use libsigc++ with Objective-C++. (15.45 KB, patch)
2013-03-20 16:01 UTC, Kjell Ahlstedt
none Details | Review
patch: Make it easier to use libsigc++ with Objective-C++. (15.44 KB, patch)
2013-06-13 07:29 UTC, Kjell Ahlstedt
none Details | Review
patch: Make it easier to use libsigc++ with Objective-C++. (9.11 KB, patch)
2014-11-12 09:20 UTC, Kjell Ahlstedt
none Details | Review
patch: Make it easier to use libsigc++ with Objective-C++ (8.07 KB, patch)
2015-12-13 19:00 UTC, Kjell Ahlstedt
committed Details | Review

Description Kjell Ahlstedt 2013-03-05 18:45:23 UTC
struct nil is defined in sigc++/functors/functor_trait.h. That's a problem when
libsigc++ is used with Objective-C++ programs, because nil is a keyword in
Objective-C++.

Régis Duchesne made an attempt to fix this problem 7 years ago with commit
https://git.gnome.org/browse/libsigc++2/commit/?id=9d769959df0957bf3329d97de623f8f62713d2b1

That commit proved to break ABI, and it was soon reverted,
https://git.gnome.org/browse/libsigc++2/commit/?id=33547a7fd18c5e9bc1ae0e9b7f8b157f761a608f

I think there is another way to fix this problem without breaking ABI. I'll
make a patch that can be tested. Whether it does or does not work out well, nil
should be changed to something else when we can break ABI.

----------------
From an email conversation with Régis Duchesne:
("> " text written by Kjell, other text written by Régis)

> I think it can be fixed without breaking ABI for every user of libsigc++.
>
> In the header files where nil exists:
>
> #ifdef SIGC_NIL_IS_A_KEYWORD
> #define nil sigc_nil
> #endif
> <<< almost all of the present header file >>>
> #ifdef SIGC_NIL_IS_A_KEYWORD
> #undef nil
> #endif
>
> SIGC_NIL_IS_A_KEYWORD can be defined or not defined in sigc++config.h,
> depending either on a configure-time check, or on a preprocessor constant
> that unambiguously identifies an Objective-C++ compiler, if there is such a
> constant.

My change at https://git.gnome.org/browse/libsigc++2/commit/?id=9d769959df0957bf3329d97de623f8f62713d2b1
did that: it used the preprocessor constant __OBJC__ to unambiguously identify
an Objective-C (or Objective-C++) compiler.

But your change is slightly different and might actually work (as long as an
Objective C++ compiler is NOT used to compile gtkmm, but why would you do that,
you should use a regular C++ compiler to compile libsigc++, glibmm, gtkmm...)

> Will you file a bug? If you won't, I can do it. In either case, I will need
> help from someone with an Objective-C++ compiler for testing a fix.

I would prefer if you file the bug, but I would be happy to help you test a fix
with an Objective-C++ compiler.

-------------- 
Added after the email conversation:

I browsed the gcc documentation and realized that it can compile Objective-
C++ programs. Previously I misunderstood, I think. gcc invokes a compiler
depending on the suffix of the compiled file. The .cc files in libsigc++ will
be compiled by the C++ compiler with __OBJC__ undefined. A .m file in an
application program will be compiled by the Objective-C compiler, and a .M
file by the Objective-C++ compiler, in both cases with __OBJC__ defined.
A configure-time check is not useful. C++ files will be compiled with
struct nil defined, Objective-C++ files with struct nil replaced by
struct sigc_nil. Might cause problems! Let's see if it works well enough.

Luckily libsigc++ consists mostly of template classes and template functions
in header files. There is no 'nil' in any name in the libsigc-2.0.so file.
Checked with "nm libsigc-2.0.so | grep nil".
There may still be problems if the application program consists of a mixture of
Objective-C[++] and C[++] files. If so, the application can define
SIGC_NIL_IS_A_KEYWORD in the C and C++ files. But not even that trick will do
if the application program also depends on glibmm or gtkmm. Both
libgiomm-2.4.so, libglibmm-2.4.so, libgdkmm-3.0.so, and libgtkmm-3.0.so contain
'nil'.

If I get a small Objective-C[++] test program or two, I can do some of the
testing myself.
Comment 1 Kjell Ahlstedt 2013-03-06 18:21:26 UTC
I've made some changes to libsigc++. Now I need a small Objective-C++ test
case. I hope that I can fix this bug without learning Objective-C++.

I made a test case by just renaming libsigc++2/tests/test_bind.cc to
test_bind.M. That didn't work, or rather it worked too well. It compiled and
run even without my changes to the header files. I need a test case that does
not compile due to illegal use of the keyword nil in libsigc++'s header files.

Régis, do you prefer to do all the testing with Objective-C++ yourself?
Is all the code you've got proprietary code that you're not allowed to
attach to this bug?
Comment 2 Kjell Ahlstedt 2013-03-13 08:22:54 UTC
Created attachment 238760 [details] [review]
patch: Make it easier to use libsigc++ with Objective-C++.

I've noticed that if I add

  #include <objc/objc.h>

to test_bind.M before other #include directives, then compilation fails both
with and without my first set of changes of libsigc++. objc.h contains

typedef struct objc_object
{
  Class class_pointer;
} *id;
#define nil (id)0

What kind of keyword is nil? I thought keywords were built into the compiler.
This is a preprocessor definition. It would clash with any "#define nil ..."
in libsigc++.

The patch contains a slightly different modification of libsigc++.
It does not break ABI when libsigc++ is used in a normal C++ program.
If SIGC_DONT_DECLARE_NIL is defined, the patched libsigc++ can be used in a
program that contains #include <objc/objc.h>, but then it breaks ABI.

The patch ought to be tested on some real Objective-C++ programs.
Comment 3 Kjell Ahlstedt 2013-03-20 16:01:05 UTC
Created attachment 239367 [details] [review]
patch: Make it easier to use libsigc++ with Objective-C++.

Here's another patch. SIGC_DONT_DECLARE_NIL is not defined automatically when
an Objective-C++ program is compiled. The definition must be added either in
the source code before the #include directives, or as a compiler option.
I'm afraid we can break some programs, if SIGC_DONT_DECLARE_NIL is defined
automatically. I feel more at ease if it's only defined manually.
Comment 4 Kjell Ahlstedt 2013-04-11 13:53:36 UTC
I'm waiting for someone who uses Objective-C++ to test the patch. I don't want
to push it unless it's tested with Objective-C++ and found useful.

The patch does not apply to HEAD in git's master branch after my latest commit.
I can update the patch, but I'll wait until someone is ready to start testing.
Comment 5 Kjell Ahlstedt 2013-06-13 07:29:48 UTC
Created attachment 246686 [details] [review]
patch: Make it easier to use libsigc++ with Objective-C++.

An updated patch.
SIGC_DONT_DECLARE_NIL has been renamed to SIGC_DONT_DECLARE_STRUCT_NIL.
If it's not defined, #undef nil. Inspired by a post on libsigc-list
https://mail.gnome.org/archives/libsigc-list/2013-June/msg00001.html

If no user of Objective-C++ is willing to test my patch, and finds it useful,
I'll just keep it here in Bugzilla as a reminder that struct nil shall be
renamed at the next ABI break.
Comment 6 Kjell Ahlstedt 2014-11-12 09:20:36 UTC
Created attachment 290480 [details] [review]
patch: Make it easier to use libsigc++ with Objective-C++.

Yet another patch. This one contains a configuration-time check for the
non-standard preprocessor directives
  #pragma push_macro("name")
  #pragma pop_macro("name")
g++, clang++ and MS Visual C++ support these directives. If nil is defined, and
the preprocessor directives are supported, they are used for temporarily
undefining nil in the header files where nil is used.

This is a better solution, provided you use a preprocessor that suports
push_macro()/pop_macro(). Still the long-term solution, when we can break ABI,
will be to change the name 'nil' in libsigc++.

I'm still waiting for comments from someone who uses libsigc++ in combination
with Objective-C++.
Comment 7 David 2015-12-12 13:36:53 UTC
I think I hit this bug when trying to compile ardor 4.4 with libsigc++ 2.6.2 (from homebrew).
compilation fails with: 

/usr/local/Cellar/libsigc++/2.6.2/include/sigc++-2.0/sigc++/functors/functor_trait.h:18:1: error: declaration of anonymous struct must be a definition

see https://gist.githubusercontent.com/david0/3c66848654c44048bf8d/raw/ffac06eac19112941bcbd356c692a48381502c1b/compile.log a full log.

I tried the newer patch (290480), but it didnt change anything. Maybe the patches need to be updated? I would be happy to test again then.
Comment 8 Kjell Ahlstedt 2015-12-13 19:00:55 UTC
Created attachment 317310 [details] [review]
patch: Make it easier to use libsigc++ with Objective-C++

Here is an updated patch.

Why would nil be a problem for you? Is nil a preprocessor macro in Mac OS C++?
Or does Ardour use Objective-C++?
Comment 9 Kjell Ahlstedt 2015-12-15 16:10:29 UTC
I'm inclined to push the patch in comment 8, but first I'd like to know if it
fixes the problem with building Ardour on Mac OS X. It's surprising if nil
is a problem now. Contrary to check() (bug 759315), nil is not new in libsigc++.
struct nil has existed at least since the year 2003, libsigc++ 2.0.0.

David, if you test it, note that it adds a new test in the configure file.
Run autogen.sh to regenerate configure. Or add
  #define SIGC_PRAGMA_PUSH_POP_MACRO 1
manually in sigc++config.h after you run configure.
Comment 10 David 2015-12-15 22:53:44 UTC
To answer your previous questions: 
No, as far as I know it dosen't use ObjC. But it uses some Mac frameworks, which use nil as an reserved keyword. 
MacTypes.h defines nil as nullptr (for C++11), is the reason that the definiton of "struct nil" by libsigc++ fails:

/usr/local/Cellar/libsigc++/2.6.2/include/sigc++-2.0/sigc++/functors/functor_trait.h:18:1: error: declaration of anonymous struct must be a definition
struct nil;

/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.11.sdk/usr/include/MacTypes.h:92:19: note: expanded from macro 'nil'
      #define nil nullptr

MacTypes.h together with an vanilla libsigc++ may have never been used successfully (Ardour is using a patched libsigc++).




Now with your patch applied and regenerating via autogen.sh, that works like a charm! 
Thank you!
Comment 11 Kjell Ahlstedt 2015-12-16 08:50:03 UTC
I have pushed the patch, but with a new title:
  Temporarily undefine the nil macro, if it's defined
https://git.gnome.org/browse/libsigc++2/commit/?id=75466ce1e1d92fe04926f72567417912779cc5c1
Comment 12 Murray Cumming 2016-03-03 12:05:34 UTC
I have removed nil from libsigc++-3.0. We don't need it now that we have variadic templates. That code is currently in the variadic_bind4 branch but will eventually be in git master.