If a cast expression needs either a conversion function or a constructor to be called, generate implicit child expressions that call them.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@81383 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp
index 3943ce1..7fc754f 100644
--- a/lib/Sema/SemaExprCXX.cpp
+++ b/lib/Sema/SemaExprCXX.cpp
@@ -224,19 +224,25 @@
//
if (NumExprs == 1) {
CastExpr::CastKind Kind = CastExpr::CK_Unknown;
- CXXMethodDecl *ConversionDecl = 0;
- if (CheckCastTypes(TypeRange, Ty, Exprs[0], Kind, ConversionDecl,
- /*functional-style*/true))
+ CXXMethodDecl *Method = 0;
+ if (CheckCastTypes(TypeRange, Ty, Exprs[0], Kind, Method,
+ /*FunctionalStyle=*/true))
return ExprError();
- // We done't build this AST for X(i) where we are constructing an object.
- if (!ConversionDecl || !isa<CXXConstructorDecl>(ConversionDecl)) {
- exprs.release();
- return Owned(new (Context) CXXFunctionalCastExpr(Ty.getNonReferenceType(),
- Ty, TyBeginLoc,
- CastExpr::CK_UserDefinedConversion,
- Exprs[0], ConversionDecl,
- RParenLoc));
+
+ exprs.release();
+ if (Method) {
+ OwningExprResult CastArg
+ = BuildCXXCastArgument(TypeRange.getBegin(), Ty.getNonReferenceType(),
+ Kind, Method, Owned(Exprs[0]));
+ if (CastArg.isInvalid())
+ return ExprError();
+
+ Exprs[0] = CastArg.takeAs<Expr>();
}
+
+ return Owned(new (Context) CXXFunctionalCastExpr(Ty.getNonReferenceType(),
+ Ty, TyBeginLoc, Kind,
+ Exprs[0], RParenLoc));
}
if (const RecordType *RT = Ty->getAs<RecordType>()) {
@@ -919,30 +925,25 @@
{
FunctionDecl *FD = ICS.UserDefined.ConversionFunction;
CastExpr::CastKind CastKind = CastExpr::CK_Unknown;
- if (CXXConversionDecl *CV = dyn_cast<CXXConversionDecl>(FD)) {
- // FIXME. Get actual Source Location.
- From =
- new (Context) CXXFunctionalCastExpr(ToType.getNonReferenceType(),
- ToType, SourceLocation(),
- CastExpr::CK_UserDefinedConversion,
- From, CV,
- SourceLocation());
+ if (isa<CXXConversionDecl>(FD))
CastKind = CastExpr::CK_UserDefinedConversion;
- }
- else if (CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
- // FIXME. Do we need to check for isLValueReferenceType?
- DefaultFunctionArrayConversion(From);
- OwningExprResult InitResult =
- BuildCXXConstructExpr(/*FIXME:ConstructLoc*/SourceLocation(),
- ToType.getNonReferenceType(), CD,
- MultiExprArg(*this, (void**)&From, 1));
- // Take ownership of this expression.
- From = InitResult.takeAs<Expr>();
- CastKind = CastExpr::CK_ConstructorConversion ;
- }
- ImpCastExprToType(From, ToType.getNonReferenceType(),
- CastKind,
- ToType->isLValueReferenceType());
+ else if (isa<CXXConstructorDecl>(FD))
+ CastKind = CastExpr::CK_ConstructorConversion;
+ else
+ assert(0 && "Unknown conversion function kind!");
+
+ OwningExprResult CastArg
+ = BuildCXXCastArgument(From->getLocStart(),
+ ToType.getNonReferenceType(),
+ CastKind, cast<CXXMethodDecl>(FD),
+ Owned(From));
+
+ if (CastArg.isInvalid())
+ return true;
+
+ From = new (Context) ImplicitCastExpr(ToType.getNonReferenceType(),
+ CastKind, CastArg.takeAs<Expr>(),
+ ToType->isLValueReferenceType());
return false;
}
@@ -1889,6 +1890,42 @@
ConvName, DeclPtrTy(), SS);
}
+Sema::OwningExprResult Sema::BuildCXXCastArgument(SourceLocation CastLoc,
+ QualType Ty,
+ CastExpr::CastKind Kind,
+ CXXMethodDecl *Method,
+ ExprArg Arg) {
+ Expr *From = Arg.takeAs<Expr>();
+
+ switch (Kind) {
+ default: assert(0 && "Unhandled cast kind!");
+ case CastExpr::CK_ConstructorConversion: {
+ DefaultFunctionArrayConversion(From);
+
+ return BuildCXXConstructExpr(CastLoc, Ty, cast<CXXConstructorDecl>(Method),
+ MultiExprArg(*this, (void **)&From, 1));
+ }
+
+ case CastExpr::CK_UserDefinedConversion: {
+ // Create an implicit member expr to refer to the conversion operator.
+ MemberExpr *ME =
+ new (Context) MemberExpr(From, From->getType()->isPointerType(), Method,
+ SourceLocation(), Method->getType());
+
+
+ // And an implicit call expr that calls it.
+ QualType ResultType = Method->getResultType().getNonReferenceType();
+ CXXMemberCallExpr *CE =
+ new (Context) CXXMemberCallExpr(Context, ME, 0, 0,
+ ResultType,
+ SourceLocation());
+
+ return Owned(CE);
+ }
+
+ }
+}
+
Sema::OwningExprResult Sema::ActOnFinishFullExpr(ExprArg Arg) {
Expr *FullExpr = Arg.takeAs<Expr>();
if (FullExpr)