Skip to content

Potential modules compilation problem #56362

Open
@3405691582

Description

@3405691582

Problem

The default libc++ modulemap does not seem to compile and see definitions in stdint.h when inttypes.h refers to a copy or symlink of stdint.h in a subdirectory (say, sys).

I can make a guess and say that it is possible that inttypes.h is incorrect to refer to sys/stdint.h because that (might?) be "outside" the module if one is not defined, but I don't know enough about modules to confidently say whether this is contra to how modules work, but in trying to reason about this, I can't seem to construct an argument to say why this affirmatively shouldn't work either. Therefore, before reporting this as a platform bug, I thought I would raise this problem here first.

Note that this is only a problem when -fmodules is enabled.

Workarounds

Also see the minimal test case, which includes some workarounds. Additional workarounds include

Adjusting the modulemap

diff --git a/c++/v1/module.modulemap b/c++/v1/module.modulemap
index d26733f..03d246d 100644
--- a/c++/v1/module.modulemap
+++ b/c++/v1/module.modulemap
@@ -4,6 +4,7 @@ module std [system] {
   module depr [extern_c] {
     module inttypes_h {
       header "inttypes.h"
+      header "stdint.h"
       export stdint_h
       export *
     }

(note the modules for cinttypes may also need to be adjusted)

Changing inttypes.h

diff --git a/inttypes.h b/inttypes.h
index 6d01e5d..93fff6c 100644
--- a/inttypes.h
+++ b/inttypes.h
@@ -1,6 +1,6 @@
 #ifndef _INTTYPES_H_
 #define _INTTYPES_H_
 
-#include <sys/stdint.h>
+#include <stdint.h>
 
 #endif

Minimal test case

Minimal test case: make a directory, then git init and git apply the below patch. Then, running _run.sh will give errors like

<stdin>:2:1: error: missing '#include "/tmp/y/stdint.h"'; 'uint8_t' must be declared before it is used
uint8_t x;
^
/tmp/y/stdint.h:13:33: note: declaration here is not visible
typedef __uint8_t               uint8_t;
                                ^
1 error generated.

Patch:

diff --git a/_run.sh b/_run.sh
new file mode 100644
index 0000000..e06b4f4
--- /dev/null
+++ b/_run.sh
@@ -0,0 +1,8 @@
+echo "Unexpected failures"
+printf '#include <stdint.h>\nuint8_t x;' | clang++ -xc++ -fmodules -c - -o /dev/null -isystem ./c++/v1/ -isystem . -nostdinc
+printf '#include <cstdint>\nuint8_t x;' | clang++ -xc++ -fmodules -c - -o /dev/null -isystem ./c++/v1/ -isystem . -nostdinc
+printf '#include <cstdint>\nuint8_t x;' | clang++ -xc++ -fmodules -c - -o /dev/null -isystem ./c++/v1/ -isystem . -nostdinc -I sys
+echo "Workarounds"
+printf '#include <stdint.h>\nuint8_t x;' | clang++ -xc++ -fmodules -c - -o /dev/null -isystem ./c++/v1/ -isystem . -nostdinc -I sys
+printf '#include <inttypes.h>\nuint8_t x;' | clang++ -xc++ -fmodules -c - -o /dev/null -isystem ./c++/v1/ -isystem . -nostdinc
+printf '#include <cinttypes>\nuint8_t x;' | clang++ -xc++ -fmodules -c - -o /dev/null -isystem ./c++/v1/ -isystem . -nostdinc
diff --git a/c++/v1/cinttypes b/c++/v1/cinttypes
new file mode 100644
index 0000000..f6641d5
--- /dev/null
+++ b/c++/v1/cinttypes
@@ -0,0 +1,2 @@
+#include <cstdint>
+#include <inttypes.h>
diff --git a/c++/v1/cstdint b/c++/v1/cstdint
new file mode 100644
index 0000000..9a6118b
--- /dev/null
+++ b/c++/v1/cstdint
@@ -0,0 +1 @@
+#include <stdint.h>
diff --git a/c++/v1/inttypes.h b/c++/v1/inttypes.h
new file mode 100644
index 0000000..25805e7
--- /dev/null
+++ b/c++/v1/inttypes.h
@@ -0,0 +1,2 @@
+#include_next <inttypes.h>
+#include <stdint.h>
diff --git a/c++/v1/module.modulemap b/c++/v1/module.modulemap
new file mode 100644
index 0000000..d26733f
--- /dev/null
+++ b/c++/v1/module.modulemap
@@ -0,0 +1,29 @@
+module std [system] {
+  export std_config
+
+  module depr [extern_c] {
+    module inttypes_h {
+      header "inttypes.h"
+      export stdint_h
+      export *
+    }
+    module stdint_h {
+      header "stdint.h"
+      export *
+      export Darwin.C.stdint
+    }
+  }
+
+  module compat {
+    module cinttypes {
+      header "cinttypes"
+      export cstdint
+      export *
+    }
+    module cstdint {
+      header "cstdint"
+      export depr.stdint_h
+      export *
+    }
+  }
+}
diff --git a/c++/v1/stdint.h b/c++/v1/stdint.h
new file mode 100644
index 0000000..286f763
--- /dev/null
+++ b/c++/v1/stdint.h
@@ -0,0 +1 @@
+#include_next <stdint.h>
diff --git a/inttypes.h b/inttypes.h
new file mode 100644
index 0000000..6d01e5d
--- /dev/null
+++ b/inttypes.h
@@ -0,0 +1,6 @@
+#ifndef _INTTYPES_H_
+#define _INTTYPES_H_
+
+#include <sys/stdint.h>
+
+#endif
diff --git a/machine/_types.h b/machine/_types.h
new file mode 100644
index 0000000..8705f73
--- /dev/null
+++ b/machine/_types.h
@@ -0,0 +1,7 @@
+#ifndef _MACHINE__TYPES_H_
+#define _MACHINE__TYPES_H_
+
+typedef signed char             __int8_t;
+typedef unsigned char           __uint8_t;
+
+#endif
diff --git a/stdint.h b/stdint.h
new file mode 120000
index 0000000..a7a8003
--- /dev/null
+++ b/stdint.h
@@ -0,0 +1 @@
+sys/stdint.h
\ No newline at end of file
diff --git a/sys/stdint.h b/sys/stdint.h
new file mode 100644
index 0000000..0b62164
--- /dev/null
+++ b/sys/stdint.h
@@ -0,0 +1,16 @@
+#ifndef _SYS_STDINT_H_
+#define _SYS_STDINT_H_
+
+#include <machine/_types.h>
+
+#ifndef _INT8_T_DEFINED_
+#define _INT8_T_DEFINED_
+typedef __int8_t                int8_t;
+#endif
+
+#ifndef _UINT8_T_DEFINED_
+#define _UINT8_T_DEFINED_
+typedef __uint8_t               uint8_t;
+#endif
+
+#endif

Metadata

Metadata

Assignees

No one assigned

    Labels

    clang:frontendLanguage frontend issues, e.g. anything involving "Sema"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