public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c/63645] New: Incorrect code generation
@ 2014-10-25 20:15 terra at gnome dot org
  2014-10-25 20:18 ` [Bug c/63645] " terra at gnome dot org
                   ` (21 more replies)
  0 siblings, 22 replies; 23+ messages in thread
From: terra at gnome dot org @ 2014-10-25 20:15 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63645

            Bug ID: 63645
           Summary: Incorrect code generation
           Product: gcc
           Version: 4.8.2
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: terra at gnome dot org

Created attachment 33809
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=33809&action=edit
Test program

I am observing valgrind errors from the to-be-attached reduced
test case.  The oper test on line 36 should fail and short circuit
the rest of the condition, but that is not what seems to happen.

Note: this smells like an aliasing issue, but I think what union
access is correct.

welinder@lenovo ~ $ gcc -Wall -g -O2 vvv.c 
welinder@lenovo ~ $ valgrind ./a.out 
==4994== Memcheck, a memory error detector
==4994== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==4994== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==4994== Command: ./a.out
==4994== 
==4994== Invalid read of size 8
==4994==    at 0x4005E8: test (vvv.c:36)
==4994==    by 0x4004D8: main (vvv.c:47)
==4994==  Address 0x51fd040 is 0 bytes inside a block of size 1 alloc'd
==4994==    at 0x4C2AB80: malloc (in
/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4994==    by 0x4005DA: test (vvv.c:54)
==4994==    by 0x4004D8: main (vvv.c:47)



welinder@lenovo ~ $ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.2-19ubuntu1'
--with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs
--enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr
--program-suffix=-4.8 --enable-shared --enable-linker-build-id
--libexecdir=/usr/lib --without-included-gettext --enable-threads=posix
--with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls
--with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug
--enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap
--enable-plugin --with-system-zlib --disable-browser-plugin
--enable-java-awt=gtk --enable-gtk-cairo
--with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home
--with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64
--with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64
--with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar
--enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686
--with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic
--enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu
--target=x86_64-linux-gnu
Thread model: posix
gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1)


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [Bug c/63645] Incorrect code generation
  2014-10-25 20:15 [Bug c/63645] New: Incorrect code generation terra at gnome dot org
@ 2014-10-25 20:18 ` terra at gnome dot org
  2014-10-25 20:22 ` pinskia at gcc dot gnu.org
                   ` (20 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: terra at gnome dot org @ 2014-10-25 20:18 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63645

--- Comment #1 from M Welinder <terra at gnome dot org> ---
Created attachment 33810
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=33810&action=edit
Preprocessed version of the program


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [Bug c/63645] Incorrect code generation
  2014-10-25 20:15 [Bug c/63645] New: Incorrect code generation terra at gnome dot org
  2014-10-25 20:18 ` [Bug c/63645] " terra at gnome dot org
  2014-10-25 20:22 ` pinskia at gcc dot gnu.org
@ 2014-10-25 20:22 ` terra at gnome dot org
  2014-10-25 21:19 ` trippels at gcc dot gnu.org
                   ` (18 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: terra at gnome dot org @ 2014-10-25 20:22 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63645

--- Comment #3 from M Welinder <terra at gnome dot org> ---
Why do you think so?

I think it is covered by this:

6.5  Expressions
[...]
       [#7] An object shall have its stored value accessed only  by
       an lvalue expression that has one of the following types:63)

         -- a  type  compatible  with  the  effective  type  of the
            object,
[...]
         -- an aggregate or union type that  includes  one  of  the
            aforementioned  types  among  its  members  (including,
            recursively, a member of a  subaggregate  or  contained
            union), or
[...]


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [Bug c/63645] Incorrect code generation
  2014-10-25 20:15 [Bug c/63645] New: Incorrect code generation terra at gnome dot org
  2014-10-25 20:18 ` [Bug c/63645] " terra at gnome dot org
@ 2014-10-25 20:22 ` pinskia at gcc dot gnu.org
  2014-10-25 20:22 ` terra at gnome dot org
                   ` (19 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: pinskia at gcc dot gnu.org @ 2014-10-25 20:22 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63645

--- Comment #2 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
I think this code violates C/C++ aliasing rules.


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [Bug c/63645] Incorrect code generation
  2014-10-25 20:15 [Bug c/63645] New: Incorrect code generation terra at gnome dot org
                   ` (2 preceding siblings ...)
  2014-10-25 20:22 ` terra at gnome dot org
@ 2014-10-25 21:19 ` trippels at gcc dot gnu.org
  2014-10-25 21:30 ` terra at gnome dot org
                   ` (17 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: trippels at gcc dot gnu.org @ 2014-10-25 21:19 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63645

Markus Trippelsdorf <trippels at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
                 CC|                            |trippels at gcc dot gnu.org
         Resolution|---                         |INVALID

--- Comment #4 from Markus Trippelsdorf <trippels at gcc dot gnu.org> ---
Your union simply takes more space than your GnmExprBinary struct
and you cast the later to the former.

vvv.c:36:13: runtime error: member access within address 0x0000011ec010 with
insufficient space for an object of type 'const GnmExpr' (aka 'const union
_GnmExpr')


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [Bug c/63645] Incorrect code generation
  2014-10-25 20:15 [Bug c/63645] New: Incorrect code generation terra at gnome dot org
                   ` (3 preceding siblings ...)
  2014-10-25 21:19 ` trippels at gcc dot gnu.org
@ 2014-10-25 21:30 ` terra at gnome dot org
  2014-10-25 21:37 ` pinskia at gcc dot gnu.org
                   ` (16 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: terra at gnome dot org @ 2014-10-25 21:30 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63645

M Welinder <terra at gnome dot org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |UNCONFIRMED
         Resolution|INVALID                     |---

--- Comment #5 from M Welinder <terra at gnome dot org> ---
You guys are trigger happy.

> Your union simply takes more space than your GnmExprBinary struct

Of course it does!  The union requires space that is large enough
for its largest member, so having a smaller member is going to be
the case in 99% of unions and the standard has no objections.
If you think otherwise, a reference to the standard would be nice.

To show that the size difference is irrelevant, simply change
GnmExprBinary to

typedef struct {
    guint8 oper;
    int argc;
    GnmFunc *func;
} GnmExprBinary;

whereupon GnmExprBinary, GnmExprFunction, and GnmExpr all take up the
same amount of space.

We still get this error from valgrind.

==6201== Conditional jump or move depends on uninitialised value(s)
==6201==    at 0x4005F8: test (vvv.c:38)
==6201==    by 0x4004D8: main (vvv.c:49)


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [Bug c/63645] Incorrect code generation
  2014-10-25 20:15 [Bug c/63645] New: Incorrect code generation terra at gnome dot org
                   ` (4 preceding siblings ...)
  2014-10-25 21:30 ` terra at gnome dot org
@ 2014-10-25 21:37 ` pinskia at gcc dot gnu.org
  2014-10-25 21:52 ` trippels at gcc dot gnu.org
                   ` (15 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: pinskia at gcc dot gnu.org @ 2014-10-25 21:37 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63645

--- Comment #6 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
This:
expr->oper == GNM_EXPR_OP_FUNCALL &&
      expr->func.argc == 1 

is being combined into:
  D.2319_2 = BIT_FIELD_REF <*expr_1, 64, 0>;
  D.2320_3 = D.2319_2 & 18446744069414584575;
  D.2320_3 == 4294967297

Which is correct and I think is valid.

Valgrind does not realize the part of expr will not match part of the
and/equals so it complains.  Basically a bug in valgrind for not tracking
uninitialized bits correctly.

The solution to asan message was provided in comment #4.


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [Bug c/63645] Incorrect code generation
  2014-10-25 20:15 [Bug c/63645] New: Incorrect code generation terra at gnome dot org
                   ` (5 preceding siblings ...)
  2014-10-25 21:37 ` pinskia at gcc dot gnu.org
@ 2014-10-25 21:52 ` trippels at gcc dot gnu.org
  2014-10-26  1:35 ` mikpelinux at gmail dot com
                   ` (14 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: trippels at gcc dot gnu.org @ 2014-10-25 21:52 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63645

Markus Trippelsdorf <trippels at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
         Resolution|---                         |INVALID

--- Comment #7 from Markus Trippelsdorf <trippels at gcc dot gnu.org> ---
(In reply to M Welinder from comment #5)
> You guys are trigger happy.
> 
> > Your union simply takes more space than your GnmExprBinary struct
> 
> Of course it does!  The union requires space that is large enough
> for its largest member, so having a smaller member is going to be
> the case in 99% of unions and the standard has no objections.
> If you think otherwise, a reference to the standard would be nice.
> 
> To show that the size difference is irrelevant, simply change
> GnmExprBinary to
> 
> typedef struct {
> 	guint8 oper;
> 	int argc;
> 	GnmFunc *func;
> } GnmExprBinary;
> 
> whereupon GnmExprBinary, GnmExprFunction, and GnmExpr all take up the
> same amount of space.

Or adjust your malloc, which is simply too small in your orginal testcase.

> We still get this error from valgrind.
> 
> ==6201== Conditional jump or move depends on uninitialised value(s)
> ==6201==    at 0x4005F8: test (vvv.c:38)
> ==6201==    by 0x4004D8: main (vvv.c:49)

That is a different issue. You access  expr->func.argc and expr->func.func  
in your if expression. And of course they are uninitialised.
>From gcc-bugs-return-464985-listarch-gcc-bugs=gcc.gnu.org@gcc.gnu.org Sat Oct 25 21:52:32 2014
Return-Path: <gcc-bugs-return-464985-listarch-gcc-bugs=gcc.gnu.org@gcc.gnu.org>
Delivered-To: listarch-gcc-bugs@gcc.gnu.org
Received: (qmail 13517 invoked by alias); 25 Oct 2014 21:52:31 -0000
Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm
Precedence: bulk
List-Id: <gcc-bugs.gcc.gnu.org>
List-Archive: <http://gcc.gnu.org/ml/gcc-bugs/>
List-Post: <mailto:gcc-bugs@gcc.gnu.org>
List-Help: <mailto:gcc-bugs-help@gcc.gnu.org>
Sender: gcc-bugs-owner@gcc.gnu.org
Delivered-To: mailing list gcc-bugs@gcc.gnu.org
Received: (qmail 13474 invoked by uid 48); 25 Oct 2014 21:52:27 -0000
From: "terra at gnome dot org" <gcc-bugzilla@gcc.gnu.org>
To: gcc-bugs@gcc.gnu.org
Subject: [Bug c/63645] Incorrect code generation
Date: Sat, 25 Oct 2014 23:12:00 -0000
X-Bugzilla-Reason: CC
X-Bugzilla-Type: changed
X-Bugzilla-Watch-Reason: None
X-Bugzilla-Product: gcc
X-Bugzilla-Component: c
X-Bugzilla-Version: 4.8.2
X-Bugzilla-Keywords:
X-Bugzilla-Severity: normal
X-Bugzilla-Who: terra at gnome dot org
X-Bugzilla-Status: RESOLVED
X-Bugzilla-Priority: P3
X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org
X-Bugzilla-Target-Milestone: ---
X-Bugzilla-Flags:
X-Bugzilla-Changed-Fields:
Message-ID: <bug-63645-4-RsC9DR5Amr@http.gcc.gnu.org/bugzilla/>
In-Reply-To: <bug-63645-4@http.gcc.gnu.org/bugzilla/>
References: <bug-63645-4@http.gcc.gnu.org/bugzilla/>
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: 7bit
X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/
Auto-Submitted: auto-generated
MIME-Version: 1.0
X-SW-Source: 2014-10/txt/msg02006.txt.bz2
Content-length: 1185

https://gcc.gnu.org/bugzilla/show_bug.cgi?idc645

--- Comment #8 from M Welinder <terra at gnome dot org> ---
> That is a different issue. You access  expr->func.argc and expr->func.func
> in your if expression. And of course they are uninitialised.

No, I don't.  You see, C has this feature for the && operator that if the
first condition is false, then the second is not evaluated.  It is in
Section 6.5.13 of the standard:

6.5.13  Logical AND operator
[...]
       [#4] Unlike the bitwise binary & operator, the  &&  operator
       guarantees  left-to-right  evaluation;  there  is a sequence
       point after the evaluation of the  first  operand.   If  the
       first operand compares equal to 0, the second operand is not
       evaluated.

The first condition is false because it compares GNM_EXPR_OP_LT to
GNM_EXPR_OP_FUNCALL.  These have the values 0 and 1 respectively,
which are comfortably within the range of allowed values for type
unsigned char.  0 and 1 are not equal, so the == operator (see
Section 6.5.9) evaluates to 0.

Still thinking about Andrew's suggestion that Valgrind might be at
fault.  It wouldn't be the first bitfield related problem there.


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [Bug c/63645] Incorrect code generation
  2014-10-25 20:15 [Bug c/63645] New: Incorrect code generation terra at gnome dot org
                   ` (6 preceding siblings ...)
  2014-10-25 21:52 ` trippels at gcc dot gnu.org
@ 2014-10-26  1:35 ` mikpelinux at gmail dot com
  2014-10-27  3:48 ` terra at gnome dot org
                   ` (13 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: mikpelinux at gmail dot com @ 2014-10-26  1:35 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63645

--- Comment #9 from Mikael Pettersson <mikpelinux at gmail dot com> ---
Can you tweak the testcase into something that throws an actual runtime error
(by faulting or returning 1 from main or doing exit(1)) instead of relying on
valgrind (which I don't trust) to spot a/the problem?


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [Bug c/63645] Incorrect code generation
  2014-10-25 20:15 [Bug c/63645] New: Incorrect code generation terra at gnome dot org
                   ` (7 preceding siblings ...)
  2014-10-26  1:35 ` mikpelinux at gmail dot com
@ 2014-10-27  3:48 ` terra at gnome dot org
  2014-10-27  7:52 ` trippels at gcc dot gnu.org
                   ` (12 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: terra at gnome dot org @ 2014-10-27  3:48 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63645

M Welinder <terra at gnome dot org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
  Attachment #33809|0                           |1
        is obsolete|                            |

--- Comment #11 from M Welinder <terra at gnome dot org> ---
Created attachment 33814
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=33814&action=edit
Updated test program

I agree that C99 says that a struct around the oper member is required.
That is Section 6.5.2.3 #5.  It is inconvenient and probably not what
the committee intended, but it is all we have.  So be it.  For the test
program I simply grab oper out of the binary member.

I haven't yet figured out how to remove valgrind from the setup.  Here's
what it says:

==20506== Invalid read of size 8
==20506==    at 0x4005E8: test (vvv.c:35)
==20506==    by 0x4004D8: main (vvv.c:46)
==20506==  Address 0x51fd040 is 0 bytes inside a block of size 1 alloc'd
==20506==    at 0x4C2AB80: malloc (in
/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==20506==    by 0x4005DA: test (vvv.c:53)
==20506==    by 0x4004D8: main (vvv.c:46)

Note: GnmExprBinary is back to a single member.  C99's Section 6.5 #7
says that such an object can be accessed through a union that contain
the type:

       [#7] An object shall have its stored value accessed only  by
       an lvalue expression that has one of the following types:63)
[...]
         -- an aggregate or union type that  includes  one  of  the
            aforementioned  types  among  its  members  (including,
            recursively, a member of a  subaggregate  or  contained
            union), or

Whatever created the error message of comment 4 therefore seems to be
wrong.  Unless something else disallows this.

- * -

I looked that the generated assembler code and here is the relevant
part that shows that both the oper and func.argc fields are being
tested in one go.  The object doesn't have the func.argc field.

.LBE4:
    .loc 1 35 0
    movabsq    $-4294967041, %rdx
.LBB7:
.LBB6:
    .loc 1 54 0
    movb    $0, (%rax)
.LBE6:
.LBE7:
    .loc 1 35 0
    andq    (%rax), %rdx
    movabsq    $4294967297, %rcx
    cmpq    %rcx, %rdx
    je    .L5


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [Bug c/63645] Incorrect code generation
  2014-10-25 20:15 [Bug c/63645] New: Incorrect code generation terra at gnome dot org
                   ` (8 preceding siblings ...)
  2014-10-27  3:48 ` terra at gnome dot org
@ 2014-10-27  7:52 ` trippels at gcc dot gnu.org
  2014-10-27  9:30 ` jakub at gcc dot gnu.org
                   ` (11 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: trippels at gcc dot gnu.org @ 2014-10-27  7:52 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63645

--- Comment #12 from Markus Trippelsdorf <trippels at gcc dot gnu.org> ---
1) Your malloc is too small. It has to be sizeof (biggest member).
So you're invoking undefined behavior.

2) In the if statement, where you probe the different members, you
also invoke undefined behavior.

So two bugs in one testcase.


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [Bug c/63645] Incorrect code generation
  2014-10-25 20:15 [Bug c/63645] New: Incorrect code generation terra at gnome dot org
                   ` (9 preceding siblings ...)
  2014-10-27  7:52 ` trippels at gcc dot gnu.org
@ 2014-10-27  9:30 ` jakub at gcc dot gnu.org
  2014-10-27 11:41 ` terra at gnome dot org
                   ` (10 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: jakub at gcc dot gnu.org @ 2014-10-27  9:30 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63645

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jakub at gcc dot gnu.org,
                   |                            |jsm28 at gcc dot gnu.org

--- Comment #13 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Pedantically speaking, the testcase is invalid I think, in C writing one union
member invalidates all the other union members.  But as a GNU extension, we
allow more relaxed handling of unions, type punning through unions etc., and
regarding the sizes of the objects, I believe we do allow having size of just
one of the union members for the whole object, what else are union tree_node in
tree-core.h or struct rtx_def's union u in rtl.h in GCC sources?  So, just by
quickly saying what the testcase does is invalid even under extensions I
believe most of the GCC codebase would be similarly invalid, don't we use
heavily
if (TREE_CODE (t) == VAR_DECL && DECL_HARD_REGISTER (t)) and similar?
TREE_CODE being t->base.code and DECL_HARD_REGISTER
t->decl_with_vis.hard_register ?  Here for many trees, the allocated size of
them is smaller than offsetof of the decl_with_vis.hard_register field, the
reason why we never hit this problem is just that sizeof (tree_base) is 8, and
thus the fold_truth_andor_1 optimization doesn't consider
if (a->fld1 == N && a->fld2 == M) to be adjacent tnough to optimize.

I believe this is the fold_truth_andor_1 optimization at work, the question is
how we'd want to change that optimization.  I'd say giving up immediately if
you access different union members would be too pessimistic, so perhaps just
bail out if the size of the first union member is smaller than the offset of
the second access + access size?


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [Bug c/63645] Incorrect code generation
  2014-10-25 20:15 [Bug c/63645] New: Incorrect code generation terra at gnome dot org
                   ` (10 preceding siblings ...)
  2014-10-27  9:30 ` jakub at gcc dot gnu.org
@ 2014-10-27 11:41 ` terra at gnome dot org
  2014-10-27 14:59 ` trippels at gcc dot gnu.org
                   ` (9 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: terra at gnome dot org @ 2014-10-27 11:41 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63645

--- Comment #14 from M Welinder <terra at gnome dot org> ---
> 1) Your malloc is too small. It has to be sizeof (biggest member).
> So you're invoking undefined behavior.

Can you produce a specific authoritative reference for that statement?
I.e., a reference to the standard not "because I say so".  Note, that
the standard's Section 6.5 #7 says that I *can* accees my GnmExprBinary
object through the union.


> 2) In the if statement, where you probe the different members, you
> also invoke undefined behavior.

Absolutely not!  I went other that in painful detail in comment 8.
Bottom line: only one member is accessed.


> Pedantically speaking, the testcase is invalid I think, in C writing
> one union member invalidates all the other union members.

While true as written, there is a read-side exception to that which
allows reading the active union member's fields through certain
inactive union members' fields:

[#5] With one exception, if the value of a member of a union
       object  is used when the most recent store to the object was
       to    a    different     member,     the     behavior     is
       implementation-defined.70)  One special guarantee is made in
       order to simplify the use of unions:  If  a  union  contains
       several structures that share a common initial sequence (see
       below), and if the union object currently  contains  one  of
       these  structures,  it  is  permitted  to inspect the common
       initial part of any of them anywhere that a  declaration  of
       the  completed type of the union is visible.  Two structures
       share a common initial  sequence  if  corresponding  members
       have compatible types (and, for bit-fields, the same widths)
       for a sequence of one or more initial members.


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [Bug c/63645] Incorrect code generation
  2014-10-25 20:15 [Bug c/63645] New: Incorrect code generation terra at gnome dot org
                   ` (11 preceding siblings ...)
  2014-10-27 11:41 ` terra at gnome dot org
@ 2014-10-27 14:59 ` trippels at gcc dot gnu.org
  2014-10-27 15:31 ` terra at gnome dot org
                   ` (8 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: trippels at gcc dot gnu.org @ 2014-10-27 14:59 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63645

--- Comment #16 from Markus Trippelsdorf <trippels at gcc dot gnu.org> ---
(In reply to M Welinder from comment #14)
> > 2) In the if statement, where you probe the different members, you
> > also invoke undefined behavior.
> 
> Absolutely not!  I went other that in painful detail in comment 8.
> Bottom line: only one member is accessed.

Let's take this example:

markus@x4 tmp % cat union.c
#include <stdlib.h>

typedef union _GnmExpr GnmExpr;
typedef char GnmFunc;
typedef unsigned char guint8;

typedef enum
{
  GNM_EXPR_OP_LT,
  GNM_EXPR_OP_FUNCALL
} GnmExprOp;

typedef struct
{
  guint8 oper;
  int argc;
  GnmFunc *func;
} GnmExprFunction;

typedef struct
{
  guint8 oper;
} GnmExprBinary;

union _GnmExpr
{
  GnmExprFunction func;
  GnmExprBinary binary;
};

int
main (void)
{
  GnmExprBinary res;
  res.oper = GNM_EXPR_OP_LT;
  GnmExpr const *expr = (GnmExpr *)&res;

  if (expr->binary.oper == GNM_EXPR_OP_FUNCALL
      && expr->func.argc == 1
      && expr->func.func == getenv ("NOT"))
    abort ();
  return 0;
}

Here the compiler even warns:

markus@x4 tmp % gcc -Wall -Wextra -g -O2 union.c
union.c: In function ‘main’:
union.c:40:7: warning: ‘res.func.func’ may be used uninitialized in this
function [-Wmaybe-uninitialized]
       && expr->func.func == getenv ("NOT"))
       ^
And that is because the compiler assumes that no undefined behavior
happens and optimizes accordingly.

The gcc documentation even mentions this case explicitly (under
-fstrict-aliasing):

»Similarly, access by taking the address, casting the resulting pointer and
dereferencing the result has undefined behavior, even if the cast uses a union
type.«
>From gcc-bugs-return-465058-listarch-gcc-bugs=gcc.gnu.org@gcc.gnu.org Mon Oct 27 14:59:20 2014
Return-Path: <gcc-bugs-return-465058-listarch-gcc-bugs=gcc.gnu.org@gcc.gnu.org>
Delivered-To: listarch-gcc-bugs@gcc.gnu.org
Received: (qmail 3539 invoked by alias); 27 Oct 2014 14:59:20 -0000
Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm
Precedence: bulk
List-Id: <gcc-bugs.gcc.gnu.org>
List-Archive: <http://gcc.gnu.org/ml/gcc-bugs/>
List-Post: <mailto:gcc-bugs@gcc.gnu.org>
List-Help: <mailto:gcc-bugs-help@gcc.gnu.org>
Sender: gcc-bugs-owner@gcc.gnu.org
Delivered-To: mailing list gcc-bugs@gcc.gnu.org
Received: (qmail 3215 invoked by uid 48); 27 Oct 2014 14:59:15 -0000
From: "redi at gcc dot gnu.org" <gcc-bugzilla@gcc.gnu.org>
To: gcc-bugs@gcc.gnu.org
Subject: [Bug c++/23055] overload resolution does not find templated function (zero -> pointer)
Date: Mon, 27 Oct 2014 15:19:00 -0000
X-Bugzilla-Reason: CC
X-Bugzilla-Type: changed
X-Bugzilla-Watch-Reason: None
X-Bugzilla-Product: gcc
X-Bugzilla-Component: c++
X-Bugzilla-Version: 4.0.0
X-Bugzilla-Keywords: rejects-valid
X-Bugzilla-Severity: normal
X-Bugzilla-Who: redi at gcc dot gnu.org
X-Bugzilla-Status: RESOLVED
X-Bugzilla-Priority: P2
X-Bugzilla-Assigned-To: jason at gcc dot gnu.org
X-Bugzilla-Target-Milestone: 4.9.0
X-Bugzilla-Flags:
X-Bugzilla-Changed-Fields: cc
Message-ID: <bug-23055-4-cE8V5P5tyt@http.gcc.gnu.org/bugzilla/>
In-Reply-To: <bug-23055-4@http.gcc.gnu.org/bugzilla/>
References: <bug-23055-4@http.gcc.gnu.org/bugzilla/>
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: 7bit
X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/
Auto-Submitted: auto-generated
MIME-Version: 1.0
X-SW-Source: 2014-10/txt/msg02079.txt.bz2
Content-length: 499

https://gcc.gnu.org/bugzilla/show_bug.cgi?id#055

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |shunichi_wakabayashi@yahoo.
                   |                            |co.jp

--- Comment #13 from Jonathan Wakely <redi at gcc dot gnu.org> ---
*** Bug 63648 has been marked as a duplicate of this bug. ***


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [Bug c/63645] Incorrect code generation
  2014-10-25 20:15 [Bug c/63645] New: Incorrect code generation terra at gnome dot org
                   ` (12 preceding siblings ...)
  2014-10-27 14:59 ` trippels at gcc dot gnu.org
@ 2014-10-27 15:31 ` terra at gnome dot org
  2014-10-27 15:40 ` terra at gnome dot org
                   ` (7 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: terra at gnome dot org @ 2014-10-27 15:31 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63645

--- Comment #17 from M Welinder <terra at gnome dot org> ---
You keep saying "undefined behaviour", but you keep avoiding
substantiating that claim.

Where, in the C99 standard, is the clause that makes things undefined?


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [Bug c/63645] Incorrect code generation
  2014-10-25 20:15 [Bug c/63645] New: Incorrect code generation terra at gnome dot org
                   ` (13 preceding siblings ...)
  2014-10-27 15:31 ` terra at gnome dot org
@ 2014-10-27 15:40 ` terra at gnome dot org
  2014-10-27 15:43 ` joseph at codesourcery dot com
                   ` (6 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: terra at gnome dot org @ 2014-10-27 15:40 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63645

--- Comment #18 from M Welinder <terra at gnome dot org> ---
The example at strict-aliasing in the gcc man page covers a different
situation: you don't get to access a double via an int.

I get it.

But the standard says that in certain circumstances you really do get
to access one structure via the fields of another.  I quoted that part
for you.

So if undefined behaviour is going on, it's something else.  It is
possible, I guess, but hand waving doesn't establish it.


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [Bug c/63645] Incorrect code generation
  2014-10-25 20:15 [Bug c/63645] New: Incorrect code generation terra at gnome dot org
                   ` (14 preceding siblings ...)
  2014-10-27 15:40 ` terra at gnome dot org
@ 2014-10-27 15:43 ` joseph at codesourcery dot com
  2014-10-27 16:25 ` jakub at gcc dot gnu.org
                   ` (5 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: joseph at codesourcery dot com @ 2014-10-27 15:43 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63645

--- Comment #19 from joseph at codesourcery dot com <joseph at codesourcery dot com> ---
Given

  GnmExprBinary res;
  GnmExpr const *expr = (GnmExpr *)&res;

the C standard does not define where the result of the conversion points; 
all that's defined is that if converted directly back to GnmExprBinary * 
(not via some sequence of intermediate types) it compares equal to the 
original pointer, if the original pointer was sufficiently aligned for 
GnmExpr * (and it is likely the latter type has stricter alignment 
requirements than GnmExprBinary *).

The effect is that the pointer resulting from the conversion cannot be 
dereferenced, only compared and converted back.

It is these limits on what pointer conversions are defined, together with 
the direct rules on what types of lvalues may access an object, that 
restrict aliasing in C.


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [Bug c/63645] Incorrect code generation
  2014-10-25 20:15 [Bug c/63645] New: Incorrect code generation terra at gnome dot org
                   ` (15 preceding siblings ...)
  2014-10-27 15:43 ` joseph at codesourcery dot com
@ 2014-10-27 16:25 ` jakub at gcc dot gnu.org
  2014-10-27 16:50 ` schwab@linux-m68k.org
                   ` (4 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: jakub at gcc dot gnu.org @ 2014-10-27 16:25 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63645

--- Comment #20 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
(In reply to joseph@codesourcery.com from comment #19)
> Given
> 
>   GnmExprBinary res;
>   GnmExpr const *expr = (GnmExpr *)&res;

Let's consider if in #c11 you change:
  GnmExprBinary *res = malloc (sizeof (GnmExprBinary));
  res->oper = op;
  return (GnmExpr*)res;
to:
  GnmExpr *res = malloc (sizeof (GnmExprBinary));
  res->binary.oper = op;
  return res;
is that also invalid?  I think that pretty much models what GCC does in its
sources, not allocating always the whole size of the union, but sometimes
allocating fewer bytes and sometimes more, based on which field of the union is
going to be used.  Malloc returned pointer should be sufficiently aligned in
this case, just will be smaller than the size of the whole union.


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [Bug c/63645] Incorrect code generation
  2014-10-25 20:15 [Bug c/63645] New: Incorrect code generation terra at gnome dot org
                   ` (16 preceding siblings ...)
  2014-10-27 16:25 ` jakub at gcc dot gnu.org
@ 2014-10-27 16:50 ` schwab@linux-m68k.org
  2014-10-27 17:30 ` terra at gnome dot org
                   ` (3 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: schwab@linux-m68k.org @ 2014-10-27 16:50 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63645

--- Comment #21 from Andreas Schwab <schwab@linux-m68k.org> ---
This is only valid if the object is of the union type (union _GnmExpr)
(§6.5.2.3#6: "if the union object currently contains one of these structures").
>From gcc-bugs-return-465072-listarch-gcc-bugs=gcc.gnu.org@gcc.gnu.org Mon Oct 27 16:50:43 2014
Return-Path: <gcc-bugs-return-465072-listarch-gcc-bugs=gcc.gnu.org@gcc.gnu.org>
Delivered-To: listarch-gcc-bugs@gcc.gnu.org
Received: (qmail 8381 invoked by alias); 27 Oct 2014 16:50:42 -0000
Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm
Precedence: bulk
List-Id: <gcc-bugs.gcc.gnu.org>
List-Archive: <http://gcc.gnu.org/ml/gcc-bugs/>
List-Post: <mailto:gcc-bugs@gcc.gnu.org>
List-Help: <mailto:gcc-bugs-help@gcc.gnu.org>
Sender: gcc-bugs-owner@gcc.gnu.org
Delivered-To: mailing list gcc-bugs@gcc.gnu.org
Received: (qmail 8279 invoked by uid 48); 27 Oct 2014 16:50:39 -0000
From: "pinskia at gcc dot gnu.org" <gcc-bugzilla@gcc.gnu.org>
To: gcc-bugs@gcc.gnu.org
Subject: [Bug rtl-optimization/63659] [4.8/4.9/5 Regression] wrong code at -O2 and -O3 on x86_64-linux-gnu
Date: Mon, 27 Oct 2014 17:10:00 -0000
X-Bugzilla-Reason: CC
X-Bugzilla-Type: changed
X-Bugzilla-Watch-Reason: None
X-Bugzilla-Product: gcc
X-Bugzilla-Component: rtl-optimization
X-Bugzilla-Version: 5.0
X-Bugzilla-Keywords: wrong-code
X-Bugzilla-Severity: normal
X-Bugzilla-Who: pinskia at gcc dot gnu.org
X-Bugzilla-Status: NEW
X-Bugzilla-Priority: P3
X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org
X-Bugzilla-Target-Milestone: 4.8.4
X-Bugzilla-Flags:
X-Bugzilla-Changed-Fields: keywords cf_gcctarget component
Message-ID: <bug-63659-4-3TO06EIMPv@http.gcc.gnu.org/bugzilla/>
In-Reply-To: <bug-63659-4@http.gcc.gnu.org/bugzilla/>
References: <bug-63659-4@http.gcc.gnu.org/bugzilla/>
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: 7bit
X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/
Auto-Submitted: auto-generated
MIME-Version: 1.0
X-SW-Source: 2014-10/txt/msg02093.txt.bz2
Content-length: 660

https://gcc.gnu.org/bugzilla/show_bug.cgi?idc659

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |wrong-code
             Target|                            |x86_64-unknown-linux-gnu
          Component|tree-optimization           |rtl-optimization

--- Comment #2 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
(In reply to Jakub Jelinek from comment #1)
> Started with r186278.

Then either a target specific issue or an RTL opt issue.  Moving to rtl-opt for
now.


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [Bug c/63645] Incorrect code generation
  2014-10-25 20:15 [Bug c/63645] New: Incorrect code generation terra at gnome dot org
                   ` (17 preceding siblings ...)
  2014-10-27 16:50 ` schwab@linux-m68k.org
@ 2014-10-27 17:30 ` terra at gnome dot org
  2014-10-27 18:29 ` joseph at codesourcery dot com
                   ` (2 subsequent siblings)
  21 siblings, 0 replies; 23+ messages in thread
From: terra at gnome dot org @ 2014-10-27 17:30 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63645

--- Comment #22 from M Welinder <terra at gnome dot org> ---
>Given
>
>  GnmExprBinary res;
>  GnmExpr const *expr = (GnmExpr *)&res;
>
>the C standard does not define where the result of the conversion points; 

How do you read C99's Section 6.5 #7, then?

Doesn't that tell me I can access my GnmExprBinary via an lvalue that
has a union type that includes a GnmExprBinary member.  GnmExpr is
such a union type.

Specifically, I read the section as allowing use of the lvalue *expr
to access (*expr).binary


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [Bug c/63645] Incorrect code generation
  2014-10-25 20:15 [Bug c/63645] New: Incorrect code generation terra at gnome dot org
                   ` (18 preceding siblings ...)
  2014-10-27 17:30 ` terra at gnome dot org
@ 2014-10-27 18:29 ` joseph at codesourcery dot com
  2014-10-27 18:46 ` joseph at codesourcery dot com
  2014-10-28 10:14 ` mikpelinux at gmail dot com
  21 siblings, 0 replies; 23+ messages in thread
From: joseph at codesourcery dot com @ 2014-10-27 18:29 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63645

--- Comment #23 from joseph at codesourcery dot com <joseph at codesourcery dot com> ---
On Mon, 27 Oct 2014, jakub at gcc dot gnu.org wrote:

> Let's consider if in #c11 you change:
>   GnmExprBinary *res = malloc (sizeof (GnmExprBinary));
>   res->oper = op;
>   return (GnmExpr*)res;
> to:
>   GnmExpr *res = malloc (sizeof (GnmExprBinary));
>   res->binary.oper = op;
>   return res;
> is that also invalid?  I think that pretty much models what GCC does in its

That's one of the poorly defined cases where it's not clear which object 
is relevant.


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [Bug c/63645] Incorrect code generation
  2014-10-25 20:15 [Bug c/63645] New: Incorrect code generation terra at gnome dot org
                   ` (19 preceding siblings ...)
  2014-10-27 18:29 ` joseph at codesourcery dot com
@ 2014-10-27 18:46 ` joseph at codesourcery dot com
  2014-10-28 10:14 ` mikpelinux at gmail dot com
  21 siblings, 0 replies; 23+ messages in thread
From: joseph at codesourcery dot com @ 2014-10-27 18:46 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63645

--- Comment #24 from joseph at codesourcery dot com <joseph at codesourcery dot com> ---
On Mon, 27 Oct 2014, terra at gnome dot org wrote:

> https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63645
> 
> --- Comment #22 from M Welinder <terra at gnome dot org> ---
> >Given
> >
> >  GnmExprBinary res;
> >  GnmExpr const *expr = (GnmExpr *)&res;
> >
> >the C standard does not define where the result of the conversion points; 
> 
> How do you read C99's Section 6.5 #7, then?

It only applies if you have validly obtained lvalues of different types 
referring to overlapping objects.

Sometimes pointer conversions will obtain those; sometimes they won't.  
The C model of pointer conversions is *not* "pointers point to a 
particular byte address, and conversions just change the type but not the 
byte address".  It's much more restricted that that.  Unless there are 
particular statements in the C standard that say what the resulting 
pointer points to (e.g. the statements about conversion from a pointer to 
a structure to a pointer to its first member, and back, *when you have a 
structure object in the first place*, or about conversions to pointers to 
character type), the result is not specified.

But if you have a union between float and int, take a pointer to the first 
member, and cast that pointer to type float *, there is no guarantee that 
the result is a pointer to the float member, absent a specific statement 
that defines the result of such a conversion (whereas if you cast 
indirectly, first to a pointer to the union then to float *, you would get 
a pointer to the float member).  And even when you have pointers to the 
two members of the union, you are still restricted in using them together 
(see DR#236) - that is the point at which 6.5#7 comes in.  But a simple 
cast from int * to float * doesn't even get that far - the value of the 
result is unspecified beyond what you get on converting it back to int *.


^ permalink raw reply	[flat|nested] 23+ messages in thread

* [Bug c/63645] Incorrect code generation
  2014-10-25 20:15 [Bug c/63645] New: Incorrect code generation terra at gnome dot org
                   ` (20 preceding siblings ...)
  2014-10-27 18:46 ` joseph at codesourcery dot com
@ 2014-10-28 10:14 ` mikpelinux at gmail dot com
  21 siblings, 0 replies; 23+ messages in thread
From: mikpelinux at gmail dot com @ 2014-10-28 10:14 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63645

--- Comment #25 from Mikael Pettersson <mikpelinux at gmail dot com> ---
So, is there a way to under-allocate a union (just allocate enough for the
member you want) and access it via the union pointer that is valid C?


^ permalink raw reply	[flat|nested] 23+ messages in thread

end of thread, other threads:[~2014-10-28 10:11 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-10-25 20:15 [Bug c/63645] New: Incorrect code generation terra at gnome dot org
2014-10-25 20:18 ` [Bug c/63645] " terra at gnome dot org
2014-10-25 20:22 ` pinskia at gcc dot gnu.org
2014-10-25 20:22 ` terra at gnome dot org
2014-10-25 21:19 ` trippels at gcc dot gnu.org
2014-10-25 21:30 ` terra at gnome dot org
2014-10-25 21:37 ` pinskia at gcc dot gnu.org
2014-10-25 21:52 ` trippels at gcc dot gnu.org
2014-10-26  1:35 ` mikpelinux at gmail dot com
2014-10-27  3:48 ` terra at gnome dot org
2014-10-27  7:52 ` trippels at gcc dot gnu.org
2014-10-27  9:30 ` jakub at gcc dot gnu.org
2014-10-27 11:41 ` terra at gnome dot org
2014-10-27 14:59 ` trippels at gcc dot gnu.org
2014-10-27 15:31 ` terra at gnome dot org
2014-10-27 15:40 ` terra at gnome dot org
2014-10-27 15:43 ` joseph at codesourcery dot com
2014-10-27 16:25 ` jakub at gcc dot gnu.org
2014-10-27 16:50 ` schwab@linux-m68k.org
2014-10-27 17:30 ` terra at gnome dot org
2014-10-27 18:29 ` joseph at codesourcery dot com
2014-10-27 18:46 ` joseph at codesourcery dot com
2014-10-28 10:14 ` mikpelinux at gmail dot com

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).