llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clangir

Author: Andy Kaylor (andykaylor)

<details>
<summary>Changes</summary>

This change adds the support needed to handle a C++ member function call, 
including arranging the function type with an argument added for the 'this' 
parameter. It was necessary to introduce the class to handle the CXXABI, but at 
this time no target-specific subclasses have been added.

---

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


14 Files Affected:

- (modified) clang/include/clang/CIR/MissingFeatures.h (+10-1) 
- (added) clang/lib/CIR/CodeGen/CIRGenCXXABI.cpp (+45) 
- (modified) clang/lib/CIR/CodeGen/CIRGenCXXABI.h (+26-1) 
- (added) clang/lib/CIR/CodeGen/CIRGenCXXExpr.cpp (+186) 
- (modified) clang/lib/CIR/CodeGen/CIRGenCall.cpp (+92-5) 
- (modified) clang/lib/CIR/CodeGen/CIRGenCall.h (+8) 
- (modified) clang/lib/CIR/CodeGen/CIRGenExpr.cpp (+32-5) 
- (modified) clang/lib/CIR/CodeGen/CIRGenFunction.cpp (+8-2) 
- (modified) clang/lib/CIR/CodeGen/CIRGenFunction.h (+15) 
- (modified) clang/lib/CIR/CodeGen/CIRGenModule.cpp (+11-4) 
- (modified) clang/lib/CIR/CodeGen/CIRGenTypes.cpp (+1-1) 
- (modified) clang/lib/CIR/CodeGen/CIRGenTypes.h (+22) 
- (modified) clang/lib/CIR/CodeGen/CMakeLists.txt (+2) 
- (added) clang/test/CIR/CodeGen/member-functions.cpp (+44) 


``````````diff
diff --git a/clang/include/clang/CIR/MissingFeatures.h 
b/clang/include/clang/CIR/MissingFeatures.h
index 484822c351746..a4324053ba476 100644
--- a/clang/include/clang/CIR/MissingFeatures.h
+++ b/clang/include/clang/CIR/MissingFeatures.h
@@ -90,7 +90,6 @@ struct MissingFeatures {
   static bool opCallArgEvaluationOrder() { return false; }
   static bool opCallCallConv() { return false; }
   static bool opCallSideEffect() { return false; }
-  static bool opCallChainCall() { return false; }
   static bool opCallNoPrototypeFunc() { return false; }
   static bool opCallMustTail() { return false; }
   static bool opCallIndirect() { return false; }
@@ -107,6 +106,13 @@ struct MissingFeatures {
   static bool opCallLandingPad() { return false; }
   static bool opCallContinueBlock() { return false; }
 
+  // FnInfoOpts -- This is used to track whether calls are chain calls or
+  // instance methods. Classic codegen uses chain call to track and extra free
+  // register for x86 and uses instance method as a condition for a thunk
+  // generation special case. It's not clear that we need either of these in
+  // pre-lowering CIR codegen.
+  static bool opCallFnInfoOpts() { return false; }
+
   // ScopeOp handling
   static bool opScopeCleanupRegion() { return false; }
 
@@ -189,6 +195,9 @@ struct MissingFeatures {
   static bool constEmitterArrayILE() { return false; }
   static bool constEmitterVectorILE() { return false; }
   static bool needsGlobalCtorDtor() { return false; }
+  static bool emitTypeCheck() { return false; }
+  static bool cxxabiThisDecl() { return false; }
+  static bool cxxabiThisAlignment() { return false; }
 
   // Missing types
   static bool dataMemberType() { return false; }
diff --git a/clang/lib/CIR/CodeGen/CIRGenCXXABI.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCXXABI.cpp
new file mode 100644
index 0000000000000..fcd45768656ff
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenCXXABI.cpp
@@ -0,0 +1,45 @@
+//===----- CirGenCXXABI.cpp - Interface to C++ ABIs 
-----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This provides an abstract class for C++ code generation. Concrete subclasses
+// of this implement code generation for specific C++ ABIs.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIRGenCXXABI.h"
+#include "CIRGenFunction.h"
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/GlobalDecl.h"
+
+using namespace clang;
+using namespace clang::CIRGen;
+
+CIRGenCXXABI::~CIRGenCXXABI() {}
+
+void CIRGenCXXABI::buildThisParam(CIRGenFunction &cgf,
+                                  FunctionArgList &params) {
+  const auto *md = cast<CXXMethodDecl>(cgf.curGD.getDecl());
+
+  // FIXME: I'm not entirely sure I like using a fake decl just for code
+  // generation. Maybe we can come up with a better way?
+  auto *thisDecl =
+      ImplicitParamDecl::Create(cgm.getASTContext(), nullptr, 
md->getLocation(),
+                                &cgm.getASTContext().Idents.get("this"),
+                                md->getThisType(), ImplicitParamKind::CXXThis);
+  params.push_back(thisDecl);
+
+  // Classic codegen save thisDecl in CodeGenFunction::CXXABIThisDecl, but it
+  // doesn't seem to be needed in CIRGen.
+  assert(!cir::MissingFeatures::cxxabiThisDecl());
+
+  // Classic codegen computes the alignment of thisDecl and saves it in
+  // CodeGenFunction::CXXABIThisAlignment, but it doesn't seem to be needed in
+  // CIRGen.
+  assert(!cir::MissingFeatures::cxxabiThisAlignment());
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h 
b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
index 5279307e19613..b5c33a29442c7 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
+++ b/clang/lib/CIR/CodeGen/CIRGenCXXABI.h
@@ -14,6 +14,7 @@
 #ifndef LLVM_CLANG_LIB_CIR_CIRGENCXXABI_H
 #define LLVM_CLANG_LIB_CIR_CIRGENCXXABI_H
 
+#include "CIRGenCall.h"
 #include "CIRGenModule.h"
 
 #include "clang/AST/Mangle.h"
@@ -31,9 +32,33 @@ class CIRGenCXXABI {
   // implemented.
   CIRGenCXXABI(CIRGenModule &cgm)
       : cgm(cgm), mangleContext(cgm.getASTContext().createMangleContext()) {}
-  ~CIRGenCXXABI();
+  virtual ~CIRGenCXXABI();
 
 public:
+  /// Get the type of the implicit "this" parameter used by a method. May 
return
+  /// zero if no specific type is applicable, e.g. if the ABI expects the 
"this"
+  /// parameter to point to some artificial offset in a complete object due to
+  /// vbases being reordered.
+  virtual const clang::CXXRecordDecl *
+  getThisArgumentTypeForMethod(const clang::CXXMethodDecl *md) {
+    return md->getParent();
+  }
+
+  /// Build a parameter variable suitable for 'this'.
+  void buildThisParam(CIRGenFunction &cgf, FunctionArgList &params);
+
+  /// Returns true if the given constructor or destructor is one of the kinds
+  /// that the ABI says returns 'this' (only applies when called non-virtually
+  /// for destructors).
+  ///
+  /// There currently is no way to indicate if a destructor returns 'this' when
+  /// called virtually, and CIR generation does not support this case.
+  virtual bool hasThisReturn(clang::GlobalDecl gd) const { return false; }
+
+  virtual bool hasMostDerivedReturn(clang::GlobalDecl gd) const {
+    return false;
+  }
+
   /// Gets the mangle context.
   clang::MangleContext &getMangleContext() { return *mangleContext; }
 };
diff --git a/clang/lib/CIR/CodeGen/CIRGenCXXExpr.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCXXExpr.cpp
new file mode 100644
index 0000000000000..906c212f0fa8a
--- /dev/null
+++ b/clang/lib/CIR/CodeGen/CIRGenCXXExpr.cpp
@@ -0,0 +1,186 @@
+//===--- CIRGenExprCXX.cpp - Emit CIR Code for C++ expressions 
------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This contains code dealing with code generation of C++ expressions
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIRGenCXXABI.h"
+#include "CIRGenFunction.h"
+
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/CIR/MissingFeatures.h"
+
+using namespace clang;
+using namespace clang::CIRGen;
+
+namespace {
+struct MemberCallInfo {
+  RequiredArgs reqArgs;
+  // Number of prefix arguments for the call. Ignores the `this` pointer.
+  unsigned prefixSize;
+};
+} // namespace
+
+static MemberCallInfo commonBuildCXXMemberOrOperatorCall(
+    CIRGenFunction &cgf, const CXXMethodDecl *md, mlir::Value thisPtr,
+    mlir::Value implicitParam, QualType implicitParamTy, const CallExpr *ce,
+    CallArgList &args, CallArgList *rtlArgs) {
+  assert(ce == nullptr || isa<CXXMemberCallExpr>(ce) ||
+         isa<CXXOperatorCallExpr>(ce));
+  assert(md->isInstance() &&
+         "Trying to emit a member or operator call expr on a static method!");
+
+  // Push the this ptr.
+  const CXXRecordDecl *rd =
+      cgf.cgm.getCXXABI().getThisArgumentTypeForMethod(md);
+  args.add(RValue::get(thisPtr), cgf.getTypes().deriveThisType(rd, md));
+
+  // If there is an implicit parameter (e.g. VTT), emit it.
+  if (implicitParam) {
+    args.add(RValue::get(implicitParam), implicitParamTy);
+  }
+
+  const auto *fpt = md->getType()->castAs<FunctionProtoType>();
+  RequiredArgs required =
+      RequiredArgs::getFromProtoWithExtraSlots(fpt, args.size());
+  unsigned prefixSize = args.size() - 1;
+
+  // Add the rest of the call args
+  if (rtlArgs) {
+    // Special case: if the caller emitted the arguments right-to-left already
+    // (prior to emitting the *this argument), we're done. This happens for
+    // assignment operators.
+    args.addFrom(*rtlArgs);
+  } else if (ce) {
+    // Special case: skip first argument of CXXOperatorCall (it is "this").
+    unsigned argsToSkip = isa<CXXOperatorCallExpr>(ce) ? 1 : 0;
+    cgf.emitCallArgs(args, fpt, drop_begin(ce->arguments(), argsToSkip),
+                     ce->getDirectCallee());
+  } else {
+    assert(
+        fpt->getNumParams() == 0 &&
+        "No CallExpr specified for function with non-zero number of 
arguments");
+  }
+
+  //  return {required, prefixSize};
+  return {required, prefixSize};
+}
+
+RValue CIRGenFunction::emitCXXMemberOrOperatorMemberCallExpr(
+    const CallExpr *ce, const CXXMethodDecl *md, ReturnValueSlot returnValue,
+    bool hasQualifier, NestedNameSpecifier *qualifier, bool isArrow,
+    const Expr *base) {
+  assert(isa<CXXMemberCallExpr>(ce) || isa<CXXOperatorCallExpr>(ce));
+
+  if (md->isVirtual()) {
+    cgm.errorNYI(ce->getSourceRange(),
+                 "emitCXXMemberOrOperatorMemberCallExpr: virtual call");
+    return RValue::get(nullptr);
+  }
+
+  bool trivialForCodegen =
+      md->isTrivial() || (md->isDefaulted() && md->getParent()->isUnion());
+  bool trivialAssignment =
+      trivialForCodegen &&
+      (md->isCopyAssignmentOperator() || md->isMoveAssignmentOperator()) &&
+      !md->getParent()->mayInsertExtraPadding();
+  (void)trivialAssignment;
+
+  // C++17 demands that we evaluate the RHS of a (possibly-compound) assignment
+  // operator before the LHS.
+  CallArgList rtlArgStorage;
+  CallArgList *rtlArgs = nullptr;
+  if (auto *oce = dyn_cast<CXXOperatorCallExpr>(ce)) {
+    cgm.errorNYI(oce->getSourceRange(),
+                 "emitCXXMemberOrOperatorMemberCallExpr: operator call");
+    return RValue::get(nullptr);
+  }
+
+  LValue thisPtr;
+  if (isArrow) {
+    LValueBaseInfo baseInfo;
+    assert(!cir::MissingFeatures::opTBAA());
+    Address thisValue = emitPointerWithAlignment(base, &baseInfo);
+    thisPtr = makeAddrLValue(thisValue, base->getType(), baseInfo);
+  } else {
+    thisPtr = emitLValue(base);
+  }
+
+  if (const CXXConstructorDecl *ctor = dyn_cast<CXXConstructorDecl>(md)) {
+    cgm.errorNYI(ce->getSourceRange(),
+                 "emitCXXMemberOrOperatorMemberCallExpr: constructor call");
+    return RValue::get(nullptr);
+  }
+
+  if (trivialForCodegen) {
+    if (isa<CXXDestructorDecl>(md))
+      return RValue::get(nullptr);
+
+    if (trivialAssignment) {
+      cgm.errorNYI(ce->getSourceRange(),
+                   "emitCXXMemberOrOperatorMemberCallExpr: trivial 
assignment");
+      return RValue::get(nullptr);
+    } else {
+      assert(md->getParent()->mayInsertExtraPadding() &&
+             "unknown trivial member function");
+    }
+  }
+
+  // Compute the function type we're calling
+  const CXXMethodDecl *calleeDecl = md;
+  const CIRGenFunctionInfo *fInfo = nullptr;
+  if (const auto *dtor = dyn_cast<CXXDestructorDecl>(calleeDecl)) {
+    cgm.errorNYI(ce->getSourceRange(),
+                 "emitCXXMemberOrOperatorMemberCallExpr: destructor call");
+    return RValue::get(nullptr);
+  } else {
+    fInfo = &cgm.getTypes().arrangeCXXMethodDeclaration(calleeDecl);
+  }
+
+  mlir::Type ty = cgm.getTypes().getFunctionType(*fInfo);
+
+  assert(!cir::MissingFeatures::sanitizers());
+  assert(!cir::MissingFeatures::emitTypeCheck());
+
+  if (const auto *dtor = dyn_cast<CXXDestructorDecl>(calleeDecl)) {
+    cgm.errorNYI(ce->getSourceRange(),
+                 "emitCXXMemberOrOperatorMemberCallExpr: destructor call");
+    return RValue::get(nullptr);
+  }
+
+  assert(!cir::MissingFeatures::sanitizers());
+  if (getLangOpts().AppleKext) {
+    cgm.errorNYI(ce->getSourceRange(),
+                 "emitCXXMemberOrOperatorMemberCallExpr: AppleKext");
+    return RValue::get(nullptr);
+  }
+  CIRGenCallee callee =
+      CIRGenCallee::forDirect(cgm.getAddrOfFunction(md, ty), GlobalDecl(md));
+
+  return emitCXXMemberOrOperatorCall(
+      calleeDecl, callee, returnValue, thisPtr.getPointer(),
+      /*ImplicitParam=*/nullptr, QualType(), ce, rtlArgs);
+}
+
+RValue CIRGenFunction::emitCXXMemberOrOperatorCall(
+    const CXXMethodDecl *md, const CIRGenCallee &callee,
+    ReturnValueSlot returnValue, mlir::Value thisPtr, mlir::Value 
implicitParam,
+    QualType implicitParamTy, const CallExpr *ce, CallArgList *rtlArgs) {
+  const auto *fpt = md->getType()->castAs<FunctionProtoType>();
+  CallArgList args;
+  MemberCallInfo callInfo = commonBuildCXXMemberOrOperatorCall(
+      *this, md, thisPtr, implicitParam, implicitParamTy, ce, args, rtlArgs);
+  auto &fnInfo = cgm.getTypes().arrangeCXXMethodCall(
+      args, fpt, callInfo.reqArgs, callInfo.prefixSize);
+  assert((ce || currSrcLoc) && "expected source location");
+  mlir::Location loc = ce ? getLoc(ce->getExprLoc()) : *currSrcLoc;
+  assert(!cir::MissingFeatures::opCallMustTail());
+  return emitCall(fnInfo, callee, returnValue, args, nullptr, loc);
+}
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index 17bfa19f9fd63..7590153410747 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -12,6 +12,7 @@
 
//===----------------------------------------------------------------------===//
 
 #include "CIRGenCall.h"
+#include "CIRGenCXXABI.h"
 #include "CIRGenFunction.h"
 #include "CIRGenFunctionInfo.h"
 #include "clang/CIR/MissingFeatures.h"
@@ -76,11 +77,30 @@ static void appendParameterTypes(const CIRGenTypes &cgt,
   cgt.getCGModule().errorNYI("appendParameterTypes: hasExtParameterInfos");
 }
 
+/// Derives the 'this' type for CIRGen purposes, i.e. ignoring method CVR
+/// qualification. Either or both of `rd` and `md` may be null. A null `rd`
+/// indicates that there is no meaningful 'this' type, and a null `md` can 
occur
+/// when calling a method pointer.
+CanQualType CIRGenTypes::deriveThisType(const CXXRecordDecl *rd,
+                                        const CXXMethodDecl *md) {
+  QualType recTy;
+  if (rd)
+    recTy = getASTContext().getTagDeclType(rd)->getCanonicalTypeInternal();
+  else
+    recTy = getASTContext().VoidTy;
+
+  if (md)
+    recTy = getASTContext().getAddrSpaceQualType(
+        recTy, md->getMethodQualifiers().getAddressSpace());
+  return getASTContext().getPointerType(CanQualType::CreateUnsafe(recTy));
+}
+
 /// Arrange the CIR function layout for a value of the given function type, on
 /// top of any implicit parameters already stored.
 static const CIRGenFunctionInfo &
 arrangeCIRFunctionInfo(CIRGenTypes &cgt, SmallVectorImpl<CanQualType> &prefix,
                        CanQual<FunctionProtoType> ftp) {
+  assert(!cir::MissingFeatures::opCallFnInfoOpts());
   RequiredArgs required =
       RequiredArgs::getFromProtoWithExtraSlots(ftp, prefix.size());
   assert(!cir::MissingFeatures::opCallExtParameterInfo());
@@ -112,24 +132,88 @@ arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, 
CIRGenModule &cgm,
   CanQualType retType = fnType->getReturnType()
                             ->getCanonicalTypeUnqualified()
                             .getUnqualifiedType();
+
+  assert(!cir::MissingFeatures::opCallFnInfoOpts());
   return cgt.arrangeCIRFunctionInfo(retType, argTypes, required);
 }
 
+/// Arrange a call to a C++ method, passing the given arguments.
+///
+/// numPrefixArgs is the number of the ABI-specific prefix arguments we have. 
It
+/// does not count `this`.
+const CIRGenFunctionInfo &CIRGenTypes::arrangeCXXMethodCall(
+    const CallArgList &args, const FunctionProtoType *proto,
+    RequiredArgs required, unsigned numPrefixArgs) {
+  assert(!cir::MissingFeatures::opCallExtParameterInfo());
+  assert(numPrefixArgs + 1 <= args.size() &&
+         "Emitting a call with less args than the required prefix?");
+
+  // FIXME: Kill copy.
+  llvm::SmallVector<CanQualType, 16> argTypes;
+  for (const CallArg &arg : args)
+    argTypes.push_back(astContext.getCanonicalParamType(arg.ty));
+
+  assert(!cir::MissingFeatures::opCallFnInfoOpts());
+  return arrangeCIRFunctionInfo(proto->getReturnType()
+                                    ->getCanonicalTypeUnqualified()
+                                    .getUnqualifiedType(),
+                                argTypes, required);
+}
+
 const CIRGenFunctionInfo &
 CIRGenTypes::arrangeFreeFunctionCall(const CallArgList &args,
                                      const FunctionType *fnType) {
   return arrangeFreeFunctionLikeCall(*this, cgm, args, fnType);
 }
 
+/// Arrange the argument and result information for a declaration or definition
+/// of the given C++ non-static member function. The member function must be an
+/// ordinary function, i.e. not a constructor or destructor.
+const CIRGenFunctionInfo &
+CIRGenTypes::arrangeCXXMethodDeclaration(const CXXMethodDecl *md) {
+  assert(!isa<CXXConstructorDecl>(md) && "wrong method for constructors!");
+  assert(!isa<CXXDestructorDecl>(md) && "wrong method for destructors!");
+
+  auto prototype =
+      md->getType()->getCanonicalTypeUnqualified().getAs<FunctionProtoType>();
+  assert(!cir::MissingFeatures::cudaSupport());
+
+  if (md->isInstance()) {
+    // The abstract case is perfectly fine.
+    auto *thisType = theCXXABI.getThisArgumentTypeForMethod(md);
+    return arrangeCXXMethodType(thisType, prototype.getTypePtr(), md);
+  }
+
+  return arrangeFreeFunctionType(prototype);
+}
+
+/// Arrange the argument and result information for a call to an unknown C++
+/// non-static member function of the given abstract type. (A null RD means we
+/// don't have any meaningful "this" argument type, so fall back to a generic
+/// pointer type). The member fucntion must be an ordinary function, i.e. not a
+/// constructor or destructor.
+const CIRGenFunctionInfo &
+CIRGenTypes::arrangeCXXMethodType(const CXXRecordDecl *rd,
+                                  const FunctionProtoType *ftp,
+                                  const CXXMethodDecl *md) {
+  llvm::SmallVector<CanQualType, 16> argTypes;
+
+  // Add the 'this' pointer.
+  argTypes.push_back(deriveThisType(rd, md));
+
+  assert(!cir::MissingFeatures::opCallFnInfoOpts());
+  return ::arrangeCIRFunctionInfo(
+      *this, argTypes,
+      ftp->getCanonicalTypeUnqualified().getAs<FunctionProtoType>());
+}
+
 /// Arrange the argument and result information for the declaration or
 /// definition of the given function.
 const CIRGenFunctionInfo &
 CIRGenTypes::arrangeFunctionDeclaration(const FunctionDecl *fd) {
-  if (const auto *md = dyn_cast<CXXMethodDecl>(fd)) {
-    if (md->isInstance()) {
-      cgm.errorNYI("arrangeFunctionDeclaration: instance method");
-    }
-  }
+  if (const auto *md = dyn_cast<CXXMethodDecl>(fd))
+    if (md->isInstance())
+      return arrangeCXXMethodDeclaration(md);
 
   CanQualType funcTy = fd->getType()->getCanonicalTypeUnqualified();
 
@@ -142,6 +226,7 @@ CIRGenTypes::arrangeFunctionDeclaration(const FunctionDecl 
*fd) {
   if (CanQual<FunctionNoProtoType> noProto =
           funcTy.getAs<FunctionNoProtoType>()) {
     assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());
+    assert(!cir::MissingFeatures::opCallFnInfoOpts());
     return arrangeCIRFunctionInfo(noProto->getReturnType(), std::nullopt,
                                   RequiredArgs::All);
   }
@@ -167,12 +252,14 @@ emitCallLikeOp(CIRGenFunction &cgf, mlir::Location 
callLoc,
 const CIRGenFunctionInfo &
 CIRGenTypes::arrangeFreeFunctionType(CanQual<FunctionProtoType> fpt) {
   SmallVector<CanQualType, 16> argTypes;
+  assert(!cir::MissingFeatures::opCallFnInfoOpts());
   return ::arrangeCIRFunctionInfo(*this, argTypes, fpt);
 }
 
 const CIRGenFunctionInfo &
 CIRGenTypes::arrangeFreeFunctionType(CanQual<FunctionNoProtoType> fnpt) {
   CanQualType resultType = fnpt->getReturnType().getUnqualifiedType();
+  assert(!cir::MissingFeatures::opCallFnInfoOpts());
   return arrangeCIRFunctionInfo(resultType, {}, RequiredArgs(0));
 }
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.h 
b/clang/lib/CIR/CodeGen/CIRGenCall.h
index 2ba1676eb6b97..5156f78e562ad 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.h
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.h
@@ -109,6 +109,14 @@ struct CallArg {
 class CallArgList : public llvm::SmallVector<CallArg, 8> {
 public:
   void add(RValue rvalue, clang::QualType type) { emplace_back(rvalue, type); }
+
+  /// Add all the arguments from another CallArgList to this one. After doing
+  /// this, the old CallArgList retains its list of arguments, but must not
+  /// be used to emit a call.
+  void addFr...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/140290
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to