The following test case fails on x86_64-pc-linux-gnu, powerpc-rtems, sparc-rtems: struct s { int i; }; register struct s *reg __asm__( "1" ); int f(void) { int i; i = reg->i; i = (reg)->i; return i; } Yields: prreg.cc:5:20: warning: call-clobbered register used for global register variable register struct s *reg __asm__( "1" ); ^ prreg.cc: In function ‘int f()’: prreg.cc:12:8: error: address of explicit register variable ‘reg’ requested i = (reg)->i; ^ Please note, that the line 11 "i = reg->i;" works.
C++11 rules about (x) have changed. If you use -std=gnu++98 you would get the same behavior as before.
Indeed -std=gnu++98 gets rid of this error. So this is working as intended for C++11 and later? This is really nice in combination with defines and macros that use ( ) around its content.
(In reply to Sebastian Huber from comment #2) > Indeed -std=gnu++98 gets rid of this error. So this is working as intended > for C++11 and later? This is really nice in combination with defines and > macros that use ( ) around its content. From http://en.cppreference.com/w/cpp/language/decltype : Note that if the name of an object is parenthesised, it becomes an lvalue expression, thus decltype(arg) and decltype((arg)) are often different types. Now I don't know the exact rules for lvalue expression so I don't know if it is working the correct way or not.
Hi, I've read the bug report and dug into the standards. This is my understanding of the issue(s): Quoting N3337 and N3797 (C++11 & 14 Standard Drafts) §7.1.1/2 (dcl.stc): "The register specifier shall be applied only to names of variables declared in a block (6.3) or to function parameters (8.4)." So gcc should reject the declaration of 'reg' outright, since it is not declared inside a block and 'reg' is not a function parameter. If 'reg' would be properly declared, namely in block scope, the note (though non-normative) in §7.1.1/3 (dcl.stc) is interesting: "The hint can be ignored and in most implementations it will be ignored if the address of the variable is taken." (Which is the case by enclosing it in braces, see below.) As for the type of '(expression)' §5.1.1/6 (expr.prim.general) says: "A parenthesized expression is a primary expression whose type and value are identical to those of the enclosed expression. The presence of parentheses does not affect whether the expression is an lvalue. The parenthesized expression can be used in exactly the same contexts as those where the enclosed expression can be used, and with the same meaning, except as otherwise indicated." So clearly, parenthesis should not change the type, but both clang (Apple LLVM version 6.1.0 (clang-602.0.53)) and gcc (gcc version 5.1.0 (Homebrew gcc 5.1.0)) do. Given the declaration of 'struct s' from the example, and a definition of 'struct s * reg;' (to avoid the register thing) the type of 'reg' is 's*', but the type of '(reg)' is 's*&'. Since now there is a reference to 'reg', its address has been taken. OTOH, §7.1.6.2/4 says that, if e is an parenthesized expression with type T, decltype(e) is T&. I would expect the type of 'reg' being different from '(reg)' only in a decltype-specifier and not otherwise. Maybe someone can explain why the decltype-rule for (the type of) parenthesized expression is applicable without the decltype-specifier there. I hope the language-lawyering brought at least some clarity.
FWIW, g++ 4.8.4 and clang 3.5 do not complain in the following code: struct s { int i; }; //register struct s *reg __asm__( "1" ); s* reg; int f(void) { int i; i = reg->i; i = (reg)->i; return i; } As from the same paragraphs of the standard, I don't think that a adding parenthesis should alter the "valueness type" outside a decltype, meaning that this could be an error lately introduced. I'll ask for a Committee member help here.
Please discard my previous comment, I read too fast. I'll do some debugging and get back with some analysis. It seems that cxx_mark_addressable() is wrongly called.
gcc 4.9.2 and 5.2 also reject the snippet if c++14 or c++1z modes are used. gcc 6 accepts the snippet if a c++11 or c++98 mode is explicitly requested, but fails like the others otherwise because it defaults to c++14.
In general, "x" and "(x)" have the same meaning as per 5.1.1p6. There are a few (spelled-out) exceptions, though. One exception is inside a decltype-specifier, where decltype(e) is different from decltype((e)) as per 7.1.6.2p4. (Another exception is the fact that (f)(y) suppresses argument-dependent lookup for "f" as per 3.4.2p1. And then, if "f" is a function-like macro, it doesn't get expanded for (f)(y).) Considering the issue in this ticket, and ignoring the fact that "reg" should be a block-scope variable, "reg" is the name of a variable and therefore an lvalue. However, being an lvalue doesn't mean its address is "taken". "reg->i" is equivalent to "(reg)->i"; in both cases, the lvalue-to-rvalue conversion is applied to "reg" to determine its pointer value (see 5.3.1p1). In short, using "decltype" to inspect the type of an expression might be misleading if you don't consider the special case in 7.1.6.2p4. May I venture a guess that the gcc implementation somehow lets the decltype special case bleed into general expression analysis?
Thanks Ville and Jens for looking into this. I'll be able to fix this during next week, so if nobody is available to solve this sooner, then please assign it to me. Regarding the global register variables, it's a GNU C extension (see https://gcc.gnu.org/onlinedocs/gcc/Explicit-Reg-Vars.html), but I think it should be rejected when compiling in strict mode (e.g. -ansi or -std=c++14). I think this should be filed as a separate issue.
(In reply to Daniel Gutson from comment #9) > Regarding the global register variables, it's a GNU C extension (see > https://gcc.gnu.org/onlinedocs/gcc/Explicit-Reg-Vars.html), but I think it > should be rejected when compiling in strict mode (e.g. -ansi or -std=c++14). > I think this should be filed as a separate issue. Those flags only disable extensions that interfere with well-formed code. To reject extensions, you want the -Werror=pedantic flag.
or simply -pedantic/-pedantic-errors :)
I tried them all, and none of those flags reject a global variable declared as register. I still think a separate issue should be filed.
It is correct that currently none of the pedantic-flags diagnose the use of this extension; perhaps that should be fixed while fixing this bug...
(In reply to Ville Voutilainen from comment #13) > It is correct that currently none of the pedantic-flags diagnose the use of > this extension; perhaps that should be fixed while fixing this bug... '-Wpedantic' does not cause warning messages for use of the alternate keywords whose names begin and end with '__'. Pedantic warnings are also disabled in the expression that follows '__extension__'. However, only system header files should use these escape routes; application programs should avoid them.
(In reply to Jason Merrill from comment #14) > (In reply to Ville Voutilainen from comment #13) > > It is correct that currently none of the pedantic-flags diagnose the use of > > this extension; perhaps that should be fixed while fixing this bug... > > '-Wpedantic' does not cause warning messages for use of the > alternate keywords whose names begin and end with '__'. Pedantic > warnings are also disabled in the expression that follows > '__extension__'. However, only system header files should use > these escape routes; application programs should avoid them. Do you refer to the __asm__? If not, do you think this is a bug too or not?
(In reply to Jason Merrill from comment #14) > '-Wpedantic' does not cause warning messages for use of the > alternate keywords whose names begin and end with '__'. Pedantic > warnings are also disabled in the expression that follows > '__extension__'. However, only system header files should use > these escape routes; application programs should avoid them. Agreed, but this: struct s { int i; }; register struct s *reg asm( "si" ); (note: no double underscores) should issue a diagnostic for violating 7.1.1p2 when invoking > g++ -std=c++14 -Wall -Wextra -Wpedantic -c reg-asm.cc right? It doesn't. Total silence. Leaving off the "asm" part gives reg-asm.cc:6:20: error: register name not specified for 'reg' register struct s *reg;
(In reply to Daniel Gutson from comment #15) > (In reply to Jason Merrill from comment #14) > > '-Wpedantic' does not cause warning messages for use of the > > alternate keywords whose names begin and end with '__'. > > Do you refer to the __asm__? Yes. I don't think we should warn about __asm__ either by default or with -pedantic, though perhaps there should be an even-more-pedantic mode that complains about __keywords__ outside system headers. For the original bug, I think force_paren_expr needs to ignore DECL_HARD_REGISTER variables. (In reply to Jens Maurer from comment #16) > Agreed, but this: > > struct s { > int i; > }; > register struct s *reg asm( "si" ); > > (note: no double underscores) should issue a diagnostic for violating > 7.1.1p2 when invoking > > > g++ -std=c++14 -Wall -Wextra -Wpedantic -c reg-asm.cc > > right? It doesn't. Total silence. Yes, that should give a pedwarn.
I created https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67105 to treat that bug separately. 67064 (this bug) interferes with RTEMS in real life thus has a much higher priority, so I will address this bug first. Please assign this to me. Thanks.
(In reply to Daniel Gutson from comment #18) > Please assign this to me. Thanks. You need to login with your @gcc.gnu.org account to be able to assign bugs (and do other Bugzilla operations).
(In reply to Manuel López-Ibáñez from comment #19) > (In reply to Daniel Gutson from comment #18) > > Please assign this to me. Thanks. > > You need to login with your @gcc.gnu.org account to be able to assign bugs > (and do other Bugzilla operations). I don't have a @gcc.gnu.org account. Should I simply send the attachment? Otherwise please assign this to me for me if it is still possible. FWIW, I've been listed in the MAINTAINER list in the past while working for CodeSourcery but my name no longer is in that list.
(In reply to Daniel Gutson from comment #20) > I don't have a @gcc.gnu.org account. Should I simply send the attachment? Sure. > Otherwise please assign this to me for me if it is still possible. Done. > FWIW, I've been listed in the MAINTAINER list in the past while working for > CodeSourcery but my name no longer is in that list. Hmm, how were you in that list without a gcc.gnu.org account?
(In reply to Jason Merrill from comment #21) > (In reply to Daniel Gutson from comment #20) > > I don't have a @gcc.gnu.org account. Should I simply send the attachment? > > Sure. > > > Otherwise please assign this to me for me if it is still possible. > > Done. Thanks. > > > FWIW, I've been listed in the MAINTAINER list in the past while working for > > CodeSourcery but my name no longer is in that list. > > Hmm, how were you in that list without a gcc.gnu.org account? I don't know/remember (maybe I did have such account? Where can I check that?) It was 2008/2009 where I mostly fixed backend erratas. In any case, how can apply for one? (Sorry for the spam to the other CC'ed people, I will continue this by private mailing).
(In reply to Daniel Gutson from comment #22) > (In reply to Jason Merrill from comment #21) > > (In reply to Daniel Gutson from comment #20) > > > FWIW, I've been listed in the MAINTAINER list in the past while working for > > > CodeSourcery but my name no longer is in that list. > > > > Hmm, how were you in that list without a gcc.gnu.org account? > > I don't know/remember (maybe I did have such account? Where can I check > that?) It was 2008/2009 where I mostly fixed backend erratas. I don't see you in /etc/passwd, so you don't seem to have one currently. > In any case, how can apply for one? https://sourceware.org/cgi-bin/pdw/ps_form.cgi
Created attachment 36337 [details] The diff for the patch
Created attachment 36338 [details] The test that fails
Hi, I've read the bug report and I've made a patch in order to fix it. I've ran all the gcc tests and I have only one fail, but that fail is also present in the original gcc. Anyway I've attached the test that fails.
I forgot to say that the patch is for gcc 5.2
(In reply to Andrés Agustín Tiraboschi from comment #26) > Hi, I've read the bug report and I've made a patch in order to fix it. > I've ran all the gcc tests and I have only one fail, but that fail is also > present in the original gcc. Anyway I've attached the test that fails. Great! However, patches need to go to gcc-patches@ See: https://gcc.gnu.org/wiki/GettingStarted#Basics:_Contributing_to_GCC_in_10_easy_steps
Author: jason Date: Tue Oct 20 06:49:13 2015 New Revision: 229021 URL: https://gcc.gnu.org/viewcvs?rev=229021&root=gcc&view=rev Log: PR c++/67064 * semantics.c (force_paren_expr): Don't mess with hard register vars. Added: trunk/gcc/testsuite/g++.dg/parse/parens3.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/semantics.c
May I ask what's wrong with Andres Tiraboschi's solution approach?
Can the bug be marked as resolved?
(In reply to Martin Liška from comment #31) > Can the bug be marked as resolved? WAITING on a reply.
(In reply to Eric Gallager from comment #32) > (In reply to Martin Liška from comment #31) > > Can the bug be marked as resolved? > > WAITING on a reply. From my point of view it is fixed I guess since Daniel Gutson didn't get an answer in the last four years, he will unlikely get it in the future.
(In reply to Sebastian Huber from comment #33) > (In reply to Eric Gallager from comment #32) > > (In reply to Martin Liška from comment #31) > > > Can the bug be marked as resolved? > > > > WAITING on a reply. > > From my point of view it is fixed > > I guess since Daniel Gutson didn't get an answer in the last four years, he > will unlikely get it in the future. ok, closing then.