Skip to content

Commit 12ae1ea

Browse files
authored
[C++20][Modules] Relax ODR check in unnamed modules (#111160)
Summary: Option `-fskip-odr-check-in-gmf` is set by default and I think it is what most of C++ developers want. But in header units, Clang ODR checking is too strict, making them hard to use, as seen in the example in the diff. This diff relaxes ODR checks for unnamed modules to match GMF ODR checking. Test Plan: check-clang
1 parent 6213aa5 commit 12ae1ea

File tree

4 files changed

+48
-1
lines changed

4 files changed

+48
-1
lines changed

clang/include/clang/AST/DeclBase.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,9 @@ class alignas(8) Decl {
687687
/// Whether this declaration comes from a named module.
688688
bool isInNamedModule() const;
689689

690+
/// Whether this declaration comes from a header unit.
691+
bool isFromHeaderUnit() const;
692+
690693
/// Return true if this declaration has an attribute which acts as
691694
/// definition of the entity, such as 'alias' or 'ifunc'.
692695
bool hasDefiningAttr() const;

clang/include/clang/Serialization/ASTReader.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2527,7 +2527,7 @@ class BitsUnpacker {
25272527

25282528
inline bool shouldSkipCheckingODR(const Decl *D) {
25292529
return D->getASTContext().getLangOpts().SkipODRCheckInGMF &&
2530-
D->isFromGlobalModule();
2530+
(D->isFromGlobalModule() || D->isFromHeaderUnit());
25312531
}
25322532

25332533
} // namespace clang

clang/lib/AST/DeclBase.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1168,6 +1168,10 @@ bool Decl::isInNamedModule() const {
11681168
return getOwningModule() && getOwningModule()->isNamedModule();
11691169
}
11701170

1171+
bool Decl::isFromHeaderUnit() const {
1172+
return getOwningModule() && getOwningModule()->isHeaderUnit();
1173+
}
1174+
11711175
static Decl::Kind getKind(const Decl *D) { return D->getKind(); }
11721176
static Decl::Kind getKind(const DeclContext *DC) { return DC->getDeclKind(); }
11731177

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
// RUN: rm -fR %t
2+
// RUN: split-file %s %t
3+
// RUN: cd %t
4+
// RUN: %clang_cc1 -verify -std=c++20 -fskip-odr-check-in-gmf -I. -emit-header-unit -xc++-user-header bz1.h
5+
// RUN: %clang_cc1 -verify -std=c++20 -fskip-odr-check-in-gmf -I. -emit-header-unit -xc++-user-header bz2.h
6+
// RUN: %clang_cc1 -verify -std=c++20 -fskip-odr-check-in-gmf -I. -emit-header-unit -xc++-user-header -fmodule-file=bz1.pcm -fmodule-file=bz2.pcm bz.cpp
7+
8+
//--- compare
9+
namespace std {
10+
namespace __detail {
11+
12+
template<typename _Tp>
13+
inline constexpr unsigned __cmp_cat_id = 1;
14+
15+
template<typename... _Ts>
16+
constexpr auto __common_cmp_cat() {
17+
(__cmp_cat_id<_Ts> | ...);
18+
}
19+
20+
} // namespace __detail
21+
} // namespace std
22+
23+
//--- bz0.h
24+
template <class T>
25+
int operator|(T, T);
26+
27+
//--- bz1.h
28+
#include "bz0.h"
29+
#include <compare>
30+
// expected-no-diagnostics
31+
32+
//--- bz2.h
33+
#include <compare>
34+
// expected-no-diagnostics
35+
36+
//--- bz.cpp
37+
#include <compare>
38+
39+
import "bz1.h"; // expected-warning {{the implementation of header units is in an experimental phase}}
40+
import "bz2.h"; // expected-warning {{the implementation of header units is in an experimental phase}}

0 commit comments

Comments
 (0)