aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/Parse/ParseTentative.cpp4
-rw-r--r--lib/Sema/SemaTemplateDeduction.cpp10
-rw-r--r--test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p8-0x.cpp47
3 files changed, 56 insertions, 5 deletions
diff --git a/lib/Parse/ParseTentative.cpp b/lib/Parse/ParseTentative.cpp
index 523054b2d8..35d72547cd 100644
--- a/lib/Parse/ParseTentative.cpp
+++ b/lib/Parse/ParseTentative.cpp
@@ -1222,6 +1222,10 @@ Parser::TPResult Parser::TryParseFunctionDeclarator() {
Tok.is(tok::kw_restrict) )
ConsumeToken();
+ // ref-qualifier[opt]
+ if (Tok.is(tok::amp) || Tok.is(tok::ampamp))
+ ConsumeToken();
+
// exception-specification
if (Tok.is(tok::kw_throw)) {
ConsumeToken();
diff --git a/lib/Sema/SemaTemplateDeduction.cpp b/lib/Sema/SemaTemplateDeduction.cpp
index 70e9973946..fd12ccf0f2 100644
--- a/lib/Sema/SemaTemplateDeduction.cpp
+++ b/lib/Sema/SemaTemplateDeduction.cpp
@@ -1154,11 +1154,11 @@ DeduceTemplateArguments(Sema &S,
const FunctionProtoType *FunctionProtoParam =
cast<FunctionProtoType>(Param);
- if (FunctionProtoParam->getTypeQuals() !=
- FunctionProtoArg->getTypeQuals())
- return Sema::TDK_NonDeducedMismatch;
-
- if (FunctionProtoParam->isVariadic() != FunctionProtoArg->isVariadic())
+ if (FunctionProtoParam->getTypeQuals()
+ != FunctionProtoArg->getTypeQuals() ||
+ FunctionProtoParam->getRefQualifier()
+ != FunctionProtoArg->getRefQualifier() ||
+ FunctionProtoParam->isVariadic() != FunctionProtoArg->isVariadic())
return Sema::TDK_NonDeducedMismatch;
// Check return types.
diff --git a/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p8-0x.cpp b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p8-0x.cpp
new file mode 100644
index 0000000000..a9173fd6be
--- /dev/null
+++ b/test/CXX/temp/temp.fct.spec/temp.deduct/temp.deduct.type/p8-0x.cpp
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s
+
+// Deductions specific to C++0x.
+
+template<typename T>
+struct member_pointer_kind {
+ static const unsigned value = 0;
+};
+
+template<class C, typename R, typename ...Args>
+struct member_pointer_kind<R (C::*)(Args...)> {
+ static const unsigned value = 1;
+};
+
+template<class C, typename R, typename ...Args>
+struct member_pointer_kind<R (C::*)(Args...) &> {
+ static const unsigned value = 2;
+};
+
+template<class C, typename R, typename ...Args>
+struct member_pointer_kind<R (C::*)(Args...) &&> {
+ static const unsigned value = 3;
+};
+
+template<class C, typename R, typename ...Args>
+struct member_pointer_kind<R (C::*)(Args...) const> {
+ static const unsigned value = 4;
+};
+
+template<class C, typename R, typename ...Args>
+struct member_pointer_kind<R (C::*)(Args...) const &> {
+ static const unsigned value = 5;
+};
+
+template<class C, typename R, typename ...Args>
+struct member_pointer_kind<R (C::*)(Args...) const &&> {
+ static const unsigned value = 6;
+};
+
+struct X { };
+
+static_assert(member_pointer_kind<int (X::*)(int)>::value == 1, "");
+static_assert(member_pointer_kind<int (X::*)(int) &>::value == 2, "");
+static_assert(member_pointer_kind<int (X::*)(int) &&>::value == 3, "");
+static_assert(member_pointer_kind<int (X::*)(int) const>::value == 4, "");
+static_assert(member_pointer_kind<int (X::*)(int) const&>::value == 5, "");
+static_assert(member_pointer_kind<int (X::*)(int) const&&>::value == 6, "");