https://github.com/Shashwatpandey4 created 
https://github.com/llvm/llvm-project/pull/182718



- Allows calls through unprototyped functions instead of errorNYI when the  
target permits variadic no-proto calls.
- In arrangeFunctionDeclaration, when isNoProtoCallVariadic() is true, emit   
no-proto functions as variadic with zero fixed parameters so multiple call 
sites with different arities do not cause CIR verification failures.
- In arrangeFreeFunctionLikeCall, do not force RequiredArgs(0) for no-proto;  
use the call-site argument types so the cast matches the promoted args  (e.g. 
noProto3).
- In emitCallArgs, set isVariadic for no-proto so arguments use promoted  
vararg types.
- Fix CIRGenFunctionInfo::Profile to use AddInteger for RequiredArgs so 
FoldingSet distinguishes RequiredArgs(0) from RequiredArgs::All.
- Update no-prototype.c tests and add no-prototype-variadic.c for the implicit 
printf / undeclared variadic case.

Fixes #182175

@andykaylor 

>From aa10b4593eed289599edd2aefcf4116967874b19 Mon Sep 17 00:00:00 2001
From: Shashwat Pandey <[email protected]>
Date: Sat, 21 Feb 2026 20:01:07 -0700
Subject: [PATCH] [CIR] Fix undeclared variadic function prototype and no-proto
 call handling

Enable no-proto calls and variadic no-proto declarations when the target
allows it; fix call-site type to use actual args; fix Profile for
RequiredArgs; add/update tests.

Fixes #182175

Co-authored-by: Cursor <[email protected]>
---
 clang/lib/CIR/CodeGen/CIRGenCall.cpp          | 39 +++++++++++++------
 clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h    |  2 +-
 .../test/CIR/CodeGen/no-prototype-variadic.c  | 12 ++++++
 clang/test/CIR/CodeGen/no-prototype.c         |  3 +-
 4 files changed, 43 insertions(+), 13 deletions(-)
 create mode 100644 clang/test/CIR/CodeGen/no-prototype-variadic.c

diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp 
b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
index 2039b439c783c..cea4ca393f76a 100644
--- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp
@@ -782,14 +782,12 @@ arrangeFreeFunctionLikeCall(CIRGenTypes &cgt, 
CIRGenModule &cgm,
       required = RequiredArgs::getFromProtoWithExtraSlots(proto, 0);
     if (proto->hasExtParameterInfos())
       cgm.errorNYI("call to functions with extra parameter info");
-  } else if (cgm.getTargetCIRGenInfo().isNoProtoCallVariadic(
-                 cast<FunctionNoProtoType>(fnType)))
-    cgm.errorNYI("call to function without a prototype");
+  }
 
   SmallVector<CanQualType, 16> argTypes;
+  argTypes.reserve(args.size());
   for (const CallArg &arg : args)
     argTypes.push_back(cgt.getASTContext().getCanonicalParamType(arg.ty));
-
   CanQualType retType = fnType->getReturnType()->getCanonicalTypeUnqualified();
 
   assert(!cir::MissingFeatures::opCallFnInfoOpts());
@@ -920,12 +918,26 @@ CIRGenTypes::arrangeFunctionDeclaration(const 
FunctionDecl *fd) {
   // TODO: setCUDAKernelCallingConvention
   assert(!cir::MissingFeatures::cudaSupport());
 
-  // When declaring a function without a prototype, always use a non-variadic
-  // type.
+  // Handle C89/gnu89 no-prototype functions (FunctionNoProtoType).
+  //
+  // In C89, a function declared without a prototype does not type-check
+  // arguments and may legally be called with additional arguments.
+  // If we model such functions as non-variadic, the first observed call-site
+  // would freeze the function signature to that arity, causing later calls
+  // with different argument counts to fail CIR verification.
+  //
+  // When the target ABI permits variadic no-proto calls, model the function
+  // as variadic with zero fixed parameters to preserve C semantics and keep
+  // the CIR function type stable across call sites.
   if (CanQual<FunctionNoProtoType> noProto =
           funcTy.getAs<FunctionNoProtoType>()) {
     assert(!cir::MissingFeatures::opCallCIRGenFuncInfoExtParamInfo());
     assert(!cir::MissingFeatures::opCallFnInfoOpts());
+
+    if (cgm.getTargetCIRGenInfo().isNoProtoCallVariadic(noProto.getTypePtr())) 
{
+      return arrangeCIRFunctionInfo(noProto->getReturnType(), {},
+                                    noProto->getExtInfo(), RequiredArgs(0));
+    }
     return arrangeCIRFunctionInfo(noProto->getReturnType(), {},
                                   noProto->getExtInfo(), RequiredArgs::All);
   }
@@ -1203,9 +1215,9 @@ void CIRGenFunction::emitCallArg(CallArgList &args, const 
clang::Expr *e,
 
   bool hasAggregateEvalKind = hasAggregateEvaluationKind(argType);
 
-  // In the Microsoft C++ ABI, aggregate arguments are destructed by the 
callee.
-  // However, we still have to push an EH-only cleanup in case we unwind before
-  // we make it to the call.
+  // In the Microsoft C++ ABI, aggregate arguments are destructed by the
+  // callee. However, we still have to push an EH-only cleanup in case we
+  // unwind before we make it to the call.
   if (argType->isRecordType() &&
       argType->castAsRecordDecl()->isParamDestroyedInCallee()) {
     assert(!cir::MissingFeatures::msabi());
@@ -1265,6 +1277,10 @@ void CIRGenFunction::emitCallArgs(
     assert(!cir::MissingFeatures::opCallCallConv());
     argTypes.assign(fpt->param_type_begin() + paramsToSkip,
                     fpt->param_type_end());
+  } else {
+    // No prototype (e.g. implicit/old-style): allow extra args.
+    // Treat as variadic so we use promoted vararg types for all arguments.
+    isVariadic = true;
   }
 
   // If we still have any arguments, emit them using the type of the argument.
@@ -1275,8 +1291,9 @@ void CIRGenFunction::emitCallArgs(
   // We must evaluate arguments from right to left in the MS C++ ABI, because
   // arguments are destroyed left to right in the callee. As a special case,
   // there are certain language constructs taht require left-to-right
-  // evaluation, and in those cases we consider the evaluation order 
requirement
-  // to trump the "destruction order is reverse construction order" guarantee.
+  // evaluation, and in those cases we consider the evaluation order
+  // requirement to trump the "destruction order is reverse construction
+  // order" guarantee.
   auto leftToRight = true;
   assert(!cir::MissingFeatures::msabi());
 
diff --git a/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h 
b/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h
index 8f421f723943f..4a06a47f67038 100644
--- a/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h
+++ b/clang/lib/CIR/CodeGen/CIRGenFunctionInfo.h
@@ -117,7 +117,7 @@ class CIRGenFunctionInfo final
                       RequiredArgs required, CanQualType resultType,
                       llvm::ArrayRef<CanQualType> argTypes) {
     id.AddBoolean(info.getNoReturn());
-    id.AddBoolean(required.getOpaqueData());
+    id.AddInteger(required.getOpaqueData());
     resultType.Profile(id);
     for (const CanQualType &arg : argTypes)
       arg.Profile(id);
diff --git a/clang/test/CIR/CodeGen/no-prototype-variadic.c 
b/clang/test/CIR/CodeGen/no-prototype-variadic.c
new file mode 100644
index 0000000000000..3e6fda491ea8c
--- /dev/null
+++ b/clang/test/CIR/CodeGen/no-prototype-variadic.c
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=gnu89 
-Wno-implicit-function-declaration -fclangir -emit-cir %s -o - | FileCheck %s
+
+int foo(const char *);
+
+int bar(void) {
+  int t = foo("x");
+  printf("Hello %d\n", t);
+  printf("Hi\n");
+  return 0;
+}
+
+// CHECK: cir.func private @printf(!cir.ptr<!s8i>, ...) -> !s32i
\ No newline at end of file
diff --git a/clang/test/CIR/CodeGen/no-prototype.c 
b/clang/test/CIR/CodeGen/no-prototype.c
index d266ccb86448a..1ef1ab40bfb23 100644
--- a/clang/test/CIR/CodeGen/no-prototype.c
+++ b/clang/test/CIR/CodeGen/no-prototype.c
@@ -11,7 +11,8 @@ int noProto0(x) int x; { return x; }
 int test0(int x) {
   // CHECK: cir.func {{.*}} @test0
   return noProto0(x); // We know the definition. Should be a direct call.
-  // CHECK: %{{.+}} = cir.call @noProto0(%{{.+}})
+  // CHECK: %{{.+}} = cir.get_global @noProto0
+  // CHECK: %{{.+}} = cir.call {{.*}}(%{{.+}})
 }
 
 // Declaration without prototype followed by its definition, then a correct 
call.

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

Reply via email to