From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 19854 invoked by alias); 17 Oct 2005 20:04:54 -0000 Mailing-List: contact gcc-help-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-help-owner@gcc.gnu.org Received: (qmail 19844 invoked by uid 22791); 17 Oct 2005 20:04:51 -0000 Received: from sccimhc91.asp.att.net (HELO sccimhc91.asp.att.net) (63.240.76.165) by sourceware.org (qpsmtpd/0.30-dev) with ESMTP; Mon, 17 Oct 2005 20:04:51 +0000 Received: from xaivrxp (12-210-217-111.client.insightbb.com[12.210.217.111]) by sccimhc91.asp.att.net (sccimhc91) with SMTP id <20051017200449i9100iosgke>; Mon, 17 Oct 2005 20:04:49 +0000 From: "John Ratliff" To: "'MSX to GCC'" Subject: RE: C++ static integer class constants... Date: Mon, 17 Oct 2005 20:04:00 -0000 MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit In-Reply-To: <2e393d080510171107l678b0570u8f9eb3876deac2a3@mail.gmail.com> X-SW-Source: 2005-10/txt/msg00102.txt.bz2 Message-ID: <20051017200400.teR4CtxXaUm6DDFDnKw1JbwVQPaOvhPtIJwZ5fX7CLo@z> Okay. I no longer think g++ 3.3 is wrong according to the standard, but I still think it is a bug. Not because it violates the standard, but because it is inconsistent with itself. Take the following example program: #include class foo { public: static const unsigned int SRAM_SIZE = 0x2000; static const int CHECKSUM_OFFSET = 0x8; static const int CHECKSUM_OFFSET2 = 0x1FF8; foo(); unsigned char getChecksum(bool redundant = false) const; private: char sram[SRAM_SIZE]; }; const int foo::CHECKSUM_OFFSET; const int foo::CHECKSUM_OFFSET2; foo::foo() { sram[CHECKSUM_OFFSET] = 1; sram[CHECKSUM_OFFSET2] = 2; } unsigned char foo::getChecksum(bool redundant) const { int offset = (redundant ? CHECKSUM_OFFSET2 : CHECKSUM_OFFSET); return sram[offset]; } int main(int, char **) { foo f; unsigned char c1 = f.getChecksum(); unsigned char c2 = f.getChecksum(true); std::cout << "c1 = " << static_cast(c1) << '\n'; std::cout << "c2 = " << static_cast(c2) << '\n'; return 0; } This program will is a conforming program according to the standard and works just fine in g++ 3.3. But, if you replace the getChecksum method with return sram[redundant ? CHECKSUM_OFFSET2 : CHECKSUM_OFFSET]; then you can safely remove the namespace scope definition. It is not technically a conforming program then according to the standard, but g++ optimizes it here to be a compile-time constant which didn't need external linkage. The program would be wrong, but g++'s behavior with regard to optimization is inconsistent with itself. If it's going to optimize, it should optimize whether you store the constant in a temporary like offset using the ternary operator or not. You can also replace getChecksum with unsigned char foo::getChecksum(bool redundant) const { int offset = CHECKSUM_OFFSET; if (redundant) offset = CHECKSUM_OFFSET2; return sram[offset]; } and g++ will optimize it into a compile-time constant not requiring external linkage. Something about the combination of the int offset and the ternary operator assignment g++ 3.3 doesn't handle the way it handles everything else. Since the 3.3 series has been closed, I won't be filing a bug report, and maybe the gcc team wouldn't even consider this a bug, but the inconsistency is present, standards conformance notwithstanding. --John Ratliff