[clang] 7fb562c - [Concepts] Add constraints checks to isSameEntity
Saar Raz via cfe-commits
cfe-commits at lists.llvm.org
Tue Mar 10 13:09:06 PDT 2020
Author: Saar Raz
Date: 2020-03-10T22:05:36+02:00
New Revision: 7fb562c1ab373a3d4e14003e40556791ec032bab
URL: https://github.com/llvm/llvm-project/commit/7fb562c1ab373a3d4e14003e40556791ec032bab
DIFF: https://github.com/llvm/llvm-project/commit/7fb562c1ab373a3d4e14003e40556791ec032bab.diff
LOG: [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.
Added:
clang/test/PCH/cxx2a-constraints.cpp
Modified:
clang/lib/Serialization/ASTReaderDecl.cpp
Removed:
################################################################################
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index 362d3eaebdd2..828f4a172b05 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -2870,7 +2870,8 @@ uint64_t ASTReader::getGlobalBitOffset(ModuleFile &M, uint32_t LocalOffset) {
return LocalOffset + M.GlobalBitOffset;
}
-static bool isSameTemplateParameterList(const TemplateParameterList *X,
+static bool isSameTemplateParameterList(const ASTContext &C,
+ const TemplateParameterList *X,
const TemplateParameterList *Y);
/// Determine whether two template parameters are similar enough
@@ -2882,7 +2883,32 @@ static bool isSameTemplateParameter(const NamedDecl *X,
if (const auto *TX = dyn_cast<TemplateTypeParmDecl>(X)) {
const auto *TY = cast<TemplateTypeParmDecl>(Y);
- return TX->isParameterPack() == TY->isParameterPack();
+ if (TX->isParameterPack() != TY->isParameterPack())
+ return false;
+ if (TX->hasTypeConstraint() != TY->hasTypeConstraint())
+ return false;
+ if (TX->hasTypeConstraint()) {
+ const TypeConstraint *TXTC = TX->getTypeConstraint();
+ const TypeConstraint *TYTC = TY->getTypeConstraint();
+ if (TXTC->getNamedConcept() != TYTC->getNamedConcept())
+ return false;
+ if (TXTC->hasExplicitTemplateArgs() != TYTC->hasExplicitTemplateArgs())
+ return false;
+ if (TXTC->hasExplicitTemplateArgs()) {
+ const auto *TXTCArgs = TXTC->getTemplateArgsAsWritten();
+ const auto *TYTCArgs = TYTC->getTemplateArgsAsWritten();
+ if (TXTCArgs->NumTemplateArgs != TYTCArgs->NumTemplateArgs)
+ return false;
+ llvm::FoldingSetNodeID XID, YID;
+ for (const auto &ArgLoc : TXTCArgs->arguments())
+ ArgLoc.getArgument().Profile(XID, X->getASTContext());
+ for (const auto &ArgLoc : TYTCArgs->arguments())
+ ArgLoc.getArgument().Profile(YID, Y->getASTContext());
+ if (XID != YID)
+ return false;
+ }
+ }
+ return true;
}
if (const auto *TX = dyn_cast<NonTypeTemplateParmDecl>(X)) {
@@ -2894,7 +2920,8 @@ static bool isSameTemplateParameter(const NamedDecl *X,
const auto *TX = cast<TemplateTemplateParmDecl>(X);
const auto *TY = cast<TemplateTemplateParmDecl>(Y);
return TX->isParameterPack() == TY->isParameterPack() &&
- isSameTemplateParameterList(TX->getTemplateParameters(),
+ isSameTemplateParameterList(TX->getASTContext(),
+ TX->getTemplateParameters(),
TY->getTemplateParameters());
}
@@ -2947,7 +2974,8 @@ static bool isSameQualifier(const NestedNameSpecifier *X,
/// Determine whether two template parameter lists are similar enough
/// that they may be used in declarations of the same template.
-static bool isSameTemplateParameterList(const TemplateParameterList *X,
+static bool isSameTemplateParameterList(const ASTContext &C,
+ const TemplateParameterList *X,
const TemplateParameterList *Y) {
if (X->size() != Y->size())
return false;
@@ -2956,6 +2984,18 @@ static bool isSameTemplateParameterList(const TemplateParameterList *X,
if (!isSameTemplateParameter(X->getParam(I), Y->getParam(I)))
return false;
+ const Expr *XRC = X->getRequiresClause();
+ const Expr *YRC = Y->getRequiresClause();
+ if (!XRC != !YRC)
+ return false;
+ if (XRC) {
+ llvm::FoldingSetNodeID XRCID, YRCID;
+ XRC->Profile(XRCID, C, /*Canonical=*/true);
+ YRC->Profile(YRCID, C, /*Canonical=*/true);
+ if (XRCID != YRCID)
+ return false;
+ }
+
return true;
}
@@ -2992,7 +3032,7 @@ static bool hasSameOverloadableAttrs(const FunctionDecl *A,
return true;
}
-/// Determine whether the two declarations refer to the same entity.
+/// Determine whether the two declarations refer to the same entity.pr
static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
assert(X->getDeclName() == Y->getDeclName() && "Declaration name mismatch!");
@@ -3067,6 +3107,19 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
}
ASTContext &C = FuncX->getASTContext();
+
+ const Expr *XRC = FuncX->getTrailingRequiresClause();
+ const Expr *YRC = FuncY->getTrailingRequiresClause();
+ if (!XRC != !YRC)
+ return false;
+ if (XRC) {
+ llvm::FoldingSetNodeID XRCID, YRCID;
+ XRC->Profile(XRCID, C, /*Canonical=*/true);
+ YRC->Profile(YRCID, C, /*Canonical=*/true);
+ if (XRCID != YRCID)
+ return false;
+ }
+
auto GetTypeAsWritten = [](const FunctionDecl *FD) {
// Map to the first declaration that we've already merged into this one.
// The TSI of redeclarations might not match (due to calling conventions
@@ -3090,6 +3143,7 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
return true;
return false;
}
+
return FuncX->getLinkageInternal() == FuncY->getLinkageInternal() &&
hasSameOverloadableAttrs(FuncX, FuncY);
}
@@ -3129,7 +3183,8 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) {
const auto *TemplateY = cast<TemplateDecl>(Y);
return isSameEntity(TemplateX->getTemplatedDecl(),
TemplateY->getTemplatedDecl()) &&
- isSameTemplateParameterList(TemplateX->getTemplateParameters(),
+ isSameTemplateParameterList(TemplateX->getASTContext(),
+ TemplateX->getTemplateParameters(),
TemplateY->getTemplateParameters());
}
diff --git a/clang/test/PCH/cxx2a-constraints.cpp b/clang/test/PCH/cxx2a-constraints.cpp
new file mode 100644
index 000000000000..593d962ea101
--- /dev/null
+++ b/clang/test/PCH/cxx2a-constraints.cpp
@@ -0,0 +1,37 @@
+// RUN: %clang_cc1 -std=c++2a -emit-pch %s -o %t
+// RUN: %clang_cc1 -std=c++2a -include-pch %t -verify %s
+
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+template<typename T, typename U = char>
+concept SizedLike = sizeof(T) == sizeof(U);
+
+template <class T> void f(T) requires (sizeof(int) == sizeof(T)) {}
+template <class T> void f(T) requires (sizeof(char) == sizeof(T)) {}
+
+template <class T> requires (sizeof(int) == sizeof(T)) void g(T) {}
+template <class T> requires (sizeof(char) == sizeof(T)) void g(T) {}
+
+template <SizedLike<int> T> void h(T) {}
+template <SizedLike<char> T> void h(T) {}
+
+template <SizedLike<int> T> void i(T) {}
+template <SizedLike T> void i(T) {}
+
+#else /*included pch*/
+
+int main() {
+ (void)f('1');
+ (void)f(1);
+ (void)g('1');
+ (void)g(1);
+ (void)h('1');
+ (void)h(1);
+ (void)i('1');
+ (void)i(1);
+}
+
+#endif // HEADER
\ No newline at end of file
More information about the cfe-commits
mailing list