[cfe-commits] r123981 - in /cfe/trunk: lib/Sema/SemaTemplateDeduction.cpp test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p9-0x.cpp
Douglas Gregor
dgregor at apple.com
Fri Jan 21 09:29:42 PST 2011
Author: dgregor
Date: Fri Jan 21 11:29:42 2011
New Revision: 123981
URL: http://llvm.org/viewvc/llvm-project?rev=123981&view=rev
Log:
Implement core issue 1164, which concerns the partial ordering of
f(T&) and f(T&&).
Added:
cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p9-0x.cpp
Modified:
cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=123981&r1=123980&r2=123981&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Fri Jan 21 11:29:42 2011
@@ -84,14 +84,29 @@
TemplateDeductionInfo &Info,
llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced);
-/// \brief Stores the result of comparing the qualifiers of two types, used
-/// when
+/// \brief Whether template argument deduction for two reference parameters
+/// resulted in the argument type, parameter type, or neither type being more
+/// qualified than the other.
enum DeductionQualifierComparison {
NeitherMoreQualified = 0,
ParamMoreQualified,
ArgMoreQualified
};
+/// \brief Stores the result of comparing two reference parameters while
+/// performing template argument deduction for partial ordering of function
+/// templates.
+struct RefParamPartialOrderingComparison {
+ /// \brief Whether the parameter type is an rvalue reference type.
+ bool ParamIsRvalueRef;
+ /// \brief Whether the argument type is an rvalue reference type.
+ bool ArgIsRvalueRef;
+
+ /// \brief Whether the parameter or argument (or neither) is more qualified.
+ DeductionQualifierComparison Qualifiers;
+};
+
+
static Sema::TemplateDeductionResult
DeduceTemplateArguments(Sema &S,
@@ -102,8 +117,8 @@
llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
unsigned TDF,
bool PartialOrdering = false,
- llvm::SmallVectorImpl<DeductionQualifierComparison> *
- QualifierComparisons = 0);
+ llvm::SmallVectorImpl<RefParamPartialOrderingComparison> *
+ RefParamComparisons = 0);
static Sema::TemplateDeductionResult
DeduceTemplateArguments(Sema &S,
@@ -638,7 +653,7 @@
/// deduction for during partial ordering for a call
/// (C++0x [temp.deduct.partial]).
///
-/// \param QualifierComparisons If we're performing template argument deduction
+/// \param RefParamComparisons If we're performing template argument deduction
/// in the context of partial ordering, the set of qualifier comparisons.
///
/// \returns the result of template argument deduction so far. Note that a
@@ -653,8 +668,8 @@
llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
unsigned TDF,
bool PartialOrdering = false,
- llvm::SmallVectorImpl<DeductionQualifierComparison> *
- QualifierComparisons = 0) {
+ llvm::SmallVectorImpl<RefParamPartialOrderingComparison> *
+ RefParamComparisons = 0) {
// Fast-path check to see if we have too many/too few arguments.
if (NumParams != NumArgs &&
!(NumParams && isa<PackExpansionType>(Params[NumParams - 1])) &&
@@ -692,7 +707,7 @@
Args[ArgIdx],
Info, Deduced, TDF,
PartialOrdering,
- QualifierComparisons))
+ RefParamComparisons))
return Result;
++ArgIdx;
@@ -750,7 +765,7 @@
if (Sema::TemplateDeductionResult Result
= DeduceTemplateArguments(S, TemplateParams, Pattern, Args[ArgIdx],
Info, Deduced, PartialOrdering,
- QualifierComparisons))
+ RefParamComparisons))
return Result;
// Capture the deduced template arguments for each parameter pack expanded
@@ -802,7 +817,7 @@
/// \param PartialOrdering Whether we're performing template argument deduction
/// in the context of partial ordering (C++0x [temp.deduct.partial]).
///
-/// \param QualifierComparisons If we're performing template argument deduction
+/// \param RefParamComparisons If we're performing template argument deduction
/// in the context of partial ordering, the set of qualifier comparisons.
///
/// \returns the result of template argument deduction so far. Note that a
@@ -816,7 +831,7 @@
llvm::SmallVectorImpl<DeducedTemplateArgument> &Deduced,
unsigned TDF,
bool PartialOrdering,
- llvm::SmallVectorImpl<DeductionQualifierComparison> *QualifierComparisons) {
+ llvm::SmallVectorImpl<RefParamPartialOrderingComparison> *RefParamComparisons) {
// We only want to look at the canonical types, since typedefs and
// sugar are not part of template argument deduction.
QualType Param = S.Context.getCanonicalType(ParamIn);
@@ -842,7 +857,7 @@
if (ArgRef)
Arg = ArgRef->getPointeeType();
- if (QualifierComparisons && ParamRef && ArgRef) {
+ if (RefParamComparisons && ParamRef && ArgRef) {
// C++0x [temp.deduct.partial]p6:
// If both P and A were reference types (before being replaced with the
// type referred to above), determine which of the two types (if any) is
@@ -852,12 +867,15 @@
//
// We save this information for later, using it only when deduction
// succeeds in both directions.
- DeductionQualifierComparison QualifierResult = NeitherMoreQualified;
+ RefParamPartialOrderingComparison Comparison;
+ Comparison.ParamIsRvalueRef = ParamRef->getAs<RValueReferenceType>();
+ Comparison.ArgIsRvalueRef = ArgRef->getAs<RValueReferenceType>();
+ Comparison.Qualifiers = NeitherMoreQualified;
if (Param.isMoreQualifiedThan(Arg))
- QualifierResult = ParamMoreQualified;
+ Comparison.Qualifiers = ParamMoreQualified;
else if (Arg.isMoreQualifiedThan(Param))
- QualifierResult = ArgMoreQualified;
- QualifierComparisons->push_back(QualifierResult);
+ Comparison.Qualifiers = ArgMoreQualified;
+ RefParamComparisons->push_back(Comparison);
}
// C++0x [temp.deduct.partial]p7:
@@ -2937,8 +2955,8 @@
FunctionTemplateDecl *FT1,
FunctionTemplateDecl *FT2,
TemplatePartialOrderingContext TPOC,
- unsigned NumCallArguments,
- llvm::SmallVectorImpl<DeductionQualifierComparison> *QualifierComparisons) {
+ unsigned NumCallArguments,
+ llvm::SmallVectorImpl<RefParamPartialOrderingComparison> *RefParamComparisons) {
FunctionDecl *FD1 = FT1->getTemplatedDecl();
FunctionDecl *FD2 = FT2->getTemplatedDecl();
const FunctionProtoType *Proto1 = FD1->getType()->getAs<FunctionProtoType>();
@@ -3004,7 +3022,7 @@
if (DeduceTemplateArguments(S, TemplateParams, Args2.data(), Args2.size(),
Args1.data(), Args1.size(), Info, Deduced,
TDF_None, /*PartialOrdering=*/true,
- QualifierComparisons))
+ RefParamComparisons))
return false;
break;
@@ -3016,7 +3034,7 @@
if (DeduceTemplateArguments(S, TemplateParams, Proto2->getResultType(),
Proto1->getResultType(), Info, Deduced,
TDF_None, /*PartialOrdering=*/true,
- QualifierComparisons))
+ RefParamComparisons))
return false;
break;
@@ -3027,7 +3045,7 @@
// types?
if (DeduceTemplateArguments(S, TemplateParams, FD2->getType(),
FD1->getType(), Info, Deduced, TDF_None,
- /*PartialOrdering=*/true, QualifierComparisons))
+ /*PartialOrdering=*/true, RefParamComparisons))
return false;
break;
}
@@ -3131,12 +3149,12 @@
SourceLocation Loc,
TemplatePartialOrderingContext TPOC,
unsigned NumCallArguments) {
- llvm::SmallVector<DeductionQualifierComparison, 4> QualifierComparisons;
+ llvm::SmallVector<RefParamPartialOrderingComparison, 4> RefParamComparisons;
bool Better1 = isAtLeastAsSpecializedAs(*this, Loc, FT1, FT2, TPOC,
NumCallArguments, 0);
bool Better2 = isAtLeastAsSpecializedAs(*this, Loc, FT2, FT1, TPOC,
NumCallArguments,
- &QualifierComparisons);
+ &RefParamComparisons);
if (Better1 != Better2) // We have a clear winner
return Better1? FT1 : FT2;
@@ -3144,7 +3162,6 @@
if (!Better1 && !Better2) // Neither is better than the other
return 0;
-
// C++0x [temp.deduct.partial]p10:
// If for each type being considered a given template is at least as
// specialized for all types and more specialized for some set of types and
@@ -3154,30 +3171,53 @@
// specialized than the other.
Better1 = false;
Better2 = false;
- for (unsigned I = 0, N = QualifierComparisons.size(); I != N; ++I) {
+ for (unsigned I = 0, N = RefParamComparisons.size(); I != N; ++I) {
// C++0x [temp.deduct.partial]p9:
// If, for a given type, deduction succeeds in both directions (i.e., the
- // types are identical after the transformations above) and if the type
- // from the argument template is more cv-qualified than the type from the
- // parameter template (as described above) that type is considered to be
- // more specialized than the other. If neither type is more cv-qualified
- // than the other then neither type is more specialized than the other.
- switch (QualifierComparisons[I]) {
- case NeitherMoreQualified:
- break;
-
- case ParamMoreQualified:
- Better1 = true;
- if (Better2)
- return 0;
- break;
-
- case ArgMoreQualified:
- Better2 = true;
- if (Better1)
- return 0;
- break;
+ // types are identical after the transformations above) and both P and A
+ // were reference types (before being replaced with the type referred to
+ // above):
+
+ // -- if the type from the argument template was an lvalue reference
+ // and the type from the parameter template was not, the argument
+ // type is considered to be more specialized than the other;
+ // otherwise,
+ if (!RefParamComparisons[I].ArgIsRvalueRef &&
+ RefParamComparisons[I].ParamIsRvalueRef) {
+ Better2 = true;
+ if (Better1)
+ return 0;
+ continue;
+ } else if (!RefParamComparisons[I].ParamIsRvalueRef &&
+ RefParamComparisons[I].ArgIsRvalueRef) {
+ Better1 = true;
+ if (Better2)
+ return 0;
+ continue;
+ }
+
+ // -- if the type from the argument template is more cv-qualified than
+ // the type from the parameter template (as described above), the
+ // argument type is considered to be more specialized than the
+ // other; otherwise,
+ switch (RefParamComparisons[I].Qualifiers) {
+ case NeitherMoreQualified:
+ break;
+
+ case ParamMoreQualified:
+ Better1 = true;
+ if (Better2)
+ return 0;
+ continue;
+
+ case ArgMoreQualified:
+ Better2 = true;
+ if (Better1)
+ return 0;
+ continue;
}
+
+ // -- neither type is more specialized than the other.
}
assert(!(Better1 && Better2) && "Should have broken out in the loop above");
@@ -3364,7 +3404,7 @@
bool Better1 = !::DeduceTemplateArguments(*this, PS2->getTemplateParameters(),
PT2, PT1, Info, Deduced, TDF_None,
/*PartialOrdering=*/true,
- /*QualifierComparisons=*/0);
+ /*RefParamComparisons=*/0);
if (Better1) {
InstantiatingTemplate Inst(*this, PS2->getLocation(), PS2,
Deduced.data(), Deduced.size(), Info);
@@ -3379,7 +3419,7 @@
bool Better2 = !::DeduceTemplateArguments(*this, PS1->getTemplateParameters(),
PT1, PT2, Info, Deduced, TDF_None,
/*PartialOrdering=*/true,
- /*QualifierComparisons=*/0);
+ /*RefParamComparisons=*/0);
if (Better2) {
InstantiatingTemplate Inst(*this, PS1->getLocation(), PS1,
Deduced.data(), Deduced.size(), Info);
Added: cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p9-0x.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p9-0x.cpp?rev=123981&view=auto
==============================================================================
--- cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p9-0x.cpp (added)
+++ cfe/trunk/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.partial/p9-0x.cpp Fri Jan 21 11:29:42 2011
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+template<typename T> int &f0(T&);
+template<typename T> float &f0(T&&);
+
+// Core issue 1164
+void test_f0(int i) {
+ int &ir0 = f0(i);
+ float &fr0 = f0(5);
+}
More information about the cfe-commits
mailing list