www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - K&R-style variadic functions

reply Jacob Carlborg <doob me.com> writes:
To my understanding this is legal C :

int foo ();

It's a K&R-style variadic functions, while their use is discouraged, 
they're still legal C.

If I, in D, declare a variadic function with C linkage that doesn't 
take, at least, one regular parameter the compiler will complain.

extern (C) int foo (...);

Error: variadic functions with non-D linkage must have at least one 
parameter

Does that mean I can't use a function like this from D?

I'm trying to figure out what my tool, DStep, should do when it 
encounters a function like this.

https://github.com/jacob-carlborg/dstep

-- 
/Jacob Carlborg
Jul 16 2012
next sibling parent reply "Mehrdad" <wfunction hotmail.com> writes:
On Tuesday, 17 July 2012 at 06:56:17 UTC, Jacob Carlborg wrote:
 To my understanding this is legal C :

 int foo ();

 It's a K&R-style variadic functions, while their use is 
 discouraged, they're still legal C.

My eyes!! They're bleeding!!
Jul 17 2012
parent reply Jacob Carlborg <doob me.com> writes:
On 2012-07-17 09:06, Mehrdad wrote:

 My eyes!! They're bleeding!!

First I wanted to know if my interpretation is correct and then I was trying to figure out how my tool should behave if it encounters a function like this. -- /Jacob Carlborg
Jul 17 2012
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-07-17 15:05, Regan Heath wrote:

 In my specific case I could add "int a" as the first parameter, and all
 was well.  Each case will be different, and it's conceivable there is a
 C old-style variadic which takes /any/ type of first parameter, which
 could be a problem, however the key issue is the size of the argument.
 If all types which could be passed are 32 bits big, then "int a" is
 sufficient to get it working in all cases.

It could just as well be no parameters. -- /Jacob Carlborg
Jul 17 2012
parent reply Jacob Carlborg <doob me.com> writes:
On 2012-07-17 16:36, Regan Heath wrote:

 I believe old-style no parameter function declarations MUST have "void"
 i.e.

      int foo(void);

That is still the case, regardless of "style"?
 They cannot read:

      int foo();

 The latter MUST have parameters, we just can't tell what they are.

Take a look at this: http://en.wikipedia.org/wiki/K%26R_C#KRC In that example none of the functions have any parameters declared and are not called with any arguments. -- /Jacob Carlborg
Jul 17 2012
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-07-17 17:11, Regan Heath wrote:

 Ahh, I've been looking at the ANSI C spec and assuming that is what
 you're basing things off, K&R C was pre-ANSI C and may have different
 rules.  I think you should probably aim to be ANSI C compliant and
 above, and ignore K&R.

This page says otherwise: http://en.wikipedia.org/wiki/ANSI_C#Compliance_detectability "...while an obsolescent non-prototype declaration is used otherwise. Those are still ANSI-compliant as of C99 and C90, but their use is discouraged".
 Looking at the ANSI C spec again, section 6.7.5.3, item 10 says:

 "The special case of an unnamed parameter of type void as the only item
 in the list specifies that the function has no parameters."

 So, "void" indicates no parameters..

 Item 14 is also applicable and says:

 "An identifier list declares only the identifiers of the parameters of
 the function. An empty list in a function declarator that is part of a
 definition of that function specifies that the function has no
 parameters. The empty list in a function declarator that is not part of
 a definition of that function specifies that no information about the
 number or types of the parameters is supplied." 124)

 The latter part of that is applicable to declarations in header files
 (the former is for definitions in c files);  "The empty list in a
 function declarator that is /not part of a definition of that function/
 specifies that /no information about the number or types of the
 parameters is supplied/."

 So, a function like:
      int foo();

 in a header "specifies that no information about the number or types of
 the parameters is supplied".

 However footnote 124) says see 6.1.6, and 6.1.6 says:

 6.11.6 Function declarators
 The use of function declarators with empty parentheses (not
 prototype-format parameter type declarators) is an obsolescent feature.

 So, coming full circle, it seems like I'm right after all .. I think.
 "void" is required to indicate no parameters and () is obsolete in ANSI C.

It's still in the standard. -- /Jacob Carlborg
Jul 17 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-07-18 12:25, Regan Heath wrote:
 In any case.  It think the practical solution to this problem is to
 assume you're working with modern code, and have a command line option
 to make it assume K&R or old-style declarations.

 In the old-style mode you would have to assume a function with an empty
 () could have any number of parameters and the best you can do is produce:

 extern (C) <ret> <name>(/* fill in the blanks please*/);

 R

Seems like this will be the solution. -- /Jacob Carlborg
Jul 18 2012
prev sibling parent Matt Soucy <msoucy csh.rit.edu> writes:
Definitely - I live in a very technologically-savvy dorm in college, and 
when I encountered it for the first time nobody there had any idea what 
it was.
...we did later find an old book in our library that had it, though.
-Matt


On 07/17/2012 02:39 PM, H. S. Teoh wrote:
 On Tue, Jul 17, 2012 at 08:07:08PM +0200, Paulo Pinto wrote:
 On Tuesday, 17 July 2012 at 15:16:56 UTC, Regan Heath wrote:

 So all K&R function declarations were <name>() with no parameters.

 R

K&R was more than that.

This modern C declaration: int main(int argc, char **argv) { exit(1); } is written thus in K&R: int main(argc, argv) int argc; char **argv; { exit(1); }
 I guess most old timers here will agree with me that it was
 not much more than glorified assembler in what concerns typing.

I guess you predate me. ;-) When I started learning C, it was already in the ANSI syntax, though there were enough K&R style code floating around that I've at least _seen_ K&R syntax. I'm guessing nowadays most people don't even know what K&R syntax is. T

Jul 17 2012
prev sibling next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-07-17 14:32, Regan Heath wrote:

 After a bit of googling and a test with my local MSVC9 I think old-style
 variadics look like this:

 #include <varargs.h>
 #include <stdio.h>

 void foo(va_alist)
      va_dcl
 {
      va_list p;
      va_start(p);
      vprintf("%d %d %d\n", p);
 }

 void main()
 {
      foo(1, 2, 3);
 }

 (the above runs and outputs "1 2 3" on the console)

 The same syntax is/was supported by GNU C, see:
 http://ftp.gnu.org/old-gnu/Manuals/glibc-2.2.3/html_chapter/libc_34.html#SEC676



 I believe, if you see an "old-style" function declaration in a header
 file like:

      int foo ();

 that you can't actually assume anything about it's parameters, it may
 have /any/ number of parameters, and may or may not be variadic.

Clang seems to interpret it as a variadic function. Then if that is correct or not I don't know. -- /Jacob Carlborg
Jul 17 2012
parent reply Jacob Carlborg <doob me.com> writes:
On 2012-07-17 16:37, Regan Heath wrote:

 All my googling for "old style" "variadic" etc returned the use of
 va_alist and va_dcl so I can't see where/why Clang would do what it's
 doing.

To be accurate it's the libclang function "clang_isFunctionTypeVariadic" that returns true. http://clang.llvm.org/doxygen/group__CINDEX__TYPES.html#ga343b2463b0ed b259739242cf26c3ae2 -- /Jacob Carlborg
Jul 17 2012
parent Jacob Carlborg <doob me.com> writes:
On 2012-07-17 17:13, Regan Heath wrote:

 Is Clang open source, can we see the code for that function?  Perhaps
 it's a bug.. ANSI C may have made () without "void" obsolete, but no
 compiler I've ever used has actually enforced that - or perhaps C++ made
 old-style function definition/declarations obsolete and allowed () back
 again.

Sure: https://llvm.org/svn/llvm-project/cfe/trunk/tools/libclang/CXType.cpp Just search for clang_isFunctionTypeVariadic. -- /Jacob Carlborg
Jul 17 2012
prev sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Wed, Jul 18, 2012 at 11:23:33AM +0100, Regan Heath wrote:
 On Tue, 17 Jul 2012 19:39:25 +0100, H. S. Teoh
 <hsteoh quickfur.ath.cx> wrote:

This modern C declaration:

	int main(int argc, char **argv) {
		exit(1);
	}

is written thus in K&R:

	int main(argc, argv)
		int argc;
		char **argv;
	{
		exit(1);
	}

Clarification. The /definition/ is as you have above, the /declaration/ is not. The declaration is what goes in the header file, and in K&R (and ANSI C for that matter) looks like: int main(); parameters are not required for the declaration, only the definition.

You are right. And also, under K&R syntax, the 'int' can be omitted from before main. I *think* the entire argc line can be omitted as well (undeclared variables default to int, IIRC). 'Tis a strange world they used to live in. :-) T -- Almost all proofs have bugs, but almost all theorems are true. -- Paul Pedersen
Jul 18 2012
prev sibling next sibling parent "Paulo Pinto" <pjmlp progtools.org> writes:
On Tuesday, 17 July 2012 at 07:06:38 UTC, Mehrdad wrote:
 On Tuesday, 17 July 2012 at 06:56:17 UTC, Jacob Carlborg wrote:
 To my understanding this is legal C :

 int foo ();

 It's a K&R-style variadic functions, while their use is 
 discouraged, they're still legal C.

My eyes!! They're bleeding!!

I had the "pleasure" to use K&R C in my early C days, around 1992, yuck!
Jul 17 2012
prev sibling next sibling parent "Regan Heath" <regan netmail.co.nz> writes:
On Tue, 17 Jul 2012 12:43:46 +0100, Jacob Carlborg <doob me.com> wrote:

 On 2012-07-17 09:06, Mehrdad wrote:

 My eyes!! They're bleeding!!

First I wanted to know if my interpretation is correct and then I was trying to figure out how my tool should behave if it encounters a function like this.

After a bit of googling and a test with my local MSVC9 I think old-style variadics look like this: #include <varargs.h> #include <stdio.h> void foo(va_alist) va_dcl { va_list p; va_start(p); vprintf("%d %d %d\n", p); } void main() { foo(1, 2, 3); } (the above runs and outputs "1 2 3" on the console) The same syntax is/was supported by GNU C, see: http://ftp.gnu.org/old-gnu/Manuals/glibc-2.2.3/html_chapter/libc_34.html#SEC676 I believe, if you see an "old-style" function declaration in a header file like: int foo (); that you can't actually assume anything about it's parameters, it may have /any/ number of parameters, and may or may not be variadic. e.g. see: http://msdn.microsoft.com/en-us/library/efx873ys.aspx The "declaration" syntax shown there for a function with 2 arguments is simply: double old_style(); In short, I don't think you can produce a valid .di/d file for old-style declarations automatically, it will require a manual step where the user enters the function type-arguments. However, if you see an old-style: int foo(void); you can be sure it has 0 parameters and can happily produce: extern (C) int foo(); So, I think you should assume no old-style function declarations but have a command line option/mode which assumes all functions declarations are old-style. In this mode you would output something like.. extern (C) <return-type> <function-name>(/*TODO: add args here*/); and require the user manually find and define these. I can't think of any other way you could do it. R p.s. I found this copy of the C spec online: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf section 6.7.5.3 appears to deal with function declarations. -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Jul 17 2012
prev sibling next sibling parent "Regan Heath" <regan netmail.co.nz> writes:
On Tue, 17 Jul 2012 13:32:08 +0100, Regan Heath <regan netmail.co.nz>  
wrote:

 On Tue, 17 Jul 2012 12:43:46 +0100, Jacob Carlborg <doob me.com> wrote:

 On 2012-07-17 09:06, Mehrdad wrote:

 My eyes!! They're bleeding!!

First I wanted to know if my interpretation is correct and then I was trying to figure out how my tool should behave if it encounters a function like this.

After a bit of googling and a test with my local MSVC9 I think old-style variadics look like this: #include <varargs.h> #include <stdio.h> void foo(va_alist) va_dcl { va_list p; va_start(p); vprintf("%d %d %d\n", p); } void main() { foo(1, 2, 3); } (the above runs and outputs "1 2 3" on the console)

Some follow up information, for interests sake. 1. va_dcl is defined in varargs.h as.. #define va_dcl va_list va_alist; So, the old-style variable args function definiton can be written: void foo(va_alist) va_list va_alist; { ... } 2. va_start in defined in varargs.h as.. #define va_start(ap) ap = (va_list)&va_alist So, it assumes a parameter called va_alist exists, and it simply takes the address of it. A new style variadic uses a definition like this.. #define _crt_va_start(ap,v) ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) ) which takes the address of 'v' (which is the argument prior to the ...) then skips past it, obtaining the address of the first ... argument. So, in effect they are doing the same thing, taking the address of the first variable argument. In which case, I can only assume if we can call new-style variadics from D, we can call old-style ones as well - provided any preceding arguments to the va_alist argument are defined correctly, .e.g. given this old-style function declaration: void foo(); which actually happens to match this old-style variadic function definition: void foo(a,b,va_alist) int a; int b; va_list va_alist; { } we could produce the following: extern (C) void foo(/*TODO: add args here*/); and, once the user filled in the args extern (C) void foo(int a, int b, ...); it should be callable from D.. in fact I just did a test (albeit with a slightly different test case..) [testdll.c] #include <varargs.h> #include <stdio.h> __declspec( dllexport ) void foo(va_alist) va_list va_alist; { va_list p; va_start(p); vprintf("%d %d %d\n", p); } (compiled with MSVC to dll and lib, lib converted with coffimplib to OMF format) [test.d] extern (C) void foo(int a, ...); int main(string[] args) { foo(1, 3, 5); return 0; } compile with dmd test.d testdll.lib, run test.exe, outputs "1 3 5" :) But, this highlights one issue I was unaware of. The D extern (C) declaration needs at least 1 parameter before the ..., having just: extern (C) void foo(...); is illegal. In my specific case I could add "int a" as the first parameter, and all was well. Each case will be different, and it's conceivable there is a C old-style variadic which takes /any/ type of first parameter, which could be a problem, however the key issue is the size of the argument. If all types which could be passed are 32 bits big, then "int a" is sufficient to get it working in all cases. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Jul 17 2012
prev sibling next sibling parent "Regan Heath" <regan netmail.co.nz> writes:
On Tue, 17 Jul 2012 15:01:02 +0100, Jacob Carlborg <doob me.com> wrote:

 On 2012-07-17 15:05, Regan Heath wrote:

 In my specific case I could add "int a" as the first parameter, and all
 was well.  Each case will be different, and it's conceivable there is a
 C old-style variadic which takes /any/ type of first parameter, which
 could be a problem, however the key issue is the size of the argument.
 If all types which could be passed are 32 bits big, then "int a" is
 sufficient to get it working in all cases.

It could just as well be no parameters.

I believe old-style no parameter function declarations MUST have "void" i.e. int foo(void); They cannot read: int foo(); The latter MUST have parameters, we just can't tell what they are. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Jul 17 2012
prev sibling next sibling parent "Regan Heath" <regan netmail.co.nz> writes:
On Tue, 17 Jul 2012 15:02:44 +0100, Jacob Carlborg <doob me.com> wrote:

 On 2012-07-17 14:32, Regan Heath wrote:

 After a bit of googling and a test with my local MSVC9 I think old-style
 variadics look like this:

 #include <varargs.h>
 #include <stdio.h>

 void foo(va_alist)
      va_dcl
 {
      va_list p;
      va_start(p);
      vprintf("%d %d %d\n", p);
 }

 void main()
 {
      foo(1, 2, 3);
 }

 (the above runs and outputs "1 2 3" on the console)

 The same syntax is/was supported by GNU C, see:
 http://ftp.gnu.org/old-gnu/Manuals/glibc-2.2.3/html_chapter/libc_34.html#SEC676



 I believe, if you see an "old-style" function declaration in a header
 file like:

      int foo ();

 that you can't actually assume anything about it's parameters, it may
 have /any/ number of parameters, and may or may not be variadic.

Clang seems to interpret it as a variadic function. Then if that is correct or not I don't know.

All my googling for "old style" "variadic" etc returned the use of va_alist and va_dcl so I can't see where/why Clang would do what it's doing. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Jul 17 2012
prev sibling next sibling parent reply deadalnix <deadalnix gmail.com> writes:
On 17/07/2012 08:56, Jacob Carlborg wrote:
 To my understanding this is legal C :

 int foo ();

 It's a K&R-style variadic functions, while their use is discouraged,
 they're still legal C.

 If I, in D, declare a variadic function with C linkage that doesn't
 take, at least, one regular parameter the compiler will complain.

 extern (C) int foo (...);

It is used in testfptr.d from dmd's testsuite.
Jul 17 2012
parent "Daniel Murphy" <yebblies nospamgmail.com> writes:
"deadalnix" <deadalnix gmail.com> wrote in message 
news:ju3uqc$55g$1 digitalmars.com...
 It is used in testfptr.d from dmd's testsuite.

No, that's a D-linkage variadic.
Jul 17 2012
prev sibling next sibling parent "Regan Heath" <regan netmail.co.nz> writes:
On Tue, 17 Jul 2012 15:46:34 +0100, Jacob Carlborg <doob me.com> wrote:

 On 2012-07-17 16:36, Regan Heath wrote:

 I believe old-style no parameter function declarations MUST have "void"
 i.e.

      int foo(void);

That is still the case, regardless of "style"?
 They cannot read:

      int foo();

 The latter MUST have parameters, we just can't tell what they are.

Take a look at this: http://en.wikipedia.org/wiki/K%26R_C#KRC In that example none of the functions have any parameters declared and are not called with any arguments.

Ahh, I've been looking at the ANSI C spec and assuming that is what you're basing things off, K&R C was pre-ANSI C and may have different rules. I think you should probably aim to be ANSI C compliant and above, and ignore K&R. Looking at the ANSI C spec again, section 6.7.5.3, item 10 says: "The special case of an unnamed parameter of type void as the only item in the list specifies that the function has no parameters." So, "void" indicates no parameters.. Item 14 is also applicable and says: "An identifier list declares only the identifiers of the parameters of the function. An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters. The empty list in a function declarator that is not part of a definition of that function specifies that no information about the number or types of the parameters is supplied." 124) The latter part of that is applicable to declarations in header files (the former is for definitions in c files); "The empty list in a function declarator that is /not part of a definition of that function/ specifies that /no information about the number or types of the parameters is supplied/." So, a function like: int foo(); in a header "specifies that no information about the number or types of the parameters is supplied". However footnote 124) says see 6.1.6, and 6.1.6 says: 6.11.6 Function declarators The use of function declarators with empty parentheses (not prototype-format parameter type declarators) is an obsolescent feature. So, coming full circle, it seems like I'm right after all .. I think. "void" is required to indicate no parameters and () is obsolete in ANSI C. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Jul 17 2012
prev sibling next sibling parent "Regan Heath" <regan netmail.co.nz> writes:
On Tue, 17 Jul 2012 15:50:27 +0100, Jacob Carlborg <doob me.com> wrote:

 On 2012-07-17 16:37, Regan Heath wrote:

 All my googling for "old style" "variadic" etc returned the use of
 va_alist and va_dcl so I can't see where/why Clang would do what it's
 doing.

To be accurate it's the libclang function "clang_isFunctionTypeVariadic" that returns true. http://clang.llvm.org/doxygen/group__CINDEX__TYPES.html#ga343b2463b0ed4b259739242cf26c3ae2

Is Clang open source, can we see the code for that function? Perhaps it's a bug.. ANSI C may have made () without "void" obsolete, but no compiler I've ever used has actually enforced that - or perhaps C++ made old-style function definition/declarations obsolete and allowed () back again. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Jul 17 2012
prev sibling next sibling parent "Regan Heath" <regan netmail.co.nz> writes:
On Tue, 17 Jul 2012 15:46:34 +0100, Jacob Carlborg <doob me.com> wrote:

 On 2012-07-17 16:36, Regan Heath wrote:

 I believe old-style no parameter function declarations MUST have "void"
 i.e.

      int foo(void);

That is still the case, regardless of "style"?
 They cannot read:

      int foo();

 The latter MUST have parameters, we just can't tell what they are.

Take a look at this: http://en.wikipedia.org/wiki/K%26R_C#KRC In that example none of the functions have any parameters declared and are not called with any arguments.

K&R C did not allow you to declare arguments at all, according to the wiki: "Since K&R function declarations did not include any information about function arguments, function parameter type checks were not performed, although some compilers would issue a warning message if a local function was called with the wrong number of arguments, or if multiple calls to an external function used different numbers or types of arguments. Separate tools such as Unix's lint utility were developed that (among other things) could check for consistency of function use across multiple source files." So all K&R function declarations were <name>() with no parameters. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Jul 17 2012
prev sibling next sibling parent "Paulo Pinto" <pjmlp progtools.org> writes:
On Tuesday, 17 July 2012 at 15:16:56 UTC, Regan Heath wrote:
 On Tue, 17 Jul 2012 15:46:34 +0100, Jacob Carlborg 
 <doob me.com> wrote:

 On 2012-07-17 16:36, Regan Heath wrote:

 I believe old-style no parameter function declarations MUST 
 have "void"
 i.e.

     int foo(void);

That is still the case, regardless of "style"?
 They cannot read:

     int foo();

 The latter MUST have parameters, we just can't tell what they 
 are.

Take a look at this: http://en.wikipedia.org/wiki/K%26R_C#KRC In that example none of the functions have any parameters declared and are not called with any arguments.

K&R C did not allow you to declare arguments at all, according to the wiki: "Since K&R function declarations did not include any information about function arguments, function parameter type checks were not performed, although some compilers would issue a warning message if a local function was called with the wrong number of arguments, or if multiple calls to an external function used different numbers or types of arguments. Separate tools such as Unix's lint utility were developed that (among other things) could check for consistency of function use across multiple source files." So all K&R function declarations were <name>() with no parameters. R

K&R was more than that. I guess most old timers here will agree with me that it was not much more than glorified assembler in what concerns typing. Much of the typing C has today, was actually brought in as part of the ANSI C standardization process. -- Paulo
Jul 17 2012
prev sibling next sibling parent "Paulo Pinto" <pjmlp progtools.org> writes:
On Tuesday, 17 July 2012 at 15:13:52 UTC, Regan Heath wrote:
 On Tue, 17 Jul 2012 15:50:27 +0100, Jacob Carlborg 
 <doob me.com> wrote:

 On 2012-07-17 16:37, Regan Heath wrote:

 All my googling for "old style" "variadic" etc returned the 
 use of
 va_alist and va_dcl so I can't see where/why Clang would do 
 what it's
 doing.

To be accurate it's the libclang function "clang_isFunctionTypeVariadic" that returns true. http://clang.llvm.org/doxygen/group__CINDEX__TYPES.html#ga343b2463b0ed4b259739242cf26c3ae2

Is Clang open source, can we see the code for that function? Perhaps it's a bug.. ANSI C may have made () without "void" obsolete, but no compiler I've ever used has actually enforced that - or perhaps C++ made old-style function definition/declarations obsolete and allowed () back again. R

In C++, a function with no parameters () is a synonym for (void). -- Paulo
Jul 17 2012
prev sibling next sibling parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Jul 17, 2012 at 08:07:08PM +0200, Paulo Pinto wrote:
 On Tuesday, 17 July 2012 at 15:16:56 UTC, Regan Heath wrote:

So all K&R function declarations were <name>() with no parameters.

R

K&R was more than that.

This modern C declaration: int main(int argc, char **argv) { exit(1); } is written thus in K&R: int main(argc, argv) int argc; char **argv; { exit(1); }
 I guess most old timers here will agree with me that it was
 not much more than glorified assembler in what concerns typing.

I guess you predate me. ;-) When I started learning C, it was already in the ANSI syntax, though there were enough K&R style code floating around that I've at least _seen_ K&R syntax. I'm guessing nowadays most people don't even know what K&R syntax is. T -- If I were two-faced, would I be wearing this one? -- Abraham Lincoln
Jul 17 2012
prev sibling next sibling parent "Lukasz" <wrzoski gmail.com> writes:
I was sure that if function is declared with empty () than you 
can call it with any arguments you imagine, as it is in following 
examples.
============================= ex. 1
<*> cat main.c
void a() {
}

int main()
{
     a(1, 2, 3);
     return 0;
}

<*> gcc -Wall -Wextra -pedantic  main.c
<*>

============================== ex. 2
<*> cat test.c
#include <stdio.h>
void a(int a, char b, void* ptr)
{
     printf("%d  %c  %p\n", a, b, ptr);
}

<*> cat main.c
extern void a();

int main()
{
     int aa = 123;
     char b = '#';
     void* ptr = (void*)0xffaaffaa;
     a(aa, b, ptr);
     return 0;
}

<*> gcc -c test.c
<*> gcc -c main.c
<*> gcc -o main main.o test.o
<*> ./main
123  #  0xffaaffaa
<*>

But this is not:
Jul 17 2012
prev sibling next sibling parent "Paulo Pinto" <pjmlp progtools.org> writes:
On Tuesday, 17 July 2012 at 18:37:54 UTC, H. S. Teoh wrote:
 I guess you predate me. ;-) When I started learning C, it was 
 already in
 the ANSI syntax, though there were enough K&R style code 
 floating around
 that I've at least _seen_ K&R syntax. I'm guessing nowadays 
 most people
 don't even know what K&R syntax is.


 T

I started coding in C around 1993 with Turbo C 2.0, but was exposed to K&R code from different sources, specially when we needed to make use of a System V based system for some OS classes. Plus as a language geek, I had the pleasure to have access a lots of books and papers since the late 70's in our university library. That is a reason why I tend to have a good background in what languages introduced which paradigm. Maybe it is the historian in me. :) -- Paulo
Jul 17 2012
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/16/2012 11:56 PM, Jacob Carlborg wrote:
 To my understanding this is legal C :

 int foo ();

 It's a K&R-style variadic functions, while their use is discouraged, they're
 still legal C.

Variadic functions, in order to work in C, need at least one parameter so that varargs can work. int foo(); declares a function with an unspecified parameter list, not a variadic one. It is specified by a definition somewhere: int foo(a,b) int a; int b; { ... } somewhere. If Dstep encounters the first declaration form, your options are to: 1. reject it (a perfectly reasonable approach) 2. treat it as: int foo(void); I suggest option 2, which is what C++ does.
Jul 18 2012
next sibling parent reply Jacob Carlborg <doob me.com> writes:
On 2012-07-18 11:41, Walter Bright wrote:

 Variadic functions, in order to work in C, need at least one parameter
 so that varargs can work.

    int foo();

 declares a function with an unspecified parameter list, not a variadic
 one. It is specified by a definition somewhere:

    int foo(a,b)
    int a;
    int b;
    { ... }

 somewhere.

I think I understand now.
 If Dstep encounters the first declaration form, your options are to:

 1. reject it (a perfectly reasonable approach)

 2. treat it as:

      int foo(void);

 I suggest option 2, which is what C++ does.

Sounds reasonable. I will also provide a flag specifying how this should be handled. I actually found library that uses this style of declaration. It's used in several places in libruby. For example: void rb_define_virtual_variable(const char*,VALUE(*)(ANYARGS),void(*)(ANYARGS)); ANYARGS is defined as: #ifdef __cplusplus #define ANYARGS ... #else #define ANYARGS #endif Does that mean that this C++ declaration: void foo (...); Is the same as this C declaration? void foo (); I'm wondering if the intention is to cast these function pointers to their correct signature before calling them. -- /Jacob Carlborg
Jul 18 2012
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/18/2012 4:59 AM, Jacob Carlborg wrote:
 Does that mean that this C++ declaration:

 void foo (...);

Not allowed in C or C++.
 Is the same as this C declaration?

 void foo ();

That is void foo(void) in C++.
Jul 18 2012
parent reply Jacob Carlborg <doob me.com> writes:
On 2012-07-18 20:43, Walter Bright wrote:
 On 7/18/2012 4:59 AM, Jacob Carlborg wrote:
 Does that mean that this C++ declaration:

 void foo (...);

Not allowed in C or C++.

When compiling in C++ mode, both Clang and GCC accepts this.
 Is the same as this C declaration?

 void foo ();

That is void foo(void) in C++.

-- /Jacob Carlborg
Jul 18 2012
parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 7/18/2012 11:47 AM, Jacob Carlborg wrote:
 On 2012-07-18 20:43, Walter Bright wrote:
 On 7/18/2012 4:59 AM, Jacob Carlborg wrote:
 Does that mean that this C++ declaration:

 void foo (...);

Not allowed in C or C++.

When compiling in C++ mode, both Clang and GCC accepts this.

How would you get the arguments inside foo?
Jul 18 2012
next sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-07-18 22:12, Walter Bright wrote:

 How would you get the arguments inside foo?

I don't know, you're the compiler writer :) I don't know these kind of things, that's why I started this thread. I'm just telling you how GCC/Clang treats these code snippets. -- /Jacob Carlborg
Jul 18 2012
prev sibling parent Jacob Carlborg <doob me.com> writes:
On 2012-07-19 11:38, Regan Heath wrote:
asn't ware that was valid ANSI C, perhaps it's a GCC/clang
 feature?  Can anyone find docs on it?

Note that it only works when compiling as C++. Perhaps it works like this: If C++ is interpreting this: void foo (); As: void foo (void); Perhaps it will interpret: void foo (...); As C would interpret this: void foo (); -- /Jacob Carlborg
Jul 19 2012
prev sibling next sibling parent "Paulo Pinto" <pjmlp progtools.org> writes:
On Wednesday, 18 July 2012 at 20:13:10 UTC, Walter Bright wrote:
 On 7/18/2012 11:47 AM, Jacob Carlborg wrote:
 On 2012-07-18 20:43, Walter Bright wrote:
 On 7/18/2012 4:59 AM, Jacob Carlborg wrote:
 Does that mean that this C++ declaration:

 void foo (...);

Not allowed in C or C++.

When compiling in C++ mode, both Clang and GCC accepts this.

How would you get the arguments inside foo?

As described here, http://pubs.opengroup.org/onlinepubs/7908799/xsh/varargs.h.html
Jul 19 2012
prev sibling parent "Regan Heath" <regan netmail.co.nz> writes:
On Thu, 19 Jul 2012 08:33:12 +0100, Paulo Pinto <pjmlp progtools.org>  
wrote:

 On Wednesday, 18 July 2012 at 20:13:10 UTC, Walter Bright wrote:
 On 7/18/2012 11:47 AM, Jacob Carlborg wrote:
 On 2012-07-18 20:43, Walter Bright wrote:
 On 7/18/2012 4:59 AM, Jacob Carlborg wrote:
 Does that mean that this C++ declaration:

 void foo (...);

Not allowed in C or C++.

When compiling in C++ mode, both Clang and GCC accepts this.

How would you get the arguments inside foo?

As described here, http://pubs.opengroup.org/onlinepubs/7908799/xsh/varargs.h.html

That /requires/ an argument in the definition (AFAIKS), e.g. execl(va_alist) <- va_alist is the argument name va_dcl <- this is #define va_dcl va_list va_alist; { } so, it's no different to any other old-style function, e.g. foo(a) int a; { } Now.. the declaration may be a different story. These would be valid declarations for the above: void execl(); <- no parameters necessary in a declaration void foo(); <- no parameters necessary in a declaration It may be that GCC allows a declaration of: void execl(...); But I wasn't ware that was valid ANSI C, perhaps it's a GCC/clang feature? Can anyone find docs on it? If we /assume/ the above declaration always refers to a function with a definition of: execl(va_alist) va_dcl { } Then we assume the first argument is /always/ going to be a 32 bit value (int, or 32 bit pointer) then we could speculatively convert to this D extern (C) void execl(int first, ...); But, if either assumption is false this would probably crash when used. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Jul 19 2012
prev sibling next sibling parent "Regan Heath" <regan netmail.co.nz> writes:
On Tue, 17 Jul 2012 20:31:19 +0100, Jacob Carlborg <doob me.com> wrote:

 On 2012-07-17 17:11, Regan Heath wrote:

 Ahh, I've been looking at the ANSI C spec and assuming that is what
 you're basing things off, K&R C was pre-ANSI C and may have different
 rules.  I think you should probably aim to be ANSI C compliant and
 above, and ignore K&R.

This page says otherwise: http://en.wikipedia.org/wiki/ANSI_C#Compliance_detectability "...while an obsolescent non-prototype declaration is used otherwise. Those are still ANSI-compliant as of C99 and C90, but their use is discouraged".

The full quote: "In the above example, a prototype is used in a function declaration for ANSI compliant implementations, while an obsolescent non-prototype declaration is used otherwise. Those are still ANSI-compliant as of C99 and C90, but their use is discouraged." 1) "a prototype is used in a function declaration for ANSI compliant implementations" implies an ANSI compliant compiler /requires/ the full prototype. 2) "obsolescent non-prototype declaration is used otherwise" implies non-prototype forms are /obsolete/ 3) "Those are still" what is being referred to by the word "those" in that sentence, it's not immediately clear to me. It could mean the non-prototype (as you've assumed) but it might also mean the entire construct (using "#if __STDC__"). R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Jul 18 2012
prev sibling next sibling parent "Regan Heath" <regan netmail.co.nz> writes:
On Tue, 17 Jul 2012 19:39:25 +0100, H. S. Teoh <hsteoh quickfur.ath.cx>  
wrote:

 On Tue, Jul 17, 2012 at 08:07:08PM +0200, Paulo Pinto wrote:
 On Tuesday, 17 July 2012 at 15:16:56 UTC, Regan Heath wrote:

So all K&R function declarations were <name>() with no parameters.

R

K&R was more than that.

This modern C declaration: int main(int argc, char **argv) { exit(1); } is written thus in K&R: int main(argc, argv) int argc; char **argv; { exit(1); }

Clarification. The /definition/ is as you have above, the /declaration/ is not. The declaration is what goes in the header file, and in K&R (and ANSI C for that matter) looks like: int main(); parameters are not required for the declaration, only the definition. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Jul 18 2012
prev sibling next sibling parent "Regan Heath" <regan netmail.co.nz> writes:
In any case.  It think the practical solution to this problem is to assume  
you're working with modern code, and have a command line option to make it  
assume K&R or old-style declarations.

In the old-style mode you would have to assume a function with an empty ()  
could have any number of parameters and the best you can do is produce:

extern (C) <ret> <name>(/* fill in the blanks please*/);

R
Jul 18 2012
prev sibling next sibling parent "Regan Heath" <regan netmail.co.nz> writes:
On Tue, 17 Jul 2012 19:08:51 +0100, Paulo Pinto <pjmlp progtools.org>  
wrote:

 On Tuesday, 17 July 2012 at 15:13:52 UTC, Regan Heath wrote:
 On Tue, 17 Jul 2012 15:50:27 +0100, Jacob Carlborg <doob me.com> wrote:

 On 2012-07-17 16:37, Regan Heath wrote:

 All my googling for "old style" "variadic" etc returned the use of
 va_alist and va_dcl so I can't see where/why Clang would do what it's
 doing.

To be accurate it's the libclang function "clang_isFunctionTypeVariadic" that returns true. http://clang.llvm.org/doxygen/group__CINDEX__TYPES.html#ga343b2463b0ed4b259739242cf26c3ae2

Is Clang open source, can we see the code for that function? Perhaps it's a bug.. ANSI C may have made () without "void" obsolete, but no compiler I've ever used has actually enforced that - or perhaps C++ made old-style function definition/declarations obsolete and allowed () back again. R

In C++, a function with no parameters () is a synonym for (void).

That's what I've been assuming all this time, but I wasn't sure if I was technically (according to the spec) right, so I didn't want to say.. :) R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Jul 18 2012
prev sibling parent "Regan Heath" <regan netmail.co.nz> writes:
On Tue, 17 Jul 2012 20:42:09 +0100, Jacob Carlborg <doob me.com> wrote:

 On 2012-07-17 17:13, Regan Heath wrote:

 Is Clang open source, can we see the code for that function?  Perhaps
 it's a bug.. ANSI C may have made () without "void" obsolete, but no
 compiler I've ever used has actually enforced that - or perhaps C++ made
 old-style function definition/declarations obsolete and allowed () back
 again.

Sure: https://llvm.org/svn/llvm-project/cfe/trunk/tools/libclang/CXType.cpp Just search for clang_isFunctionTypeVariadic.

It certainly seems intentional: if (T->getAs<FunctionNoProtoType>()) return 1; I wonder if it's a case of "we can't be certain, so lets assume it is" or similar. R -- Using Opera's revolutionary email client: http://www.opera.com/mail/
Jul 18 2012