This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Additional features for -fms-extensions
- From: "Schönbeck, Andreas" <Andreas dot Schoenbeck2 at fabalabs dot org>
- To: <gcc-patches at gcc dot gnu dot org>
- Date: Sat, 30 Oct 2004 18:39:30 +0200
- Subject: [PATCH] Additional features for -fms-extensions
Hi!
I am submitting six patches. They address some problems a company had while porting their sourcecode to GNU/Linux. Until now they compiled their code with the microsoft c++ compiler. When doing this with GCC there were some errors the microsoft compiler didn't complain about. So they tried the -fms-extensions but this did not address all of the problems so they asked me to add some features to the -fms-extensions.
I know that the behavior of the GCC is as it is expected. But I think it is a benefit for the GCC if it CAN do these things as the microsoft compiler can. So I'd be delighted if these patches I submit could be taken into the sources.
I tested those patches on a i686 on a SuSE System and they where tested by the above mentioned company (Fabasoft) with their sources and everything worked fine.
The prblems addressed are: (each with a short description and an example)
+ An ellipsis does not take variables of non-POD type as arguments:
====================================
/*
Results:
GCC:
test2.cxx: In function 'int main()':
test2.cxx:xx: warning: cannot pass objects of non-POD type 'Class Point'
through '...'; call will abort at runtime
*/
void test(...)
{
}
class Point
{
public:
Point(int x, int y) { this->x = x; this->y = y; }
int getX() { return x; }
int getY() { return y; }
private:
int x;
int y;
};
int main()
{
Point p(1,1);
test(p);
return 0;
}
====================================
+ When passing a lvalue to a function which wants to take a reference there is an error thrown:
====================================
/*
Results:
GCC:
test2.cxx: In function 'int main()':
test2.cxx:xx: error: no matching function for call to 'Class2::add(Class1)'
test2.cxx:xx: error: candidates are: static void Class2::add(Class1&)
*/
class A
{
public:
A() {}
};
class B
{
public:
static void test(A& a) {}
};
int main()
{
B::test(A());
return 0;
}
====================================
+ When declaring a not-anonymous union within an anonymous union an error is thrown
====================================
/*
Results:
GCC:
test3.cxx:xx: error: Union 'TestStruct::<anonymous union>::TestUnion'
invalid; an anonymous union can only have non-static data members
*/
struct TestStruct
{
union
{
union TestUnion
{
int test;
};
};
};
int main()
{
return 0;
}
====================================
+ When declaring something extern and later static an error is thrown
====================================
/*
Results:
GCC:
test4.cxx:xx: error: 'void test()' was declared 'extern' and later 'static'
*/GCC (3.3):
class A
{
friend void test();
};
static void test()
{
}
int main()
{
test();
return 0;
}
====================================
+ There can't be a forward declaration of an enum
====================================
/*
Results:
GCC:
test5.cxx:xx: error: use of enum 'A' without previous declaration
*/
enum A;
int main()
{
return 0;
}
====================================
+ The address of a member of a packed struct can't be retrieved
====================================
/*
Results:
GCC (3.4.2):
test8.cxx:xx: error: cannot bind packed field `a.A::field2' to `int&'
*/
#include <unistd.h>
struct A
{
char field1;
int field2;
} __attribute__((packed));
void test(int& value)
{
}
int main()
{
A a;
test(a.field2);
return 0;
}
====================================
Index: ./gcc/gcc/cp/call.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.517
diff -c -3 -p -r1.517 call.c
*** ./gcc/gcc/cp/call.c 28 Oct 2004 05:17:08 -0000 1.517
--- ./gcc/gcc/cp/call.c 30 Oct 2004 15:52:23 -0000
*************** convert_arg_to_ellipsis (tree arg)
*** 4394,4400 ****
arg = require_complete_type (arg);
if (arg != error_mark_node
! && !pod_type_p (TREE_TYPE (arg)))
{
/* Undefined behavior [expr.call] 5.2.2/7. We used to just warn
here and do a bitwise copy, but now cp_expr_size will abort if we
--- 4396,4403 ----
arg = require_complete_type (arg);
if (arg != error_mark_node
! && !pod_type_p (TREE_TYPE (arg))
! && !flag_ms_extensions)
{
/* Undefined behavior [expr.call] 5.2.2/7. We used to just warn
here and do a bitwise copy, but now cp_expr_size will abort if we
*************** build_x_va_arg (tree expr, tree type)
*** 4426,4432 ****
if (expr == error_mark_node || !type)
return error_mark_node;
! if (! pod_type_p (type))
{
/* Undefined behavior [expr.call] 5.2.2/7. */
warning ("cannot receive objects of non-POD type %q#T' through %<...%>; "
--- 4429,4435 ----
if (expr == error_mark_node || !type)
return error_mark_node;
! if (! pod_type_p (type) && ! flag_ms_extensions)
{
/* Undefined behavior [expr.call] 5.2.2/7. */
warning ("cannot receive objects of non-POD type %q#T' through %<...%>; "
Index: ./gcc/gcc/cp/call.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.517
diff -c -3 -p -r1.517 call.c
*** ./gcc/gcc/cp/call.c 28 Oct 2004 05:17:08 -0000 1.517
--- ./gcc/gcc/cp/call.c 30 Oct 2004 15:52:23 -0000
*************** convert_like_real (conversion *convs, tr
*** 4295,4301 ****
{
tree type = convs->u.next->type;
! if (!CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (ref_type)))
{
/* If the reference is volatile or non-const, we
cannot create a temporary. */
--- 4296,4303 ----
{
tree type = convs->u.next->type;
! if (!CP_TYPE_CONST_NON_VOLATILE_P (TREE_TYPE (ref_type))
! && !flag_ms_extensions)
{
/* If the reference is volatile or non-const, we
cannot create a temporary. */
Index: ./gcc/gcc/cp/call.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.517
diff -c -3 -p -r1.517 call.c
*** ./gcc/gcc/cp/call.c 28 Oct 2004 05:17:08 -0000 1.517
--- ./gcc/gcc/cp/call.c 30 Oct 2004 15:52:23 -0000
*************** reference_binding (tree rto, tree rfrom,
*** 1164,1171 ****
/* [dcl.init.ref]
! Otherwise, the reference shall be to a non-volatile const type. */
! if (!CP_TYPE_CONST_NON_VOLATILE_P (to))
return NULL;
/* [dcl.init.ref]
--- 1164,1172 ----
/* [dcl.init.ref]
! Otherwise, the reference shall be to a non-volatile const type,
! except when using fms-extensions */
! if (!CP_TYPE_CONST_NON_VOLATILE_P (to) && !flag_ms_extensions)
return NULL;
/* [dcl.init.ref]
Index: ./gcc/gcc/cp/class.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/cp/class.c,v
retrieving revision 1.686
diff -c -3 -p -r1.686 class.c
*** ./gcc/gcc/cp/class.c 21 Oct 2004 21:23:38 -0000 1.686
--- ./gcc/gcc/cp/class.c 30 Oct 2004 16:02:36 -0000
*************** finish_struct_anon (tree t)
*** 2413,2419 ****
we also allow unnamed types used for defining fields. */
if (DECL_ARTIFICIAL (elt)
&& (!DECL_IMPLICIT_TYPEDEF_P (elt)
! || TYPE_ANONYMOUS_P (TREE_TYPE (elt))))
continue;
if (TREE_CODE (elt) != FIELD_DECL)
--- 2413,2420 ----
we also allow unnamed types used for defining fields. */
if (DECL_ARTIFICIAL (elt)
&& (!DECL_IMPLICIT_TYPEDEF_P (elt)
! || TYPE_ANONYMOUS_P (TREE_TYPE (elt)))
! || flag_ms_extensions)
continue;
if (TREE_CODE (elt) != FIELD_DECL)
Index: ./gcc/gcc/cp/decl.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1322
diff -c -3 -p -r1.1322 decl.c
*** ./gcc/gcc/cp/decl.c 29 Oct 2004 07:16:44 -0000 1.1322
--- ./gcc/gcc/cp/decl.c 30 Oct 2004 16:00:57 -0000
*************** xref_tag (enum tag_types tag_code, tree
*** 9235,9241 ****
and record it as the "definition".
When a real declaration of this type is found,
the forward-reference will be altered into a real type. */
! if (code == ENUMERAL_TYPE)
{
error ("use of enum %q#D without previous declaration", name);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
--- 9239,9245 ----
and record it as the "definition".
When a real declaration of this type is found,
the forward-reference will be altered into a real type. */
! if (code == ENUMERAL_TYPE && !flag_ms_extensions)
{
error ("use of enum %q#D without previous declaration", name);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
Index: ./gcc/gcc/cp/decl.c
===================================================================
RCS file: /cvsroot/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1322
diff -c -3 -p -r1.1322 decl.c
*** ./gcc/gcc/cp/decl.c 29 Oct 2004 07:16:44 -0000 1.1322
--- ./gcc/gcc/cp/decl.c 30 Oct 2004 16:00:57 -0000
*************** decls_match (tree newdecl, tree olddecl)
*** 1098,1104 ****
}
/* If NEWDECL is `static' and an `extern' was seen previously,
! warn about it. OLDDECL is the previous declaration.
Note that this does not apply to the C++ case of declaring
a variable `extern const' and then later `const'.
--- 1098,1105 ----
}
/* If NEWDECL is `static' and an `extern' was seen previously,
! warn about it except when using the fms-extensions. OLDDECL
! is the previous declaration.
Note that this does not apply to the C++ case of declaring
a variable `extern const' and then later `const'.
*************** warn_extern_redeclared_static (tree newd
*** 1132,1137 ****
--- 1133,1141 ----
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_ARTIFICIAL (olddecl))
return;
+
+ if (flag_ms_extensions)
+ return;
name = DECL_ASSEMBLER_NAME (newdecl);
pedwarn ("%qD was declared %<extern%> and later %<static%>", newdecl);