Skip to content

Conflicting declaration error with __using_if_exists__ in libc++ #85335

Open
@petrhosek

Description

@petrhosek

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    embeddedSupport for embedded developmentlibc++libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions