summaryrefslogtreecommitdiffstats
path: root/lib/Sema
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2015-01-10 18:16:25 +0000
committerNathan Sidwell <nathan@acm.org>2015-01-10 18:16:25 +0000
commit0c50e1a203c66774d91742b69654576bb65defd6 (patch)
tree29d28ea39546d67eb0766b21370f615d97bf5161 /lib/Sema
parenta2cf25d8f4e3ad9d13346331832554066c25754e (diff)
fix pr18645. Correct logic concerning 'T &&' deduction against lvalues.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@225587 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema')
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp47
1 files changed, 17 insertions, 30 deletions
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index dd2a4d2697..90384f0b0a 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -3136,34 +3136,16 @@ static bool AdjustFunctionParmAndArgTypesForDeduction(Sema &S,
// 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 AdjustFunctionParmAndArgTypesForDeduction(Sema &S,
}
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 {