Name: clC74495 Date: 04/28/99
When using JDK 1.2 javah to generate old-style (JDK 1.0.2) native methods
stubs, there are two places where illegal code is generated when the code
is to be compiled by C++.
First, two function declarations are generated for the native method
to be called, one at file scope in the generated .h file and one at
local scope in the generated .c file. Greatly simplified, it looks
like this:
struct Hcaller { ... };
struct HABC { ... };
extern "C" {
extern void caller_nm1(struct Hcaller *,struct HABC *);
void the_stub_name() {
extern void caller_nm1(void *,void *);
}
}
Note that one declaration uses real types, the other void*'s.
This is illegal in ANSI/ISO C++, because the functions have different
type signatures and would therefore be considered overloaded, except
that extern "C" functions cannot be overloaded. (The local declaration
doesn't hide the outer one because despite being local itself it is
declaring an entity at file scope.) The EDG C++ compiler front end,
very commonly used in the industry, rejects this usage. (The current
egcs compiler accepts it, as obviously does the Sun compiler.)
Included below is a fix to OldStubs.java for this problem, by simply
wrapping the local definition in an #ifndef __cplusplus ... #endif
bracket.
The second problem occurs when native methods have class or array
parameters, or are non-static (meaning they have a class "this"
parameter). The generated code, again greatly simplified, looks like:
struct Hcaller { };
struct HABC { };
union Stack {
...
void* p;
};
extern union Stack _P_[1];
extern "C" {
extern void caller_nm1(struct Hcaller *,struct HABC *);
void the_stub() {
(void) caller_nm1(0, _P_[0].p);
}
}
This code assumes there is a standard, implicit conversion in C++
from void* to pointer-to-struct. But there is not, so the code
is ill-formed. (Again, EDG-based compilers reject it; egcs gives
a warning.)
Included below is a fix to OldHeaders.java and OldStubs.java that
solves this problem, by including casts where necessary.
For generated code to be most portable across systems, these fixes
should be incorporated in a subsequent release of JDK 1.2.
*** OldHeaders.java..orig Tue Dec 1 13:45:32 1998
--- OldHeaders.java Tue Apr 27 14:21:35 1999
***************
*** 293,302 ****
* method declartion (prototypes) or object declaration (C
* struct).
*/
! private static final int FOR_FIELD = 0;
! private static final int FOR_METHOD = 1;
! private String getCType(Type t, int ForM) {
int tc = t.getTypeCode();
switch (tc) {
case TC_VOID: return "void";
--- 293,304 ----
* method declartion (prototypes) or object declaration (C
* struct).
*/
! // SCO jls 1999-04-27 make this method and its constants protected rather
! // than private because we are now using them in subclass OldStubs
! protected static final int FOR_FIELD = 0;
! protected static final int FOR_METHOD = 1;
! protected String getCType(Type t, int ForM) {
int tc = t.getTypeCode();
switch (tc) {
case TC_VOID: return "void";
*** OldStubs.java..orig Tue Dec 1 13:45:32 1998
--- OldStubs.java Tue Apr 27 14:30:19 1999
***************
*** 37,43 ****
*
* @version 1.1, 07/21/98
*/
! public class OldStubs extends Gen {
protected String getIncludes() {
return "#include <StubPreamble.h>\n";
--- 37,43 ----
*
* @version 1.1, 07/21/98
*/
! public class OldStubs extends OldHeaders { // SCO jls
protected String getIncludes() {
return "#include <StubPreamble.h>\n";
***************
*** 100,105 ****
--- 100,109 ----
boolean returnIsVoid = (rtc == TC_VOID);
/* return value */
+ // SCO jls 1999-04-27 C++ does not allow multiple declarations of
+ // extern "C" functions with different parameter profiles across
+ // global and local scope, so suppress the local declaration
+ proto.append("#ifndef __cplusplus\n");
proto.append("\textern ");
proto.append(getStubCType(retType, true));
proto.append(' ');
***************
*** 132,137 ****
--- 136,146 ----
if (method.isStatic()) {
call.append("NULL");
} else {
+ // SCO jls 1999-04-27 C++ does not allow implicit conversion
+ // of void* to pointer-to-struct, so insert cast
+ call.append("(struct H");
+ call.append(mangledClazz);
+ call.append("*)");
call.append("_P_[0].p");
}
/* arguments */
***************
*** 163,168 ****
--- 172,185 ----
call.append(nthWord);
call.append(')');
} else {
+ // SCO jls 1999-04-27 C++ does not allow implicit conversion
+ // of void* to pointer-to-class, so insert casts here,
+ // making use of method in OldHeaders (that we now extend)
+ if (atc == TC_CLASS || atc == TC_ARRAY) {
+ call.append("(");
+ call.append(getCType(argTypes[j], FOR_METHOD));
+ call.append(")");
+ }
call.append("((_P_[");
call.append(nthWord);
call.append("].");
***************
*** 189,194 ****
--- 206,212 ----
/* finished arguments */
proto.append(");\n");
+ proto.append("#endif\n"); // SCO jls
if (returnIs64)
call.append(')');
call.append(");\n");
(Review ID: 57555)
======================================================================
- duplicates
-
JDK-4110521 portability : javah doesn't generate the right prototypes for stub files
-
- Closed
-