@@ -79,11 +79,10 @@ RValue CIRGenFunction::emitCXXMemberOrOperatorMemberCallExpr(
79
79
const Expr *base) {
80
80
assert (isa<CXXMemberCallExpr>(ce) || isa<CXXOperatorCallExpr>(ce));
81
81
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 ());
87
86
88
87
// Note on trivial assignment
89
88
// --------------------------
@@ -127,7 +126,8 @@ RValue CIRGenFunction::emitCXXMemberOrOperatorMemberCallExpr(
127
126
return RValue::get (nullptr );
128
127
129
128
// Compute the function type we're calling
130
- const CXXMethodDecl *calleeDecl = md;
129
+ const CXXMethodDecl *calleeDecl =
130
+ devirtualizedMethod ? devirtualizedMethod : md;
131
131
const CIRGenFunctionInfo *fInfo = nullptr ;
132
132
if (isa<CXXDestructorDecl>(calleeDecl)) {
133
133
cgm.errorNYI (ce->getSourceRange (),
@@ -137,25 +137,46 @@ RValue CIRGenFunction::emitCXXMemberOrOperatorMemberCallExpr(
137
137
138
138
fInfo = &cgm.getTypes ().arrangeCXXMethodDeclaration (calleeDecl);
139
139
140
- mlir::Type ty = cgm.getTypes ().getFunctionType (*fInfo );
140
+ cir::FuncType ty = cgm.getTypes ().getFunctionType (*fInfo );
141
141
142
142
assert (!cir::MissingFeatures::sanitizers ());
143
143
assert (!cir::MissingFeatures::emitTypeCheck ());
144
144
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
+
145
153
if (isa<CXXDestructorDecl>(calleeDecl)) {
146
154
cgm.errorNYI (ce->getSourceRange (),
147
155
" emitCXXMemberOrOperatorMemberCallExpr: destructor call" );
148
156
return RValue::get (nullptr );
149
157
}
150
158
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);
156
179
}
157
- CIRGenCallee callee =
158
- CIRGenCallee::forDirect (cgm.getAddrOfFunction (md, ty), GlobalDecl (md));
159
180
160
181
return emitCXXMemberOrOperatorCall (
161
182
calleeDecl, callee, returnValue, thisPtr.getPointer (),
0 commit comments