Preserve the FoundDecl when performing overload resolution for constructors.

This is in preparation for C++ P0136R1, which switches the model for inheriting
constructors over from synthesizing a constructor to finding base class
constructors (via using shadow decls) when looking for derived class
constructors.

llvm-svn: 269231
This commit is contained in:
Richard Smith 2016-05-11 20:37:46 +00:00
parent 1455de2171
commit c2bebe9aca
15 changed files with 251 additions and 214 deletions

View File

@ -16,6 +16,7 @@
#define LLVM_CLANG_AST_EXPRCXX_H
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/Expr.h"
#include "clang/AST/LambdaCapture.h"
#include "clang/AST/TemplateBase.h"
@ -26,9 +27,6 @@
namespace clang {
class CXXConstructorDecl;
class CXXDestructorDecl;
class CXXMethodDecl;
class CXXTemporary;
class MSPropertyDecl;
class TemplateArgumentListInfo;
@ -1168,18 +1166,21 @@ private:
SourceLocation Loc;
SourceRange ParenOrBraceRange;
unsigned NumArgs : 16;
bool Elidable : 1;
bool HadMultipleCandidates : 1;
bool ListInitialization : 1;
bool StdInitListInitialization : 1;
bool ZeroInitialization : 1;
unsigned Elidable : 1;
unsigned HadMultipleCandidates : 1;
unsigned ListInitialization : 1;
unsigned StdInitListInitialization : 1;
unsigned ZeroInitialization : 1;
unsigned ConstructKind : 2;
Stmt **Args;
void setConstructor(CXXConstructorDecl *C) { Constructor = C; }
protected:
CXXConstructExpr(const ASTContext &C, StmtClass SC, QualType T,
SourceLocation Loc,
CXXConstructorDecl *d, bool elidable,
NamedDecl *Found, CXXConstructorDecl *Ctor,
bool Elidable,
ArrayRef<Expr *> Args,
bool HadMultipleCandidates,
bool ListInitialization,
@ -1198,15 +1199,13 @@ protected:
public:
/// \brief Construct an empty C++ construction expression.
explicit CXXConstructExpr(EmptyShell Empty)
: Expr(CXXConstructExprClass, Empty), Constructor(nullptr),
NumArgs(0), Elidable(false), HadMultipleCandidates(false),
ListInitialization(false), ZeroInitialization(false),
ConstructKind(0), Args(nullptr)
{ }
: CXXConstructExpr(CXXConstructExprClass, Empty) {}
static CXXConstructExpr *Create(const ASTContext &C, QualType T,
SourceLocation Loc,
CXXConstructorDecl *D, bool Elidable,
NamedDecl *Found,
CXXConstructorDecl *Ctor,
bool Elidable,
ArrayRef<Expr *> Args,
bool HadMultipleCandidates,
bool ListInitialization,
@ -1215,8 +1214,11 @@ public:
ConstructionKind ConstructKind,
SourceRange ParenOrBraceRange);
/// \brief Get the declaration that was found by name lookup.
NamedDecl *getFoundDecl() const;
/// \brief Get the constructor that this expression will (ultimately) call.
CXXConstructorDecl *getConstructor() const { return Constructor; }
void setConstructor(CXXConstructorDecl *C) { Constructor = C; }
SourceLocation getLocation() const { return Loc; }
void setLocation(SourceLocation Loc) { this->Loc = Loc; }
@ -1382,7 +1384,9 @@ class CXXTemporaryObjectExpr : public CXXConstructExpr {
TypeSourceInfo *Type;
public:
CXXTemporaryObjectExpr(const ASTContext &C, CXXConstructorDecl *Cons,
CXXTemporaryObjectExpr(const ASTContext &C,
NamedDecl *Found,
CXXConstructorDecl *Cons,
TypeSourceInfo *Type,
ArrayRef<Expr *> Args,
SourceRange ParenOrBraceRange,

View File

@ -199,6 +199,7 @@ namespace clang {
/// conversions are either identity conversions or derived-to-base
/// conversions.
CXXConstructorDecl *CopyConstructor;
DeclAccessPair FoundCopyConstructor;
void setFromType(QualType T) { FromTypePtr = T.getAsOpaquePtr(); }
void setToType(unsigned Idx, QualType T) {
@ -282,7 +283,7 @@ namespace clang {
/// Represents an ambiguous user-defined conversion sequence.
struct AmbiguousConversionSequence {
typedef SmallVector<FunctionDecl*, 4> ConversionSet;
typedef SmallVector<std::pair<NamedDecl*, FunctionDecl*>, 4> ConversionSet;
void *FromTypePtr;
void *ToTypePtr;
@ -305,8 +306,8 @@ namespace clang {
return *reinterpret_cast<const ConversionSet*>(Buffer);
}
void addConversion(FunctionDecl *D) {
conversions().push_back(D);
void addConversion(NamedDecl *Found, FunctionDecl *D) {
conversions().push_back(std::make_pair(Found, D));
}
typedef ConversionSet::iterator iterator;
@ -797,6 +798,29 @@ namespace clang {
const OverloadCandidate& Cand2,
SourceLocation Loc,
bool UserDefinedConversion = false);
struct ConstructorInfo {
DeclAccessPair FoundDecl;
CXXConstructorDecl *Constructor;
FunctionTemplateDecl *ConstructorTmpl;
};
// FIXME: Add an AddOverloadCandidate / AddTemplateOverloadCandidate overload
// that takes one of these.
inline ConstructorInfo getConstructorInfo(NamedDecl *ND) {
if (isa<UsingDecl>(ND))
return ConstructorInfo{};
// For constructors, the access check is performed against the underlying
// declaration, not the found declaration.
auto *D = ND->getUnderlyingDecl();
ConstructorInfo Info = {DeclAccessPair::make(ND, D->getAccess()), nullptr,
nullptr};
Info.ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D);
if (Info.ConstructorTmpl)
D = Info.ConstructorTmpl->getTemplatedDecl();
Info.Constructor = cast<CXXConstructorDecl>(D);
return Info;
}
} // end namespace clang
#endif // LLVM_CLANG_SEMA_OVERLOAD_H

View File

@ -2526,7 +2526,8 @@ public:
bool PartialOverloading = false);
// Emit as a 'note' the specific overload candidate
void NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType = QualType(),
void NoteOverloadCandidate(NamedDecl *Found, FunctionDecl *Fn,
QualType DestType = QualType(),
bool TakingAddress = false);
// Emit as a series of 'note's all template and non-templates identified by
@ -4273,6 +4274,7 @@ public:
/// \param ConstructKind - a CXXConstructExpr::ConstructionKind
ExprResult
BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
NamedDecl *FoundDecl,
CXXConstructorDecl *Constructor, MultiExprArg Exprs,
bool HadMultipleCandidates, bool IsListInitialization,
bool IsStdInitListInitialization,
@ -4283,6 +4285,7 @@ public:
// the constructor can be elidable?
ExprResult
BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
NamedDecl *FoundDecl,
CXXConstructorDecl *Constructor, bool Elidable,
MultiExprArg Exprs, bool HadMultipleCandidates,
bool IsListInitialization,

View File

@ -244,6 +244,10 @@ struct DeductionFailureInfo {
/// TODO: In the future, we may need to unify/generalize this with
/// OverloadCandidate.
struct TemplateSpecCandidate {
/// \brief The declaration that was looked up, together with its access.
/// Might be a UsingShadowDecl, but usually a FunctionTemplateDecl.
DeclAccessPair FoundDecl;
/// Specialization - The actual specialization that this candidate
/// represents. When NULL, this may be a built-in candidate.
Decl *Specialization;
@ -251,7 +255,8 @@ struct TemplateSpecCandidate {
/// Template argument deduction info
DeductionFailureInfo DeductionFailure;
void set(Decl *Spec, DeductionFailureInfo Info) {
void set(DeclAccessPair Found, Decl *Spec, DeductionFailureInfo Info) {
FoundDecl = Found;
Specialization = Spec;
DeductionFailure = Info;
}

View File

@ -5767,9 +5767,14 @@ Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) {
if (T.isNull())
return nullptr;
NamedDecl *ToFound =
dyn_cast<NamedDecl>(Importer.Import(E->getFoundDecl()));
if (!ToFound)
return nullptr;
CXXConstructorDecl *ToCCD =
dyn_cast<CXXConstructorDecl>(Importer.Import(E->getConstructor()));
if (!ToCCD && E->getConstructor())
if (!ToCCD)
return nullptr;
SmallVector<Expr *, 6> ToArgs(E->getNumArgs());
@ -5779,7 +5784,7 @@ Expr *ASTNodeImporter::VisitCXXConstructExpr(CXXConstructExpr *E) {
return CXXConstructExpr::Create(Importer.getToContext(), T,
Importer.Import(E->getLocation()),
ToCCD, E->isElidable(),
ToFound, ToCCD, E->isElidable(),
ToArgs, E->hadMultipleCandidates(),
E->isListInitialization(),
E->isStdInitListInitialization(),

View File

@ -432,6 +432,12 @@ SourceLocation CXXConstructExpr::getLocEnd() const {
return End;
}
NamedDecl *CXXConstructExpr::getFoundDecl() const {
if (auto *Template = Constructor->getPrimaryTemplate())
return Template;
return Constructor;
}
SourceRange CXXOperatorCallExpr::getSourceRangeImpl() const {
OverloadedOperatorKind Kind = getOperator();
if (Kind == OO_PlusPlus || Kind == OO_MinusMinus) {
@ -717,6 +723,7 @@ CXXBindTemporaryExpr *CXXBindTemporaryExpr::Create(const ASTContext &C,
}
CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(const ASTContext &C,
NamedDecl *Found,
CXXConstructorDecl *Cons,
TypeSourceInfo *Type,
ArrayRef<Expr*> Args,
@ -728,7 +735,7 @@ CXXTemporaryObjectExpr::CXXTemporaryObjectExpr(const ASTContext &C,
: CXXConstructExpr(C, CXXTemporaryObjectExprClass,
Type->getType().getNonReferenceType(),
Type->getTypeLoc().getBeginLoc(),
Cons, false, Args,
Found, Cons, false, Args,
HadMultipleCandidates,
ListInitialization,
StdInitListInitialization,
@ -750,7 +757,9 @@ SourceLocation CXXTemporaryObjectExpr::getLocEnd() const {
CXXConstructExpr *CXXConstructExpr::Create(const ASTContext &C, QualType T,
SourceLocation Loc,
CXXConstructorDecl *D, bool Elidable,
NamedDecl *Found,
CXXConstructorDecl *Ctor,
bool Elidable,
ArrayRef<Expr*> Args,
bool HadMultipleCandidates,
bool ListInitialization,
@ -758,8 +767,8 @@ CXXConstructExpr *CXXConstructExpr::Create(const ASTContext &C, QualType T,
bool ZeroInitialization,
ConstructionKind ConstructKind,
SourceRange ParenOrBraceRange) {
return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, Loc, D,
Elidable, Args,
return new (C) CXXConstructExpr(C, CXXConstructExprClass, T, Loc,
Found, Ctor, Elidable, Args,
HadMultipleCandidates, ListInitialization,
StdInitListInitialization,
ZeroInitialization, ConstructKind,
@ -768,8 +777,9 @@ CXXConstructExpr *CXXConstructExpr::Create(const ASTContext &C, QualType T,
CXXConstructExpr::CXXConstructExpr(const ASTContext &C, StmtClass SC,
QualType T, SourceLocation Loc,
CXXConstructorDecl *D, bool elidable,
ArrayRef<Expr*> args,
NamedDecl *Found, CXXConstructorDecl *Ctor,
bool Elidable,
ArrayRef<Expr*> Args,
bool HadMultipleCandidates,
bool ListInitialization,
bool StdInitListInitialization,
@ -780,28 +790,30 @@ CXXConstructExpr::CXXConstructExpr(const ASTContext &C, StmtClass SC,
T->isDependentType(), T->isDependentType(),
T->isInstantiationDependentType(),
T->containsUnexpandedParameterPack()),
Constructor(D), Loc(Loc), ParenOrBraceRange(ParenOrBraceRange),
NumArgs(args.size()),
Elidable(elidable), HadMultipleCandidates(HadMultipleCandidates),
Constructor(Ctor), Loc(Loc), ParenOrBraceRange(ParenOrBraceRange),
NumArgs(Args.size()),
Elidable(Elidable), HadMultipleCandidates(HadMultipleCandidates),
ListInitialization(ListInitialization),
StdInitListInitialization(StdInitListInitialization),
ZeroInitialization(ZeroInitialization),
ConstructKind(ConstructKind), Args(nullptr)
{
assert(declaresSameEntity(Found, Ctor) ||
declaresSameEntity(Found, Ctor->getPrimaryTemplate()));
if (NumArgs) {
Args = new (C) Stmt*[args.size()];
this->Args = new (C) Stmt*[Args.size()];
for (unsigned i = 0; i != args.size(); ++i) {
assert(args[i] && "NULL argument in CXXConstructExpr");
for (unsigned i = 0; i != Args.size(); ++i) {
assert(Args[i] && "NULL argument in CXXConstructExpr");
if (args[i]->isValueDependent())
if (Args[i]->isValueDependent())
ExprBits.ValueDependent = true;
if (args[i]->isInstantiationDependent())
if (Args[i]->isInstantiationDependent())
ExprBits.InstantiationDependent = true;
if (args[i]->containsUnexpandedParameterPack())
if (Args[i]->containsUnexpandedParameterPack())
ExprBits.ContainsUnexpandedParameterPack = true;
Args[i] = args[i];
this->Args[i] = Args[i];
}
}
}

View File

@ -3305,6 +3305,7 @@ CodeGenFunction::GenerateObjCAtomicGetterCopyHelperFunction(
CXXConstructExpr *TheCXXConstructExpr =
CXXConstructExpr::Create(C, Ty, SourceLocation(),
CXXConstExpr->getFoundDecl(),
CXXConstExpr->getConstructor(),
CXXConstExpr->isElidable(),
ConstructorArgs,

View File

@ -11369,6 +11369,7 @@ static bool hasOneRealArgument(MultiExprArg Args) {
ExprResult
Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
NamedDecl *FoundDecl,
CXXConstructorDecl *Constructor,
MultiExprArg ExprArgs,
bool HadMultipleCandidates,
@ -11395,7 +11396,8 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
Elidable = SubExpr->isTemporaryObject(Context, Constructor->getParent());
}
return BuildCXXConstructExpr(ConstructLoc, DeclInitType, Constructor,
return BuildCXXConstructExpr(ConstructLoc, DeclInitType,
FoundDecl, Constructor,
Elidable, ExprArgs, HadMultipleCandidates,
IsListInitialization,
IsStdInitListInitialization, RequiresZeroInit,
@ -11406,7 +11408,9 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
/// including handling of its default argument expressions.
ExprResult
Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
CXXConstructorDecl *Constructor, bool Elidable,
NamedDecl *FoundDecl,
CXXConstructorDecl *Constructor,
bool Elidable,
MultiExprArg ExprArgs,
bool HadMultipleCandidates,
bool IsListInitialization,
@ -11416,9 +11420,9 @@ Sema::BuildCXXConstructExpr(SourceLocation ConstructLoc, QualType DeclInitType,
SourceRange ParenRange) {
MarkFunctionReferenced(ConstructLoc, Constructor);
return CXXConstructExpr::Create(
Context, DeclInitType, ConstructLoc, Constructor, Elidable, ExprArgs,
HadMultipleCandidates, IsListInitialization, IsStdInitListInitialization,
RequiresZeroInit,
Context, DeclInitType, ConstructLoc, FoundDecl, Constructor, Elidable,
ExprArgs, HadMultipleCandidates, IsListInitialization,
IsStdInitListInitialization, RequiresZeroInit,
static_cast<CXXConstructExpr::ConstructionKind>(ConstructKind),
ParenRange);
}

View File

@ -3077,7 +3077,7 @@ static ExprResult BuildCXXCastArgument(Sema &S,
return ExprError();
ExprResult Result = S.BuildCXXConstructExpr(
CastLoc, Ty, cast<CXXConstructorDecl>(Method),
CastLoc, Ty, FoundDecl, cast<CXXConstructorDecl>(Method),
ConstructorArgs, HadMultipleCandidates,
/*ListInit*/ false, /*StdInitListInit*/ false, /*ZeroInit*/ false,
CXXConstructExpr::CK_Complete, SourceRange());
@ -3228,13 +3228,15 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
ConstructorArgs))
return ExprError();
return BuildCXXConstructExpr(
/*FIXME:ConstructLoc*/ SourceLocation(), ToType, SCS.CopyConstructor,
/*FIXME:ConstructLoc*/ SourceLocation(), ToType,
SCS.FoundCopyConstructor, SCS.CopyConstructor,
ConstructorArgs, /*HadMultipleCandidates*/ false,
/*ListInit*/ false, /*StdInitListInit*/ false, /*ZeroInit*/ false,
CXXConstructExpr::CK_Complete, SourceRange());
}
return BuildCXXConstructExpr(
/*FIXME:ConstructLoc*/ SourceLocation(), ToType, SCS.CopyConstructor,
/*FIXME:ConstructLoc*/ SourceLocation(), ToType,
SCS.FoundCopyConstructor, SCS.CopyConstructor,
From, /*HadMultipleCandidates*/ false,
/*ListInit*/ false, /*StdInitListInit*/ false, /*ZeroInit*/ false,
CXXConstructExpr::CK_Complete, SourceRange());

View File

@ -3449,18 +3449,13 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
CandidateSet.clear();
for (NamedDecl *D : Ctors) {
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
auto Info = getConstructorInfo(D);
if (!Info.Constructor)
continue;
bool SuppressUserConversions = false;
// Find the constructor (which may be a template).
CXXConstructorDecl *Constructor = nullptr;
FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D);
if (ConstructorTmpl)
Constructor = cast<CXXConstructorDecl>(
ConstructorTmpl->getTemplatedDecl());
else {
Constructor = cast<CXXConstructorDecl>(D);
if (!Info.ConstructorTmpl) {
// C++11 [over.best.ics]p4:
// ... and the constructor or user-defined conversion function is a
// candidate by
@ -3477,15 +3472,15 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
// parameter of a constructor of X.
if ((CopyInitializing ||
(IsListInit && Args.size() == 1 && isa<InitListExpr>(Args[0]))) &&
Constructor->isCopyOrMoveConstructor())
Info.Constructor->isCopyOrMoveConstructor())
SuppressUserConversions = true;
}
if (!Constructor->isInvalidDecl() &&
(AllowExplicit || !Constructor->isExplicit()) &&
(!OnlyListConstructors || S.isInitListConstructor(Constructor))) {
if (ConstructorTmpl)
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
if (!Info.Constructor->isInvalidDecl() &&
(AllowExplicit || !Info.Constructor->isExplicit()) &&
(!OnlyListConstructors || S.isInitListConstructor(Info.Constructor))) {
if (Info.ConstructorTmpl)
S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl,
/*ExplicitArgs*/ nullptr, Args,
CandidateSet, SuppressUserConversions);
else {
@ -3497,9 +3492,9 @@ ResolveConstructorOverload(Sema &S, SourceLocation DeclLoc,
// are also considered.
bool AllowExplicitConv = AllowExplicit && !CopyInitializing &&
Args.size() == 1 &&
Constructor->isCopyOrMoveConstructor();
S.AddOverloadCandidate(Constructor, FoundDecl, Args, CandidateSet,
SuppressUserConversions,
Info.Constructor->isCopyOrMoveConstructor();
S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, Args,
CandidateSet, SuppressUserConversions,
/*PartialOverloading=*/false,
/*AllowExplicit=*/AllowExplicitConv);
}
@ -3991,26 +3986,19 @@ static OverloadingResult TryRefInitWithConversionFunction(Sema &S,
CXXRecordDecl *T1RecordDecl = cast<CXXRecordDecl>(T1RecordType->getDecl());
for (NamedDecl *D : S.LookupConstructors(T1RecordDecl)) {
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
auto Info = getConstructorInfo(D);
if (!Info.Constructor)
continue;
// Find the constructor (which may be a template).
CXXConstructorDecl *Constructor = nullptr;
FunctionTemplateDecl *ConstructorTmpl = dyn_cast<FunctionTemplateDecl>(D);
if (ConstructorTmpl)
Constructor = cast<CXXConstructorDecl>(
ConstructorTmpl->getTemplatedDecl());
else
Constructor = cast<CXXConstructorDecl>(D);
if (!Constructor->isInvalidDecl() &&
Constructor->isConvertingConstructor(AllowExplicit)) {
if (ConstructorTmpl)
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
if (!Info.Constructor->isInvalidDecl() &&
Info.Constructor->isConvertingConstructor(AllowExplicit)) {
if (Info.ConstructorTmpl)
S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl,
/*ExplicitArgs*/ nullptr,
Initializer, CandidateSet,
/*SuppressUserConversions=*/true);
else
S.AddOverloadCandidate(Constructor, FoundDecl,
S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl,
Initializer, CandidateSet,
/*SuppressUserConversions=*/true);
}
@ -4614,27 +4602,19 @@ static void TryUserDefinedConversion(Sema &S,
Con = CopyOfCon.begin(), ConEnd = CopyOfCon.end();
Con != ConEnd; ++Con) {
NamedDecl *D = *Con;
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
auto Info = getConstructorInfo(D);
if (!Info.Constructor)
continue;
// Find the constructor (which may be a template).
CXXConstructorDecl *Constructor = nullptr;
FunctionTemplateDecl *ConstructorTmpl
= dyn_cast<FunctionTemplateDecl>(D);
if (ConstructorTmpl)
Constructor = cast<CXXConstructorDecl>(
ConstructorTmpl->getTemplatedDecl());
else
Constructor = cast<CXXConstructorDecl>(D);
if (!Constructor->isInvalidDecl() &&
Constructor->isConvertingConstructor(AllowExplicit)) {
if (ConstructorTmpl)
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
if (!Info.Constructor->isInvalidDecl() &&
Info.Constructor->isConvertingConstructor(AllowExplicit)) {
if (Info.ConstructorTmpl)
S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl,
/*ExplicitArgs*/ nullptr,
Initializer, CandidateSet,
/*SuppressUserConversions=*/true);
else
S.AddOverloadCandidate(Constructor, FoundDecl,
S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl,
Initializer, CandidateSet,
/*SuppressUserConversions=*/true);
}
@ -5378,38 +5358,33 @@ static void LookupCopyAndMoveConstructors(Sema &S,
for (SmallVectorImpl<NamedDecl *>::iterator
CI = Ctors.begin(), CE = Ctors.end(); CI != CE; ++CI) {
NamedDecl *D = *CI;
CXXConstructorDecl *Constructor = nullptr;
auto Info = getConstructorInfo(D);
if (!Info.Constructor)
continue;
if ((Constructor = dyn_cast<CXXConstructorDecl>(D))) {
// Handle copy/moveconstructors, only.
if (!Constructor || Constructor->isInvalidDecl() ||
!Constructor->isCopyOrMoveConstructor() ||
!Constructor->isConvertingConstructor(/*AllowExplicit=*/true))
if (!Info.ConstructorTmpl) {
// Handle copy/move constructors, only.
if (Info.Constructor->isInvalidDecl() ||
!Info.Constructor->isCopyOrMoveConstructor() ||
!Info.Constructor->isConvertingConstructor(/*AllowExplicit=*/true))
continue;
DeclAccessPair FoundDecl
= DeclAccessPair::make(Constructor, Constructor->getAccess());
S.AddOverloadCandidate(Constructor, FoundDecl,
S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl,
CurInitExpr, CandidateSet);
continue;
}
// Handle constructor templates.
FunctionTemplateDecl *ConstructorTmpl = cast<FunctionTemplateDecl>(D);
if (ConstructorTmpl->isInvalidDecl())
if (Info.ConstructorTmpl->isInvalidDecl())
continue;
Constructor = cast<CXXConstructorDecl>(
ConstructorTmpl->getTemplatedDecl());
if (!Constructor->isConvertingConstructor(/*AllowExplicit=*/true))
if (!Info.Constructor->isConvertingConstructor(/*AllowExplicit=*/true))
continue;
// FIXME: Do we need to limit this to copy-constructor-like
// candidates?
DeclAccessPair FoundDecl
= DeclAccessPair::make(ConstructorTmpl, ConstructorTmpl->getAccess());
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl, nullptr,
CurInitExpr, CandidateSet, true);
S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl,
nullptr, CurInitExpr, CandidateSet, true);
}
}
@ -5584,7 +5559,8 @@ static ExprResult CopyObject(Sema &S,
return ExprError();
// Actually perform the constructor call.
CurInit = S.BuildCXXConstructExpr(Loc, T, Constructor, Elidable,
CurInit = S.BuildCXXConstructExpr(Loc, T, Best->FoundDecl, Constructor,
Elidable,
ConstructorArgs,
HadMultipleCandidates,
/*ListInit*/ false,
@ -5770,9 +5746,10 @@ PerformConstructorInitialization(Sema &S,
: Kind.getParenRange();
CurInit = new (S.Context) CXXTemporaryObjectExpr(
S.Context, Constructor, TSInfo, ConstructorArgs, ParenOrBraceRange,
HadMultipleCandidates, IsListInitialization,
IsStdInitListInitialization, ConstructorInitRequiresZeroInit);
S.Context, Step.Function.FoundDecl, Constructor, TSInfo,
ConstructorArgs, ParenOrBraceRange, HadMultipleCandidates,
IsListInitialization, IsStdInitListInitialization,
ConstructorInitRequiresZeroInit);
} else {
CXXConstructExpr::ConstructionKind ConstructKind =
CXXConstructExpr::CK_Complete;
@ -5797,6 +5774,7 @@ PerformConstructorInitialization(Sema &S,
// unconditionally.
if (Entity.allowsNRVO())
CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
Step.Function.FoundDecl,
Constructor, /*Elidable=*/true,
ConstructorArgs,
HadMultipleCandidates,
@ -5807,6 +5785,7 @@ PerformConstructorInitialization(Sema &S,
ParenOrBraceRange);
else
CurInit = S.BuildCXXConstructExpr(Loc, Entity.getType(),
Step.Function.FoundDecl,
Constructor,
ConstructorArgs,
HadMultipleCandidates,
@ -6511,7 +6490,8 @@ InitializationSequence::Perform(Sema &S,
return ExprError();
// Build an expression that constructs a temporary.
CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor,
CurInit = S.BuildCXXConstructExpr(Loc, Step->Type,
FoundFn, Constructor,
ConstructorArgs,
HadMultipleCandidates,
/*ListInit*/ false,

View File

@ -3196,7 +3196,7 @@ Sema::LookupLiteralOperator(Scope *S, LookupResult &R,
if (FoundRaw && FoundTemplate) {
Diag(R.getNameLoc(), diag::err_ovl_ambiguous_call) << R.getLookupName();
for (LookupResult::iterator I = R.begin(), E = R.end(); I != E; ++I)
NoteOverloadCandidate((*I)->getUnderlyingDecl()->getAsFunction());
NoteOverloadCandidate(*I, (*I)->getUnderlyingDecl()->getAsFunction());
return LOLR_Error;
}

View File

@ -1218,11 +1218,13 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
S.IsDerivedFrom(From->getLocStart(), FromCanon, ToCanon))) {
// Turn this into a "standard" conversion sequence, so that it
// gets ranked with standard conversion sequences.
DeclAccessPair Found = ICS.UserDefined.FoundConversionFunction;
ICS.setStandard();
ICS.Standard.setAsIdentityConversion();
ICS.Standard.setFromType(From->getType());
ICS.Standard.setAllToTypes(ToType);
ICS.Standard.CopyConstructor = Constructor;
ICS.Standard.FoundCopyConstructor = Found;
if (ToCanon != FromCanon)
ICS.Standard.Second = ICK_Derived_To_Base;
}
@ -1236,7 +1238,7 @@ TryUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
for (OverloadCandidateSet::iterator Cand = Conversions.begin();
Cand != Conversions.end(); ++Cand)
if (Cand->Viable)
ICS.Ambiguous.addConversion(Cand->Function);
ICS.Ambiguous.addConversion(Cand->FoundDecl, Cand->Function);
break;
// Fall through.
@ -3051,39 +3053,26 @@ IsInitializerListConstructorConversion(Sema &S, Expr *From, QualType ToType,
UserDefinedConversionSequence &User,
OverloadCandidateSet &CandidateSet,
bool AllowExplicit) {
DeclContext::lookup_result R = S.LookupConstructors(To);
for (DeclContext::lookup_iterator Con = R.begin(), ConEnd = R.end();
Con != ConEnd; ++Con) {
NamedDecl *D = *Con;
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
for (auto *D : S.LookupConstructors(To)) {
auto Info = getConstructorInfo(D);
if (!Info.Constructor)
continue;
// Find the constructor (which may be a template).
CXXConstructorDecl *Constructor = nullptr;
FunctionTemplateDecl *ConstructorTmpl
= dyn_cast<FunctionTemplateDecl>(D);
if (ConstructorTmpl)
Constructor
= cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl());
else
Constructor = cast<CXXConstructorDecl>(D);
bool Usable = !Constructor->isInvalidDecl() &&
S.isInitListConstructor(Constructor) &&
(AllowExplicit || !Constructor->isExplicit());
bool Usable = !Info.Constructor->isInvalidDecl() &&
S.isInitListConstructor(Info.Constructor) &&
(AllowExplicit || !Info.Constructor->isExplicit());
if (Usable) {
// If the first argument is (a reference to) the target type,
// suppress conversions.
bool SuppressUserConversions =
isFirstArgumentCompatibleWithType(S.Context, Constructor, ToType);
if (ConstructorTmpl)
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
/*ExplicitArgs*/ nullptr,
From, CandidateSet,
SuppressUserConversions);
bool SuppressUserConversions = isFirstArgumentCompatibleWithType(
S.Context, Info.Constructor, ToType);
if (Info.ConstructorTmpl)
S.AddTemplateOverloadCandidate(Info.ConstructorTmpl, Info.FoundDecl,
/*ExplicitArgs*/ nullptr, From,
CandidateSet, SuppressUserConversions);
else
S.AddOverloadCandidate(Constructor, FoundDecl,
From, CandidateSet,
SuppressUserConversions);
S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl, From,
CandidateSet, SuppressUserConversions);
}
}
@ -3183,27 +3172,17 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
ListInitializing = true;
}
DeclContext::lookup_result R = S.LookupConstructors(ToRecordDecl);
for (DeclContext::lookup_iterator Con = R.begin(), ConEnd = R.end();
Con != ConEnd; ++Con) {
NamedDecl *D = *Con;
DeclAccessPair FoundDecl = DeclAccessPair::make(D, D->getAccess());
for (auto *D : S.LookupConstructors(ToRecordDecl)) {
auto Info = getConstructorInfo(D);
if (!Info.Constructor)
continue;
// Find the constructor (which may be a template).
CXXConstructorDecl *Constructor = nullptr;
FunctionTemplateDecl *ConstructorTmpl
= dyn_cast<FunctionTemplateDecl>(D);
if (ConstructorTmpl)
Constructor
= cast<CXXConstructorDecl>(ConstructorTmpl->getTemplatedDecl());
else
Constructor = cast<CXXConstructorDecl>(D);
bool Usable = !Constructor->isInvalidDecl();
bool Usable = !Info.Constructor->isInvalidDecl();
if (ListInitializing)
Usable = Usable && (AllowExplicit || !Constructor->isExplicit());
Usable = Usable && (AllowExplicit || !Info.Constructor->isExplicit());
else
Usable = Usable &&Constructor->isConvertingConstructor(AllowExplicit);
Usable = Usable &&
Info.Constructor->isConvertingConstructor(AllowExplicit);
if (Usable) {
bool SuppressUserConversions = !ConstructorsOnly;
if (SuppressUserConversions && ListInitializing) {
@ -3212,18 +3191,18 @@ IsUserDefinedConversion(Sema &S, Expr *From, QualType ToType,
// If the first argument is (a reference to) the target type,
// suppress conversions.
SuppressUserConversions = isFirstArgumentCompatibleWithType(
S.Context, Constructor, ToType);
S.Context, Info.Constructor, ToType);
}
}
if (ConstructorTmpl)
S.AddTemplateOverloadCandidate(ConstructorTmpl, FoundDecl,
/*ExplicitArgs*/ nullptr,
llvm::makeArrayRef(Args, NumArgs),
CandidateSet, SuppressUserConversions);
if (Info.ConstructorTmpl)
S.AddTemplateOverloadCandidate(
Info.ConstructorTmpl, Info.FoundDecl,
/*ExplicitArgs*/ nullptr, llvm::makeArrayRef(Args, NumArgs),
CandidateSet, SuppressUserConversions);
else
// Allow one user-defined conversion when user specifies a
// From->ToType conversion via an static cast (c-style, etc).
S.AddOverloadCandidate(Constructor, FoundDecl,
S.AddOverloadCandidate(Info.Constructor, Info.FoundDecl,
llvm::makeArrayRef(Args, NumArgs),
CandidateSet, SuppressUserConversions);
}
@ -4288,7 +4267,7 @@ FindConversionForRefInit(Sema &S, ImplicitConversionSequence &ICS,
for (OverloadCandidateSet::iterator Cand = CandidateSet.begin();
Cand != CandidateSet.end(); ++Cand)
if (Cand->Viable)
ICS.Ambiguous.addConversion(Cand->Function);
ICS.Ambiguous.addConversion(Cand->FoundDecl, Cand->Function);
return true;
case OR_No_Viable_Function:
@ -8862,6 +8841,7 @@ enum OverloadCandidateKind {
};
OverloadCandidateKind ClassifyOverloadCandidate(Sema &S,
NamedDecl *Found,
FunctionDecl *Fn,
std::string &Description) {
bool isTemplate = false;
@ -8990,13 +8970,13 @@ bool Sema::checkAddressOfFunctionIsAvailable(const FunctionDecl *Function,
}
// Notes the location of an overload candidate.
void Sema::NoteOverloadCandidate(FunctionDecl *Fn, QualType DestType,
bool TakingAddress) {
void Sema::NoteOverloadCandidate(NamedDecl *Found, FunctionDecl *Fn,
QualType DestType, bool TakingAddress) {
if (TakingAddress && !checkAddressOfCandidateIsAvailable(*this, Fn))
return;
std::string FnDesc;
OverloadCandidateKind K = ClassifyOverloadCandidate(*this, Fn, FnDesc);
OverloadCandidateKind K = ClassifyOverloadCandidate(*this, Found, Fn, FnDesc);
PartialDiagnostic PD = PDiag(diag::note_ovl_candidate)
<< (unsigned) K << FnDesc;
@ -9019,11 +8999,11 @@ void Sema::NoteAllOverloadCandidates(Expr *OverloadedExpr, QualType DestType,
I != IEnd; ++I) {
if (FunctionTemplateDecl *FunTmpl =
dyn_cast<FunctionTemplateDecl>((*I)->getUnderlyingDecl()) ) {
NoteOverloadCandidate(FunTmpl->getTemplatedDecl(), DestType,
NoteOverloadCandidate(*I, FunTmpl->getTemplatedDecl(), DestType,
TakingAddress);
} else if (FunctionDecl *Fun
= dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl()) ) {
NoteOverloadCandidate(Fun, DestType, TakingAddress);
NoteOverloadCandidate(*I, Fun, DestType, TakingAddress);
}
}
}
@ -9047,7 +9027,7 @@ void ImplicitConversionSequence::DiagnoseAmbiguousConversion(
if (CandsShown >= 4 && ShowOverloads == Ovl_Best)
break;
++CandsShown;
S.NoteOverloadCandidate(*I);
S.NoteOverloadCandidate(I->first, I->second);
}
if (I != E)
S.Diag(SourceLocation(), diag::note_ovl_too_many_candidates) << int(E - I);
@ -9072,7 +9052,8 @@ static void DiagnoseBadConversion(Sema &S, OverloadCandidate *Cand,
}
std::string FnDesc;
OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, FnDesc);
OverloadCandidateKind FnKind =
ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn, FnDesc);
Expr *FromExpr = Conv.Bad.FromExpr;
QualType FromTy = Conv.Bad.getFromType();
@ -9318,7 +9299,8 @@ static bool CheckArityMismatch(Sema &S, OverloadCandidate *Cand,
}
/// General arity mismatch diagnosis over a candidate in a candidate set.
static void DiagnoseArityMismatch(Sema &S, Decl *D, unsigned NumFormalArgs) {
static void DiagnoseArityMismatch(Sema &S, NamedDecl *Found, Decl *D,
unsigned NumFormalArgs) {
assert(isa<FunctionDecl>(D) &&
"The templated declaration should at least be a function"
" when diagnosing bad template argument deduction due to too many"
@ -9348,7 +9330,8 @@ static void DiagnoseArityMismatch(Sema &S, Decl *D, unsigned NumFormalArgs) {
}
std::string Description;
OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, Description);
OverloadCandidateKind FnKind =
ClassifyOverloadCandidate(S, Found, Fn, Description);
if (modeCount == 1 && Fn->getParamDecl(0)->getDeclName())
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_arity_one)
@ -9365,7 +9348,7 @@ static void DiagnoseArityMismatch(Sema &S, Decl *D, unsigned NumFormalArgs) {
static void DiagnoseArityMismatch(Sema &S, OverloadCandidate *Cand,
unsigned NumFormalArgs) {
if (!CheckArityMismatch(S, Cand, NumFormalArgs))
DiagnoseArityMismatch(S, Cand->Function, NumFormalArgs);
DiagnoseArityMismatch(S, Cand->FoundDecl, Cand->Function, NumFormalArgs);
}
static TemplateDecl *getDescribedTemplate(Decl *Templated) {
@ -9376,7 +9359,7 @@ static TemplateDecl *getDescribedTemplate(Decl *Templated) {
}
/// Diagnose a failed template-argument deduction.
static void DiagnoseBadDeduction(Sema &S, Decl *Templated,
static void DiagnoseBadDeduction(Sema &S, NamedDecl *Found, Decl *Templated,
DeductionFailureInfo &DeductionFailure,
unsigned NumArgs,
bool TakingCandidateAddress) {
@ -9466,7 +9449,7 @@ static void DiagnoseBadDeduction(Sema &S, Decl *Templated,
case Sema::TDK_TooManyArguments:
case Sema::TDK_TooFewArguments:
DiagnoseArityMismatch(S, Templated, NumArgs);
DiagnoseArityMismatch(S, Found, Templated, NumArgs);
return;
case Sema::TDK_InstantiationDepth:
@ -9596,7 +9579,7 @@ static void DiagnoseBadDeduction(Sema &S, OverloadCandidate *Cand,
if (CheckArityMismatch(S, Cand, NumArgs))
return;
}
DiagnoseBadDeduction(S, Cand->Function, // pattern
DiagnoseBadDeduction(S, Cand->FoundDecl, Cand->Function, // pattern
Cand->DeductionFailure, NumArgs, TakingCandidateAddress);
}
@ -9609,7 +9592,8 @@ static void DiagnoseBadTarget(Sema &S, OverloadCandidate *Cand) {
CalleeTarget = S.IdentifyCUDATarget(Callee);
std::string FnDesc;
OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Callee, FnDesc);
OverloadCandidateKind FnKind =
ClassifyOverloadCandidate(S, Cand->FoundDecl, Callee, FnDesc);
S.Diag(Callee->getLocation(), diag::note_ovl_candidate_bad_target)
<< (unsigned)FnKind << CalleeTarget << CallerTarget;
@ -9686,7 +9670,8 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
if (Cand->Viable && (Fn->isDeleted() ||
S.isFunctionConsideredUnavailable(Fn))) {
std::string FnDesc;
OverloadCandidateKind FnKind = ClassifyOverloadCandidate(S, Fn, FnDesc);
OverloadCandidateKind FnKind =
ClassifyOverloadCandidate(S, Cand->FoundDecl, Fn, FnDesc);
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_deleted)
<< FnKind << FnDesc
@ -9697,7 +9682,7 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
// We don't really have anything else to say about viable candidates.
if (Cand->Viable) {
S.NoteOverloadCandidate(Fn);
S.NoteOverloadCandidate(Cand->FoundDecl, Fn);
return;
}
@ -9707,7 +9692,8 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
return DiagnoseArityMismatch(S, Cand, NumArgs);
case ovl_fail_bad_deduction:
return DiagnoseBadDeduction(S, Cand, NumArgs, TakingCandidateAddress);
return DiagnoseBadDeduction(S, Cand, NumArgs,
TakingCandidateAddress);
case ovl_fail_illegal_constructor: {
S.Diag(Fn->getLocation(), diag::note_ovl_candidate_illegal_constructor)
@ -9719,7 +9705,7 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
case ovl_fail_trivial_conversion:
case ovl_fail_bad_final_conversion:
case ovl_fail_final_conversion_not_exact:
return S.NoteOverloadCandidate(Fn);
return S.NoteOverloadCandidate(Cand->FoundDecl, Fn);
case ovl_fail_bad_conversion: {
unsigned I = (Cand->IgnoreObjectArgument ? 1 : 0);
@ -9730,7 +9716,7 @@ static void NoteFunctionCandidate(Sema &S, OverloadCandidate *Cand,
// FIXME: this currently happens when we're called from SemaInit
// when user-conversion overload fails. Figure out how to handle
// those conditions and diagnose them well.
return S.NoteOverloadCandidate(Fn);
return S.NoteOverloadCandidate(Cand->FoundDecl, Fn);
}
case ovl_fail_bad_target:
@ -9808,8 +9794,8 @@ static void NoteAmbiguousUserConversions(Sema &S, SourceLocation OpLoc,
if (ICS.isBad()) break; // all meaningless after first invalid
if (!ICS.isAmbiguous()) continue;
ICS.DiagnoseAmbiguousConversion(S, OpLoc,
S.PDiag(diag::note_ambiguous_type_conversion));
ICS.DiagnoseAmbiguousConversion(
S, OpLoc, S.PDiag(diag::note_ambiguous_type_conversion));
}
}
@ -10176,7 +10162,7 @@ struct CompareTemplateSpecCandidatesForDisplay {
/// deductions.
void TemplateSpecCandidate::NoteDeductionFailure(Sema &S,
bool ForTakingAddress) {
DiagnoseBadDeduction(S, Specialization, // pattern
DiagnoseBadDeduction(S, FoundDecl, Specialization, // pattern
DeductionFailure, /*NumArgs=*/0, ForTakingAddress);
}
@ -10429,7 +10415,7 @@ private:
Info, /*InOverloadResolution=*/true)) {
// Make a note of the failed deduction for diagnostics.
FailedCandidates.addCandidate()
.set(FunctionTemplate->getTemplatedDecl(),
.set(CurAccessFunPair, FunctionTemplate->getTemplatedDecl(),
MakeDeductionFailureInfo(Context, Result, Info));
return false;
}
@ -10595,7 +10581,7 @@ public:
if (FunctionDecl *Fun =
dyn_cast<FunctionDecl>((*I)->getUnderlyingDecl()))
if (!functionHasPassObjectSizeParams(Fun))
S.NoteOverloadCandidate(Fun, TargetFunctionType,
S.NoteOverloadCandidate(*I, Fun, TargetFunctionType,
/*TakingAddress=*/true);
FailedCandidates.NoteCandidates(S, OvlExpr->getLocStart());
}
@ -10801,7 +10787,7 @@ Sema::ResolveSingleFunctionTemplateSpecialization(OverloadExpr *ovl,
// Make a note of the failed deduction for diagnostics.
// TODO: Actually use the failed-deduction info?
FailedCandidates.addCandidate()
.set(FunctionTemplate->getTemplatedDecl(),
.set(I.getPair(), FunctionTemplate->getTemplatedDecl(),
MakeDeductionFailureInfo(Context, Result, Info));
continue;
}

View File

@ -2791,8 +2791,9 @@ Sema::CheckVarTemplateId(VarTemplateDecl *Template, SourceLocation TemplateLoc,
DeduceTemplateArguments(Partial, TemplateArgList, Info)) {
// Store the failed-deduction information for use in diagnostics, later.
// TODO: Actually use the failed-deduction info?
FailedCandidates.addCandidate()
.set(Partial, MakeDeductionFailureInfo(Context, Result, Info));
FailedCandidates.addCandidate().set(
DeclAccessPair::make(Template, AS_public), Partial,
MakeDeductionFailureInfo(Context, Result, Info));
(void)Result;
} else {
Matched.push_back(PartialSpecMatchResult());
@ -6895,12 +6896,13 @@ bool Sema::CheckFunctionTemplateSpecialization(
FunctionDecl *Specialization = nullptr;
if (TemplateDeductionResult TDK = DeduceTemplateArguments(
cast<FunctionTemplateDecl>(FunTmpl->getFirstDecl()),
ExplicitTemplateArgs ? &Args : nullptr, FT, Specialization, Info)) {
ExplicitTemplateArgs ? &Args : nullptr, FT, Specialization,
Info)) {
// Template argument deduction failed; record why it failed, so
// that we can provide nifty diagnostics.
FailedCandidates.addCandidate()
.set(FunTmpl->getTemplatedDecl(),
MakeDeductionFailureInfo(Context, TDK, Info));
FailedCandidates.addCandidate().set(
I.getPair(), FunTmpl->getTemplatedDecl(),
MakeDeductionFailureInfo(Context, TDK, Info));
(void)TDK;
continue;
}
@ -7925,7 +7927,7 @@ DeclResult Sema::ActOnExplicitInstantiation(Scope *S,
R, Specialization, Info)) {
// Keep track of almost-matches.
FailedCandidates.addCandidate()
.set(FunTmpl->getTemplatedDecl(),
.set(P.getPair(), FunTmpl->getTemplatedDecl(),
MakeDeductionFailureInfo(Context, TDK, Info));
(void)TDK;
continue;

View File

@ -2321,8 +2321,9 @@ bool Sema::InstantiateClassTemplateSpecialization(
Info)) {
// Store the failed-deduction information for use in diagnostics, later.
// TODO: Actually use the failed-deduction info?
FailedCandidates.addCandidate()
.set(Partial, MakeDeductionFailureInfo(Context, Result, Info));
FailedCandidates.addCandidate().set(
DeclAccessPair::make(Template, AS_public), Partial,
MakeDeductionFailureInfo(Context, Result, Info));
(void)Result;
} else {
Matched.push_back(PartialSpecMatchResult());

View File

@ -2637,6 +2637,7 @@ public:
/// Subclasses may override this routine to provide different behavior.
ExprResult RebuildCXXConstructExpr(QualType T,
SourceLocation Loc,
NamedDecl *Found,
CXXConstructorDecl *Constructor,
bool IsElidable,
MultiExprArg Args,
@ -2651,7 +2652,8 @@ public:
ConvertedArgs))
return ExprError();
return getSema().BuildCXXConstructExpr(Loc, T, Constructor, IsElidable,
return getSema().BuildCXXConstructExpr(Loc, T, Found, Constructor,
IsElidable,
ConvertedArgs,
HadMultipleCandidates,
ListInitialization,
@ -9880,6 +9882,11 @@ TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) {
if (T.isNull())
return ExprError();
NamedDecl *FoundDecl = cast_or_null<NamedDecl>(
getDerived().TransformDecl(E->getLocStart(), E->getFoundDecl()));
if (!FoundDecl)
return ExprError();
CXXConstructorDecl *Constructor
= cast_or_null<CXXConstructorDecl>(
getDerived().TransformDecl(E->getLocStart(),
@ -9895,6 +9902,7 @@ TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) {
if (!getDerived().AlwaysRebuild() &&
T == E->getType() &&
FoundDecl == E->getFoundDecl() &&
Constructor == E->getConstructor() &&
!ArgumentChanged) {
// Mark the constructor as referenced.
@ -9904,8 +9912,8 @@ TreeTransform<Derived>::TransformCXXConstructExpr(CXXConstructExpr *E) {
}
return getDerived().RebuildCXXConstructExpr(T, /*FIXME:*/E->getLocStart(),
Constructor, E->isElidable(),
Args,
FoundDecl, Constructor,
E->isElidable(), Args,
E->hadMultipleCandidates(),
E->isListInitialization(),
E->isStdInitListInitialization(),