Skip to content

Commit ef2c0d8

Browse files
ChuanqiXu9yuxuanchen1997
authored andcommitted
[C++20] [Modules] Skip ODR checks if either declaration comes from GMF
Summary: This patch tries to workaround the case that: - in a module unit that imports another module unit - both the module units including overlapped headers - the compiler emits false positive ODR violation diagnostics for the overlapped headers if ODR check is enabled - the current module units enables PCH For the third point, we disabled ODR check if the declarations comes from GMF. However, due to the forth point, the check whether the declaration comes from GMF failed. Then we still going to check it and then the users get false positive checks. What's worse is that, this always happens in clangd, where will generate the PCH automatically before parsing the input files. The root cause of the problem we mixed the modules in the semantical level and the module in the serialization level. The problem is pretty fundamental and we need time to fix that. But 19.x is going to be branched and I hope to give clangd better user experience. So I decided to land this workaround even if it is pretyy niche and may only work for the case of clangd's pattern. Test Plan: Reviewers: Subscribers: Tasks: Tags: Differential Revision: https://phabricator.intern.facebook.com/D60251291
1 parent 2be976d commit ef2c0d8

File tree

3 files changed

+54
-2
lines changed

3 files changed

+54
-2
lines changed

clang/lib/Serialization/ASTReader.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9875,6 +9875,7 @@ void ASTReader::finishPendingActions() {
98759875
// We only perform ODR checks for decls not in the explicit
98769876
// global module fragment.
98779877
!shouldSkipCheckingODR(FD) &&
9878+
!shouldSkipCheckingODR(NonConstDefn) &&
98789879
FD->getODRHash() != NonConstDefn->getODRHash()) {
98799880
if (!isa<CXXMethodDecl>(FD)) {
98809881
PendingFunctionOdrMergeFailures[FD].push_back(NonConstDefn);

clang/lib/Serialization/ASTReaderDecl.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -821,7 +821,7 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) {
821821
Reader.mergeDefinitionVisibility(OldDef, ED);
822822
// We don't want to check the ODR hash value for declarations from global
823823
// module fragment.
824-
if (!shouldSkipCheckingODR(ED) &&
824+
if (!shouldSkipCheckingODR(ED) && !shouldSkipCheckingODR(OldDef) &&
825825
OldDef->getODRHash() != ED->getODRHash())
826826
Reader.PendingEnumOdrMergeFailures[OldDef].push_back(ED);
827827
} else {
@@ -2134,7 +2134,7 @@ void ASTDeclReader::MergeDefinitionData(
21342134
}
21352135

21362136
// We don't want to check ODR for decls in the global module fragment.
2137-
if (shouldSkipCheckingODR(MergeDD.Definition))
2137+
if (shouldSkipCheckingODR(MergeDD.Definition) || shouldSkipCheckingODR(D))
21382138
return;
21392139

21402140
if (D->getODRHash() != MergeDD.ODRHash) {
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// Test that we will skip ODR checks for declarations from PCH if they
2+
// were from GMF.
3+
//
4+
// RUN: rm -rf %t
5+
// RUN: mkdir -p %t
6+
// RUN: split-file %s %t
7+
//
8+
// RUN: %clang_cc1 -std=c++20 -emit-reduced-module-interface %t/A.cppm \
9+
// RUN: -o %t/A.pcm -fskip-odr-check-in-gmf
10+
// RUN: %clang_cc1 -std=c++20 -DDIFF -x c++-header %t/foo.h \
11+
// RUN: -emit-pch -o %t/foo.pch -fskip-odr-check-in-gmf
12+
// RUN: %clang_cc1 -std=c++20 %t/B.cppm -fmodule-file=A=%t/A.pcm -include-pch \
13+
// RUN: %t/foo.pch -verify -fsyntax-only -fskip-odr-check-in-gmf
14+
15+
//--- foo.h
16+
#ifndef FOO_H
17+
#define FOO_H
18+
inline int foo() {
19+
#ifndef DIFF
20+
return 43;
21+
#else
22+
return 45;
23+
#endif
24+
}
25+
26+
class f {
27+
public:
28+
int mem() {
29+
#ifndef DIFF
30+
return 47;
31+
#else
32+
return 45;
33+
#endif
34+
}
35+
};
36+
#endif
37+
38+
//--- A.cppm
39+
module;
40+
#include "foo.h"
41+
export module A;
42+
export using ::foo;
43+
export using ::f;
44+
45+
//--- B.cppm
46+
// expected-no-diagnostics
47+
module;
48+
#include "foo.h"
49+
export module B;
50+
import A;
51+
export int b = foo() + f().mem();

0 commit comments

Comments
 (0)