Skip to content

[modules] Compilation success depends on order of declarations in the modulemap #131814

Open
@ldionne

Description

@ldionne

Consider the following set of headers:

// myvector.h
#ifndef MYVECTOR_H
#define MYVECTOR_H

#include <bit_ref.h>

template <class _Allocator>
struct MyVector {
  typedef bool value_type;
  typedef unsigned long __storage_type;
  friend class MyBitIterator<MyVector, false>;
};

#endif
// bit_ref.h
#ifndef BIT_REF_H
#define BIT_REF_H

#include <bit_ref_fwd.h>

#endif
// bit_ref_fwd.h
#ifndef BIT_REF_FWD_H
#define BIT_REF_FWD_H

template <class _Cp, bool _IsConst, typename _Cp::__storage_type = 0>
class MyBitIterator {};

#endif

And the following modulemap:

module mystd {
  module myvector {
    header "myvector.h"
    export mystd.bit_ref
  }

  module bit_ref_fwd {
    header "bit_ref_fwd.h"
  }
  module bit_ref {
    header "bit_ref.h"
    export mystd.bit_ref_fwd
  }
}

The following fails to compile:

echo '#include <myvector.h>' | clang++ -x c++ - -std=c++17 -fmodules -fcxx-modules -Xclang -fmodules-local-submodule-visibility -fsyntax-only -I $(dirname ${0}) -fmodules-cache-path="$(mktemp -d)"

The error is:

While building module 'mystd' imported from <stdin>:1:
In file included from <module-includes>:1:
./repro-modules/myvector.h:11:16: error: missing '#include "bit_ref_fwd.h"'; 'MyBitIterator' must be declared before it is used
   11 |   friend class MyBitIterator<MyVector, false>;
      |                ^
./repro-modules/bit_ref_fwd.h:5:7: note: declaration here is not visible
    5 | class MyBitIterator {};
      |       ^
<stdin>:1:10: fatal error: could not build module 'mystd'
    1 | #include <myvector.h>
      |  ~~~~~~~~^
2 errors generated.

A few things can be observed:

  1. If we move the definition of bit_ref_fwd and bit_ref before the definition of myvector in the modulemap, the issue goes away.
  2. If we remove export mystd.bit_ref from the myvector module, the issue goes away.
  3. If we add a direct include of #include <bit_ref_fwd.h> in myvector.h, the issue goes away.

Is this behavior intended? If the order of module definitions in a modulemap matters, there should be a warning that tells us when the compiler encounters something that has not been defined yet in the modulemap. If the order is irrelevant, then there's a bug in Clang.

This was discovered while investigating #127015.

Metadata

Metadata

Assignees

No one assigned

    Labels

    clang:modulesC++20 modules and Clang Header Modules

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions