diff options
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 35 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateDeduction.cpp | 60 |
2 files changed, 72 insertions, 23 deletions
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 85c292ff4cb..13face95e95 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -5777,19 +5777,29 @@ bool Sema::isStdInitializerList(QualType Ty, QualType *Element) { 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 @@ bool Sema::isStdInitializerList(QualType Ty, QualType *Element) { 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; } diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index ab2c2a3e678..738e596ef38 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -2971,6 +2971,28 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, 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 @@ Sema::DeduceTemplateArguments(FunctionTemplateDecl *FunctionTemplate, 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 |