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
diff --git a/lib/CodeGen/CGExprCXX.cpp b/lib/CodeGen/CGExprCXX.cpp
index 77ccdd0..246ecb2 100644
--- a/lib/CodeGen/CGExprCXX.cpp
+++ b/lib/CodeGen/CGExprCXX.cpp
@@ -93,6 +93,8 @@
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 @@
if (MD->isTrivial()) {
if (isa<CXXDestructorDecl>(MD)) return RValue::get(0);
+ if (isa<CXXConstructorDecl>(MD) &&
+ cast<CXXConstructorDecl>(MD)->isDefaultConstructor())
+ 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 (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 @@
} 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 f48b7a5..acbf3a5 100644
--- a/lib/Parse/ParseExpr.cpp
+++ b/lib/Parse/ParseExpr.cpp
@@ -1171,11 +1171,13 @@
// 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 26fdb2e..45e0c33 100644
--- a/lib/Sema/SemaExpr.cpp
+++ b/lib/Sema/SemaExpr.cpp
@@ -3902,6 +3902,12 @@
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 80ef65e..4bb9591 100644
--- a/lib/Sema/SemaOverload.cpp
+++ b/lib/Sema/SemaOverload.cpp
@@ -7904,7 +7904,11 @@
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)