From e2b2a2c4eacda0ffe0242a36eb58a88bc1041893 Mon Sep 17 00:00:00 2001 From: Andy Kaylor Date: Fri, 2 May 2025 14:40:54 -0700 Subject: [PATCH] [CIR] Add test for begin/end range for statements This adds a test to verify range for loops based on begin() and end() funtion calls. The functionality to enable this was added in previous commits, but those commits were only indirectly related to this test. The general intent of this commit is to work towards enabling iterator-based range for loops. The test did reveal one minor problem in call argument handling, which is corrected here. --- clang/lib/CIR/CodeGen/CIRGenCall.cpp | 2 +- clang/test/CIR/CodeGen/forrange.cpp | 49 ++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 clang/test/CIR/CodeGen/forrange.cpp diff --git a/clang/lib/CIR/CodeGen/CIRGenCall.cpp b/clang/lib/CIR/CodeGen/CIRGenCall.cpp index bed0db28818f1..693e73ceb62ab 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCall.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCall.cpp @@ -304,7 +304,7 @@ void CIRGenFunction::emitCallArg(CallArgList &args, const clang::Expr *e, if (e->isGLValue()) { assert(e->getObjectKind() == OK_Ordinary); - args.add(emitReferenceBindingToExpr(e), argType); + return args.add(emitReferenceBindingToExpr(e), argType); } bool hasAggregateEvalKind = hasAggregateEvaluationKind(argType); diff --git a/clang/test/CIR/CodeGen/forrange.cpp b/clang/test/CIR/CodeGen/forrange.cpp new file mode 100644 index 0000000000000..80b936318334c --- /dev/null +++ b/clang/test/CIR/CodeGen/forrange.cpp @@ -0,0 +1,49 @@ +// RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir %s -o %t.cir +// RUN: FileCheck --input-file=%t.cir %s --check-prefix=CIR + +struct Element {}; +struct Container {}; + +Element *begin(Container &); +Element *end(Container &); + +void for_range() { + Container c; + for (Element &e : c) + ; +} + +// CIR: cir.func @_Z5beginR9Container(!cir.ptr) -> !cir.ptr +// CIR: cir.func @_Z3endR9Container(!cir.ptr) -> !cir.ptr{{.*}} ["__range1", init, const] +// CIR: %[[BEGIN_ADDR:.*]] = cir.alloca !cir.ptr{{.*}} ["__begin1", init] +// CIR: %[[END_ADDR:.*]] = cir.alloca !cir.ptr{{.*}} ["__end1", init] +// CIR: %[[E_ADDR:.*]] = cir.alloca !cir.ptr{{.*}} ["e", init, const] +// CIR: cir.store %[[C_ADDR]], %[[RANGE_ADDR]] +// CIR: %[[C_REF:.*]] = cir.load %[[RANGE_ADDR]] +// CIR: %[[BEGIN:.*]] = cir.call @_Z5beginR9Container(%[[C_REF]]) +// CIR: cir.store %[[BEGIN]], %[[BEGIN_ADDR]] +// CIR: %[[C_REF2:.*]] = cir.load %[[RANGE_ADDR]] +// CIR: %[[END:.*]] = cir.call @_Z3endR9Container(%[[C_REF2]]) +// CIR: cir.store %[[END]], %[[END_ADDR]] +// CIR: cir.for : cond { +// CIR: %[[BEGIN:.*]] = cir.load %[[BEGIN_ADDR]] +// CIR: %[[END:.*]] = cir.load %[[END_ADDR]] +// CIR: %[[CMP:.*]] = cir.cmp(ne, %[[BEGIN]], %[[END]]) +// CIR: cir.condition(%[[CMP]]) +// CIR: } body { +// CIR: %[[E:.*]] = cir.load deref %[[BEGIN_ADDR]] +// CIR: cir.store %[[E]], %[[E_ADDR]] +// CIR: cir.yield +// CIR: } step { +// CIR: %[[BEGIN:.*]] = cir.load %[[BEGIN_ADDR]] +// CIR: %[[STEP:.*]] = cir.const #cir.int<1> +// CIR: %[[NEXT:.*]] = cir.ptr_stride(%[[BEGIN]] {{.*}}, %[[STEP]] {{.*}}) +// CIR: cir.store %[[NEXT]], %[[BEGIN_ADDR]] +// CIR: cir.yield +// CIR: } +// CIR: }