Skip to content

Commit 4e41127

Browse files
committed
[Concepts] Add constraints checks to isSameEntity
isSameEntity was missing constraints checking, causing constrained overloads to not travel well accross serialization. (bug #45115) Add constraints checking to isSameEntity. (cherry picked from commit 7fb562c)
1 parent 52cebc4 commit 4e41127

File tree

2 files changed

+98
-6
lines changed

2 files changed

+98
-6
lines changed

clang/lib/Serialization/ASTReaderDecl.cpp

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2867,7 +2867,8 @@ uint64_t ASTReader::getGlobalBitOffset(ModuleFile &M, uint32_t LocalOffset) {
28672867
return LocalOffset + M.GlobalBitOffset;
28682868
}
28692869

2870-
static bool isSameTemplateParameterList(const TemplateParameterList *X,
2870+
static bool isSameTemplateParameterList(const ASTContext &C,
2871+
const TemplateParameterList *X,
28712872
const TemplateParameterList *Y);
28722873

28732874
/// Determine whether two template parameters are similar enough
@@ -2879,7 +2880,32 @@ static bool isSameTemplateParameter(const NamedDecl *X,
28792880

28802881
if (const auto *TX = dyn_cast<TemplateTypeParmDecl>(X)) {
28812882
const auto *TY = cast<TemplateTypeParmDecl>(Y);
2882-
return TX->isParameterPack() == TY->isParameterPack();
2883+
if (TX->isParameterPack() != TY->isParameterPack())
2884+
return false;
2885+
if (TX->hasTypeConstraint() != TY->hasTypeConstraint())
2886+
return false;
2887+
if (TX->hasTypeConstraint()) {
2888+
const TypeConstraint *TXTC = TX->getTypeConstraint();
2889+
const TypeConstraint *TYTC = TY->getTypeConstraint();
2890+
if (TXTC->getNamedConcept() != TYTC->getNamedConcept())
2891+
return false;
2892+
if (TXTC->hasExplicitTemplateArgs() != TYTC->hasExplicitTemplateArgs())
2893+
return false;
2894+
if (TXTC->hasExplicitTemplateArgs()) {
2895+
const auto *TXTCArgs = TXTC->getTemplateArgsAsWritten();
2896+
const auto *TYTCArgs = TYTC->getTemplateArgsAsWritten();
2897+
if (TXTCArgs->NumTemplateArgs != TYTCArgs->NumTemplateArgs)
2898+
return false;
2899+
llvm::FoldingSetNodeID XID, YID;
2900+
for (const auto &ArgLoc : TXTCArgs->arguments())
2901+
ArgLoc.getArgument().Profile(XID, X->getASTContext());
2902+
for (const auto &ArgLoc : TYTCArgs->arguments())
2903+
ArgLoc.getArgument().Profile(YID, Y->getASTContext());
2904+
if (XID != YID)
2905+
return false;
2906+
}
2907+
}
2908+
return true;
28832909
}
28842910

28852911
if (const auto *TX = dyn_cast<NonTypeTemplateParmDecl>(X)) {
@@ -2891,7 +2917,8 @@ static bool isSameTemplateParameter(const NamedDecl *X,
28912917
const auto *TX = cast<TemplateTemplateParmDecl>(X);
28922918
const auto *TY = cast<TemplateTemplateParmDecl>(Y);
28932919
return TX->isParameterPack() == TY->isParameterPack() &&
2894-
isSameTemplateParameterList(TX->getTemplateParameters(),
2920+
isSameTemplateParameterList(TX->getASTContext(),
2921+
TX->getTemplateParameters(),
28952922
TY->getTemplateParameters());
28962923
}
28972924

@@ -2944,7 +2971,8 @@ static bool isSameQualifier(const NestedNameSpecifier *X,
29442971

29452972
/// Determine whether two template parameter lists are similar enough
29462973
/// that they may be used in declarations of the same template.
2947-
static bool isSameTemplateParameterList(const TemplateParameterList *X,
2974+
static bool isSameTemplateParameterList(const ASTContext &C,
2975+
const TemplateParameterList *X,
29482976
const TemplateParameterList *Y) {
29492977
if (X->size() != Y->size())
29502978
return false;
@@ -2953,6 +2981,18 @@ static bool isSameTemplateParameterList(const TemplateParameterList *X,
29532981
if (!isSameTemplateParameter(X->getParam(I), Y->getParam(I)))
29542982
return false;
29552983

2984+
const Expr *XRC = X->getRequiresClause();
2985+
const Expr *YRC = Y->getRequiresClause();
2986+
if (!XRC != !YRC)
2987+
return false;
2988+
if (XRC) {
2989+
llvm::FoldingSetNodeID XRCID, YRCID;
2990+
XRC->Profile(XRCID, C, /*Canonical=*/true);
2991+
YRC->Profile(YRCID, C, /*Canonical=*/true);
2992+
if (XRCID != YRCID)
2993+
return false;
2994+
}
2995+
29562996
return true;
29572997
}
29582998

@@ -2989,7 +3029,7 @@ static bool hasSameOverloadableAttrs(const FunctionDecl *A,
29893029
return true;
29903030
}
29913031

2992-
/// Determine whether the two declarations refer to the same entity.
3032+
/// Determine whether the two declarations refer to the same entity.pr
29933033
static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
29943034
assert(X->getDeclName() == Y->getDeclName() && "Declaration name mismatch!");
29953035

@@ -3064,6 +3104,19 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
30643104
}
30653105

30663106
ASTContext &C = FuncX->getASTContext();
3107+
3108+
const Expr *XRC = FuncX->getTrailingRequiresClause();
3109+
const Expr *YRC = FuncY->getTrailingRequiresClause();
3110+
if (!XRC != !YRC)
3111+
return false;
3112+
if (XRC) {
3113+
llvm::FoldingSetNodeID XRCID, YRCID;
3114+
XRC->Profile(XRCID, C, /*Canonical=*/true);
3115+
YRC->Profile(YRCID, C, /*Canonical=*/true);
3116+
if (XRCID != YRCID)
3117+
return false;
3118+
}
3119+
30673120
auto GetTypeAsWritten = [](const FunctionDecl *FD) {
30683121
// Map to the first declaration that we've already merged into this one.
30693122
// The TSI of redeclarations might not match (due to calling conventions
@@ -3087,6 +3140,7 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
30873140
return true;
30883141
return false;
30893142
}
3143+
30903144
return FuncX->getLinkageInternal() == FuncY->getLinkageInternal() &&
30913145
hasSameOverloadableAttrs(FuncX, FuncY);
30923146
}
@@ -3126,7 +3180,8 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
31263180
const auto *TemplateY = cast<TemplateDecl>(Y);
31273181
return isSameEntity(TemplateX->getTemplatedDecl(),
31283182
TemplateY->getTemplatedDecl()) &&
3129-
isSameTemplateParameterList(TemplateX->getTemplateParameters(),
3183+
isSameTemplateParameterList(TemplateX->getASTContext(),
3184+
TemplateX->getTemplateParameters(),
31303185
TemplateY->getTemplateParameters());
31313186
}
31323187

clang/test/PCH/cxx2a-constraints.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// RUN: %clang_cc1 -std=c++2a -emit-pch %s -o %t
2+
// RUN: %clang_cc1 -std=c++2a -include-pch %t -verify %s
3+
4+
// expected-no-diagnostics
5+
6+
#ifndef HEADER
7+
#define HEADER
8+
9+
template<typename T, typename U = char>
10+
concept SizedLike = sizeof(T) == sizeof(U);
11+
12+
template <class T> void f(T) requires (sizeof(int) == sizeof(T)) {}
13+
template <class T> void f(T) requires (sizeof(char) == sizeof(T)) {}
14+
15+
template <class T> requires (sizeof(int) == sizeof(T)) void g(T) {}
16+
template <class T> requires (sizeof(char) == sizeof(T)) void g(T) {}
17+
18+
template <SizedLike<int> T> void h(T) {}
19+
template <SizedLike<char> T> void h(T) {}
20+
21+
template <SizedLike<int> T> void i(T) {}
22+
template <SizedLike T> void i(T) {}
23+
24+
#else /*included pch*/
25+
26+
int main() {
27+
(void)f('1');
28+
(void)f(1);
29+
(void)g('1');
30+
(void)g(1);
31+
(void)h('1');
32+
(void)h(1);
33+
(void)i('1');
34+
(void)i(1);
35+
}
36+
37+
#endif // HEADER

0 commit comments

Comments
 (0)