llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clangir

Author: Erich Keane (erichkeane)

<details>
<summary>Changes</summary>

In cases with inheritance/vertual tables/etc, we need to generate a series of 
constructors to delegate to.  There are a handful slightly different cases 
where we need to generate these/generate calls to these, so this patch does 
that lowering.

The test check-lines are a bit confusing thanks to the ordering differences 
between declarations. However the LLVM/OGCG lines are copy pasted (plus minor 
attribute differences), with the exception of the call to a delegated 
constructor.

One thing of note here: There is a difference in behavior with the delegated 
constructor, which is called out in the test in a comment. Classic codegen has 
a bug where it correctly creates the declaration without arguments (since this 
constructor is only for initializing the vtable pointers, arguments aren't 
necessary).  However, when classic-codegen creates the call, it doesn't omit 
them.

This isn't a problem there, however in CIR, this causes us to fail the 
verifier, so this fixes that in CIR, but leaves it alone in OGCG.

---

Patch is 26.51 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/191467.diff


7 Files Affected:

- (modified) clang/lib/CIR/CodeGen/CIRGenCall.cpp (+11-3) 
- (modified) clang/lib/CIR/CodeGen/CIRGenClass.cpp (+130-6) 
- (modified) clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp (+5-2) 
- (modified) clang/lib/CIR/CodeGen/CIRGenFunction.cpp (+12-6) 
- (modified) clang/lib/CIR/CodeGen/CIRGenFunction.h (+66) 
- (modified) clang/lib/CIR/CodeGen/CIRGenTypes.h (+6) 
- (added) clang/test/CIR/CodeGen/inherited-ctors.cpp (+182) 


``````````diff
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index 876fef687b477..4dc24113f71b9 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -736,9 +736,8 @@ CIRGenTypes::arrangeCXXStructorDeclaration(GlobalDecl gd) {
   if (auto *cd = dyn_cast<CXXConstructorDecl>(md)) {
     // A base class inheriting constructor doesn't get forwarded arguments
     // needed to construct a virtual base (or base class thereof)
-    if (cd->getInheritedConstructor())
-      cgm.errorNYI(cd->getSourceRange(),
-                   "arrangeCXXStructorDeclaration: inheriting constructor");
+    if (auto inherited = cd->getInheritedConstructor())
+      passParams = inheritingCtorHasParams(inherited, gd.getCtorType());
   }
 
   CanQual<FunctionProtoType> fpt = getFormalType(md);
@@ -1427,3 +1426,12 @@ void CIRGenFunction::emitCallArgs(
       std::reverse(args.begin() + callArgsStart, args.end());
   }
 }
+
+bool CIRGenTypes::inheritingCtorHasParams(
+    const InheritedConstructor &inherited, CXXCtorType type) {
+  // Parameters are unnecessary if we're constructing a base class subobject
+  // and the inherited constructor lives in a virtual base.
+  return type == Ctor_Complete ||
+         !inherited.getShadowDecl()->constructsVirtualBase() ||
+         !getASTContext().getTargetInfo().getCXXABI().hasConstructorVariants();
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenClass.cpp 
b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
index 748d450d6dc10..bf0e28ae30ba5 100644
--- a/clang/lib/CIR/CodeGen/CIRGenClass.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenClass.cpp
@@ -1344,14 +1344,134 @@ void CIRGenFunction::emitCXXConstructorCall(const 
clang::CXXConstructorDecl *d,
 
   assert(!cir::MissingFeatures::opCallArgEvaluationOrder());
 
-  emitCallArgs(args, fpt, e->arguments(), e->getConstructor(),
-               /*ParamsToSkip=*/0);
+  if (auto inherited = d->getInheritedConstructor();
+      !inherited || cgm.getTypes().inheritingCtorHasParams(inherited, type))
+    emitCallArgs(args, fpt, e->arguments(), e->getConstructor(),
+                 /*ParamsToSkip=*/0);
 
   assert(!cir::MissingFeatures::sanitizers());
   emitCXXConstructorCall(d, type, forVirtualBase, delegating, thisAddr, args,
                          e->getExprLoc());
 }
 
+static bool canEmitDelegateCallArgs(CIRGenModule &cgm, ASTContext &ctx,
+                                    const CXXConstructorDecl *d,
+                                    CXXCtorType type) {
+  // We can't forward a variadic call.
+  if (d->isVariadic())
+    return false;
+
+  if (ctx.getTargetInfo().getCXXABI().areArgsDestroyedLeftToRightInCallee()) {
+    // If the parameters are callee-cleanup, it's not safe to forward.
+    if (llvm::any_of(d->parameters(), [&ctx](const ParmVarDecl *param) {
+          return param->needsDestruction(ctx);
+        }))
+      return false;
+
+    // FIXME(CIR): It isn't clear to me that this is the right answer here,
+    // classic-codegen decides the answer is 'false' if there is an inalloca
+    // argument. What our default should be in this case, or what we want to 
do.
+    // When we get an understanding of what the the calling-convention code
+    // needs here, we should be able to replace this with either a 'return
+    // false' or 'return true'.
+    cgm.errorNYI(d->getSourceRange(),
+                 "canEmitDelegateCallArgs: args-destroyed-L-to-R in callee");
+  }
+
+  return true;
+}
+
+void CIRGenFunction::emitInheritedCXXConstructorCall(
+    const CXXConstructorDecl *d, bool forVirtualBase, Address thisAddr,
+    bool inheritedFromVBase, const CXXInheritedCtorInitExpr *e) {
+
+  CallArgList ctorArgs;
+  CallArg thisArg(RValue::get(getAsNaturalPointerTo(
+                      thisAddr, d->getThisType()->getPointeeType())),
+                  d->getThisType());
+
+  if (inheritedFromVBase &&
+      cgm.getTarget().getCXXABI().hasConstructorVariants()) {
+    cgm.errorNYI(
+        e->getSourceRange(),
+        "emitInheritedCXXConstructorCall inheritedFromVBasewith ctor 
variants");
+    return;
+  } else if (!cxxInheritedCtorInitExprArgs.empty()) {
+    // The inheriting constructor was inlined; just inject its arguments.
+    assert(cxxInheritedCtorInitExprArgs.size() >= d->getNumParams() &&
+           "wrong number of parameters for inherited constructor call");
+    ctorArgs = cxxInheritedCtorInitExprArgs;
+    ctorArgs[0] = thisArg;
+  } else {
+    ctorArgs.push_back(thisArg);
+    const auto *outerCtor = cast<CXXConstructorDecl>(curCodeDecl);
+    assert(outerCtor->getNumParams() == d->getNumParams());
+    assert(!outerCtor->isVariadic() && "should have been inlined");
+
+    for (const ParmVarDecl *param : outerCtor->parameters()) {
+      assert(getContext().hasSameUnqualifiedType(
+          outerCtor->getParamDecl(param->getFunctionScopeIndex())->getType(),
+          param->getType()));
+      emitDelegateCallArg(ctorArgs, param, e->getLocation());
+
+      if (param->hasAttr<PassObjectSizeAttr>())
+        cgm.errorNYI(
+            e->getLocation(),
+            "emitInheritedCXXConstructorCall: pass object size attr argument");
+    }
+  }
+
+  emitCXXConstructorCall(d, Ctor_Base, forVirtualBase, /*delegating=*/false,
+                         thisAddr, ctorArgs, e->getLocation());
+}
+
+void CIRGenFunction::emitInlinedInheritingCXXConstructorCall(
+    SourceLocation loc, const CXXConstructorDecl *d, CXXCtorType ctorType,
+    bool forVirtualBase, bool delegating, CallArgList &args) {
+  GlobalDecl gd(d, ctorType);
+  assert(!cir::MissingFeatures::generateDebugInfo());
+  assert(!cir::MissingFeatures::runCleanupsScope());
+  InlinedInheritingConstructorScope scope(*this, gd);
+
+  // Save the arguments to be passed to the inherited constructor.
+  cxxInheritedCtorInitExprArgs = args;
+
+  FunctionArgList params;
+  QualType retTy = buildFunctionArgList(gd, params);
+
+  cgm.getCXXABI().addImplicitConstructorArgs(*this, d, ctorType, 
forVirtualBase,
+                                             delegating, args);
+
+  // Emit a simplified prolog. We only need to emit the implicit params.
+  assert(args.size() >= params.size() && "too few arguments for call");
+  for (auto [idx, arg, parm] :
+       llvm::zip_longest(llvm::index_range{0, args.size()}, args, params)) {
+    if (idx < params.size() && isa<ImplicitParamDecl>(*parm)) {
+      mlir::Location parmLoc = getLoc((*parm)->getSourceRange());
+      RValue argVal = arg->getRValue(*this, parmLoc);
+
+      LValue allocaVal = makeAddrLValue(
+          createTempAlloca(convertType((*parm)->getType()),
+                           getContext().getDeclAlign(*parm), parmLoc),
+          (*parm)->getType());
+
+      emitStoreThroughLValue(argVal, allocaVal, /*isInit=*/true);
+
+      setAddrOfLocalVar((*parm), allocaVal.getAddress());
+    }
+  }
+
+  // FIXME(cir): it isn't clear what it takes to get here with a constructor?
+  // Leave as an NYI until we come across a reproducer.
+  if (!retTy->isVoidType())
+    cgm.errorNYI(d->getSourceRange(),
+                 "emitInlinedInheritingCXXConstructorCall: non-void return");
+
+  cgm.getCXXABI().emitInstanceFunctionProlog(loc, *this);
+  cxxThisValue = cxxabiThisValue;
+  emitCtorPrologue(d, ctorType, params);
+}
+
 void CIRGenFunction::emitCXXConstructorCall(
     const CXXConstructorDecl *d, CXXCtorType type, bool forVirtualBase,
     bool delegating, Address thisAddr, CallArgList &args, SourceLocation loc) {
@@ -1370,10 +1490,14 @@ void CIRGenFunction::emitCXXConstructorCall(
   bool passPrototypeArgs = true;
 
   // Check whether we can actually emit the constructor before trying to do so.
-  if (d->getInheritedConstructor()) {
-    cgm.errorNYI(d->getSourceRange(),
-                 "emitCXXConstructorCall: inherited constructor");
-    return;
+  if (auto inherited = d->getInheritedConstructor()) {
+    passPrototypeArgs = getTypes().inheritingCtorHasParams(inherited, type);
+    if (passPrototypeArgs &&
+        !canEmitDelegateCallArgs(cgm, cgm.getASTContext(), d, type)) {
+      emitInlinedInheritingCXXConstructorCall(loc, d, type, forVirtualBase,
+                                              delegating, args);
+      return;
+    }
   }
 
   // Insert any ABI-specific implicit constructor arguments.
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp 
b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
index ffce8a6bf86a7..21a6f9209bb17 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprAggregate.cpp
@@ -501,8 +501,11 @@ class AggExprEmitter : public StmtVisitor<AggExprEmitter> {
     Visit(dae->getExpr());
   }
   void VisitCXXInheritedCtorInitExpr(const CXXInheritedCtorInitExpr *e) {
-    cgf.cgm.errorNYI(e->getSourceRange(),
-                     "AggExprEmitter: VisitCXXInheritedCtorInitExpr");
+    AggValueSlot slot =
+        ensureSlot(cgf.getLoc(e->getSourceRange()), e->getType());
+    cgf.emitInheritedCXXConstructorCall(e->getConstructor(),
+                                        e->constructsVBase(), 
slot.getAddress(),
+                                        e->inheritedFromVBase(), e);
   }
 
   /// Emit the initializer for a std::initializer_list initialized with a
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp 
b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
index f7f9331060956..fcfbeb809371e 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.cpp
@@ -990,13 +990,19 @@ clang::QualType 
CIRGenFunction::buildFunctionArgList(clang::GlobalDecl gd,
     cgm.getCXXABI().buildThisParam(*this, args);
   }
 
+  bool passedParams = true;
   if (const auto *cd = dyn_cast<CXXConstructorDecl>(fd))
-    if (cd->getInheritedConstructor())
-      cgm.errorNYI(fd->getSourceRange(),
-                   "buildFunctionArgList: inherited constructor");
-
-  for (auto *param : fd->parameters())
-    args.push_back(param);
+    if (auto inherited = cd->getInheritedConstructor())
+      passedParams =
+          getTypes().inheritingCtorHasParams(inherited, gd.getCtorType());
+
+  if (passedParams) {
+    for (auto *param : fd->parameters()) {
+      args.push_back(param);
+      if (param->hasAttr<PassObjectSizeAttr>())
+        cgm.errorNYI(param->getSourceRange(), "pass-object-size attribute");
+    }
+  }
 
   if (md && (isa<CXXConstructorDecl>(md) || isa<CXXDestructorDecl>(md)))
     cgm.getCXXABI().addImplicitStructorParams(*this, retTy, args);
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunction.h 
b/clang/lib/CIR/CodeGen/CIRGenFunction.h
index 88c7996eab569..612fee560f8ee 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunction.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunction.h
@@ -137,11 +137,16 @@ class CIRGenFunction : public CIRGenTypeCache {
   /// expression.
   Address cxxDefaultInitExprThis = Address::invalid();
 
+  /// The values of function arguments to use when evaluating
+  /// CXXInheritedCtorInitExprs within this context.
+  CallArgList cxxInheritedCtorInitExprArgs;
+
   // Holds the Decl for the current outermost non-closure context
   const clang::Decl *curFuncDecl = nullptr;
   /// This is the inner-most code context, which includes blocks.
   const clang::Decl *curCodeDecl = nullptr;
   const CIRGenFunctionInfo *curFnInfo = nullptr;
+  QualType fnRetTy;
 
   /// The current function or global initializer that is generated code for.
   /// This is usually a cir::FuncOp, but it can also be a cir::GlobalOp for
@@ -1564,6 +1569,15 @@ class CIRGenFunction : public CIRGenTypeCache {
                               bool delegating, Address thisAddr,
                               CallArgList &args, clang::SourceLocation loc);
 
+  void emitInheritedCXXConstructorCall(const CXXConstructorDecl *d,
+                                       bool forVirtualBase, Address thisAddr,
+                                       bool inheritedFromVBase,
+                                       const CXXInheritedCtorInitExpr *e);
+
+  void emitInlinedInheritingCXXConstructorCall(
+      SourceLocation loc, const CXXConstructorDecl *d, CXXCtorType ctorType,
+      bool forVirtualBase, bool delegating, CallArgList &args);
+
   void emitCXXDeleteExpr(const CXXDeleteExpr *e);
 
   void emitCXXDestructorCall(const CXXDestructorDecl *dd, CXXDtorType type,
@@ -2395,6 +2409,58 @@ class CIRGenFunction : public CIRGenTypeCache {
 
 private:
   QualType getVarArgType(const Expr *arg);
+
+  class InlinedInheritingConstructorScope {
+  public:
+    InlinedInheritingConstructorScope(CIRGenFunction &cgf, GlobalDecl gd)
+        : cgf(cgf), oldCurGD(cgf.curGD), oldCurFuncDecl(cgf.curFuncDecl),
+          oldCurCodeDecl(cgf.curCodeDecl),
+          oldCxxabiThisDecl(cgf.cxxabiThisDecl),
+          oldCxxThisValue(cgf.cxxThisValue),
+          oldCxxThisAlignment(cgf.cxxThisAlignment),
+          oldReturnValue(cgf.returnValue), oldFnRetTy(cgf.fnRetTy),
+          oldCxxInheritedCtorInitExprArgs(
+              std::move(cgf.cxxInheritedCtorInitExprArgs)) {
+      cgf.curGD = gd;
+      cgf.curFuncDecl = cast<CXXConstructorDecl>(gd.getDecl());
+      cgf.curCodeDecl = cgf.curFuncDecl;
+      cgf.cxxabiThisDecl = nullptr;
+      cgf.cxxabiThisValue = nullptr;
+      cgf.cxxThisValue = nullptr;
+      cgf.cxxThisAlignment = CharUnits();
+      cgf.returnValue = Address::invalid();
+      cgf.fnRetTy = QualType();
+      cgf.cxxInheritedCtorInitExprArgs.clear();
+      // FIXME: at one point when we wnat to call one of these, we'll need
+      // CXXInheritedCtorInitExprArgs here too.
+    }
+    ~InlinedInheritingConstructorScope() {
+      cgf.curGD = oldCurGD;
+      cgf.curFuncDecl = oldCurFuncDecl;
+      cgf.curCodeDecl = oldCurCodeDecl;
+      cgf.cxxabiThisDecl = oldCxxabiThisDecl;
+      cgf.cxxabiThisValue = oldCxxabiThisValue;
+      cgf.cxxThisValue = oldCxxThisValue;
+      cgf.cxxThisAlignment = oldCxxThisAlignment;
+      cgf.returnValue = oldReturnValue;
+      cgf.fnRetTy = oldFnRetTy;
+      cgf.cxxInheritedCtorInitExprArgs =
+          std::move(oldCxxInheritedCtorInitExprArgs);
+    }
+
+  private:
+    CIRGenFunction &cgf;
+    GlobalDecl oldCurGD;
+    const Decl *oldCurFuncDecl;
+    const Decl *oldCurCodeDecl;
+    ImplicitParamDecl *oldCxxabiThisDecl;
+    mlir::Value oldCxxabiThisValue;
+    mlir::Value oldCxxThisValue;
+    clang::CharUnits oldCxxThisAlignment;
+    Address oldReturnValue;
+    QualType oldFnRetTy;
+    CallArgList oldCxxInheritedCtorInitExprArgs;
+  };
 };
 
 } // namespace clang::CIRGen
diff --git a/clang/lib/CIR/CodeGen/CIRGenTypes.h 
b/clang/lib/CIR/CodeGen/CIRGenTypes.h
index 172b348ac78cf..c881b1b6e69e4 100644
--- a/clang/lib/CIR/CodeGen/CIRGenTypes.h
+++ b/clang/lib/CIR/CodeGen/CIRGenTypes.h
@@ -29,6 +29,7 @@ class ASTContext;
 class FunctionType;
 class GlobalDecl;
 class QualType;
+class TargetInfo;
 class Type;
 } // namespace clang
 
@@ -132,6 +133,11 @@ class CIRGenTypes {
 
   cir::FuncType getFunctionType(clang::GlobalDecl gd);
 
+  /// Determine if a C++ inheriting constructor should have parameters matching
+  /// those of its inherited constructor.
+  bool inheritingCtorHasParams(const InheritedConstructor &inherited,
+                               CXXCtorType type);
+
   // The arrangement methods are split into three families:
   //   - those meant to drive the signature and prologue/epilogue
   //     of a function declaration or definition,
diff --git a/clang/test/CIR/CodeGen/inherited-ctors.cpp 
b/clang/test/CIR/CodeGen/inherited-ctors.cpp
new file mode 100644
index 0000000000000..158bc9f11b94a
--- /dev/null
+++ b/clang/test/CIR/CodeGen/inherited-ctors.cpp
@@ -0,0 +1,182 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o 
%t.cir
+// RUN: FileCheck --check-prefix=CIR --input-file=%t.cir %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o 
%t-cir.ll
+// RUN: FileCheck --check-prefix=LLVM --input-file=%t-cir.ll %s
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o %t.ll
+// RUN: FileCheck --check-prefix=OGCG --input-file=%t.ll %s
+
+struct Base {
+  Base(int i);
+  Base(float, ...);
+};
+
+struct Derived : Base {
+  using Base::Base;
+};
+
+struct VirtDerived : virtual Base {
+  using Base::Base;
+};
+
+struct VirtualDelegatingCtor : VirtDerived {
+  VirtualDelegatingCtor(int x) : Base(x), VirtDerived(x){}
+};
+
+void emitDelegateCallArgs() {
+  // ONLY PassPrototypeArgs
+  Derived canEmitDelegateCallArgs{1};
+}
+
+void cannotEmitDelegateCallArgs() {
+  // Inside of the PassPrototypeArgs && !canEmitDelegateCallArgs
+  Derived cannotEmitDelgateCallArgs{1.1f,2,3.0};
+}
+void fallsthrough() {
+  // !PassPrototypeArgs
+  VirtualDelegatingCtor noInheritingCtorHasParams{1};
+}
+
+
+// LLVM and OGCG check labels are identical other than the 1 difference called 
out (and ordering).
+// CIR-LABEL: cir.func private @_ZN4BaseC2Ei(!cir.ptr<!rec_Base>{{.*}}, 
!s32i{{.*}}) special_member<#cir.cxx_ctor<!rec_Base, custom>>
+// LLVM-LABEL: declare void @_ZN4BaseC2Ei(ptr {{.*}}, i32 {{.*}})
+//
+//
+// CIR-LABEL: cir.func no_inline comdat linkonce_odr 
@_ZN7DerivedCI24BaseEi(%{{.*}}: !cir.ptr<!rec_Derived>{{.*}}, %{{.*}}: 
!s32i{{.*}}) special_member<#cir.cxx_ctor<!rec_Derived, custom>>
+// CIR: %[[THIS_ALLOCA:.*]] = cir.alloca !cir.ptr<!rec_Derived>, 
!cir.ptr<!cir.ptr<!rec_Derived>>, ["this", init]
+// CIR: %[[INT_ALLOCA:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["", init]
+// CIR: %[[THIS_LOAD:.*]] = cir.load %[[THIS_ALLOCA]] : 
!cir.ptr<!cir.ptr<!rec_Derived>>, !cir.ptr<!rec_Derived>
+// CIR: %[[BASE_ADDR:.*]] = cir.base_class_addr %[[THIS_LOAD]] : 
!cir.ptr<!rec_Derived> nonnull [0] -> !cir.ptr<!rec_Base>
+// CIR: %[[INT:.*]] = cir.load align(4) %[[INT_ALLOCA]] : !cir.ptr<!s32i>, 
!s32i
+// CIR: cir.call @_ZN4BaseC2Ei(%[[BASE_ADDR]], %[[INT]]) : 
(!cir.ptr<!rec_Base>{{.*}}, !s32i{{.*}}) -> () 
+//
+// LLVM-LABEL: define linkonce_odr void @_ZN7DerivedCI24BaseEi(ptr {{.*}}, i32 
{{.*}})
+// LLVM: %[[THIS_ALLOCA:.*]] = alloca ptr
+// LLVM: %[[INT_ALLOCA:.*]] = alloca i32
+// LLVM: %[[BASE_ADDR:.*]] = load ptr, ptr %[[THIS_ALLOCA]]
+// LLVM: %[[INT:.*]] = load i32, ptr %[[INT_ALLOCA]]
+// LLVM: call void @_ZN4BaseC2Ei(ptr {{.*}}%[[BASE_ADDR]], i32 {{.*}}[[INT]])
+//
+//
+// CIR-LABEL: cir.func no_inline dso_local @_Z20emitDelegateCallArgsv()
+// CIR: cir.call @_ZN7DerivedCI14BaseEi(%{{.*}}, %{{.*}}) : 
(!cir.ptr<!rec_Derived>{{.*}}, !s32i{{.*}}) -> ()
+// LLVM-LABEL: define dso_local void @_Z20emitDelegateCallArgsv()
+// LLVM: call void @_ZN7DerivedCI14BaseEi(ptr {{.*}}, i32 {{.*}}1)
+//
+// CIR-LABEL: cir.func private @_ZN4BaseC2Efz(!cir.ptr<!rec_Base>{{.*}}, 
!cir.float{{.*}}, ...) special_member<#cir.cxx_ctor<!rec_Base, custom>>
+// LLVM-LABEL: declare void @_ZN4BaseC2Efz(ptr {{.*}}, float {{.*}}, ...)
+//
+// CIR-LABEL: cir.func no_inline dso_local @_Z26cannotEmitDelegateCallArgsv()
+// CIR: %[[TMP_ALLOCA:.*]] = cir.alloca !cir.ptr<!rec_Derived>, 
!cir.ptr<!cir.ptr<!rec_Derived>>, ["tmp", init]
+// CIR: %[[FP_1_1:.*]] = cir.const #cir.fp<1.1{{.*}}> : !cir.float
+// CIR: %[[TWO:.*]] = cir.const #cir.int<2> : !s32i
+// CIR: %[[THREE:.*]] = cir.const #cir.fp<3.0{{.*}}> : !cir.double
+// CIR: %[[LOAD_DERIVED:.*]] = cir.load %[[TMP_ALLOCA]] : 
!cir.ptr<!cir.ptr<!rec_Derived>>, !cir.ptr<!rec_Derived>
+// CIR: %[[BASE_ADDR:.*]] = cir.base_class_addr %[[LOAD_DERIVED]] : 
!cir.ptr<!rec_Derived> nonnull [0] -> !cir.ptr<!rec_Base>
+// CIR: cir.call @_ZN4BaseC2Efz(%[[BASE_ADDR]], %[[FP_1_1]], %[[TWO]], 
%[[THREE]]) : (!cir.ptr<!rec_Base>{{.*}}, !cir.float{{.*}}, !s32i{{.*}}, 
!cir.double{{.*}}) -> ()
+//
+// LLVM-LABEL: define dso_local void @_Z26cannotEmitDelegateCallArgsv()
+// LLVM: %[[TMP_ALLOCA:.*]] = alloca ptr
+// LLVM: %[[TMP_LOAD:.*]] = load ptr, ptr %[[TMP_ALLOCA]]
+// LLVM: call void (ptr, float, ...) @_ZN4BaseC2Efz(ptr {{.*}}%[[TMP_LOAD]], 
float {{.*}}0x3FF19999A{{.*}}, i32 {{.*}}2, double {{.*}}3.000000e+00)
+//
+// CIR-LABEL: cir.func no_inline comdat linkonce_odr 
@_ZN11VirtDerivedCI24BaseEi(%{{.*}}: !cir.ptr<!rec_VirtDerived> {{.*}}, 
%{{.*}}: !cir.ptr<!cir.ptr<!void>>{{.*}}) 
special_member<#cir.cxx_ctor<!rec_VirtDerived, custom>>
+// CIR: %[[THIS_ALLOCA:.*]] = cir.alloca !cir.ptr<!rec_VirtDerived>, 
!cir.ptr<!cir.ptr<!rec_VirtDerived>>, ["this", init] {alignment = 8 : i64}
+// CIR: %[[VTT_ALLOCA:.]] = cir.alloca !cir.ptr<!cir.ptr<!void>>, 
!cir.ptr<!cir.ptr<!cir.ptr<!void>>>, ["vtt", init] {alignment = 8 : i64}
+// CIR: %[[THIS:.*]] = cir.load %[[THIS_ALLOCA]] : !cir.ptr<...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/191467
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to