[cfe-commits] r91323 - in /cfe/trunk/lib/Sema: SemaInit.cpp SemaInit.h
Douglas Gregor
dgregor at apple.com
Mon Dec 14 12:49:28 PST 2009
Author: dgregor
Date: Mon Dec 14 14:49:26 2009
New Revision: 91323
URL: http://llvm.org/viewvc/llvm-project?rev=91323&view=rev
Log:
Constructor initialization for InitializationSequence. Untested WIP.
Modified:
cfe/trunk/lib/Sema/SemaInit.cpp
cfe/trunk/lib/Sema/SemaInit.h
Modified: cfe/trunk/lib/Sema/SemaInit.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.cpp?rev=91323&r1=91322&r2=91323&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.cpp (original)
+++ cfe/trunk/lib/Sema/SemaInit.cpp Mon Dec 14 14:49:26 2009
@@ -1969,6 +1969,7 @@
case SK_QualificationConversionRValue:
case SK_QualificationConversionLValue:
case SK_ListInitialization:
+ case SK_ConstructorInitialization:
break;
case SK_ConversionSequence:
@@ -2036,6 +2037,17 @@
Steps.push_back(S);
}
+void
+InitializationSequence::AddConstructorInitializationStep(
+ CXXConstructorDecl *Constructor,
+ QualType T) {
+ Step S;
+ S.Kind = SK_ConstructorInitialization;
+ S.Type = T;
+ S.Function = Constructor;
+ Steps.push_back(S);
+}
+
void InitializationSequence::SetOverloadFailure(FailureKind Failure,
OverloadingResult Result) {
SequenceKind = FailedSequence;
@@ -2462,7 +2474,70 @@
const InitializationKind &Kind,
Expr **Args, unsigned NumArgs,
InitializationSequence &Sequence) {
- // FIXME: Implement!
+ Sequence.setSequenceKind(InitializationSequence::ConstructorConversion);
+
+ // Build the candidate set directly in the initialization sequence
+ // structure, so that it will persist if we fail.
+ OverloadCandidateSet &CandidateSet = Sequence.getFailedCandidateSet();
+ CandidateSet.clear();
+
+ // Determine whether we are allowed to call explicit constructors or
+ // explicit conversion operators.
+ bool AllowExplicit = (Kind.getKind() == InitializationKind::IK_Direct ||
+ Kind.getKind() == InitializationKind::IK_Value ||
+ Kind.getKind() == InitializationKind::IK_Default);
+
+ // The type we're converting to is a class type. Enumerate its constructors
+ // to see if one is suitable.
+ QualType DestType = Entity.getType().getType();
+ const RecordType *DestRecordType = DestType->getAs<RecordType>();
+ assert(DestRecordType && "Constructor initialization requires record type");
+ CXXRecordDecl *DestRecordDecl
+ = cast<CXXRecordDecl>(DestRecordType->getDecl());
+
+ DeclarationName ConstructorName
+ = S.Context.DeclarationNames.getCXXConstructorName(
+ S.Context.getCanonicalType(DestType).getUnqualifiedType());
+ DeclContext::lookup_iterator Con, ConEnd;
+ for (llvm::tie(Con, ConEnd) = DestRecordDecl->lookup(ConstructorName);
+ Con != ConEnd; ++Con) {
+ // Find the constructor (which may be a template).
+ CXXConstructorDecl *Constructor = 0;
+ FunctionTemplateDecl *ConstructorTmpl
+ = dyn_cast<FunctionTemplateDecl>(*Con);
+ if (ConstructorTmpl)
+ Constructor = cast<CXXConstructorDecl>(
+ ConstructorTmpl->getTemplatedDecl());
+ else
+ Constructor = cast<CXXConstructorDecl>(*Con);
+
+ if (!Constructor->isInvalidDecl() &&
+ Constructor->isConvertingConstructor(AllowExplicit)) {
+ if (ConstructorTmpl)
+ S.AddTemplateOverloadCandidate(ConstructorTmpl, /*ExplicitArgs*/ 0,
+ Args, NumArgs, CandidateSet);
+ else
+ S.AddOverloadCandidate(Constructor, Args, NumArgs, CandidateSet);
+ }
+ }
+
+ SourceLocation DeclLoc = Kind.getLocation();
+
+ // Perform overload resolution. If it fails, return the failed result.
+ OverloadCandidateSet::iterator Best;
+ if (OverloadingResult Result
+ = S.BestViableFunction(CandidateSet, DeclLoc, Best)) {
+ Sequence.SetOverloadFailure(
+ InitializationSequence::FK_ConstructorOverloadFailed,
+ Result);
+ return;
+ }
+
+ // Add the constructor initialization step. Any cv-qualification conversion is
+ // subsumed by the initialization.
+ Sequence.AddConstructorInitializationStep(
+ cast<CXXConstructorDecl>(Best->Function),
+ DestType);
}
/// \brief Attempt a user-defined conversion between two types (C++ [dcl.init]),
@@ -2968,6 +3043,30 @@
CurInit = S.Owned(InitList);
break;
}
+
+ case SK_ConstructorInitialization: {
+ CXXConstructorDecl *Constructor
+ = cast<CXXConstructorDecl>(Step->Function);
+
+ // Build a call to the selected constructor.
+ ASTOwningVector<&ActionBase::DeleteExpr> ConstructorArgs(S);
+ SourceLocation Loc = Kind.getLocation();
+
+ // Determine the arguments required to actually perform the constructor
+ // call.
+ if (S.CompleteConstructorCall(Constructor, move(Args),
+ Loc, ConstructorArgs))
+ return S.ExprError();
+
+ // Build the an expression that constructs a temporary.
+ CurInit = S.BuildCXXConstructExpr(Loc, Step->Type, Constructor,
+ move_arg(ConstructorArgs));
+ if (CurInit.isInvalid())
+ return S.ExprError();
+
+ CurInit = S.MaybeBindToTemporary(CurInit.takeAs<Expr>());
+ break;
+ }
}
}
@@ -3101,6 +3200,50 @@
S.Diag(Kind.getLocation(), diag::err_init_list_bad_dest_type)
<< (DestType->isRecordType()) << DestType << Args[0]->getSourceRange();
break;
+
+ case FK_ConstructorOverloadFailed: {
+ SourceRange ArgsRange;
+ if (NumArgs)
+ ArgsRange = SourceRange(Args[0]->getLocStart(),
+ Args[NumArgs - 1]->getLocEnd());
+
+ // FIXME: Using "DestType" for the entity we're printing is probably
+ // bad.
+ switch (FailedOverloadResult) {
+ case OR_Ambiguous:
+ S.Diag(Kind.getLocation(), diag::err_ovl_ambiguous_init)
+ << DestType << ArgsRange;
+ S.PrintOverloadCandidates(FailedCandidateSet, true);
+ break;
+
+ case OR_No_Viable_Function:
+ S.Diag(Kind.getLocation(), diag::err_ovl_no_viable_function_in_init)
+ << DestType << ArgsRange;
+ S.PrintOverloadCandidates(FailedCandidateSet, false);
+ break;
+
+ case OR_Deleted: {
+ S.Diag(Kind.getLocation(), diag::err_ovl_deleted_init)
+ << true << DestType << ArgsRange;
+ OverloadCandidateSet::iterator Best;
+ OverloadingResult Ovl = S.BestViableFunction(FailedCandidateSet,
+ Kind.getLocation(),
+ Best);
+ if (Ovl == OR_Deleted) {
+ S.Diag(Best->Function->getLocation(), diag::note_unavailable_here)
+ << Best->Function->isDeleted();
+ } else {
+ llvm_unreachable("Inconsistent overload resolution?");
+ }
+ break;
+ }
+
+ case OR_Success:
+ llvm_unreachable("Conversion did not fail!");
+ break;
+ }
+ break;
+ }
}
return true;
Modified: cfe/trunk/lib/Sema/SemaInit.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaInit.h?rev=91323&r1=91322&r2=91323&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaInit.h (original)
+++ cfe/trunk/lib/Sema/SemaInit.h Mon Dec 14 14:49:26 2009
@@ -306,6 +306,9 @@
/// \brief A user-defined conversion sequence.
UserDefinedConversion,
+ /// \brief A constructor call.
+ ConstructorConversion,
+
/// \brief A reference binding.
ReferenceBinding,
@@ -337,7 +340,9 @@
/// \brief Perform an implicit conversion sequence.
SK_ConversionSequence,
/// \brief Perform list-initialization
- SK_ListInitialization
+ SK_ListInitialization,
+ /// \brief Perform initialization via a constructor.
+ SK_ConstructorInitialization
};
/// \brief A single step in the initialization sequence.
@@ -405,7 +410,9 @@
/// initializer list.
FK_InitListBadDestinationType,
/// \brief Overloading for a user-defined conversion failed.
- FK_UserConversionOverloadFailed
+ FK_UserConversionOverloadFailed,
+ /// \brief Overloaded for initialization by constructor failed.
+ FK_ConstructorOverloadFailed
};
private:
@@ -529,6 +536,10 @@
/// \brief Add a list-initialiation step
void AddListInitializationStep(QualType T);
+ /// \brief Add a a constructor-initialization step.
+ void AddConstructorInitializationStep(CXXConstructorDecl *Constructor,
+ QualType T);
+
/// \brief Note that this initialization sequence failed.
void SetFailed(FailureKind Failure) {
SequenceKind = FailedSequence;
More information about the cfe-commits
mailing list