Skip to content

Commit c434c6b

Browse files
author
git apple-llvm automerger
committed
Merge commit '3f193bcc5a72' from llvm.org/release/19.x into stable/20240723
2 parents 38e25fd + 3f193bc commit c434c6b

File tree

3 files changed

+154
-16
lines changed

3 files changed

+154
-16
lines changed

clang/lib/Serialization/ASTReaderDecl.cpp

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3686,6 +3686,54 @@ static void inheritDefaultTemplateArguments(ASTContext &Context,
36863686
}
36873687
}
36883688

3689+
// [basic.link]/p10:
3690+
// If two declarations of an entity are attached to different modules,
3691+
// the program is ill-formed;
3692+
static void checkMultipleDefinitionInNamedModules(ASTReader &Reader, Decl *D,
3693+
Decl *Previous) {
3694+
Module *M = Previous->getOwningModule();
3695+
3696+
// We only care about the case in named modules.
3697+
if (!M || !M->isNamedModule())
3698+
return;
3699+
3700+
// If it is previous implcitly introduced, it is not meaningful to
3701+
// diagnose it.
3702+
if (Previous->isImplicit())
3703+
return;
3704+
3705+
// FIXME: Get rid of the enumeration of decl types once we have an appropriate
3706+
// abstract for decls of an entity. e.g., the namespace decl and using decl
3707+
// doesn't introduce an entity.
3708+
if (!isa<VarDecl, FunctionDecl, TagDecl, RedeclarableTemplateDecl>(Previous))
3709+
return;
3710+
3711+
// Skip implicit instantiations since it may give false positive diagnostic
3712+
// messages.
3713+
// FIXME: Maybe this shows the implicit instantiations may have incorrect
3714+
// module owner ships. But given we've finished the compilation of a module,
3715+
// how can we add new entities to that module?
3716+
if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(Previous);
3717+
VTSD && !VTSD->isExplicitSpecialization())
3718+
return;
3719+
if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(Previous);
3720+
CTSD && !CTSD->isExplicitSpecialization())
3721+
return;
3722+
if (auto *Func = dyn_cast<FunctionDecl>(Previous))
3723+
if (auto *FTSI = Func->getTemplateSpecializationInfo();
3724+
FTSI && !FTSI->isExplicitSpecialization())
3725+
return;
3726+
3727+
// It is fine if they are in the same module.
3728+
if (Reader.getContext().isInSameModule(M, D->getOwningModule()))
3729+
return;
3730+
3731+
Reader.Diag(Previous->getLocation(),
3732+
diag::err_multiple_decl_in_different_modules)
3733+
<< cast<NamedDecl>(Previous) << M->Name;
3734+
Reader.Diag(D->getLocation(), diag::note_also_found);
3735+
}
3736+
36893737
void ASTDeclReader::attachPreviousDecl(ASTReader &Reader, Decl *D,
36903738
Decl *Previous, Decl *Canon) {
36913739
assert(D && Previous);
@@ -3699,22 +3747,7 @@ void ASTDeclReader::attachPreviousDecl(ASTReader &Reader, Decl *D,
36993747
#include "clang/AST/DeclNodes.inc"
37003748
}
37013749

3702-
// [basic.link]/p10:
3703-
// If two declarations of an entity are attached to different modules,
3704-
// the program is ill-formed;
3705-
//
3706-
// FIXME: Get rid of the enumeration of decl types once we have an appropriate
3707-
// abstract for decls of an entity. e.g., the namespace decl and using decl
3708-
// doesn't introduce an entity.
3709-
if (Module *M = Previous->getOwningModule();
3710-
M && M->isNamedModule() &&
3711-
isa<VarDecl, FunctionDecl, TagDecl, RedeclarableTemplateDecl>(Previous) &&
3712-
!Reader.getContext().isInSameModule(M, D->getOwningModule())) {
3713-
Reader.Diag(Previous->getLocation(),
3714-
diag::err_multiple_decl_in_different_modules)
3715-
<< cast<NamedDecl>(Previous) << M->Name;
3716-
Reader.Diag(D->getLocation(), diag::note_also_found);
3717-
}
3750+
checkMultipleDefinitionInNamedModules(Reader, D, Previous);
37183751

37193752
// If the declaration was visible in one module, a redeclaration of it in
37203753
// another module remains visible even if it wouldn't be visible by itself.

clang/test/Modules/pr102349.cppm

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
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/a.cppm -emit-module-interface -o %t/a.pcm
6+
// RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-module-interface -o %t/b.pcm \
7+
// RUN: -fprebuilt-module-path=%t
8+
// RUN: %clang_cc1 -std=c++20 %t/c.cppm -emit-module-interface -o %t/c.pcm \
9+
// RUN: -fprebuilt-module-path=%t
10+
// RUN: %clang_cc1 -std=c++20 %t/d.cpp -fsyntax-only -verify \
11+
// RUN: -fprebuilt-module-path=%t
12+
13+
//--- a.cppm
14+
export module a;
15+
16+
export template<typename>
17+
struct a;
18+
19+
template<typename>
20+
struct a {
21+
};
22+
23+
export template<typename T>
24+
constexpr auto aa = a<T>();
25+
26+
//--- b.cppm
27+
export module b;
28+
29+
import a;
30+
31+
static void b() {
32+
static_cast<void>(a<void>());
33+
}
34+
35+
//--- c.cppm
36+
export module c;
37+
38+
import a;
39+
40+
static void c() {
41+
static_cast<void>(aa<void>);
42+
}
43+
44+
//--- d.cpp
45+
// expected-no-diagnostics
46+
import a;
47+
import b;
48+
import c;
49+
50+
static void d() {
51+
static_cast<void>(a<void>());
52+
}

clang/test/Modules/pr102360.cppm

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
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/a.cppm -emit-module-interface -o %t/a.pcm
6+
// RUN: %clang_cc1 -std=c++20 %t/b.cppm -emit-module-interface -o %t/b.pcm \
7+
// RUN: -fprebuilt-module-path=%t
8+
// RUN: %clang_cc1 -std=c++20 %t/c.cppm -emit-module-interface -o %t/c.pcm \
9+
// RUN: -fprebuilt-module-path=%t
10+
// RUN: %clang_cc1 -std=c++20 %t/d.cpp -fsyntax-only -verify \
11+
// RUN: -fprebuilt-module-path=%t
12+
13+
//--- a.cppm
14+
export module a;
15+
16+
template<typename>
17+
constexpr auto impl = true;
18+
19+
export template<typename T>
20+
void a() {
21+
}
22+
23+
export template<typename T> requires impl<T>
24+
void a() {
25+
}
26+
27+
//--- b.cppm
28+
export module b;
29+
30+
import a;
31+
32+
static void b() {
33+
a<void>();
34+
}
35+
36+
//--- c.cppm
37+
export module c;
38+
39+
import a;
40+
41+
static void c() {
42+
a<void>();
43+
}
44+
45+
//--- d.cpp
46+
// expected-no-diagnostics
47+
import a;
48+
import b;
49+
import c;
50+
51+
static void d() {
52+
a<void>();
53+
}

0 commit comments

Comments
 (0)