Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conflicting declaration error with __using_if_exists__ in libc++ #85335

Open
petrhosek opened this issue Mar 14, 2024 · 1 comment
Open

Conflicting declaration error with __using_if_exists__ in libc++ #85335

petrhosek opened this issue Mar 14, 2024 · 1 comment
Labels
embedded Support for embedded development libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.

Comments

@petrhosek
Copy link
Member

When trying to use libc++ with LLVM libc on a baremetal platform, we encountered an issue with the __using_if_exists__ attribute which was introduced in https://reviews.llvm.org/D90188:

In file included from /llvm_libcxx/include/algorithm:1973:                                                                                                                                                                                                                                                                                                                             
/llvm_libcxx/include/__algorithm/remove.h:28:1: error: declaration conflicts with target of using declaration already in scope                                                                                                                                                                                                                                                         
   28 | remove(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) {                                                                                                                                                                                                                                                                                                                                                   
      | ^                                                                                                                                                                                                                                                                                                                                                                                                                                 
/llvm_libcxx/include/cstdio:155:1: note: target of using declaration                                                                                                                                                                                                                                                                                                                   
  155 | using ::remove _LIBCPP_USING_IF_EXISTS;                                                                                                                                                                                                                                                                                                                                                                                           
      | ^                                                                                                                                                                                                                                                                                                                                                                                                                                 
/llvm_libcxx/include/cstdio:155:9: note: using declaration                                                                                                                                                                                                                                                                                                                             
  155 | using ::remove _LIBCPP_USING_IF_EXISTS;                                                                                                                                                                                                                                                                                                                                                                                           
      |         ^                                 

This is because baremetal version of the stdio.h libc header doesn't include remove (since there's no filesystem support).

A more minimal example of this issue is:

void foo();

namespace N {
  void bar();

  using ::foo __attribute__((__using_if_exists__));
  using ::bar __attribute__((__using_if_exists__));
}

void baz() {
  N::bar();
}

This results in the following error (you can also see it at https://godbolt.org/z/dTxqnc1oP):

<source>:7:11: error: target of using declaration conflicts with declaration already in scope
    7 |   using ::bar __attribute__((__using_if_exists__));
      |           ^
<source>:7:3: note: target of using declaration
    7 |   using ::bar __attribute__((__using_if_exists__));
      |   ^
<source>:4:8: note: conflicting declaration
    4 |   void bar();
      |        ^
1 error generated.
Compiler returned: 1

Normally, remove is declared in stdio.h, which corresponds to the foo case.

In our case, there's no remove symbol in stdio.h and as such there's no such symbol in the global namespace, but there's remove in the std:: namespace introduced by algorithm corresponding to the bar case.

Is this an issue with the __using_if_exists__ implementation or intended behavior?

This is related to issue #84879.

CC @ldionne @zygoloid @AaronBallman @epilk

@petrhosek petrhosek added libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. embedded Support for embedded development labels Mar 14, 2024
petrhosek added a commit to petrhosek/llvm-project that referenced this issue Mar 14, 2024
This is required to avoid compilation error in libc++.

See llvm#85335 for more details.
petrhosek added a commit that referenced this issue Mar 17, 2024
This is required to avoid compilation error in libc++.

See #85335 for more details.
@ldionne
Copy link
Member

ldionne commented Mar 27, 2024

Thanks for filing this issue! I've come across this several times on various platforms and I believe this is a Clang bug in the way it implements the attribute. Basically the intent is that if there is no ::bar declaration, the using ::bar __attribute__((using_if_exists)); declaration shouldn't declare anything. But the way this is implemented in Clang IIRC is that we actually do create a special kind of declaration representing "no declaration at all". And then that conflicts with the existing declaration for N::bar.

@PiJoules PiJoules assigned PiJoules and unassigned PiJoules Jun 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
embedded Support for embedded development libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

No branches or pull requests

3 participants