Skip to content

Commit 085eae6

Browse files
committed
[C++20] [Modules] Allow to merge enums with the same underlying interger types
Close #76638. See the issue for the context of the change.
1 parent 9096bcc commit 085eae6

File tree

2 files changed

+118
-2
lines changed

2 files changed

+118
-2
lines changed

clang/lib/AST/ODRHash.cpp

+49-2
Original file line numberDiff line numberDiff line change
@@ -741,8 +741,55 @@ void ODRHash::AddEnumDecl(const EnumDecl *Enum) {
741741
if (Enum->isScoped())
742742
AddBoolean(Enum->isScopedUsingClassTag());
743743

744-
if (Enum->getIntegerTypeSourceInfo())
745-
AddQualType(Enum->getIntegerType());
744+
if (Enum->getIntegerTypeSourceInfo()) {
745+
// FIMXE: This allows two enums with different spellings to have the same
746+
// hash.
747+
//
748+
// // mod1.cppm
749+
// module;
750+
// extern "C" {
751+
// typedef unsigned __int64 size_t;
752+
// }
753+
// namespace std {
754+
// using :: size_t;
755+
// }
756+
//
757+
// extern "C++" {
758+
// namespace std {
759+
// enum class align_val_t : std::size_t {};
760+
// }
761+
// }
762+
//
763+
// export module mod1;
764+
// export using std::align_val_t;
765+
//
766+
// // mod2.cppm
767+
// module;
768+
// extern "C" {
769+
// typedef unsigned __int64 size_t;
770+
// }
771+
//
772+
// extern "C++" {
773+
// namespace std {
774+
// enum class align_val_t : size_t {};
775+
// }
776+
// }
777+
//
778+
// export module mod2;
779+
// import mod1;
780+
// export using std::align_val_t;
781+
//
782+
// The above example should be disallowed since it violates
783+
// [basic.def.odr]p14:
784+
//
785+
// Each such definition shall consist of the same sequence of tokens
786+
//
787+
// The definitions of `std::align_val_t` in two module units have different
788+
// spellings but we failed to give an error here.
789+
//
790+
// See https://github.com/llvm/llvm-project/issues/76638 for details.
791+
AddQualType(Enum->getIntegerType().getCanonicalType());
792+
}
746793

747794
// Filter out sub-Decls which will not be processed in order to get an
748795
// accurate count of Decl's.

clang/test/Modules/pr76638.cppm

+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// RUN: rm -rf %t
2+
// RUN: mkdir -p %t
3+
// RUN: split-file %s %t
4+
//
5+
// RUN: %clang_cc1 -std=c++20 %t/mod1.cppm -emit-module-interface -o %t/mod1.pcm
6+
// RUN: %clang_cc1 -std=c++20 %t/mod2.cppm -fmodule-file=mod1=%t/mod1.pcm \
7+
// RUN: -fsyntax-only -verify
8+
//
9+
// RUN: %clang_cc1 -std=c++20 %t/mod3.cppm -emit-module-interface -o %t/mod3.pcm
10+
// RUN: %clang_cc1 -std=c++20 %t/mod4.cppm -fmodule-file=mod3=%t/mod3.pcm \
11+
// RUN: -fsyntax-only -verify
12+
13+
//--- size_t.h
14+
15+
extern "C" {
16+
typedef unsigned int size_t;
17+
}
18+
19+
//--- csize_t
20+
namespace std {
21+
using :: size_t;
22+
}
23+
24+
//--- align.h
25+
namespace std {
26+
enum class align_val_t : size_t {};
27+
}
28+
29+
//--- mod1.cppm
30+
module;
31+
#include "size_t.h"
32+
#include "align.h"
33+
export module mod1;
34+
export using std::align_val_t;
35+
36+
//--- mod2.cppm
37+
// expected-no-diagnostics
38+
module;
39+
#include "size_t.h"
40+
#include "csize_t"
41+
#include "align.h"
42+
export module mod2;
43+
import mod1;
44+
export using std::align_val_t;
45+
46+
//--- signed_size_t.h
47+
// Test that we can still find the case if the underlying type is different
48+
extern "C" {
49+
typedef signed int size_t;
50+
}
51+
52+
//--- mod3.cppm
53+
module;
54+
#include "size_t.h"
55+
#include "align.h"
56+
export module mod3;
57+
export using std::align_val_t;
58+
59+
//--- mod4.cppm
60+
module;
61+
#include "signed_size_t.h"
62+
#include "csize_t"
63+
#include "align.h"
64+
export module mod4;
65+
import mod3;
66+
export using std::align_val_t;
67+
68+
// [email protected]:* {{'std::align_val_t' has different definitions in different modules; defined here first difference is enum with specified type 'size_t' (aka 'int')}}
69+
// [email protected]:* {{but in 'mod3.<global>' found enum with specified type 'size_t' (aka 'unsigned int')}}

0 commit comments

Comments
 (0)