diff options
author | Francois Pichet <pichet2000@gmail.com> | 2011-01-18 05:04:39 +0000 |
---|---|---|
committer | Francois Pichet <pichet2000@gmail.com> | 2011-01-18 05:04:39 +0000 |
commit | dbee3411a22b0dbb03267f5445f7b796104991bb (patch) | |
tree | aa3c7e4cf0f0f5e7f1e4617715e10efbf1cfaa9d /lib | |
parent | 4dccb90e92ba9e4abffe0177493b6db9949678dd (diff) |
Add support for explicit constructor calls in Microsoft mode.
For example:
class A{
public:
A& operator=(const A& that) {
if (this != &that) {
this->A::~A();
this->A::A(that); // <=== explicit constructor call.
}
return *this;
}
};
More work will be needed to support an explicit call to a template constructor.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123735 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/CodeGen/CGExprCXX.cpp | 48 | ||||
-rw-r--r-- | lib/Parse/ParseExpr.cpp | 4 | ||||
-rw-r--r-- | lib/Sema/SemaExpr.cpp | 6 | ||||
-rw-r--r-- | lib/Sema/SemaOverload.cpp | 6 |
4 files changed, 49 insertions, 15 deletions
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp index 77ccdd0d72..246ecb2d2c 100644 --- a/lib/CodeGen/CGExprCXX.cpp +++ b/lib/CodeGen/CGExprCXX.cpp @@ -93,6 +93,8 @@ static bool canDevirtualizeMemberFunctionCalls(const Expr *Base, return false; } +// Note: This function also emit constructor calls to support a MSVC +// extensions allowing explicit constructor function call. RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE, ReturnValueSlot ReturnValue) { if (isa<BinaryOperator>(CE->getCallee()->IgnoreParens())) @@ -127,25 +129,42 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE, if (MD->isTrivial()) { if (isa<CXXDestructorDecl>(MD)) return RValue::get(0); - - assert(MD->isCopyAssignmentOperator() && "unknown trivial member function"); - // We don't like to generate the trivial copy assignment operator when - // it isn't necessary; just produce the proper effect here. - llvm::Value *RHS = EmitLValue(*CE->arg_begin()).getAddress(); - EmitAggregateCopy(This, RHS, CE->getType()); - return RValue::get(This); + if (isa<CXXConstructorDecl>(MD) && + cast<CXXConstructorDecl>(MD)->isDefaultConstructor()) + return RValue::get(0); + + if (MD->isCopyAssignmentOperator()) { + // We don't like to generate the trivial copy assignment operator when + // it isn't necessary; just produce the proper effect here. + llvm::Value *RHS = EmitLValue(*CE->arg_begin()).getAddress(); + EmitAggregateCopy(This, RHS, CE->getType()); + return RValue::get(This); + } + + if (isa<CXXConstructorDecl>(MD) && + cast<CXXConstructorDecl>(MD)->isCopyConstructor()) { + llvm::Value *RHS = EmitLValue(*CE->arg_begin()).getAddress(); + EmitSynthesizedCXXCopyCtorCall(cast<CXXConstructorDecl>(MD), This, RHS, + CE->arg_begin(), CE->arg_end()); + return RValue::get(This); + } + llvm_unreachable("unknown trivial member function"); } // Compute the function type we're calling. - const CGFunctionInfo &FInfo = - (isa<CXXDestructorDecl>(MD) - ? CGM.getTypes().getFunctionInfo(cast<CXXDestructorDecl>(MD), - Dtor_Complete) - : CGM.getTypes().getFunctionInfo(MD)); + const CGFunctionInfo *FInfo = 0; + if (isa<CXXDestructorDecl>(MD)) + FInfo = &CGM.getTypes().getFunctionInfo(cast<CXXDestructorDecl>(MD), + Dtor_Complete); + else if (isa<CXXConstructorDecl>(MD)) + FInfo = &CGM.getTypes().getFunctionInfo(cast<CXXConstructorDecl>(MD), + Ctor_Complete); + else + FInfo = &CGM.getTypes().getFunctionInfo(MD); const FunctionProtoType *FPT = MD->getType()->getAs<FunctionProtoType>(); const llvm::Type *Ty - = CGM.getTypes().GetFunctionType(FInfo, FPT->isVariadic()); + = CGM.getTypes().GetFunctionType(*FInfo, FPT->isVariadic()); // C++ [class.virtual]p12: // Explicit qualification with the scope operator (5.1) suppresses the @@ -163,6 +182,9 @@ RValue CodeGenFunction::EmitCXXMemberCallExpr(const CXXMemberCallExpr *CE, } else { Callee = CGM.GetAddrOfFunction(GlobalDecl(Dtor, Dtor_Complete), Ty); } + } else if (const CXXConstructorDecl *Ctor = + dyn_cast<CXXConstructorDecl>(MD)) { + Callee = CGM.GetAddrOfFunction(GlobalDecl(Ctor, Ctor_Complete), Ty); } else if (UseVirtualCall) { Callee = BuildVirtualCall(MD, This, Ty); } else { diff --git a/lib/Parse/ParseExpr.cpp b/lib/Parse/ParseExpr.cpp index f48b7a5faa..acbf3a5a92 100644 --- a/lib/Parse/ParseExpr.cpp +++ b/lib/Parse/ParseExpr.cpp @@ -1171,11 +1171,13 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { // expression), or we didn't see a '~' in the right place. We // can still parse a destructor name here, but in that case it // names a real destructor. + // Allow explicit constructor calls in Microsoft mode. + // FIXME: Add support for explicit call of template constructor. UnqualifiedId Name; if (ParseUnqualifiedId(SS, /*EnteringContext=*/false, /*AllowDestructorName=*/true, - /*AllowConstructorName=*/false, + /*AllowConstructorName=*/ getLang().Microsoft, ObjectType, Name)) LHS = ExprError(); diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 26fdb2e059..45e0c3377b 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -3902,6 +3902,12 @@ ExprResult Sema::ActOnMemberAccessExpr(Scope *S, Expr *Base, if (SS.isSet() && SS.isInvalid()) return ExprError(); + // Warn about the explicit constructor calls Microsoft extension. + if (getLangOptions().Microsoft && + Id.getKind() == UnqualifiedId::IK_ConstructorName) + Diag(Id.getSourceRange().getBegin(), + diag::ext_ms_explicit_constructor_call); + TemplateArgumentListInfo TemplateArgsBuffer; // Decompose the name into its component parts. diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 80ef65e433..4bb95912e6 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -7904,7 +7904,11 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE, if (isa<UsingShadowDecl>(Func)) Func = cast<UsingShadowDecl>(Func)->getTargetDecl(); - if ((Method = dyn_cast<CXXMethodDecl>(Func))) { + // Microsoft supports direct constructor calls. + if (getLangOptions().Microsoft && isa<CXXConstructorDecl>(Func)) { + AddOverloadCandidate(cast<CXXConstructorDecl>(Func), I.getPair(), Args, NumArgs, + CandidateSet); + } else if ((Method = dyn_cast<CXXMethodDecl>(Func))) { // If explicit template arguments were provided, we can't call a // non-template member function. if (TemplateArgs) |