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

Using import after #include may cause redeclaration errors #61329

Closed
rnikander opened this issue Mar 10, 2023 · 9 comments
Closed

Using import after #include may cause redeclaration errors #61329

rnikander opened this issue Mar 10, 2023 · 9 comments
Labels
clang:modules C++20 modules and Clang Header Modules duplicate Resolved as duplicate

Comments

@rnikander
Copy link

rnikander commented Mar 10, 2023

I'm new to C++20 modules, so I don't know if this is supposed to work or not. It seems like a C++ file that uses modules and traditional #includes can get errors.

Here is a minimal example, using a recent HEAD (Clang 17).

build.sh (obviously needs to be adjusted a bit for your environment):

CLANG_DIR=/Users/rob/Dev/llvm-project/build
CXX=${CLANG_DIR}/bin/clang++

# Need on my macOS system
ISYS="-isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.1.sdk"

$CXX $ISYS -std=c++2b foo.ccm --precompile -o foo.pcm 
$CXX $ISYS -std=c++2b main.cc -fprebuilt-module-path=. foo.pcm -o final.out

foo.ccm:

module;
#include <iostream>
export module foo;
export void foo_func() {
    std::cout << "in foo_func\n";
}

main.cc:

import foo;
#include <iostream>
int main(int argc, char *argv[])
{
    std::cout << "Test\n";
    return 0;
}

Leads to these errors:

In file included from main.cc:3:
In file included from /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/iostream:43:
In file included from /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/ios:221:
In file included from /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/__locale:18:
In file included from /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/mutex:191:
In file included from /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/__memory/shared_ptr.h:30:
In file included from /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/__memory/uninitialized_algorithms.h:13:
In file included from /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/__algorithm/copy.h:12:
In file included from /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/__algorithm/copy_move_common.h:14:
In file included from /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/__algorithm/unwrap_range.h:19:
In file included from /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/__utility/pair.h:13:
/Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/__compare/synth_three_way.h:28:45: error: redeclaration of '__synth_three_way' with a different type: 'const std::__1::(lambda at /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/__compare/synth_three_way.h:29:3)' vs 'const std::__1::(lambda at /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/__compare/synth_three_way.h:29:3)'
_LIBCPP_HIDE_FROM_ABI inline constexpr auto __synth_three_way =
                                            ^
/Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/__compare/synth_three_way.h:28:45: note: previous definition is here
_LIBCPP_HIDE_FROM_ABI inline constexpr auto __synth_three_way =
                                            ^
In file included from main.cc:3:
In file included from /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/iostream:43:
In file included from /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/ios:221:
In file included from /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/__locale:18:
In file included from /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/mutex:191:
In file included from /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/__memory/shared_ptr.h:30:
In file included from /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/__memory/uninitialized_algorithms.h:13:
In file included from /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/__algorithm/copy.h:12:
In file included from /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/__algorithm/copy_move_common.h:14:
In file included from /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/__algorithm/unwrap_range.h:19:
/Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/__utility/pair.h:440:9: error: use of undeclared identifier '__synth_three_way_result'
        __synth_three_way_result<_T1>,
        ^
/Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/__utility/pair.h:441:39: error: expected unqualified-id
        __synth_three_way_result<_T2> >
                                      ^
In file included from main.cc:3:
In file included from /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/iostream:43:
In file included from /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/ios:221:
In file included from /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/__locale:18:
In file included from /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/mutex:192:
In file included from /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/__mutex_base:20:
In file included from /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/system_error:154:
In file included from /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/string:560:
In file included from /Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/__memory_resource/polymorphic_allocator.h:20:
/Users/rob/Dev/llvm-project/build/bin/../include/c++/v1/tuple:1571:30: error: use of undeclared identifier '__synth_three_way_result'
common_comparison_category_t<__synth_three_way_result<_Tp, _Up>...>
                             ^
@EugeneZelenko EugeneZelenko added clang:modules C++20 modules and Clang Header Modules and removed new issue labels Mar 10, 2023
@llvmbot
Copy link
Member

llvmbot commented Mar 10, 2023

@llvm/issue-subscribers-clang-modules

@ChuanqiXu9
Copy link
Member

ChuanqiXu9 commented Mar 11, 2023

Could you try the following one?

#include <iostream>
import foo;

int main(int argc, char *argv[])
{
    std::cout << "Test\n";
    return 0;
}

In short, your codes are correct but the compiler fails to handle it due to some implementation limitations/defects.

In detail, if we include first and import then, the compiler will perform the checking and merging in the deserializer. But if we import first and include second, the compiler will perform the checking and merging in the semantic analyzer. So there is a divergence in the code paths in the implementation. I heard MSVC has the same problem. It is not your fault.

@rnikander
Copy link
Author

Yes, switching the order to #include, then import causes the error to go away. I'm trying to think now if that will always be possible. It would be a problem if an include'd header had an import, but I guess that shouldn't happen.

@ChuanqiXu9
Copy link
Member

It would be a problem if an include'd header had an import, but I guess that shouldn't happen.

A header shouldn't contain an import. This should be a bad manner. (Although I heard some people don't agree on this.)

@iains
Copy link
Contributor

iains commented Mar 14, 2023

It would be a problem if an include'd header had an import, but I guess that shouldn't happen.

A header shouldn't contain an import. This should be a bad manner. (Although I heard some people don't agree on this.)

There are specific rules for module TUs (currently clang does not diagnose these cases) :

  • in the global module imports must be in a header .
  • in the module purview, textually included files must not have import lines

(these two things we should fix soon, since we now track the module phase in the pre-processor).

For a non-modular TU AFAIU, it is permitted to include textually a header that has an import - perhaps that is bad style, but I have no strong opinion except to say that maybe it is better to have consistent style between the module purview and an importer.

@mordante
Copy link
Member

FYI I ran into the same issue while testing libc++'s tests with the WIP version of the std module. Moving the import after #includes fixed the issue for me too. If this is hard to fix I will add it to the known limitations for using the std module.

@ChuanqiXu9
Copy link
Member

ChuanqiXu9 commented Mar 16, 2023

FYI I ran into the same issue while testing libc++'s tests with the WIP version of the std module. Moving the import after #includes fixed the issue for me too. If this is hard to fix I will add it to the known limitations for using the std module.

It is even not accurate to say "hard to fix it"... since it consists a lot of problems, e.g., we don't merge concepts well in Sema, we don't merge requires well in Sema ... This is a long list so it is hard to say when we can fix it. BTW, the deserializer has similar problems too. Just the deseriailizer does a better merging job than sema now.

If this is hard to fix I will add it to the known limitations for using the std module.

I think it'd better to mention this in the document for modules. Let me try to take it.

@mordante
Copy link
Member

Thanks for the info @ChuanqiXu9.

@ChuanqiXu9 ChuanqiXu9 changed the title Using import and #include causes redeclaration errors Using import after #include may cause redeclaration errors Mar 16, 2023
@ChuanqiXu9
Copy link
Member

Let's track the issue in #61465 instead.

@EugeneZelenko EugeneZelenko added the duplicate Resolved as duplicate label Mar 17, 2023
@EugeneZelenko EugeneZelenko closed this as not planned Won't fix, can't repro, duplicate, stale Mar 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:modules C++20 modules and Clang Header Modules duplicate Resolved as duplicate
Projects
None yet
Development

No branches or pull requests

6 participants