From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id 91299386F425; Wed, 27 May 2020 08:04:03 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 91299386F425 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1590566643; bh=ljZFxZgzBfRMhkliFbNQo1TzVgZrnh+IcHttqUXH9f0=; h=From:To:Subject:Date:In-Reply-To:References:From; b=hf8ikbla4loRSKlAVSwsPimradQw6f9R98BB9EeVzj6MYEhdv3R9bDuca+F/v7E4l gbIk3cp/iP/BE/KEa0kEqKGhIHEP9/jrOVgYW217PCl9D2T4PISR14qEncodWH3zXe /i/+jfGUr/LsC7+jxwoJAgWdxTtlixh7qbanakI8= From: "rguenth at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug c++/95349] Using std::launder(p) produces unexpected behavior where (p) produces expected behavior Date: Wed, 27 May 2020 08:04:03 +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: 10.1.0 X-Bugzilla-Keywords: alias, wrong-code X-Bugzilla-Severity: normal X-Bugzilla-Who: rguenth at gcc dot gnu.org X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Resolution: 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: cc keywords Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-BeenThere: gcc-bugs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-bugs mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 27 May 2020 08:04:03 -0000 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D95349 Richard Biener changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |rguenth at gcc dot gnu.org Keywords| |alias, wrong-code --- Comment #1 from Richard Biener --- I think std::launder merely acts as optimization barrier here and without we manage to propagate the constant. We still "miscompile" things dependent on what exactly the C++ standard says. When seeing std::uint64_t* s3(double* p) { unsigned char storage[sizeof(std::uint64_t)]; std::memcpy(storage, p, sizeof(storage)); auto t =3D new(p) std::uint64_t; std::memcpy(t, storage, sizeof(storage)); return t; } the placement new has no effect (it's just passing through a pointer) and memcpy has C semantics, transfering the active dynamic type of 'p' through 'storage' back to 'p'. std::uint64_t f3() { double d =3D 3.14159; return *s3(&d); } ... which is still 'double'. Which you then access via an lvalue of type uint64_t which invokes undefined behavior. So in GCCs implementation reading of relevant standards you need -fno-strict-aliasing and your program is not conforming. So what goes on is that GCC optimizes s3 to just { return (uint64t *)p; } w= hich makes f3 effectively do double d =3D 3.14159; return *(uint64_t *)&d; which arguably is bogus. Without the std::launder we are nice to the user and "optimize" the above to return the correct value. With std::launder we cannot do this since it breaks the pointer flow and we'll DSE the initialization of 'd' because it is not used (due to the undefinedness in case the load would alias it).=