RE: [sqlite] Fix for sqlite3.h in version 3.3.10

2007-01-25 Thread James Dennett


> -Original Message-
> From: Joe Wilson [mailto:[EMAIL PROTECTED]
> Sent: Wednesday, January 24, 2007 5:04 PM
> To: sqlite-users@sqlite.org
> Subject: RE: [sqlite] Fix for sqlite3.h in version 3.3.10
> 
> --- James Dennett <[EMAIL PROTECTED]> wrote:
> > Joe Wilson wrote:
> > > The proposed expression ((sqlite3_destructor_type)-1) is
equivalent to
> > > ((void(*)(void *))-1). They are interchangable.
> >
> > Not in C++.  The difference being linkage; with the typedef declared
in
> > an extern "C" block, the type is something that can't be written
> > directly.
> 
> Now I understand your confusion. SQLite is a C. All its API
definitions in
> sqlite3.h and its function pointers are obviously C-based. 

They are intended, I believe, to be usable from both C and C++, and they
have code present to allow their use from C++ -- it's just not quite
complete.

> So to avoid
> these
> warnings related to using SQLITE_TRANSIENT (or SIG_ERR for that
matter)
> in your C++ code, your C++ implementation file must do the following:

That would be one workaround, but it's cleaner to make the header work
with C++ as intended.  The #ifdef __cplusplus sections in the header
file are clearly present to allow its use from C++ without needing
contortions.  That is common practice in C header files which make some
basic effort to integrate smoothly with C++.  The effort required is not
large.

> // example.cpp
> #include "sqlite3.h"
> extern "C" {
>   void example(sqlite3_context* c, const char* b, int n) {
> sqlite3_result_text(c, b, n, SQLITE_TRANSIENT);
>   }
>   // you can even put class member function implementations in here
>   // i.e., void Foo::bar() {...}
>   // without affecting their C++ linkage.
> }
> 
> You'll find that it compiles in Sun C++ 5.8 2005/10/13 without
warnings
> using the unmodified sqlite3.h file.

I expect it would, but it's suboptimal.  C++ code ought not to need such
extern "C" blocks except for 

> The C++ code does not need the proposed typedef to handle
> SQLITE_TRANSIENT,
> although if it were added to sqlite3.h it would not do any harm, and
you
> might be able to avoid the extern "C" block around your sqlite-related
> function implementations.

Correct.

> > >   #define SIG_IGN (void(*)(int))1
> > >   #define SIG_ERR (void(*)(int))-1
> > >
> > > Such C code is grandfathered in C++. If it wasn't you wouldn't be
able
> > > to do any UNIX systems programming in C++.
> >
> > It's not portable C, and it's not portable C++.  It does seem to be
> > blessed by POSIX, but POSIX is just a subset of the much larger
range of
> > platforms supported by ISO/ANSI C and C++.
> 
> In your original question you asked:
> 
>  On a related but separate note, is there any standard that guarantees
>  that casting -1 to a function pointer type is reasonably portable?
> 
> And yes, it is reasonably portable as shown by every UNIX variant that
> must deal with POSIX and every major C++ compiler vendor, as a
> consequence.

The POSIX reference you provided didn't show any such examples though,
unless I missed something.  It shows APIs that specify that certain
arguments can use given named values or function pointers, but the named
values aren't specified, and could themselves be distinguished function
pointers.

POSIX does blur the distinction between data pointers and code pointers
(e.g., with dlsym), but that's a separate issue.

> That's good enough for me. It may or may not be blessed by the C++
> standard,
> but if you can dig up a modern popular C++ compiler that does not work
> with
> such code, I'd be surprised.

It's likely that I can find C++ tools that will diagnose it as an error;
there are reasonable implementation techniques which would mean that it
is not reliable (such as ignoring the bottom bits of function pointers).
I don't know of any platform which would have problems, but why break
the rules when a standards-conforming solution is trivial?

My proposed patch didn't address the int->void(*)(void*) conversion
issue, only the C++-compatibility wart.  Is there any good argument for
not doing so?

-- James

-
To unsubscribe, send email to [EMAIL PROTECTED]
-



RE: [sqlite] Fix for sqlite3.h in version 3.3.10

2007-01-24 Thread Joe Wilson
--- James Dennett <[EMAIL PROTECTED]> wrote:
> Joe Wilson wrote:
> > The proposed expression ((sqlite3_destructor_type)-1) is equivalent to
> > ((void(*)(void *))-1). They are interchangable.
> 
> Not in C++.  The difference being linkage; with the typedef declared in
> an extern "C" block, the type is something that can't be written
> directly.

Now I understand your confusion. SQLite is a C. All its API definitions in 
sqlite3.h and its function pointers are obviously C-based. So to avoid these 
warnings related to using SQLITE_TRANSIENT (or SIG_ERR for that matter)
in your C++ code, your C++ implementation file must do the following:

// example.cpp
#include "sqlite3.h"
extern "C" {
  void example(sqlite3_context* c, const char* b, int n) {
sqlite3_result_text(c, b, n, SQLITE_TRANSIENT);
  }
  // you can even put class member function implementations in here
  // i.e., void Foo::bar() {...}
  // without affecting their C++ linkage.
}

You'll find that it compiles in Sun C++ 5.8 2005/10/13 without warnings 
using the unmodified sqlite3.h file. 

The C++ code does not need the proposed typedef to handle SQLITE_TRANSIENT, 
although if it were added to sqlite3.h it would not do any harm, and you 
might be able to avoid the extern "C" block around your sqlite-related 
function implementations.

> >   #define SIG_IGN (void(*)(int))1
> >   #define SIG_ERR (void(*)(int))-1
> > 
> > Such C code is grandfathered in C++. If it wasn't you wouldn't be able
> > to do any UNIX systems programming in C++.
> 
> It's not portable C, and it's not portable C++.  It does seem to be
> blessed by POSIX, but POSIX is just a subset of the much larger range of
> platforms supported by ISO/ANSI C and C++.

In your original question you asked:

 On a related but separate note, is there any standard that guarantees
 that casting -1 to a function pointer type is reasonably portable?

And yes, it is reasonably portable as shown by every UNIX variant that 
must deal with POSIX and every major C++ compiler vendor, as a consequence. 
That's good enough for me. It may or may not be blessed by the C++ standard,
but if you can dig up a modern popular C++ compiler that does not work with
such code, I'd be surprised.



 

The fish are biting. 
Get more visitors on your site using Yahoo! Search Marketing.
http://searchmarketing.yahoo.com/arp/sponsoredsearch_v2.php

-
To unsubscribe, send email to [EMAIL PROTECTED]
-



RE: [sqlite] Fix for sqlite3.h in version 3.3.10

2007-01-23 Thread James Dennett
> -Original Message-
> From: Joe Wilson [mailto:[EMAIL PROTECTED]
> Sent: Monday, January 22, 2007 5:20 PM
> To: sqlite-users@sqlite.org
> Subject: RE: [sqlite] Fix for sqlite3.h in version 3.3.10
> 
> --- James Dennett <[EMAIL PROTECTED]> wrote:
> > > -Original Message-
> > > From: Joe Wilson [mailto:[EMAIL PROTECTED]
> > > Subject: Re: [sqlite] Fix for sqlite3.h in version 3.3.10
> > [snip]
> >
> > > > I don't know if this is the right place to post suggestions to
the
> > > > SQLite developers, but why don't you do something like
> > > > #define SQLITE_COMPAT_MODE
> > > > and do these things like making SQLITE_TRANSIENT point to real
> > > > function under #ifndef SQLITE_COMPAT_MODE? So the older users
can
> > > > compile under SQLITE_COMPAT_MODE and avoid having problems,
while
> > > > newly written code can rely on proper, clean code?
> > >
> > > By whose definition of proper code?
> >
> > The ANSI/ISO C and C++ committees, and the standards produced by
them.
> 
> Please cite the passage in either the C or C++ standards.

There are two issues: the linkage issue, and the undefined nature of the
conversion from an int to a function pointer type.  

The linkage issue is certainly spelled out in normative text in the C++
standard; see primarily the section "Linkage specifications" [dcl.link].
The section number in N2135 is 7.5; I don't have the IS handy to see if
that's changed (likely it has).

Regarding the undefined nature of the conversion in question, I'd have
to check to see whether it's explicitly called out as undefined, or
whether it is simply undefined because nothing defines it.  Even casting
-1 to an (int*) is not portable, to allow for systems where alignment
requirements are enforced at conversion time among other things.

> The proposed expression ((sqlite3_destructor_type)-1) is equivalent to
> ((void(*)(void *))-1). They are interchangable.

Not in C++.  The difference being linkage; with the typedef declared in
an extern "C" block, the type is something that can't be written
directly.  The types named by the following two typedefs are not the
same:

extern "C" { typedef void(*has_c_linkage)(void*); };
typedef void(*has_cpp_linkage)(void*);

This issue doesn't affect C.

> > > It would be a lot of effort to "solve" a problem that does not
exist.
> > >
> > > >>>> which is diagnosed, though only as a warning, by Sun CC
> > >
> > > It's just a harmless warning produced by the cast when compiled by
> > > a certain overly pedantic C++ compiler.
> >
> > No; the type mismatch is a real problem that can cause real crashes
with
> > valid C++ compilers, in the case that C and C++ use different
calling
> > conventions.
> >
> > > The proposed typedef offered
> > > by the original poster seems like a reasonable appeasement:
> > >
> > >  -#define SQLITE_STATIC  ((void(*)(void *))0)
> > >  -#define SQLITE_TRANSIENT   ((void(*)(void *))-1)
> > >  +typedef void (*sqlite3_destructor_type)(void*);
> > >  +#define SQLITE_STATIC  ((sqlite3_destructor_type)0)
> > >  +#define SQLITE_TRANSIENT   ((sqlite3_destructor_type)-1)
> > >
> > > But the typedef should not be required.
> >
> > In C++, it is required to give the function pointer the correct
type.
> 
> Please show the source code that produces this Sun C++ compiler
warning
> with the exact text of the warning.

Here is a small example program:

extern "C" { typedef void(*has_c_linkage)(void*); }
typedef void(*has_cpp_linkage)(void*);

void fn_c(has_c_linkage a);
void fn_cpp(has_c_linkage a);

void sample_with_cpp_linkage(void*) {}
extern "C" void sample_with_c_linkage(void*) {}

int main()
{
fn_c(sample_with_c_linkage);
fn_cpp(sample_with_cpp_linkage);

fn_cpp(sample_with_c_linkage);
fn_c(sample_with_cpp_linkage);
}

The result of compiling with Sun CC is:
"linkage.cpp", line 13: Warning (Anachronism): Formal argument a of type
extern "C" void(*)(void*) in call to fn_cpp(extern "C" void(*)(void*))
is being passed void(*)(void*).
"linkage.cpp", line 16: Warning (Anachronism): Formal argument a of type
extern "C" void(*)(void*) in call to fn_c(extern "C" void(*)(void*)) is
being passed void(*)(void*).
2 Warning(s) detected.

Comeau's C++ compiler is widely viewed as a paragon of compliance, being
based on the excellent EDG frontend.  It offers similar diagnostics:

bash-2.05$ como -A linkage.cpp
"linkage.cpp", line 13: error: argument of type "v

RE: [sqlite] Fix for sqlite3.h in version 3.3.10

2007-01-22 Thread Joe Wilson
--- James Dennett <[EMAIL PROTECTED]> wrote:
> > -Original Message-
> > From: Joe Wilson [mailto:[EMAIL PROTECTED]
> > Subject: Re: [sqlite] Fix for sqlite3.h in version 3.3.10
> [snip]
>  
> > > I don't know if this is the right place to post suggestions to the
> > > SQLite developers, but why don't you do something like
> > > #define SQLITE_COMPAT_MODE
> > > and do these things like making SQLITE_TRANSIENT point to real
> > > function under #ifndef SQLITE_COMPAT_MODE? So the older users can
> > > compile under SQLITE_COMPAT_MODE and avoid having problems, while
> > > newly written code can rely on proper, clean code?
> > 
> > By whose definition of proper code?
> 
> The ANSI/ISO C and C++ committees, and the standards produced by them.

Please cite the passage in either the C or C++ standards.

The proposed expression ((sqlite3_destructor_type)-1) is equivalent to 
((void(*)(void *))-1). They are interchangable.

> > It would be a lot of effort to "solve" a problem that does not exist.
> > 
> > >>>> which is diagnosed, though only as a warning, by Sun CC
> > 
> > It's just a harmless warning produced by the cast when compiled by
> > a certain overly pedantic C++ compiler. 
> 
> No; the type mismatch is a real problem that can cause real crashes with
> valid C++ compilers, in the case that C and C++ use different calling
> conventions.
> 
> > The proposed typedef offered
> > by the original poster seems like a reasonable appeasement:
> > 
> >  -#define SQLITE_STATIC  ((void(*)(void *))0)
> >  -#define SQLITE_TRANSIENT   ((void(*)(void *))-1)
> >  +typedef void (*sqlite3_destructor_type)(void*);
> >  +#define SQLITE_STATIC  ((sqlite3_destructor_type)0)
> >  +#define SQLITE_TRANSIENT   ((sqlite3_destructor_type)-1)
> > 
> > But the typedef should not be required.
> 
> In C++, it is required to give the function pointer the correct type.

Please show the source code that produces this Sun C++ compiler warning 
with the exact text of the warning.

> Any C++ compiler that does not issue a diagnostic for this fails to
> conform to the C++ standard in this regard (which is not to say that
> such compilers are uncommon).

You're making the assumption that Sun's C++ compiler warning is correct 
in this case.

Should Sun change their definitions of the following as well?

  #define SIG_IGN (void(*)(int))1
  #define SIG_ERR (void(*)(int))-1

Such C code is grandfathered in C++. If it wasn't you wouldn't be able 
to do any UNIX systems programming in C++.



 

The fish are biting. 
Get more visitors on your site using Yahoo! Search Marketing.
http://searchmarketing.yahoo.com/arp/sponsoredsearch_v2.php

-
To unsubscribe, send email to [EMAIL PROTECTED]
-



RE: [sqlite] Fix for sqlite3.h in version 3.3.10

2007-01-22 Thread James Dennett
> -Original Message-
> From: Joe Wilson [mailto:[EMAIL PROTECTED]
> Sent: Sunday, January 21, 2007 10:34 AM
> To: sqlite-users@sqlite.org
> Subject: Re: [sqlite] Fix for sqlite3.h in version 3.3.10
> 

[snip]
 
> > I don't know if this is the right place to post suggestions to the
> > SQLite developers, but why don't you do something like
> > #define SQLITE_COMPAT_MODE
> > and do these things like making SQLITE_TRANSIENT point to real
> > function under #ifndef SQLITE_COMPAT_MODE? So the older users can
> > compile under SQLITE_COMPAT_MODE and avoid having problems, while
> > newly written code can rely on proper, clean code?
> 
> By whose definition of proper code?

The ANSI/ISO C and C++ committees, and the standards produced by them.

> It would be a lot of effort to "solve" a problem that does not exist.
> 
> >>>> which is diagnosed, though only as a warning, by Sun CC
> 
> It's just a harmless warning produced by the cast when compiled by
> a certain overly pedantic C++ compiler. 

No; the type mismatch is a real problem that can cause real crashes with
valid C++ compilers, in the case that C and C++ use different calling
conventions.

> The proposed typedef offered
> by the original poster seems like a reasonable appeasement:
> 
>  -#define SQLITE_STATIC  ((void(*)(void *))0)
>  -#define SQLITE_TRANSIENT   ((void(*)(void *))-1)
>  +typedef void (*sqlite3_destructor_type)(void*);
>  +#define SQLITE_STATIC  ((sqlite3_destructor_type)0)
>  +#define SQLITE_TRANSIENT   ((sqlite3_destructor_type)-1)
> 
> But the typedef should not be required.

In C++, it is required to give the function pointer the correct type.
Any C++ compiler that does not issue a diagnostic for this fails to
conform to the C++ standard in this regard (which is not to say that
such compilers are uncommon).

-- James


-
To unsubscribe, send email to [EMAIL PROTECTED]
-



Re: [sqlite] Fix for sqlite3.h in version 3.3.10

2007-01-21 Thread Joe Wilson
> >> Having SQLITE_TRANSIENT point to a real function is perhaps a
> >> good idea.  The problem is such a change would break backwards
> >> compatibility of the API.  Somebody who compiled against an
> >> older SQLite and who drops in a newer DLL with this change will
> >> find that their code no longer works.  This is something we work
> >> very hard to avoid.
> 
> > You could redefine SQLITE_TRANSIENT and still check for the older -1
> > value in the SQLite code (where you've got better control what the
> > compiler does).

> I don't know if this is the right place to post suggestions to the
> SQLite developers, but why don't you do something like
> #define SQLITE_COMPAT_MODE
> and do these things like making SQLITE_TRANSIENT point to real
> function under #ifndef SQLITE_COMPAT_MODE? So the older users can
> compile under SQLITE_COMPAT_MODE and avoid having problems, while
> newly written code can rely on proper, clean code?

By whose definition of proper code?
It would be a lot of effort to "solve" a problem that does not exist.

 which is diagnosed, though only as a warning, by Sun CC

It's just a harmless warning produced by the cast when compiled by 
a certain overly pedantic C++ compiler. The proposed typedef offered 
by the original poster seems like a reasonable appeasement:

 -#define SQLITE_STATIC  ((void(*)(void *))0)
 -#define SQLITE_TRANSIENT   ((void(*)(void *))-1)
 +typedef void (*sqlite3_destructor_type)(void*);
 +#define SQLITE_STATIC  ((sqlite3_destructor_type)0)
 +#define SQLITE_TRANSIENT   ((sqlite3_destructor_type)-1)

But the typedef should not be required.


 

Never miss an email again!
Yahoo! Toolbar alerts you the instant new Mail arrives.
http://tools.search.yahoo.com/toolbar/features/mail/

-
To unsubscribe, send email to [EMAIL PROTECTED]
-



Re: [sqlite] Fix for sqlite3.h in version 3.3.10

2007-01-21 Thread Florian Weimer
> Having SQLITE_TRANSIENT point to a real function is perhaps a
> good idea.  The problem is such a change would break backwards
> compatibility of the API.  Somebody who compiled against an
> older SQLite and who drops in a newer DLL with this change will
> find that their code no longer works.  This is something we work
> very hard to avoid.

You could redefine SQLITE_TRANSIENT and still check for the older -1
value in the SQLite code (where you've got better control what the
compiler does).

-
To unsubscribe, send email to [EMAIL PROTECTED]
-



Re: [sqlite] Fix for sqlite3.h in version 3.3.10

2007-01-20 Thread Joe Wilson
> On a related but separate note, is there any standard that guarantees
> that casting -1 to a function pointer type is reasonably portable?

This idiom is used widely enough to overload an argument so that it can
contain either a valid pointer, or convey a non-pointer state.

Take /usr/include/pthread.h, for example. It's not a function pointer,
but it's in the same ballpark:

GNU LIBC:

  #define PTHREAD_CANCELED ((void *)-1)

Solaris:

  #define PTHREAD_CANCELED (void *)-19

FreeBSD:

  #define PTHREAD_CANCELED ((void *) 1)

NetBSD:

  /*
   * POSIX 1003.1-2001, section 2.5.9.3: "The symbolic constant
   * PTHREAD_CANCELED expands to a constant expression of type (void *)
   * whose value matches no pointer to an object in memory nor the value
   * NULL."
   */
  #define PTHREAD_CANCELED ((void *) 1)

The UNIX call sigaction() does actually use such "invalid" casted function 
pointers:

  http://www.opengroup.org/onlinepubs/7990989775/xsh/sigaction.html

Where the function pointer sa_handler member of the struct sigaction can 
contain 
SIG_IGN and SIG_ERR. On one popular version of UNIX they are defined as:

  #define SIG_IGN (void(*)(int))1
  #define SIG_ERR (void(*)(int))-1



 

Do you Yahoo!?
Everyone is raving about the all-new Yahoo! Mail beta.
http://new.mail.yahoo.com

-
To unsubscribe, send email to [EMAIL PROTECTED]
-



Re: [sqlite] Fix for sqlite3.h in version 3.3.10

2007-01-20 Thread drh
"James Dennett" <[EMAIL PROTECTED]> wrote:
>  
> On a related but separate note, is there any standard that guarantees
> that casting -1 to a function pointer type is reasonably portable?  My
> experience is that it doesn't cause problems, but certainly it's not
> portable C or C++ from the viewpoint of the language standards.  That's
> a separate issue though. The portable way would be to provide a real
> function for SQLITE_TRANSIENT to point to, but still have it recognized
> as a special case.  Would there be any interest in a patch to make that
> change?
>  

Having SQLITE_TRANSIENT point to a real function is perhaps a
good idea.  The problem is such a change would break backwards
compatibility of the API.  Somebody who compiled against an
older SQLite and who drops in a newer DLL with this change will
find that their code no longer works.  This is something we work
very hard to avoid.
--
D. Richard Hipp  <[EMAIL PROTECTED]>


-
To unsubscribe, send email to [EMAIL PROTECTED]
-