[PATCH] D18868: [Sema] PR27155: Fix a template argument deduction bug with base classes
Erik Pilkington via cfe-commits
cfe-commits at lists.llvm.org
Thu Apr 7 14:22:17 PDT 2016
erik.pilkington created this revision.
erik.pilkington added a reviewer: rsmith.
erik.pilkington added a subscriber: cfe-commits.
Previously, clang would incorrectly reject the following:
```
struct S {};
template<class T, int i> struct D : T {};
template<class T> void Foo(D<T, 1>);
int fn() {
D<D<S, 1>, 0> v;
Foo(v);
}
```
The problem is that clang initially tries to apply D<S, 1> for T in Foo, storing the result (in Deduced). Then clang tries to match 0 for 1 in Foo, would fail, and begin to consider the base classes of v (per temp.deduct.call p4.3), without resetting the original faulty assumption. This patch simply saves the deduced arguments before attempting the faulty deduction, then restores them once the faulty deduction fails.
Note: This section of code still has a somewhat related latent bug where ambiguous base class deductions are left undiagnosed, for example:
```
int fn2() {
D<D<D<S, 1>, 1>, 0> v;
Foo(v); // error, is T deduced to be S or D<S, 1>?
}
```
Which is outlawed by temp.deduct.call p5. I have another patch that fixes this, which I'll submit once(/if) this goes through.
http://reviews.llvm.org/D18868
Files:
lib/Sema/SemaTemplateDeduction.cpp
test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp
Index: test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp
===================================================================
--- test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp
+++ test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.call/p3.cpp
@@ -146,3 +146,17 @@
}
}
+
+namespace PR27155 {
+
+struct B {};
+
+template<class T, int i> struct D : T {};
+template<class T> void Foo(D<T, 1>);
+
+int fn() {
+ D<D<B, 1>, 0> f;
+ Foo(f);
+}
+
+}
Index: lib/Sema/SemaTemplateDeduction.cpp
===================================================================
--- lib/Sema/SemaTemplateDeduction.cpp
+++ lib/Sema/SemaTemplateDeduction.cpp
@@ -1421,21 +1421,29 @@
const TemplateSpecializationType *SpecParam
= cast<TemplateSpecializationType>(Param);
+ SmallVector<DeducedTemplateArgument, 8> DeducedOrig(Deduced.begin(),
+ Deduced.end());
+
// Try to deduce template arguments from the template-id.
Sema::TemplateDeductionResult Result
= DeduceTemplateArguments(S, TemplateParams, SpecParam, Arg,
Info, Deduced);
if (Result && (TDF & TDF_DerivedClass)) {
- // C++ [temp.deduct.call]p3b3:
- // If P is a class, and P has the form template-id, then A can be a
- // derived class of the deduced A. Likewise, if P is a pointer to a
- // class of the form template-id, A can be a pointer to a derived
- // class pointed to by the deduced A.
+ // C++14 [temp.deduct.call] p4b3:
+ // If P is a class and P has the form simple-template-id, then the
+ // 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.
//
- // More importantly:
// These alternatives are considered only if type deduction would
- // otherwise fail.
+ // otherwise fail. If they yield more than one possible deduced A, the
+ // type deduction fails.
+
+ // Reset the incorrectly deduced argument from above.
+ Deduced = DeducedOrig;
+
if (const RecordType *RecordT = Arg->getAs<RecordType>()) {
// We cannot inspect base classes as part of deduction when the type
// is incomplete, so either instantiate any templates necessary to
@@ -1450,8 +1458,6 @@
SmallVector<const RecordType *, 8> ToVisit;
ToVisit.push_back(RecordT);
bool Successful = false;
- SmallVector<DeducedTemplateArgument, 8> DeducedOrig(Deduced.begin(),
- Deduced.end());
while (!ToVisit.empty()) {
// Retrieve the next class in the inheritance hierarchy.
const RecordType *NextT = ToVisit.pop_back_val();
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D18868.52948.patch
Type: text/x-patch
Size: 3016 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20160407/fc6394d1/attachment.bin>
More information about the cfe-commits
mailing list