[PATCH] D84048: DR2303: Prefer 'nearer' base classes during template deduction.
Erich Keane via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Fri Jul 17 09:53:19 PDT 2020
erichkeane created this revision.
erichkeane added reviewers: rsmith, rjmccall, aaron.ballman.
DR2303 fixes the case where the derived-base match for template
deduction is ambiguous if a base-of-base ALSO matches. The canonical
example (as shown in the test) is just like the MSVC implementation of
std::tuple.
This fixes a fairly sizable issue, where if a user inherits from
std::tuple on Windows (with the MS STL), they cannot use that type to
call a function that takes std::tuple.
https://reviews.llvm.org/D84048
Files:
clang/lib/Sema/SemaTemplateDeduction.cpp
clang/test/CXX/drs/dr23xx.cpp
Index: clang/test/CXX/drs/dr23xx.cpp
===================================================================
--- clang/test/CXX/drs/dr23xx.cpp
+++ clang/test/CXX/drs/dr23xx.cpp
@@ -113,3 +113,26 @@
extern template const int d<const int>;
#endif
}
+
+#if __cplusplus >= 201103L
+namespace dr2303 {
+template <typename... T>
+struct A;
+template <>
+struct A<> {};
+template <typename T, typename... Ts>
+struct A<T, Ts...> : A<Ts...> {};
+struct B : A<int> {};
+
+template <typename... T>
+void f(const A<T...> &);
+template <typename... T>
+void f2(const A<T...> *);
+
+void g() {
+ f(B{}); // This is no longer ambiguous.
+ B b;
+ f2(&b);
+}
+} //namespace dr2303
+#endif
Index: clang/lib/Sema/SemaTemplateDeduction.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateDeduction.cpp
+++ clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -1792,7 +1792,10 @@
// transformed A can be a derived class of the deduced A. Likewise if
// P is a pointer to a class of the form simple-template-id, the
// transformed A can be a pointer to a derived class pointed to by the
- // deduced A.
+ // deduced A. However, if there is a class C that is a (direct or
+ // indirect) base class of D and derived (directly or indirectly) from a
+ // class B and that would be a valid deduced A, the deduced A cannot be
+ // B or pointer to B, respectively.
//
// These alternatives are considered only if type deduction would
// otherwise fail. If they yield more than one possible deduced A, the
@@ -1812,6 +1815,7 @@
while (!ToVisit.empty()) {
// Retrieve the next class in the inheritance hierarchy.
const RecordType *NextT = ToVisit.pop_back_val();
+ bool SkipBases = false;
// If we have already seen this type, skip it.
if (!Visited.insert(NextT).second)
@@ -1840,21 +1844,33 @@
Info.Param = BaseInfo.Param;
Info.FirstArg = BaseInfo.FirstArg;
Info.SecondArg = BaseInfo.SecondArg;
+
+ // In order to implement CWG2303 (added the following to p4b3):
+ // However, if there is a class C that is a (direct or indirect)
+ // base class of D and derived (directly or indirectly) from a
+ // class B and that would be a valid deduced A, the deduced A
+ // cannot be B or pointer to B, respectively.
+ // We shouldn't visit the bases of a successful match ('C'), as they
+ // could only be 'B' here.
+ SkipBases = true;
}
Deduced = DeducedOrig;
}
// Visit base classes
- CXXRecordDecl *Next = cast<CXXRecordDecl>(NextT->getDecl());
- for (const auto &Base : Next->bases()) {
- assert(Base.getType()->isRecordType() &&
- "Base class that isn't a record?");
- ToVisit.push_back(Base.getType()->getAs<RecordType>());
+ if (!SkipBases) {
+ CXXRecordDecl *Next = cast<CXXRecordDecl>(NextT->getDecl());
+ for (const auto &Base : Next->bases()) {
+ assert(Base.getType()->isRecordType() &&
+ "Base class that isn't a record?");
+ ToVisit.push_back(Base.getType()->getAs<RecordType>());
+ }
}
}
if (Successful) {
+ // TODO
std::swap(SuccessfulDeduced, Deduced);
return Sema::TDK_Success;
}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D84048.278821.patch
Type: text/x-patch
Size: 3503 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20200717/885b1d05/attachment-0001.bin>
More information about the cfe-commits
mailing list