On 01/09/15 23:27, Richard Smith wrote:
You can make the test a bit simpler:
template<typename F> F Quux(F &&f);
float (&Baz)(float&&) = Quux(Quux<float>);
Thanks. I went with 'auto Baz = ...'
(The BoundMemberTy check is missing compared to the original, but it looks like
that never actually did anything here, because we'd fall through into the second
copy of the 'create an lvalue reference' code regardless.)
right. sorry I forgot to mention that.
committed
nathan
Index: src/tools/clang/lib/Sema/SemaTemplateDeduction.cpp
===================================================================
--- src/tools/clang/lib/Sema/SemaTemplateDeduction.cpp (revision 225586)
+++ src/tools/clang/lib/Sema/SemaTemplateDeduction.cpp (working copy)
@@ -3136,34 +3136,16 @@ static bool AdjustFunctionParmAndArgType
// are ignored for type deduction.
if (ParamType.hasQualifiers())
ParamType = ParamType.getUnqualifiedType();
- const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>();
- if (ParamRefType) {
- QualType PointeeType = ParamRefType->getPointeeType();
-
- // If the argument has incomplete array type, try to complete its type.
- if (ArgType->isIncompleteArrayType() && !S.RequireCompleteExprType(Arg, 0))
- ArgType = Arg->getType();
-
- // [C++0x] If P is an rvalue reference to a cv-unqualified
- // template parameter and the argument is an lvalue, the type
- // "lvalue reference to A" is used in place of A for type
- // deduction.
- if (isa<RValueReferenceType>(ParamType)) {
- if (!PointeeType.getQualifiers() &&
- isa<TemplateTypeParmType>(PointeeType) &&
- Arg->Classify(S.Context).isLValue() &&
- Arg->getType() != S.Context.OverloadTy &&
- Arg->getType() != S.Context.BoundMemberTy)
- ArgType = S.Context.getLValueReferenceType(ArgType);
- }
- // [...] If P is a reference type, the type referred to by P is used
- // for type deduction.
- ParamType = PointeeType;
- }
+ // [...] If P is a reference type, the type referred to by P is
+ // used for type deduction.
+ const ReferenceType *ParamRefType = ParamType->getAs<ReferenceType>();
+ if (ParamRefType)
+ ParamType = ParamRefType->getPointeeType();
- // Overload sets usually make this parameter an undeduced
- // context, but there are sometimes special circumstances.
+ // Overload sets usually make this parameter an undeduced context,
+ // but there are sometimes special circumstances. Typically
+ // involving a template-id-expr.
if (ArgType == S.Context.OverloadTy) {
ArgType = ResolveOverloadForDeduction(S, TemplateParams,
Arg, ParamType,
@@ -3173,12 +3155,17 @@ static bool AdjustFunctionParmAndArgType
}
if (ParamRefType) {
+ // If the argument has incomplete array type, try to complete its type.
+ if (ArgType->isIncompleteArrayType() && !S.RequireCompleteExprType(Arg, 0))
+ ArgType = Arg->getType();
+
// C++0x [temp.deduct.call]p3:
- // [...] If P is of the form T&&, where T is a template parameter, and
- // the argument is an lvalue, the type A& is used in place of A for
- // type deduction.
+ // If P is an rvalue reference to a cv-unqualified template
+ // parameter and the argument is an lvalue, the type "lvalue
+ // reference to A" is used in place of A for type deduction.
if (ParamRefType->isRValueReferenceType() &&
- ParamRefType->getAs<TemplateTypeParmType>() &&
+ !ParamType.getQualifiers() &&
+ isa<TemplateTypeParmType>(ParamType) &&
Arg->isLValue())
ArgType = S.Context.getLValueReferenceType(ArgType);
} else {
Index: src/tools/clang/test/SemaTemplate/deduction.cpp
===================================================================
--- src/tools/clang/test/SemaTemplate/deduction.cpp (revision 225586)
+++ src/tools/clang/test/SemaTemplate/deduction.cpp (working copy)
@@ -202,3 +202,8 @@ namespace PR19372 {
using T = S<int, int>;
}
}
+
+namespace PR18645 {
+ template<typename F> F Quux(F &&f);
+ auto Baz = Quux(Quux<float>);
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits