Bug 67064 - Register asm variable broken
Summary: Register asm variable broken
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 6.0
: P3 normal
Target Milestone: ---
Assignee: Daniel Gutson
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2015-07-30 06:41 UTC by Sebastian Huber
Modified: 2019-02-20 13:35 UTC (History)
8 users (show)

See Also:
Host:
Target: x86_64-pc-linux-gnu
Build:
Known to work: 4.9.3
Known to fail: 6.0
Last reconfirmed: 2015-07-30 00:00:00


Attachments
The diff for the patch (1.20 KB, patch)
2015-09-15 20:17 UTC, Andrés Agustín Tiraboschi
Details | Diff
The test that fails (369 bytes, text/x-csrc)
2015-09-15 20:18 UTC, Andrés Agustín Tiraboschi
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Sebastian Huber 2015-07-30 06:41:51 UTC
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.
Comment 1 Andrew Pinski 2015-07-30 06:44:16 UTC
C++11 rules about (x) have changed.  If you use -std=gnu++98 you would get the same behavior as before.
Comment 2 Sebastian Huber 2015-07-30 06:51:09 UTC
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.
Comment 3 Andrew Pinski 2015-07-30 07:10:10 UTC
(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.
Comment 4 hannes_weisbach 2015-07-30 14:31:49 UTC
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.
Comment 5 Daniel Gutson 2015-07-30 15:23:37 UTC
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.
Comment 6 Daniel Gutson 2015-07-30 16:34:36 UTC
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.
Comment 7 Ville Voutilainen 2015-07-30 17:34:30 UTC
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.
Comment 8 Jens Maurer 2015-07-30 17:54:32 UTC
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?
Comment 9 Daniel Gutson 2015-07-30 18:27:17 UTC
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.
Comment 10 Jason Merrill 2015-07-30 18:47:35 UTC
(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.
Comment 11 Ville Voutilainen 2015-07-30 18:50:15 UTC
or simply -pedantic/-pedantic-errors :)
Comment 12 Daniel Gutson 2015-07-30 18:52:19 UTC
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.
Comment 13 Ville Voutilainen 2015-07-30 19:08:39 UTC
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...
Comment 14 Jason Merrill 2015-07-30 19:18:28 UTC
(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.
Comment 15 Daniel Gutson 2015-07-31 14:53:42 UTC
(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?
Comment 16 Jens Maurer 2015-07-31 20:24:39 UTC
(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;
Comment 17 Jason Merrill 2015-08-03 15:46:54 UTC
(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.
Comment 18 Daniel Gutson 2015-08-03 18:43:40 UTC
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.
Comment 19 Manuel López-Ibáñez 2015-08-03 18:53:51 UTC
(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).
Comment 20 Daniel Gutson 2015-08-03 19:03:40 UTC
(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.
Comment 21 Jason Merrill 2015-08-17 18:15:19 UTC
(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?
Comment 22 Daniel Gutson 2015-08-17 18:28:42 UTC
(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).
Comment 23 Jason Merrill 2015-08-17 18:55:27 UTC
(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
Comment 24 Andrés Agustín Tiraboschi 2015-09-15 20:17:09 UTC
Created attachment 36337 [details]
The diff for the patch
Comment 25 Andrés Agustín Tiraboschi 2015-09-15 20:18:20 UTC
Created attachment 36338 [details]
The test that fails
Comment 26 Andrés Agustín Tiraboschi 2015-09-15 20:22:21 UTC
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.
Comment 27 Andrés Agustín Tiraboschi 2015-09-16 14:18:46 UTC
I forgot to say that the patch is for gcc 5.2
Comment 28 Manuel López-Ibáñez 2015-09-16 15:55:25 UTC
(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
Comment 29 Jason Merrill 2015-10-20 06:49:45 UTC
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
Comment 30 Daniel Gutson 2015-10-20 11:43:02 UTC
May I ask what's wrong with Andres Tiraboschi's solution approach?
Comment 31 Martin Liška 2018-11-19 13:39:42 UTC
Can the bug be marked as resolved?
Comment 32 Eric Gallager 2019-02-19 17:52:57 UTC
(In reply to Martin Liška from comment #31)
> Can the bug be marked as resolved?

WAITING on a reply.
Comment 33 Sebastian Huber 2019-02-20 07:42:30 UTC
(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.
Comment 34 Eric Gallager 2019-02-20 13:35:06 UTC
(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.