[cfe-commits] r148352 - in /cfe/trunk: lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaTemplateDeduction.cpp test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
Sebastian Redl
sebastian.redl at getdesigned.at
Tue Jan 17 14:49:58 PST 2012
Author: cornedbee
Date: Tue Jan 17 16:49:58 2012
New Revision: 148352
URL: http://llvm.org/viewvc/llvm-project?rev=148352&view=rev
Log:
Template argument deduction for std::initializer_list arguments from initializer lists.
Modified:
cfe/trunk/lib/Sema/SemaDeclCXX.cpp
cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=148352&r1=148351&r2=148352&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Tue Jan 17 16:49:58 2012
@@ -5777,19 +5777,29 @@
if (!StdNamespace) // If we haven't seen namespace std yet, this can't be it.
return false;
- const RecordType *RT = Ty->getAs<RecordType>();
- if (!RT)
- return false;
+ ClassTemplateDecl *Template = 0;
+ const TemplateArgument *Arguments = 0;
- ClassTemplateSpecializationDecl *Specialization =
- dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
- if (!Specialization)
- return false;
+ if (const RecordType *RT = Ty->getAs<RecordType>()) {
- if (Specialization->getSpecializationKind() != TSK_ImplicitInstantiation)
- return false;
+ ClassTemplateSpecializationDecl *Specialization =
+ dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl());
+ if (!Specialization)
+ return false;
- ClassTemplateDecl *Template = Specialization->getSpecializedTemplate();
+ if (Specialization->getSpecializationKind() != TSK_ImplicitInstantiation)
+ return false;
+
+ Template = Specialization->getSpecializedTemplate();
+ Arguments = Specialization->getTemplateArgs().data();
+ } else if (const TemplateSpecializationType *TST =
+ Ty->getAs<TemplateSpecializationType>()) {
+ Template = dyn_cast_or_null<ClassTemplateDecl>(
+ TST->getTemplateName().getAsTemplateDecl());
+ Arguments = TST->getArgs();
+ }
+ if (!Template)
+ return false;
if (!StdInitializerList) {
// Haven't recognized std::initializer_list yet, maybe this is it.
@@ -5814,9 +5824,8 @@
return false;
// This is an instance of std::initializer_list. Find the argument type.
- if (Element) {
- *Element = Specialization->getTemplateArgs()[0].getAsType();
- }
+ if (Element)
+ *Element = Arguments[0].getAsType();
return true;
}
Modified: cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp?rev=148352&r1=148351&r2=148352&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplateDeduction.cpp Tue Jan 17 16:49:58 2012
@@ -2971,6 +2971,28 @@
if (!hasDeducibleTemplateParameters(*this, FunctionTemplate, ParamType))
continue;
+ // If the argument is an initializer list ...
+ if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg)) {
+ // ... then the parameter is an undeduced context, unless the parameter
+ // type is (reference to cv) std::initializer_list<P'>, in which case
+ // deduction is done for each element of the initializer list, and the
+ // result is the deduced type if it's the same for all elements.
+ QualType X;
+ // Removing references was already done.
+ if (!isStdInitializerList(ParamType, &X))
+ continue;
+
+ for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) {
+ if (TemplateDeductionResult Result =
+ DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams, X,
+ ILE->getInit(i)->getType(),
+ Info, Deduced, TDF))
+ return Result;
+ }
+ // Don't track the argument type, since an initializer list has none.
+ continue;
+ }
+
// Keep track of the argument type and corresponding parameter index,
// so we can check for compatibility between the deduced A and A.
OriginalCallArgs.push_back(OriginalCallArg(OrigParamType, ArgIdx-1,
@@ -3042,17 +3064,35 @@
break;
}
- // Keep track of the argument type and corresponding argument index,
- // so we can check for compatibility between the deduced A and A.
- if (hasDeducibleTemplateParameters(*this, FunctionTemplate, ParamType))
- OriginalCallArgs.push_back(OriginalCallArg(OrigParamType, ArgIdx,
- ArgType));
+ // As above, initializer lists need special handling.
+ if (InitListExpr *ILE = dyn_cast<InitListExpr>(Arg)) {
+ QualType X;
+ if (!isStdInitializerList(ParamType, &X)) {
+ ++ArgIdx;
+ break;
+ }
- if (TemplateDeductionResult Result
- = DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams,
- ParamType, ArgType, Info,
- Deduced, TDF))
- return Result;
+ for (unsigned i = 0, e = ILE->getNumInits(); i < e; ++i) {
+ if (TemplateDeductionResult Result =
+ DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams, X,
+ ILE->getInit(i)->getType(),
+ Info, Deduced, TDF))
+ return Result;
+ }
+ } else {
+
+ // Keep track of the argument type and corresponding argument index,
+ // so we can check for compatibility between the deduced A and A.
+ if (hasDeducibleTemplateParameters(*this, FunctionTemplate, ParamType))
+ OriginalCallArgs.push_back(OriginalCallArg(OrigParamType, ArgIdx,
+ ArgType));
+
+ if (TemplateDeductionResult Result
+ = DeduceTemplateArgumentsByTypeMatch(*this, TemplateParams,
+ ParamType, ArgType, Info,
+ Deduced, TDF))
+ return Result;
+ }
// Capture the deduced template arguments for each parameter pack expanded
// by this pack expansion, add them to the list of arguments we've deduced
Modified: cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp?rev=148352&r1=148351&r2=148352&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp (original)
+++ cfe/trunk/test/SemaCXX/cxx0x-initializer-stdinitializerlist.cpp Tue Jan 17 16:49:58 2012
@@ -32,6 +32,11 @@
};
}
+template <typename T, typename U>
+struct same_type { static const bool value = false; };
+template <typename T>
+struct same_type<T, T> { static const bool value = true; };
+
struct one { char c[1]; };
struct two { char c[2]; };
@@ -87,3 +92,20 @@
// But here, user-defined is worst in both cases.
ov2({1, 2, D()}); // expected-error {{ambiguous}}
}
+
+template <typename T>
+T deduce(std::initializer_list<T>); // expected-note {{conflicting types for parameter 'T' ('int' vs. 'double')}}
+template <typename T>
+T deduce_ref(const std::initializer_list<T>&); // expected-note {{conflicting types for parameter 'T' ('int' vs. 'double')}}
+
+void argument_deduction() {
+ static_assert(same_type<decltype(deduce({1, 2, 3})), int>::value, "bad deduction");
+ static_assert(same_type<decltype(deduce({1.0, 2.0, 3.0})), double>::value, "bad deduction");
+
+ deduce({1, 2.0}); // expected-error {{no matching function}}
+
+ static_assert(same_type<decltype(deduce_ref({1, 2, 3})), int>::value, "bad deduction");
+ static_assert(same_type<decltype(deduce_ref({1.0, 2.0, 3.0})), double>::value, "bad deduction");
+
+ deduce_ref({1, 2.0}); // expected-error {{no matching function}}
+}
More information about the cfe-commits
mailing list