@@ -79,11 +79,10 @@ RValue CIRGenFunction::emitCXXMemberOrOperatorMemberCallExpr(
7979 const Expr *base) {
8080 assert (isa<CXXMemberCallExpr>(ce) || isa<CXXOperatorCallExpr>(ce));
8181
82- if (md->isVirtual ()) {
83- cgm.errorNYI (ce->getSourceRange (),
84- " emitCXXMemberOrOperatorMemberCallExpr: virtual call" );
85- return RValue::get (nullptr );
86- }
82+ // Compute the object pointer.
83+ bool canUseVirtualCall = md->isVirtual () && !hasQualifier;
84+ const CXXMethodDecl *devirtualizedMethod = nullptr ;
85+ assert (!cir::MissingFeatures::devirtualizeMemberFunction ());
8786
8887 // Note on trivial assignment
8988 // --------------------------
@@ -127,7 +126,8 @@ RValue CIRGenFunction::emitCXXMemberOrOperatorMemberCallExpr(
127126 return RValue::get (nullptr );
128127
129128 // Compute the function type we're calling
130- const CXXMethodDecl *calleeDecl = md;
129+ const CXXMethodDecl *calleeDecl =
130+ devirtualizedMethod ? devirtualizedMethod : md;
131131 const CIRGenFunctionInfo *fInfo = nullptr ;
132132 if (isa<CXXDestructorDecl>(calleeDecl)) {
133133 cgm.errorNYI (ce->getSourceRange (),
@@ -137,25 +137,46 @@ RValue CIRGenFunction::emitCXXMemberOrOperatorMemberCallExpr(
137137
138138 fInfo = &cgm.getTypes ().arrangeCXXMethodDeclaration (calleeDecl);
139139
140- mlir::Type ty = cgm.getTypes ().getFunctionType (*fInfo );
140+ cir::FuncType ty = cgm.getTypes ().getFunctionType (*fInfo );
141141
142142 assert (!cir::MissingFeatures::sanitizers ());
143143 assert (!cir::MissingFeatures::emitTypeCheck ());
144144
145+ // C++ [class.virtual]p12:
146+ // Explicit qualification with the scope operator (5.1) suppresses the
147+ // virtual call mechanism.
148+ //
149+ // We also don't emit a virtual call if the base expression has a record type
150+ // because then we know what the type is.
151+ bool useVirtualCall = canUseVirtualCall && !devirtualizedMethod;
152+
145153 if (isa<CXXDestructorDecl>(calleeDecl)) {
146154 cgm.errorNYI (ce->getSourceRange (),
147155 " emitCXXMemberOrOperatorMemberCallExpr: destructor call" );
148156 return RValue::get (nullptr );
149157 }
150158
151- assert (!cir::MissingFeatures::sanitizers ());
152- if (getLangOpts ().AppleKext ) {
153- cgm.errorNYI (ce->getSourceRange (),
154- " emitCXXMemberOrOperatorMemberCallExpr: AppleKext" );
155- return RValue::get (nullptr );
159+ CIRGenCallee callee;
160+ if (useVirtualCall) {
161+ callee = CIRGenCallee::forVirtual (ce, md, thisPtr.getAddress (), ty);
162+ } else {
163+ assert (!cir::MissingFeatures::sanitizers ());
164+ if (getLangOpts ().AppleKext ) {
165+ cgm.errorNYI (ce->getSourceRange (),
166+ " emitCXXMemberOrOperatorMemberCallExpr: AppleKext" );
167+ return RValue::get (nullptr );
168+ }
169+
170+ callee = CIRGenCallee::forDirect (cgm.getAddrOfFunction (calleeDecl, ty),
171+ GlobalDecl (calleeDecl));
172+ }
173+
174+ if (md->isVirtual ()) {
175+ Address newThisAddr =
176+ cgm.getCXXABI ().adjustThisArgumentForVirtualFunctionCall (
177+ *this , calleeDecl, thisPtr.getAddress (), useVirtualCall);
178+ thisPtr.setAddress (newThisAddr);
156179 }
157- CIRGenCallee callee =
158- CIRGenCallee::forDirect (cgm.getAddrOfFunction (md, ty), GlobalDecl (md));
159180
160181 return emitCXXMemberOrOperatorCall (
161182 calleeDecl, callee, returnValue, thisPtr.getPointer (),
0 commit comments