summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/ExprCXX.cpp10
-rw-r--r--clang/lib/Sema/SemaCast.cpp3
-rw-r--r--clang/lib/Sema/SemaDecl.cpp103
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp2
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp92
-rw-r--r--clang/lib/Sema/SemaInit.cpp220
-rw-r--r--clang/lib/Sema/SemaTemplateDeduction.cpp87
7 files changed, 387 insertions, 130 deletions
diff --git a/clang/lib/AST/ExprCXX.cpp b/clang/lib/AST/ExprCXX.cpp
index ad510e0070e..6713fca0457 100644
--- a/clang/lib/AST/ExprCXX.cpp
+++ b/clang/lib/AST/ExprCXX.cpp
@@ -734,23 +734,23 @@ CXXBindTemporaryExpr *CXXBindTemporaryExpr::Create(const ASTContext &C,
CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(const ASTContext &C,
CXXConstructorDecl *Cons,
- TypeSourceInfo *Type,
+ QualType Type,
+ TypeSourceInfo *TSI,
ArrayRef<Expr*> Args,
SourceRange ParenOrBraceRange,
bool HadMultipleCandidates,
bool ListInitialization,
bool StdInitListInitialization,
bool ZeroInitialization)
- : CXXConstructExpr(C, CXXTemporaryObjectExprClass,
- Type->getType().getNonReferenceType(),
- Type->getTypeLoc().getBeginLoc(),
+ : CXXConstructExpr(C, CXXTemporaryObjectExprClass, Type,
+ TSI->getTypeLoc().getBeginLoc(),
Cons, false, Args,
HadMultipleCandidates,
ListInitialization,
StdInitListInitialization,
ZeroInitialization,
CXXConstructExpr::CK_Complete, ParenOrBraceRange),
- Type(Type) {
+ Type(TSI) {
}
SourceLocation CXXTemporaryObjectExpr::getLocStart() const {
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);
}
OpenPOWER on IntegriCloud