diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaCast.cpp | 3 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 103 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprCXX.cpp | 92 | ||||
-rw-r--r-- | clang/lib/Sema/SemaInit.cpp | 220 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplateDeduction.cpp | 87 |
6 files changed, 382 insertions, 125 deletions
diff --git a/clang/lib/Sema/SemaCast.cpp b/clang/lib/Sema/SemaCast.cpp index 6f9852aaf53..39e85e76d6f 100644 --- a/clang/lib/Sema/SemaCast.cpp +++ b/clang/lib/Sema/SemaCast.cpp @@ -2627,11 +2627,12 @@ ExprResult Sema::BuildCStyleCastExpr(SourceLocation LPLoc, } ExprResult Sema::BuildCXXFunctionalCastExpr(TypeSourceInfo *CastTypeInfo, + QualType Type, SourceLocation LPLoc, Expr *CastExpr, SourceLocation RPLoc) { assert(LPLoc.isValid() && "List-initialization shouldn't get here."); - CastOperation Op(*this, CastTypeInfo->getType(), CastExpr); + CastOperation Op(*this, Type, CastExpr); Op.DestRange = CastTypeInfo->getTypeLoc().getSourceRange(); Op.OpRange = SourceRange(Op.DestRange.getBegin(), CastExpr->getLocEnd()); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index f103f30b4df..658146d6389 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -9807,16 +9807,33 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl, DeducedType *Deduced = Type->getContainedDeducedType(); assert(Deduced && "deduceVarTypeFromInitializer for non-deduced type"); + ArrayRef<Expr*> DeduceInits = Init ? ArrayRef<Expr*>(Init) : None; + if (DirectInit) { + if (auto *PL = dyn_cast_or_null<ParenListExpr>(Init)) + DeduceInits = PL->exprs(); + } + if (isa<DeducedTemplateSpecializationType>(Deduced)) { - Diag(Init->getLocStart(), diag::err_deduced_class_template_not_supported); + assert(VDecl && "non-auto type for init capture deduction?"); + InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl); + InitializationKind Kind = InitializationKind::CreateForInit( + VDecl->getLocation(), DirectInit, Init); + // FIXME: Initialization should not be taking a mutable list of inits. + SmallVector<Expr*, 8> InitsCopy(DeduceInits.begin(), DeduceInits.end()); + return DeduceTemplateSpecializationFromInitializer(TSI, Entity, Kind, + InitsCopy); + } + + // C++11 [dcl.spec.auto]p3 + if (!Init) { + assert(VDecl && "no init for init capture deduction?"); + Diag(VDecl->getLocation(), diag::err_auto_var_requires_init) + << VDecl->getDeclName() << Type; return QualType(); } - ArrayRef<Expr *> DeduceInits = Init; if (DirectInit) { - if (auto *PL = dyn_cast<ParenListExpr>(Init)) - DeduceInits = PL->exprs(); - else if (auto *IL = dyn_cast<InitListExpr>(Init)) + if (auto *IL = dyn_cast<InitListExpr>(Init)) DeduceInits = IL->inits(); } @@ -9902,6 +9919,36 @@ QualType Sema::deduceVarTypeFromInitializer(VarDecl *VDecl, return DeducedType; } +bool Sema::DeduceVariableDeclarationType(VarDecl *VDecl, bool DirectInit, + Expr *Init) { + QualType DeducedType = deduceVarTypeFromInitializer( + VDecl, VDecl->getDeclName(), VDecl->getType(), VDecl->getTypeSourceInfo(), + VDecl->getSourceRange(), DirectInit, Init); + if (DeducedType.isNull()) { + VDecl->setInvalidDecl(); + return true; + } + + VDecl->setType(DeducedType); + assert(VDecl->isLinkageValid()); + + // In ARC, infer lifetime. + if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(VDecl)) + VDecl->setInvalidDecl(); + + // If this is a redeclaration, check that the type we just deduced matches + // the previously declared type. + if (VarDecl *Old = VDecl->getPreviousDecl()) { + // We never need to merge the type, because we cannot form an incomplete + // array of auto, nor deduce such a type. + MergeVarDeclTypes(VDecl, Old, /*MergeTypeWithPrevious*/ false); + } + + // Check the deduced type is valid for a variable declaration. + CheckVariableDeclarationType(VDecl); + return VDecl->isInvalidDecl(); +} + /// AddInitializerToDecl - Adds the initializer Init to the /// declaration dcl. If DirectInit is true, this is C++ direct /// initialization rather than copy initialization. @@ -9941,32 +9988,7 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { } Init = Res.get(); - QualType DeducedType = deduceVarTypeFromInitializer( - VDecl, VDecl->getDeclName(), VDecl->getType(), - VDecl->getTypeSourceInfo(), VDecl->getSourceRange(), DirectInit, Init); - if (DeducedType.isNull()) { - RealDecl->setInvalidDecl(); - return; - } - - VDecl->setType(DeducedType); - assert(VDecl->isLinkageValid()); - - // In ARC, infer lifetime. - if (getLangOpts().ObjCAutoRefCount && inferObjCARCLifetime(VDecl)) - VDecl->setInvalidDecl(); - - // If this is a redeclaration, check that the type we just deduced matches - // the previously declared type. - if (VarDecl *Old = VDecl->getPreviousDecl()) { - // We never need to merge the type, because we cannot form an incomplete - // array of auto, nor deduce such a type. - MergeVarDeclTypes(VDecl, Old, /*MergeTypeWithPrevious*/ false); - } - - // Check the deduced type is valid for a variable declaration. - CheckVariableDeclarationType(VDecl); - if (VDecl->isInvalidDecl()) + if (DeduceVariableDeclarationType(VDecl, DirectInit, Init)) return; } @@ -10085,15 +10107,8 @@ void Sema::AddInitializerToDecl(Decl *RealDecl, Expr *Init, bool DirectInit) { } InitializedEntity Entity = InitializedEntity::InitializeVariable(VDecl); - InitializationKind Kind = - DirectInit - ? CXXDirectInit - ? InitializationKind::CreateDirect(VDecl->getLocation(), - Init->getLocStart(), - Init->getLocEnd()) - : InitializationKind::CreateDirectList(VDecl->getLocation()) - : InitializationKind::CreateCopy(VDecl->getLocation(), - Init->getLocStart()); + InitializationKind Kind = InitializationKind::CreateForInit( + VDecl->getLocation(), DirectInit, Init); MultiExprArg Args = Init; if (CXXDirectInit) @@ -10417,13 +10432,9 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) { return; } - // C++11 [dcl.spec.auto]p3 - if (Type->isUndeducedType()) { - Diag(Var->getLocation(), diag::err_auto_var_requires_init) - << Var->getDeclName() << Type; - Var->setInvalidDecl(); + if (Type->isUndeducedType() && + DeduceVariableDeclarationType(Var, false, nullptr)) return; - } // C++11 [class.static.data]p3: A static data member can be declared with // the constexpr specifier; if so, its declaration shall specify diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 974e09f78d4..1e0df808305 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -8556,7 +8556,7 @@ QualType Sema::BuildStdInitializerList(QualType Element, SourceLocation Loc) { CheckTemplateIdType(TemplateName(StdInitializerList), Loc, Args)); } -bool Sema::isInitListConstructor(const CXXConstructorDecl* Ctor) { +bool Sema::isInitListConstructor(const FunctionDecl *Ctor) { // C++ [dcl.init.list]p2: // A constructor is an initializer-list constructor if its first parameter // is of type std::initializer_list<E> or reference to possibly cv-qualified diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 1185dacc227..7937654f279 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1266,15 +1266,6 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, RParenLoc); } - // C++1z [expr.type.conv]p1: - // If the type is a placeholder for a deduced class type, [...perform class - // template argument deduction...] - DeducedType *Deduced = Ty->getContainedDeducedType(); - if (Deduced && isa<DeducedTemplateSpecializationType>(Deduced)) { - Diag(TyBeginLoc, diag::err_deduced_class_template_not_supported); - return ExprError(); - } - bool ListInitialization = LParenLoc.isInvalid(); assert((!ListInitialization || (Exprs.size() == 1 && isa<InitListExpr>(Exprs[0]))) && @@ -1282,13 +1273,34 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, SourceRange FullRange = SourceRange(TyBeginLoc, ListInitialization ? Exprs[0]->getSourceRange().getEnd() : RParenLoc); + InitializedEntity Entity = InitializedEntity::InitializeTemporary(TInfo); + InitializationKind Kind = + Exprs.size() + ? ListInitialization + ? InitializationKind::CreateDirectList(TyBeginLoc) + : InitializationKind::CreateDirect(TyBeginLoc, LParenLoc, + RParenLoc) + : InitializationKind::CreateValue(TyBeginLoc, LParenLoc, RParenLoc); + + // C++1z [expr.type.conv]p1: + // If the type is a placeholder for a deduced class type, [...perform class + // template argument deduction...] + DeducedType *Deduced = Ty->getContainedDeducedType(); + if (Deduced && isa<DeducedTemplateSpecializationType>(Deduced)) { + Ty = DeduceTemplateSpecializationFromInitializer(TInfo, Entity, + Kind, Exprs); + if (Ty.isNull()) + return ExprError(); + Entity = InitializedEntity::InitializeTemporary(TInfo, Ty); + } + // C++ [expr.type.conv]p1: // If the expression list is a single expression, the type conversion // expression is equivalent (in definedness, and if defined in meaning) to the // corresponding cast expression. if (Exprs.size() == 1 && !ListInitialization) { Expr *Arg = Exprs[0]; - return BuildCXXFunctionalCastExpr(TInfo, LParenLoc, Arg, RParenLoc); + return BuildCXXFunctionalCastExpr(TInfo, Ty, LParenLoc, Arg, RParenLoc); } // C++14 [expr.type.conv]p2: The expression T(), where T is a @@ -1313,12 +1325,6 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, diag::err_invalid_incomplete_type_use, FullRange)) return ExprError(); - InitializedEntity Entity = InitializedEntity::InitializeTemporary(TInfo); - InitializationKind Kind = - Exprs.size() ? ListInitialization - ? InitializationKind::CreateDirectList(TyBeginLoc) - : InitializationKind::CreateDirect(TyBeginLoc, LParenLoc, RParenLoc) - : InitializationKind::CreateValue(TyBeginLoc, LParenLoc, RParenLoc); InitializationSequence InitSeq(*this, Entity, Kind, Exprs); ExprResult Result = InitSeq.Perform(*this, Entity, Kind, Exprs); @@ -1339,7 +1345,7 @@ Sema::BuildCXXTypeConstructExpr(TypeSourceInfo *TInfo, // is sometimes handled by initialization and sometimes not. QualType ResultType = Result.get()->getType(); Result = CXXFunctionalCastExpr::Create( - Context, ResultType, Expr::getValueKindForType(TInfo->getType()), TInfo, + Context, ResultType, Expr::getValueKindForType(Ty), TInfo, CK_NoOp, Result.get(), /*Path=*/nullptr, LParenLoc, RParenLoc); } @@ -1665,13 +1671,38 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, NumInits = List->getNumExprs(); } + // C++11 [expr.new]p15: + // A new-expression that creates an object of type T initializes that + // object as follows: + InitializationKind Kind + // - If the new-initializer is omitted, the object is default- + // initialized (8.5); if no initialization is performed, + // the object has indeterminate value + = initStyle == CXXNewExpr::NoInit + ? InitializationKind::CreateDefault(TypeRange.getBegin()) + // - Otherwise, the new-initializer is interpreted according to the + // initialization rules of 8.5 for direct-initialization. + : initStyle == CXXNewExpr::ListInit + ? InitializationKind::CreateDirectList(TypeRange.getBegin()) + : InitializationKind::CreateDirect(TypeRange.getBegin(), + DirectInitRange.getBegin(), + DirectInitRange.getEnd()); + // C++11 [dcl.spec.auto]p6. Deduce the type which 'auto' stands in for. - if (AllocType->isUndeducedType()) { - if (isa<DeducedTemplateSpecializationType>( - AllocType->getContainedDeducedType())) - return ExprError(Diag(TypeRange.getBegin(), - diag::err_deduced_class_template_not_supported)); + auto *Deduced = AllocType->getContainedDeducedType(); + if (Deduced && isa<DeducedTemplateSpecializationType>(Deduced)) { + if (ArraySize) + return ExprError(Diag(ArraySize->getExprLoc(), + diag::err_deduced_class_template_compound_type) + << /*array*/ 2 << ArraySize->getSourceRange()); + InitializedEntity Entity + = InitializedEntity::InitializeNew(StartLoc, AllocType); + AllocType = DeduceTemplateSpecializationFromInitializer( + AllocTypeInfo, Entity, Kind, MultiExprArg(Inits, NumInits)); + if (AllocType.isNull()) + return ExprError(); + } else if (Deduced) { if (initStyle == CXXNewExpr::NoInit || NumInits == 0) return ExprError(Diag(StartLoc, diag::err_auto_new_requires_ctor_arg) << AllocType << TypeRange); @@ -1958,23 +1989,6 @@ Sema::BuildCXXNew(SourceRange Range, bool UseGlobal, else InitType = AllocType; - // C++11 [expr.new]p15: - // A new-expression that creates an object of type T initializes that - // object as follows: - InitializationKind Kind - // - If the new-initializer is omitted, the object is default- - // initialized (8.5); if no initialization is performed, - // the object has indeterminate value - = initStyle == CXXNewExpr::NoInit - ? InitializationKind::CreateDefault(TypeRange.getBegin()) - // - Otherwise, the new-initializer is interpreted according to the - // initialization rules of 8.5 for direct-initialization. - : initStyle == CXXNewExpr::ListInit - ? InitializationKind::CreateDirectList(TypeRange.getBegin()) - : InitializationKind::CreateDirect(TypeRange.getBegin(), - DirectInitRange.getBegin(), - DirectInitRange.getEnd()); - InitializedEntity Entity = InitializedEntity::InitializeNew(StartLoc, InitType); InitializationSequence InitSeq(*this, Entity, Kind, diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp index 8a70d50a78c..23ea650dd30 100644 --- a/clang/lib/Sema/SemaInit.cpp +++ b/clang/lib/Sema/SemaInit.cpp @@ -5914,7 +5914,8 @@ PerformConstructorInitialization(Sema &S, S.MarkFunctionReferenced(Loc, Constructor); CurInit = new (S.Context) CXXTemporaryObjectExpr( - S.Context, Constructor, TSInfo, + S.Context, Constructor, + Entity.getType().getNonLValueExprType(S.Context), TSInfo, ConstructorArgs, ParenOrBraceRange, HadMultipleCandidates, IsListInitialization, IsStdInitListInitialization, ConstructorInitRequiresZeroInit); @@ -6982,7 +6983,7 @@ InitializationSequence::Perform(Sema &S, Kind.getRange().getBegin()); CurInit = new (S.Context) CXXScalarValueInitExpr( - TSInfo->getType().getNonLValueExprType(S.Context), TSInfo, + Entity.getType().getNonLValueExprType(S.Context), TSInfo, Kind.getRange().getEnd()); } else { CurInit = new (S.Context) ImplicitValueInitExpr(Step->Type); @@ -7755,7 +7756,8 @@ bool InitializationSequence::Diagnose(Sema &S, (void)Ovl; assert(Ovl == OR_Success && "Inconsistent overload resolution"); CXXConstructorDecl *CtorDecl = cast<CXXConstructorDecl>(Best->Function); - S.Diag(CtorDecl->getLocation(), diag::note_constructor_declared_here); + S.Diag(CtorDecl->getLocation(), + diag::note_explicit_ctor_deduction_guide_here) << false; break; } } @@ -8219,3 +8221,215 @@ Sema::PerformCopyInitialization(const InitializedEntity &Entity, return Result; } + +QualType Sema::DeduceTemplateSpecializationFromInitializer( + TypeSourceInfo *TSInfo, const InitializedEntity &Entity, + const InitializationKind &Kind, MultiExprArg Inits) { + auto *DeducedTST = dyn_cast<DeducedTemplateSpecializationType>( + TSInfo->getType()->getContainedDeducedType()); + assert(DeducedTST && "not a deduced template specialization type"); + + // We can only perform deduction for class templates. + auto TemplateName = DeducedTST->getTemplateName(); + auto *Template = + dyn_cast_or_null<ClassTemplateDecl>(TemplateName.getAsTemplateDecl()); + if (!Template) { + Diag(Kind.getLocation(), + diag::err_deduced_non_class_template_specialization_type) + << (int)getTemplateNameKindForDiagnostics(TemplateName) << TemplateName; + if (auto *TD = TemplateName.getAsTemplateDecl()) + Diag(TD->getLocation(), diag::note_template_decl_here); + return QualType(); + } + + // FIXME: Perform "exact type" matching first, per CWG discussion? + // Or implement this via an implied 'T(T) -> T' deduction guide? + + // FIXME: Do we need/want a std::initializer_list<T> special case? + + // C++1z [over.match.class.deduct]p1: + // A set of functions and function templates is formed comprising: + bool HasDefaultConstructor = false; + SmallVector<DeclAccessPair, 16> CtorsAndGuides; + CXXRecordDecl *Primary = Template->getTemplatedDecl(); + bool Complete = isCompleteType(TSInfo->getTypeLoc().getEndLoc(), + Context.getTypeDeclType(Primary)); + if (Complete) { + for (NamedDecl *D : LookupConstructors(Template->getTemplatedDecl())) { + // - For each constructor of the class template designated by the + // template-name, a function template [...] + auto Info = getConstructorInfo(D); + if (!Info.Constructor || Info.Constructor->isInvalidDecl()) + continue; + + // FIXME: Synthesize a deduction guide. + + if (Info.Constructor->isDefaultConstructor()) + HasDefaultConstructor = true; + } + } + + // - For each deduction-guide, a function or function template [...] + DeclarationNameInfo NameInfo( + Context.DeclarationNames.getCXXDeductionGuideName(Template), + TSInfo->getTypeLoc().getEndLoc()); + LookupResult Guides(*this, NameInfo, LookupOrdinaryName); + LookupQualifiedName(Guides, Template->getDeclContext()); + for (auto I = Guides.begin(), E = Guides.end(); I != E; ++I) { + auto *FD = dyn_cast<FunctionDecl>(*I); + if (FD && FD->getMinRequiredArguments() == 0) + HasDefaultConstructor = true; + CtorsAndGuides.push_back(I.getPair()); + } + + // FIXME: Do not diagnose inaccessible deduction guides. The standard isn't + // clear on this, but they're not found by name so access does not apply. + Guides.suppressDiagnostics(); + + // Figure out if this is list-initialization. + InitListExpr *ListInit = + (Inits.size() == 1 && Kind.getKind() != InitializationKind::IK_Direct) + ? dyn_cast<InitListExpr>(Inits[0]) + : nullptr; + + // C++1z [over.match.class.deduct]p1: + // Initialization and overload resolution are performed as described in + // [dcl.init] and [over.match.ctor], [over.match.copy], or [over.match.list] + // (as appropriate for the type of initialization performed) for an object + // of a hypothetical class type, where the selected functions and function + // templates are considered to be the constructors of that class type + // + // Since we know we're initializing a class type of a type unrelated to that + // of the initializer, this reduces to something fairly reasonable. + OverloadCandidateSet Candidates(Kind.getLocation(), + OverloadCandidateSet::CSK_Normal); + OverloadCandidateSet::iterator Best; + auto tryToResolveOverload = + [&](bool OnlyListConstructors) -> OverloadingResult { + Candidates.clear(); + for (DeclAccessPair Pair : CtorsAndGuides) { + NamedDecl *D = Pair.getDecl()->getUnderlyingDecl(); + if (D->isInvalidDecl()) + continue; + + FunctionTemplateDecl *TD = dyn_cast<FunctionTemplateDecl>(D); + FunctionDecl *FD = + TD ? TD->getTemplatedDecl() : dyn_cast<FunctionDecl>(D); + if (!FD) + continue; + + // C++ [over.match.ctor]p1: (non-list copy-initialization from non-class) + // For copy-initialization, the candidate functions are all the + // converting constructors (12.3.1) of that class. + // C++ [over.match.copy]p1: (non-list copy-initialization from class) + // The converting constructors of T are candidate functions. + if (Kind.isCopyInit() && !ListInit) { + // FIXME: if (FD->isExplicit()) continue; + + // When looking for a converting constructor, deduction guides that + // could never be called with one argument are not interesting. + if (FD->getMinRequiredArguments() > 1 || + (FD->getNumParams() == 0 && !FD->isVariadic())) + continue; + } + + // C++ [over.match.list]p1.1: (first phase list initialization) + // Initially, the candidate functions are the initializer-list + // constructors of the class T + if (OnlyListConstructors && !isInitListConstructor(FD)) + continue; + + // C++ [over.match.list]p1.2: (second phase list initialization) + // the candidate functions are all the constructors of the class T + // C++ [over.match.ctor]p1: (all other cases) + // the candidate functions are all the constructors of the class of + // the object being initialized + + // C++ [over.best.ics]p4: + // When [...] the constructor [...] is a candidate by + // - [over.match.copy] (in all cases) + // FIXME: The "second phase of [over.match.list] case can also + // theoretically happen here, but it's not clear whether we can + // ever have a parameter of the right type. + bool SuppressUserConversions = Kind.isCopyInit(); + + // FIXME: These are definitely wrong in the non-deduction-guide case. + if (TD) + AddTemplateOverloadCandidate(TD, Pair, /*ExplicitArgs*/ nullptr, Inits, + Candidates, SuppressUserConversions); + else + AddOverloadCandidate(FD, Pair, Inits, Candidates, + SuppressUserConversions); + } + return Candidates.BestViableFunction(*this, Kind.getLocation(), Best); + }; + + OverloadingResult Result = OR_No_Viable_Function; + + // C++11 [over.match.list]p1, per DR1467: for list-initialization, first + // try initializer-list constructors. + if (ListInit) { + if (ListInit->getNumInits() || !HasDefaultConstructor) + Result = tryToResolveOverload(/*OnlyListConstructor*/true); + // Then unwrap the initializer list and try again considering all + // constructors. + Inits = MultiExprArg(ListInit->getInits(), ListInit->getNumInits()); + } + + // If list-initialization fails, or if we're doing any other kind of + // initialization, we (eventually) consider constructors. + if (Result == OR_No_Viable_Function) + Result = tryToResolveOverload(/*OnlyListConstructor*/false); + + switch (Result) { + case OR_Ambiguous: + Diag(Kind.getLocation(), diag::err_deduced_class_template_ctor_ambiguous) + << TemplateName; + // FIXME: For list-initialization candidates, it'd usually be better to + // list why they were not viable when given the initializer list itself as + // an argument. + Candidates.NoteCandidates(*this, OCD_ViableCandidates, Inits); + return QualType(); + + case OR_No_Viable_Function: + Diag(Kind.getLocation(), + Complete ? diag::err_deduced_class_template_ctor_no_viable + : diag::err_deduced_class_template_incomplete) + << TemplateName << !CtorsAndGuides.empty(); + Candidates.NoteCandidates(*this, OCD_AllCandidates, Inits); + return QualType(); + + case OR_Deleted: { + Diag(Kind.getLocation(), diag::err_deduced_class_template_deleted) + << TemplateName; + NoteDeletedFunction(Best->Function); + return QualType(); + } + + case OR_Success: + // C++ [over.match.list]p1: + // In copy-list-initialization, if an explicit constructor is chosen, the + // initialization is ill-formed. + if (Kind.isCopyInit() && ListInit && + false /*FIXME: Best->Function->isExplicit()*/) { + bool IsDeductionGuide = !Best->Function->isImplicit(); + Diag(Kind.getLocation(), diag::err_deduced_class_template_explicit) + << TemplateName << IsDeductionGuide; + Diag(Best->Function->getLocation(), + diag::note_explicit_ctor_deduction_guide_here) + << IsDeductionGuide; + return QualType(); + } + + // Make sure we didn't select an unusable deduction guide, and mark it + // as referenced. + DiagnoseUseOfDecl(Best->Function, Kind.getLocation()); + MarkFunctionReferenced(Kind.getLocation(), Best->Function); + break; + } + + // C++ [dcl.type.class.deduct]p1: + // The placeholder is replaced by the return type of the function selected + // by overload resolution for class template deduction. + return SubstAutoType(TSInfo->getType(), Best->Function->getReturnType()); +} diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp index 57957c0728a..571ef55e4df 100644 --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -4019,17 +4019,26 @@ Sema::TemplateDeductionResult Sema::DeduceTemplateArguments( } namespace { - /// Substitute the 'auto' type specifier within a type for a given replacement - /// type. - class SubstituteAutoTransform : - public TreeTransform<SubstituteAutoTransform> { + /// Substitute the 'auto' specifier or deduced template specialization type + /// specifier within a type for a given replacement type. + class SubstituteDeducedTypeTransform : + public TreeTransform<SubstituteDeducedTypeTransform> { QualType Replacement; - bool UseAutoSugar; + bool UseTypeSugar; public: - SubstituteAutoTransform(Sema &SemaRef, QualType Replacement, - bool UseAutoSugar = true) - : TreeTransform<SubstituteAutoTransform>(SemaRef), - Replacement(Replacement), UseAutoSugar(UseAutoSugar) {} + SubstituteDeducedTypeTransform(Sema &SemaRef, QualType Replacement, + bool UseTypeSugar = true) + : TreeTransform<SubstituteDeducedTypeTransform>(SemaRef), + Replacement(Replacement), UseTypeSugar(UseTypeSugar) {} + + QualType TransformDesugared(TypeLocBuilder &TLB, DeducedTypeLoc TL) { + assert(isa<TemplateTypeParmType>(Replacement) && + "unexpected unsugared replacement kind"); + QualType Result = Replacement; + TemplateTypeParmTypeLoc NewTL = TLB.push<TemplateTypeParmTypeLoc>(Result); + NewTL.setNameLoc(TL.getNameLoc()); + return Result; + } QualType TransformAutoType(TypeLocBuilder &TLB, AutoTypeLoc TL) { // If we're building the type pattern to deduce against, don't wrap the @@ -4039,21 +4048,29 @@ namespace { // auto &&lref = lvalue; // must transform into "rvalue reference to T" not "rvalue reference to // auto type deduced as T" in order for [temp.deduct.call]p3 to apply. - if (!UseAutoSugar) { - assert(isa<TemplateTypeParmType>(Replacement) && - "unexpected unsugared replacement kind"); - QualType Result = Replacement; - TemplateTypeParmTypeLoc NewTL = - TLB.push<TemplateTypeParmTypeLoc>(Result); - NewTL.setNameLoc(TL.getNameLoc()); - return Result; - } else { - QualType Result = SemaRef.Context.getAutoType( - Replacement, TL.getTypePtr()->getKeyword(), Replacement.isNull()); - AutoTypeLoc NewTL = TLB.push<AutoTypeLoc>(Result); - NewTL.setNameLoc(TL.getNameLoc()); - return Result; - } + // + // FIXME: Is this still necessary? + if (!UseTypeSugar) + return TransformDesugared(TLB, TL); + + QualType Result = SemaRef.Context.getAutoType( + Replacement, TL.getTypePtr()->getKeyword(), Replacement.isNull()); + auto NewTL = TLB.push<AutoTypeLoc>(Result); + NewTL.setNameLoc(TL.getNameLoc()); + return Result; + } + + QualType TransformDeducedTemplateSpecializationType( + TypeLocBuilder &TLB, DeducedTemplateSpecializationTypeLoc TL) { + if (!UseTypeSugar) + return TransformDesugared(TLB, TL); + + QualType Result = SemaRef.Context.getDeducedTemplateSpecializationType( + TL.getTypePtr()->getTemplateName(), + Replacement, Replacement.isNull()); + auto NewTL = TLB.push<DeducedTemplateSpecializationTypeLoc>(Result); + NewTL.setNameLoc(TL.getNameLoc()); + return Result; } ExprResult TransformLambdaExpr(LambdaExpr *E) { @@ -4104,7 +4121,7 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result, if (!DependentDeductionDepth && (Type.getType()->isDependentType() || Init->isTypeDependent())) { - Result = SubstituteAutoTransform(*this, QualType()).Apply(Type); + Result = SubstituteDeducedTypeTransform(*this, QualType()).Apply(Type); assert(!Result.isNull() && "substituting DependentTy can't fail"); return DAR_Succeeded; } @@ -4127,7 +4144,7 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result, return DAR_FailedAlreadyDiagnosed; // FIXME: Support a non-canonical deduced type for 'auto'. Deduced = Context.getCanonicalType(Deduced); - Result = SubstituteAutoTransform(*this, Deduced).Apply(Type); + Result = SubstituteDeducedTypeTransform(*this, Deduced).Apply(Type); if (Result.isNull()) return DAR_FailedAlreadyDiagnosed; return DAR_Succeeded; @@ -4152,7 +4169,7 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result, Loc, Loc, TemplParamPtr, Loc, nullptr); QualType FuncParam = - SubstituteAutoTransform(*this, TemplArg, /*UseAutoSugar*/false) + SubstituteDeducedTypeTransform(*this, TemplArg, /*UseTypeSugar*/false) .Apply(Type); assert(!FuncParam.isNull() && "substituting template parameter for 'auto' failed"); @@ -4167,7 +4184,7 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result, // might acquire a matching type in the instantiation. auto DeductionFailed = [&]() -> DeduceAutoResult { if (Init->isTypeDependent()) { - Result = SubstituteAutoTransform(*this, QualType()).Apply(Type); + Result = SubstituteDeducedTypeTransform(*this, QualType()).Apply(Type); assert(!Result.isNull() && "substituting DependentTy can't fail"); return DAR_Succeeded; } @@ -4215,7 +4232,7 @@ Sema::DeduceAutoType(TypeLoc Type, Expr *&Init, QualType &Result, return DAR_FailedAlreadyDiagnosed; } - Result = SubstituteAutoTransform(*this, DeducedType).Apply(Type); + Result = SubstituteDeducedTypeTransform(*this, DeducedType).Apply(Type); if (Result.isNull()) return DAR_FailedAlreadyDiagnosed; @@ -4238,22 +4255,22 @@ QualType Sema::SubstAutoType(QualType TypeWithAuto, QualType TypeToReplaceAuto) { if (TypeToReplaceAuto->isDependentType()) TypeToReplaceAuto = QualType(); - return SubstituteAutoTransform(*this, TypeToReplaceAuto) + return SubstituteDeducedTypeTransform(*this, TypeToReplaceAuto) .TransformType(TypeWithAuto); } -TypeSourceInfo* Sema::SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto, - QualType TypeToReplaceAuto) { +TypeSourceInfo *Sema::SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto, + QualType TypeToReplaceAuto) { if (TypeToReplaceAuto->isDependentType()) TypeToReplaceAuto = QualType(); - return SubstituteAutoTransform(*this, TypeToReplaceAuto) + return SubstituteDeducedTypeTransform(*this, TypeToReplaceAuto) .TransformType(TypeWithAuto); } QualType Sema::ReplaceAutoType(QualType TypeWithAuto, QualType TypeToReplaceAuto) { - return SubstituteAutoTransform(*this, TypeToReplaceAuto, - /*UseAutoSugar*/ false) + return SubstituteDeducedTypeTransform(*this, TypeToReplaceAuto, + /*UseTypeSugar*/ false) .TransformType(TypeWithAuto); } |