Attribute on constructor parameter rejected

Hi,

While testing some code with attributes I found the following that looks
like a bug to me:

  $ clang-check /tmp/unused.cpp -- -std=c++11

  struct AB {
    AB([[gnu::unused]] int i) {}
    // ^~~~~~~~~~~~~~~ /tmp/unused.cpp:2:5: error: an attribute list cannot appear here

    void f([[gnu::unused]] int i) {} // no error for this line
  };

Do constructors have different parameter-declaration-list than member
functions?

They do not -- are you using ToT? I get no errors with your code on a
relatively recent build.

~Aaron

Hum, I updated yesterday so it's quite recent. I tried the following
with both my system-wide install of clang (version 3.2) and the one I
built after my update yesterday:

  [papin_g:~/GSoC/build]$ cat /tmp/gnu-unused.cpp
  struct AB {
    AB([[gnu::unused]] int i) {}
    void f([[gnu::unused]] int i) {} // no error for this line
  };
  [papin_g:~/GSoC/build]$ ./bin/clang++ -std=c++11 -fsyntax-only /tmp/gnu-unused.cpp
  /tmp/gnu-unused.cpp:2:6: error: expected member name or ';' after declaration specifiers
    AB([[gnu::unused]] int i) {}
    ~~ ^
  /tmp/gnu-unused.cpp:2:6: error: an attribute list cannot appear here
    AB([[gnu::unused]] int i) {}
       ^~~~~~~~~~~~~~~
  /tmp/gnu-unused.cpp:2:22: error: expected ')'
    AB([[gnu::unused]] int i) {}
                       ^
  /tmp/gnu-unused.cpp:2:5: note: to match this '('
    AB([[gnu::unused]] int i) {}
      ^
  3 errors generated.

I will update Clang tomorrow and see if the problem persists. Maybe it's
only me and I checked out at the wrong time or it's has been fixed since
yesterday.

Aaron Ballman <aaron@aaronballman.com> writes:

Hum, I updated yesterday so it's quite recent. I tried the following
with both my system-wide install of clang (version 3.2) and the one I
built after my update yesterday:

  [papin_g:~/GSoC/build]$ cat /tmp/gnu-unused.cpp
  struct AB {
    AB([[gnu::unused]] int i) {}
    void f([[gnu::unused]] int i) {} // no error for this line
  };
  [papin_g:~/GSoC/build]$ ./bin/clang++ -std=c++11 -fsyntax-only
/tmp/gnu-unused.cpp
  /tmp/gnu-unused.cpp:2:6: error: expected member name or ';' after
declaration specifiers
    AB([[gnu::unused]] int i) {}
    ~~ ^
  /tmp/gnu-unused.cpp:2:6: error: an attribute list cannot appear here
    AB([[gnu::unused]] int i) {}
       ^~~~~~~~~~~~~~~
  /tmp/gnu-unused.cpp:2:22: error: expected ')'
    AB([[gnu::unused]] int i) {}
                       ^
  /tmp/gnu-unused.cpp:2:5: note: to match this '('
    AB([[gnu::unused]] int i) {}
      ^
  3 errors generated.

I will update Clang tomorrow and see if the problem persists. Maybe it's
only me and I checked out at the wrong time or it's has been fixed since
yesterday.

This was a bug in our disambiguation of constructor / non-constructor
declarations. Fixed in r190111, thanks.

Great, that was fast.

Just in case someone read the code of the example, I believe the
attribute [[gnu::unused]] should be used after the parameter name
instead of before its type.

  void f(int i [[gnu::unused]]) {}

Richard Smith <richard@metafoo.co.uk> writes:

Great, that was fast.

Just in case someone read the code of the example, I believe the
attribute [[gnu::unused]] should be used after the parameter name
instead of before its type.

  void f(int i [[gnu::unused]]) {}

As it happens, both locations are valid, and mean the same thing. You could
move the attribute after the parameter name to work around the problem,
however.

Okay, so why did this work for me on ToT on Windows prior to your
patch? Do we have different constructor disambiguation for
-fms-compatibility?

~Aaron

Okay, so why did this work for me on ToT on Windows prior to your
patch? Do we have different constructor disambiguation for
-fms-compatibility?

-fms-extensions enables recognition of the single-square-bracket
(IDL-style) attribute syntax, which it seems we just silently ignore. So
when we were testing whether this looks like a constructor in MS mode, we
skipped over the attribute. (But when actually parsing it, we'd still parse
it as a C++11 attribute.)

~Aaron

Thank you for the explanation, that makes perfect sense to me now. :slight_smile:

~Aaron