Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

478 changes: 478 additions & 0 deletions clang/test/CodeGen/voidptr-vaarg.c

Large diffs are not rendered by default.

24 changes: 12 additions & 12 deletions clang/test/CodeGenCUDA/cuda-builtin-vars.cu
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,21 @@
__attribute__((global))
void kernel(int *out) {
int i = 0;
out[i++] = threadIdx.x; // CHECK: call noundef i32 @llvm.nvvm.read.ptx.sreg.tid.x()
out[i++] = threadIdx.y; // CHECK: call noundef i32 @llvm.nvvm.read.ptx.sreg.tid.y()
out[i++] = threadIdx.z; // CHECK: call noundef i32 @llvm.nvvm.read.ptx.sreg.tid.z()
out[i++] = threadIdx.x; // CHECK: call noundef{{.*}} i32 @llvm.nvvm.read.ptx.sreg.tid.x()
out[i++] = threadIdx.y; // CHECK: call noundef{{.*}} i32 @llvm.nvvm.read.ptx.sreg.tid.y()
out[i++] = threadIdx.z; // CHECK: call noundef{{.*}} i32 @llvm.nvvm.read.ptx.sreg.tid.z()

out[i++] = blockIdx.x; // CHECK: call noundef i32 @llvm.nvvm.read.ptx.sreg.ctaid.x()
out[i++] = blockIdx.y; // CHECK: call noundef i32 @llvm.nvvm.read.ptx.sreg.ctaid.y()
out[i++] = blockIdx.z; // CHECK: call noundef i32 @llvm.nvvm.read.ptx.sreg.ctaid.z()
out[i++] = blockIdx.x; // CHECK: call noundef{{.*}} i32 @llvm.nvvm.read.ptx.sreg.ctaid.x()
out[i++] = blockIdx.y; // CHECK: call noundef{{.*}} i32 @llvm.nvvm.read.ptx.sreg.ctaid.y()
out[i++] = blockIdx.z; // CHECK: call noundef{{.*}} i32 @llvm.nvvm.read.ptx.sreg.ctaid.z()

out[i++] = blockDim.x; // CHECK: call noundef i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
out[i++] = blockDim.y; // CHECK: call noundef i32 @llvm.nvvm.read.ptx.sreg.ntid.y()
out[i++] = blockDim.z; // CHECK: call noundef i32 @llvm.nvvm.read.ptx.sreg.ntid.z()
out[i++] = blockDim.x; // CHECK: call noundef{{.*}} i32 @llvm.nvvm.read.ptx.sreg.ntid.x()
out[i++] = blockDim.y; // CHECK: call noundef{{.*}} i32 @llvm.nvvm.read.ptx.sreg.ntid.y()
out[i++] = blockDim.z; // CHECK: call noundef{{.*}} i32 @llvm.nvvm.read.ptx.sreg.ntid.z()

out[i++] = gridDim.x; // CHECK: call noundef i32 @llvm.nvvm.read.ptx.sreg.nctaid.x()
out[i++] = gridDim.y; // CHECK: call noundef i32 @llvm.nvvm.read.ptx.sreg.nctaid.y()
out[i++] = gridDim.z; // CHECK: call noundef i32 @llvm.nvvm.read.ptx.sreg.nctaid.z()
out[i++] = gridDim.x; // CHECK: call noundef{{.*}} i32 @llvm.nvvm.read.ptx.sreg.nctaid.x()
out[i++] = gridDim.y; // CHECK: call noundef{{.*}} i32 @llvm.nvvm.read.ptx.sreg.nctaid.y()
out[i++] = gridDim.z; // CHECK: call noundef{{.*}} i32 @llvm.nvvm.read.ptx.sreg.nctaid.z()

out[i++] = warpSize; // CHECK: store i32 32,

Expand Down
181 changes: 181 additions & 0 deletions clang/test/CodeGenCXX/inline-then-fold-variadics.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --function-signature
// REQUIRES: webassembly-registered-target

// Simple calls to known variadic functions that are completely elided when
// optimisations are on This is a functional check that the expand-variadic pass
// is consistent with clang's va_arg handling

// When expand-variadics is added to the default pipeline, clang -O1 will
// suffice here -Wno-varargs avoids warning second argument to 'va_start' is not
// the last named parameter

// RUN: %clang_cc1 %s -triple wasm32-unknown-unknown -Wno-varargs -O1 -emit-llvm -o - | opt - -S --passes='module(expand-variadics,default<O1>)' --expand-variadics-override=optimize -o - | FileCheck %s

#include <stdarg.h>
#include <stdint.h>

template <typename X, typename Y> static X first(...) {
va_list va;
__builtin_va_start(va, 0);
X r = va_arg(va, X);
va_end(va);
return r;
}

template <typename X, typename Y> static Y second(...) {
va_list va;
__builtin_va_start(va, 0);
va_arg(va, X);
Y r = va_arg(va, Y);
va_end(va);
return r;
}

extern "C" {

// CHECK-LABEL: define {{[^@]+}}@first_pair_i32
// CHECK-SAME: (i32 noundef returned [[X:%.*]], i32 noundef [[Y:%.*]])
// CHECK-NEXT: entry:
// CHECK-NEXT: ret i32 [[X]]
//
int first_pair_i32(int x, int y) { return first<int, int>(x, y); }

// CHECK-LABEL: define {{[^@]+}}@second_pair_i32
// CHECK-SAME: (i32 noundef [[X:%.*]], i32 noundef returned [[Y:%.*]])
// CHECK-NEXT: entry:
// CHECK-NEXT: ret i32 [[Y]]
//
int second_pair_i32(int x, int y) { return second<int, int>(x, y); }

// CHECK-LABEL: define {{[^@]+}}@first_pair_f64
// CHECK-SAME: (double noundef returned [[X:%.*]], double noundef [[Y:%.*]])
// CHECK-NEXT: entry:
// CHECK-NEXT: ret double [[X]]
//
double first_pair_f64(double x, double y) {
return first<double, double>(x, y);
}

// CHECK-LABEL: define {{[^@]+}}@second_pair_f64
// CHECK-SAME: (double noundef [[X:%.*]], double noundef returned [[Y:%.*]])
// CHECK-NEXT: entry:
// CHECK-NEXT: ret double [[Y]]
//
double second_pair_f64(double x, double y) {
return second<double, double>(x, y);
}
}

extern "C" {

// CHECK-LABEL: define {{[^@]+}}@first_i32_f64
// CHECK-SAME: (i32 noundef returned [[X:%.*]], double noundef [[Y:%.*]])
// CHECK-NEXT: entry:
// CHECK-NEXT: ret i32 [[X]]
//
int first_i32_f64(int x, double y) { return first<int, double>(x, y); }

// CHECK-LABEL: define {{[^@]+}}@second_i32_f64
// CHECK-SAME: (i32 noundef [[X:%.*]], double noundef returned [[Y:%.*]])
// CHECK-NEXT: entry:
// CHECK-NEXT: ret double [[Y]]
//
double second_i32_f64(int x, double y) { return second<int, double>(x, y); }

// CHECK-LABEL: define {{[^@]+}}@first_f64_i32
// CHECK-SAME: (double noundef returned [[X:%.*]], i32 noundef [[Y:%.*]])
// CHECK-NEXT: entry:
// CHECK-NEXT: ret double [[X]]
//
double first_f64_i32(double x, int y) { return first<double, int>(x, y); }

// CHECK-LABEL: define {{[^@]+}}@second_f64_i32
// CHECK-SAME: (double noundef [[X:%.*]], i32 noundef returned [[Y:%.*]])
// CHECK-NEXT: entry:
// CHECK-NEXT: ret i32 [[Y]]
//
int second_f64_i32(double x, int y) { return second<double, int>(x, y); }
}

extern "C" {
typedef uint64_t ulong2 __attribute__((__vector_size__(16), __aligned__(16)));

// CHECK-LABEL: define {{[^@]+}}@first_i32_ulong2
// CHECK-SAME: (i32 noundef returned [[X:%.*]], ptr nocapture noundef readonly [[Y:%.*]])
// CHECK-NEXT: entry:
// CHECK-NEXT: ret i32 [[X]]
//
int first_i32_ulong2(int x, ulong2 *y) { return first<int, ulong2>(x, *y); }

// CHECK-LABEL: define {{[^@]+}}@second_i32_ulong2
// CHECK-SAME: (i32 noundef [[X:%.*]], ptr nocapture noundef readonly [[Y:%.*]], ptr nocapture noundef writeonly [[R:%.*]]) local_unnamed_addr #[[ATTR1:[0-9]+]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = load <2 x i64>, ptr [[Y]], align 16, !tbaa [[TBAA2:![0-9]+]]
// CHECK-NEXT: store <2 x i64> [[TMP0]], ptr [[R]], align 16, !tbaa [[TBAA2]]
// CHECK-NEXT: ret void
//
void second_i32_ulong2(int x, ulong2 *y, ulong2 *r) {
*r = second<int, ulong2>(x, *y);
}

// CHECK-LABEL: define {{[^@]+}}@first_ulong2_i32
// CHECK-SAME: (ptr nocapture noundef readonly [[X:%.*]], i32 noundef [[Y:%.*]], ptr nocapture noundef writeonly [[R:%.*]]) local_unnamed_addr #[[ATTR1]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: [[TMP0:%.*]] = load <2 x i64>, ptr [[X]], align 16, !tbaa [[TBAA2]]
// CHECK-NEXT: store <2 x i64> [[TMP0]], ptr [[R]], align 16, !tbaa [[TBAA2]]
// CHECK-NEXT: ret void
//
void first_ulong2_i32(ulong2 *x, int y, ulong2 *r) {
*r = first<ulong2, int>(*x, y);
}

// CHECK-LABEL: define {{[^@]+}}@second_ulong2_i32
// CHECK-SAME: (ptr nocapture noundef readonly [[X:%.*]], i32 noundef returned [[Y:%.*]])
// CHECK-NEXT: entry:
// CHECK-NEXT: ret i32 [[Y]]
//
int second_ulong2_i32(ulong2 *x, int y) { return second<ulong2, int>(*x, y); }
}

// ascending alignment
typedef struct {
char c;
short s;
int i;
long l;
float f;
double d;
} asc;

extern "C" {

// CHECK-LABEL: define {{[^@]+}}@first_i32_asc
// CHECK-SAME: (i32 noundef returned [[X:%.*]], ptr nocapture noundef readonly [[Y:%.*]])
// CHECK-NEXT: entry:
// CHECK-NEXT: ret i32 [[X]]
//
int first_i32_asc(int x, asc *y) { return first<int, asc>(x, *y); }

// CHECK-LABEL: define {{[^@]+}}@second_i32_asc
// CHECK-SAME: (i32 noundef [[X:%.*]], ptr nocapture noundef readonly [[Y:%.*]], ptr nocapture noundef writeonly [[R:%.*]]) local_unnamed_addr #[[ATTR1]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: tail call void @llvm.memmove.p0.p0.i32(ptr noundef nonnull align 8 dereferenceable(24) [[R]], ptr noundef nonnull align 1 dereferenceable(24) [[Y]], i32 24, i1 false)
// CHECK-NEXT: ret void
//
void second_i32_asc(int x, asc *y, asc *r) { *r = second<int, asc>(x, *y); }

// CHECK-LABEL: define {{[^@]+}}@first_asc_i32
// CHECK-SAME: (ptr nocapture noundef readonly [[X:%.*]], i32 noundef [[Y:%.*]], ptr nocapture noundef writeonly [[R:%.*]]) local_unnamed_addr #[[ATTR1]] {
// CHECK-NEXT: entry:
// CHECK-NEXT: tail call void @llvm.memmove.p0.p0.i32(ptr noundef nonnull align 8 dereferenceable(24) [[R]], ptr noundef nonnull align 1 dereferenceable(24) [[X]], i32 24, i1 false)
// CHECK-NEXT: ret void
//
void first_asc_i32(asc *x, int y, asc *r) { *r = first<asc, int>(*x, y); }

// CHECK-LABEL: define {{[^@]+}}@second_asc_i32
// CHECK-SAME: (ptr nocapture noundef readonly [[X:%.*]], i32 noundef returned [[Y:%.*]])
// CHECK-NEXT: entry:
// CHECK-NEXT: ret i32 [[Y]]
//
int second_asc_i32(asc *x, int y) { return second<asc, int>(*x, y); }
}
1 change: 1 addition & 0 deletions clang/test/CodeGenCXX/pointers-to-data-members.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 %s -emit-llvm -o %t.ll -triple=x86_64-apple-darwin10
// RUN: %clang_cc1 %s -emit-llvm -o %t.ll -triple=x86_64-apple-darwin10 -fexperimental-new-constant-interpreter
// RUN: FileCheck %s < %t.ll
// RUN: FileCheck -check-prefix=CHECK-GLOBAL %s < %t.ll

Expand Down
1 change: 1 addition & 0 deletions clang/test/CodeGenCXX/template-param-objects-linkage.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++20 %s -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++20 %s -emit-llvm -o - -fexperimental-new-constant-interpreter | FileCheck %s

struct S { char buf[32]; };
template<S s> constexpr const char* f() { return s.buf; }
Expand Down
2 changes: 2 additions & 0 deletions clang/test/CodeGenOpenCL/amdgpu-features.cl
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
// RUN: %clang_cc1 -triple amdgcn -target-cpu gfx1103 -emit-llvm -o - %s | FileCheck --check-prefix=GFX1103 %s
// RUN: %clang_cc1 -triple amdgcn -target-cpu gfx1150 -emit-llvm -o - %s | FileCheck --check-prefix=GFX1150 %s
// RUN: %clang_cc1 -triple amdgcn -target-cpu gfx1151 -emit-llvm -o - %s | FileCheck --check-prefix=GFX1151 %s
// RUN: %clang_cc1 -triple amdgcn -target-cpu gfx1152 -emit-llvm -o - %s | FileCheck --check-prefix=GFX1152 %s
// RUN: %clang_cc1 -triple amdgcn -target-cpu gfx1200 -emit-llvm -o - %s | FileCheck --check-prefix=GFX1200 %s
// RUN: %clang_cc1 -triple amdgcn -target-cpu gfx1201 -emit-llvm -o - %s | FileCheck --check-prefix=GFX1201 %s

Expand Down Expand Up @@ -100,6 +101,7 @@
// GFX1103: "target-features"="+16-bit-insts,+atomic-fadd-rtn-insts,+ci-insts,+dl-insts,+dot10-insts,+dot5-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize32"
// GFX1150: "target-features"="+16-bit-insts,+atomic-fadd-rtn-insts,+ci-insts,+dl-insts,+dot10-insts,+dot5-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize32"
// GFX1151: "target-features"="+16-bit-insts,+atomic-fadd-rtn-insts,+ci-insts,+dl-insts,+dot10-insts,+dot5-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize32"
// GFX1152: "target-features"="+16-bit-insts,+atomic-fadd-rtn-insts,+ci-insts,+dl-insts,+dot10-insts,+dot5-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize32"
// GFX1200: "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-ds-pk-add-16-insts,+atomic-fadd-rtn-insts,+atomic-flat-pk-add-16-insts,+atomic-global-pk-add-bf16-inst,+ci-insts,+dl-insts,+dot10-insts,+dot11-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+fp8-conversion-insts,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx12-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize32"
// GFX1201: "target-features"="+16-bit-insts,+atomic-buffer-global-pk-add-f16-insts,+atomic-ds-pk-add-16-insts,+atomic-fadd-rtn-insts,+atomic-flat-pk-add-16-insts,+atomic-global-pk-add-bf16-inst,+ci-insts,+dl-insts,+dot10-insts,+dot11-insts,+dot7-insts,+dot8-insts,+dot9-insts,+dpp,+fp8-conversion-insts,+gfx10-3-insts,+gfx10-insts,+gfx11-insts,+gfx12-insts,+gfx8-insts,+gfx9-insts,+wavefrontsize32"

Expand Down
1 change: 1 addition & 0 deletions clang/test/CodeGenOpenCL/builtins-amdgcn-gfx11.cl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx1103 -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx1150 -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx1151 -emit-llvm -o - %s | FileCheck %s
// RUN: %clang_cc1 -triple amdgcn-unknown-unknown -target-cpu gfx1152 -emit-llvm -o - %s | FileCheck %s

typedef unsigned int uint;
typedef unsigned long ulong;
Expand Down
19 changes: 19 additions & 0 deletions clang/test/Driver/aarch64-oryon-1.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// RUN: %clang -target aarch64 -mcpu=oryon-1 -### -c %s 2>&1 | FileCheck -check-prefix=Phoenix %s
// RUN: %clang -target aarch64 -mlittle-endian -mcpu=oryon-1 -### -c %s 2>&1 | FileCheck -check-prefix=Phoenix %s
// RUN: %clang -target aarch64_be -mlittle-endian -mcpu=oryon-1 -### -c %s 2>&1 | FileCheck -check-prefix=Phoenix %s
// RUN: %clang -target aarch64 -mtune=oryon-1 -### -c %s 2>&1 | FileCheck -check-prefix=Phoenix-TUNE %s
// RUN: %clang -target aarch64 -mlittle-endian -mtune=oryon-1 -### -c %s 2>&1 | FileCheck -check-prefix=Phoenix-TUNE %s
// RUN: %clang -target aarch64_be -mlittle-endian -mtune=oryon-1 -### -c %s 2>&1 | FileCheck -check-prefix=Phoenix-TUNE %s
// Phoenix: "-cc1"{{.*}} "-triple" "aarch64{{(--)?}}"{{.*}} "-target-cpu" "oryon-1" "-target-feature" "+v8.6a"
// Phoenix-TUNE: "-cc1"{{.*}} "-triple" "aarch64{{(--)?}}"{{.*}} "-target-cpu" "generic"

// RUN: %clang -target arm64 -mcpu=oryon-1 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-Phoenix %s
// RUN: %clang -target arm64 -mlittle-endian -mcpu=oryon-1 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-Phoenix %s
// RUN: %clang -target arm64 -mtune=oryon-1 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-Phoenix-TUNE %s
// RUN: %clang -target arm64 -mlittle-endian -mtune=oryon-1 -### -c %s 2>&1 | FileCheck -check-prefix=ARM64-Phoenix-TUNE %s
// ARM64-Phoenix: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "oryon-1" "-target-feature" "+v8.6a"
// ARM64-Phoenix-TUNE: "-cc1"{{.*}} "-triple" "arm64{{.*}}" "-target-cpu" "generic"

// RUN: %clang -target aarch64 -mcpu=oryon-1 -mtune=cortex-a53 -### -c %s 2>&1 | FileCheck -check-prefix=MCPU-MTUNE-Phoenix %s
// RUN: %clang -target aarch64 -mtune=cortex-a53 -mcpu=oryon-1 -### -c %s 2>&1 | FileCheck -check-prefix=MCPU-MTUNE-Phoenix %s
// MCPU-MTUNE-Phoenix: "-cc1"{{.*}} "-triple" "aarch64{{.*}}" "-target-cpu" "oryon-1"
1 change: 1 addition & 0 deletions clang/test/Driver/amdgpu-macros.cl
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@
// RUN: %clang -E -dM -target amdgcn -mcpu=gfx1103 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=32 -DCPU=gfx1103 -DFAMILY=GFX11
// RUN: %clang -E -dM -target amdgcn -mcpu=gfx1150 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=32 -DCPU=gfx1150 -DFAMILY=GFX11
// RUN: %clang -E -dM -target amdgcn -mcpu=gfx1151 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=32 -DCPU=gfx1151 -DFAMILY=GFX11
// RUN: %clang -E -dM -target amdgcn -mcpu=gfx1152 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=32 -DCPU=gfx1152 -DFAMILY=GFX11
// RUN: %clang -E -dM -target amdgcn -mcpu=gfx1200 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=32 -DCPU=gfx1200 -DFAMILY=GFX12
// RUN: %clang -E -dM -target amdgcn -mcpu=gfx1201 %s 2>&1 | FileCheck --check-prefixes=ARCH-GCN,FAST_FMAF %s -DWAVEFRONT_SIZE=32 -DCPU=gfx1201 -DFAMILY=GFX12

Expand Down
2 changes: 2 additions & 0 deletions clang/test/Driver/amdgpu-mcpu.cl
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
// RUN: %clang -### -target amdgcn -mcpu=gfx1103 %s 2>&1 | FileCheck --check-prefix=GFX1103 %s
// RUN: %clang -### -target amdgcn -mcpu=gfx1150 %s 2>&1 | FileCheck --check-prefix=GFX1150 %s
// RUN: %clang -### -target amdgcn -mcpu=gfx1151 %s 2>&1 | FileCheck --check-prefix=GFX1151 %s
// RUN: %clang -### -target amdgcn -mcpu=gfx1152 %s 2>&1 | FileCheck --check-prefix=GFX1152 %s
// RUN: %clang -### -target amdgcn -mcpu=gfx1200 %s 2>&1 | FileCheck --check-prefix=GFX1200 %s
// RUN: %clang -### -target amdgcn -mcpu=gfx1201 %s 2>&1 | FileCheck --check-prefix=GFX1201 %s

Expand Down Expand Up @@ -164,6 +165,7 @@
// GFX1103: "-target-cpu" "gfx1103"
// GFX1150: "-target-cpu" "gfx1150"
// GFX1151: "-target-cpu" "gfx1151"
// GFX1152: "-target-cpu" "gfx1152"
// GFX1200: "-target-cpu" "gfx1200"
// GFX1201: "-target-cpu" "gfx1201"

Expand Down
8 changes: 8 additions & 0 deletions clang/test/Interpreter/pretty-print.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// REQUIRES: host-supports-jit
// UNSUPPORTED: system-aix
// RUN: cat %s | clang-repl -Xcc -xc | FileCheck %s
// RUN: cat %s | clang-repl -Xcc -std=c++11 | FileCheck %s

const char* c_str = "Hello, world!"; c_str

// CHECK: Not implement yet.
8 changes: 4 additions & 4 deletions clang/test/Misc/target-invalid-cpu-note.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@

// RUN: not %clang_cc1 -triple arm64--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix AARCH64
// AARCH64: error: unknown target CPU 'not-a-cpu'
// AARCH64-NEXT: note: valid target CPU values are: cortex-a34, cortex-a35, cortex-a53, cortex-a55, cortex-a510, cortex-a520, cortex-a520ae, cortex-a57, cortex-a65, cortex-a65ae, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78ae, cortex-a78c, cortex-a710, cortex-a715, cortex-a720, cortex-a720ae, cortex-r82, cortex-r82ae, cortex-x1, cortex-x1c, cortex-x2, cortex-x3, cortex-x4, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-n3, neoverse-512tvb, neoverse-v1, neoverse-v2, neoverse-v3, neoverse-v3ae, cyclone, apple-a7, apple-a8, apple-a9, apple-a10, apple-a11, apple-a12, apple-a13, apple-a14, apple-a15, apple-a16, apple-a17, apple-m1, apple-m2, apple-m3, apple-s4, apple-s5, exynos-m3, exynos-m4, exynos-m5, falkor, saphira, kryo, thunderx2t99, thunderx3t110, thunderx, thunderxt88, thunderxt81, thunderxt83, tsv110, a64fx, carmel, ampere1, ampere1a, ampere1b, cobalt-100, grace{{$}}
// AARCH64-NEXT: note: valid target CPU values are: cortex-a34, cortex-a35, cortex-a53, cortex-a55, cortex-a510, cortex-a520, cortex-a520ae, cortex-a57, cortex-a65, cortex-a65ae, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78ae, cortex-a78c, cortex-a710, cortex-a715, cortex-a720, cortex-a720ae, cortex-r82, cortex-r82ae, cortex-x1, cortex-x1c, cortex-x2, cortex-x3, cortex-x4, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-n3, neoverse-512tvb, neoverse-v1, neoverse-v2, neoverse-v3, neoverse-v3ae, cyclone, apple-a7, apple-a8, apple-a9, apple-a10, apple-a11, apple-a12, apple-a13, apple-a14, apple-a15, apple-a16, apple-a17, apple-m1, apple-m2, apple-m3, apple-s4, apple-s5, exynos-m3, exynos-m4, exynos-m5, falkor, saphira, kryo, thunderx2t99, thunderx3t110, thunderx, thunderxt88, thunderxt81, thunderxt83, tsv110, a64fx, carmel, ampere1, ampere1a, ampere1b, oryon-1, cobalt-100, grace{{$}}

// RUN: not %clang_cc1 -triple arm64--- -tune-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix TUNE_AARCH64
// TUNE_AARCH64: error: unknown target CPU 'not-a-cpu'
// TUNE_AARCH64-NEXT: note: valid target CPU values are: cortex-a34, cortex-a35, cortex-a53, cortex-a55, cortex-a510, cortex-a520, cortex-a520ae, cortex-a57, cortex-a65, cortex-a65ae, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78ae, cortex-a78c, cortex-a710, cortex-a715, cortex-a720, cortex-a720ae, cortex-r82, cortex-r82ae, cortex-x1, cortex-x1c, cortex-x2, cortex-x3, cortex-x4, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-n3, neoverse-512tvb, neoverse-v1, neoverse-v2, neoverse-v3, neoverse-v3ae, cyclone, apple-a7, apple-a8, apple-a9, apple-a10, apple-a11, apple-a12, apple-a13, apple-a14, apple-a15, apple-a16, apple-a17, apple-m1, apple-m2, apple-m3, apple-s4, apple-s5, exynos-m3, exynos-m4, exynos-m5, falkor, saphira, kryo, thunderx2t99, thunderx3t110, thunderx, thunderxt88, thunderxt81, thunderxt83, tsv110, a64fx, carmel, ampere1, ampere1a, ampere1b, cobalt-100, grace{{$}}
// TUNE_AARCH64-NEXT: note: valid target CPU values are: cortex-a34, cortex-a35, cortex-a53, cortex-a55, cortex-a510, cortex-a520, cortex-a520ae, cortex-a57, cortex-a65, cortex-a65ae, cortex-a72, cortex-a73, cortex-a75, cortex-a76, cortex-a76ae, cortex-a77, cortex-a78, cortex-a78ae, cortex-a78c, cortex-a710, cortex-a715, cortex-a720, cortex-a720ae, cortex-r82, cortex-r82ae, cortex-x1, cortex-x1c, cortex-x2, cortex-x3, cortex-x4, neoverse-e1, neoverse-n1, neoverse-n2, neoverse-n3, neoverse-512tvb, neoverse-v1, neoverse-v2, neoverse-v3, neoverse-v3ae, cyclone, apple-a7, apple-a8, apple-a9, apple-a10, apple-a11, apple-a12, apple-a13, apple-a14, apple-a15, apple-a16, apple-a17, apple-m1, apple-m2, apple-m3, apple-s4, apple-s5, exynos-m3, exynos-m4, exynos-m5, falkor, saphira, kryo, thunderx2t99, thunderx3t110, thunderx, thunderxt88, thunderxt81, thunderxt83, tsv110, a64fx, carmel, ampere1, ampere1a, ampere1b, oryon-1, cobalt-100, grace{{$}}

// RUN: not %clang_cc1 -triple i386--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix X86
// X86: error: unknown target CPU 'not-a-cpu'
Expand All @@ -29,15 +29,15 @@

// RUN: not %clang_cc1 -triple nvptx--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix NVPTX
// NVPTX: error: unknown target CPU 'not-a-cpu'
// NVPTX-NEXT: note: valid target CPU values are: sm_20, sm_21, sm_30, sm_32, sm_35, sm_37, sm_50, sm_52, sm_53, sm_60, sm_61, sm_62, sm_70, sm_72, sm_75, sm_80, sm_86, sm_87, sm_89, sm_90, sm_90a, gfx600, gfx601, gfx602, gfx700, gfx701, gfx702, gfx703, gfx704, gfx705, gfx801, gfx802, gfx803, gfx805, gfx810, gfx9-generic, gfx900, gfx902, gfx904, gfx906, gfx908, gfx909, gfx90a, gfx90c, gfx940, gfx941, gfx942, gfx10-1-generic, gfx1010, gfx1011, gfx1012, gfx1013, gfx10-3-generic, gfx1030, gfx1031, gfx1032, gfx1033, gfx1034, gfx1035, gfx1036, gfx11-generic, gfx1100, gfx1101, gfx1102, gfx1103, gfx1150, gfx1151, gfx12-generic, gfx1200, gfx1201{{$}}
// NVPTX-NEXT: note: valid target CPU values are: sm_20, sm_21, sm_30, sm_32, sm_35, sm_37, sm_50, sm_52, sm_53, sm_60, sm_61, sm_62, sm_70, sm_72, sm_75, sm_80, sm_86, sm_87, sm_89, sm_90, sm_90a, gfx600, gfx601, gfx602, gfx700, gfx701, gfx702, gfx703, gfx704, gfx705, gfx801, gfx802, gfx803, gfx805, gfx810, gfx9-generic, gfx900, gfx902, gfx904, gfx906, gfx908, gfx909, gfx90a, gfx90c, gfx940, gfx941, gfx942, gfx10-1-generic, gfx1010, gfx1011, gfx1012, gfx1013, gfx10-3-generic, gfx1030, gfx1031, gfx1032, gfx1033, gfx1034, gfx1035, gfx1036, gfx11-generic, gfx1100, gfx1101, gfx1102, gfx1103, gfx1150, gfx1151, gfx1152, gfx12-generic, gfx1200, gfx1201{{$}}

// RUN: not %clang_cc1 -triple r600--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix R600
// R600: error: unknown target CPU 'not-a-cpu'
// R600-NEXT: note: valid target CPU values are: r600, rv630, rv635, r630, rs780, rs880, rv610, rv620, rv670, rv710, rv730, rv740, rv770, cedar, palm, cypress, hemlock, juniper, redwood, sumo, sumo2, barts, caicos, aruba, cayman, turks{{$}}

// RUN: not %clang_cc1 -triple amdgcn--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix AMDGCN
// AMDGCN: error: unknown target CPU 'not-a-cpu'
// AMDGCN-NEXT: note: valid target CPU values are: gfx600, tahiti, gfx601, pitcairn, verde, gfx602, hainan, oland, gfx700, kaveri, gfx701, hawaii, gfx702, gfx703, kabini, mullins, gfx704, bonaire, gfx705, gfx801, carrizo, gfx802, iceland, tonga, gfx803, fiji, polaris10, polaris11, gfx805, tongapro, gfx810, stoney, gfx900, gfx902, gfx904, gfx906, gfx908, gfx909, gfx90a, gfx90c, gfx940, gfx941, gfx942, gfx1010, gfx1011, gfx1012, gfx1013, gfx1030, gfx1031, gfx1032, gfx1033, gfx1034, gfx1035, gfx1036, gfx1100, gfx1101, gfx1102, gfx1103, gfx1150, gfx1151, gfx1200, gfx1201, gfx9-generic, gfx10-1-generic, gfx10-3-generic, gfx11-generic, gfx12-generic{{$}}
// AMDGCN-NEXT: note: valid target CPU values are: gfx600, tahiti, gfx601, pitcairn, verde, gfx602, hainan, oland, gfx700, kaveri, gfx701, hawaii, gfx702, gfx703, kabini, mullins, gfx704, bonaire, gfx705, gfx801, carrizo, gfx802, iceland, tonga, gfx803, fiji, polaris10, polaris11, gfx805, tongapro, gfx810, stoney, gfx900, gfx902, gfx904, gfx906, gfx908, gfx909, gfx90a, gfx90c, gfx940, gfx941, gfx942, gfx1010, gfx1011, gfx1012, gfx1013, gfx1030, gfx1031, gfx1032, gfx1033, gfx1034, gfx1035, gfx1036, gfx1100, gfx1101, gfx1102, gfx1103, gfx1150, gfx1151, gfx1152, gfx1200, gfx1201, gfx9-generic, gfx10-1-generic, gfx10-3-generic, gfx11-generic, gfx12-generic{{$}}

// RUN: not %clang_cc1 -triple wasm64--- -target-cpu not-a-cpu -fsyntax-only %s 2>&1 | FileCheck %s --check-prefix WEBASM
// WEBASM: error: unknown target CPU 'not-a-cpu'
Expand Down
1 change: 1 addition & 0 deletions clang/test/SemaCXX/attr-weak.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -verify -std=c++11 %s
// RUN: %clang_cc1 -triple x86_64-pc-linux-gnu -fsyntax-only -verify -std=c++11 %s -fexperimental-new-constant-interpreter

static int test0 __attribute__((weak)); // expected-error {{weak declaration cannot have internal linkage}}
static void test1() __attribute__((weak)); // expected-error {{weak declaration cannot have internal linkage}}
Expand Down
34 changes: 34 additions & 0 deletions clang/test/SemaCXX/builtin-is-bitwise-cloneable-fsanitize.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// RUN: %clang_cc1 -triple x86_64-unknown-linux -DSANITIZER_ENABLED -fsanitize=address -fsanitize-address-field-padding=1 %s
// RUN: %clang_cc1 -triple x86_64-unknown-linux %s

struct S {
~S() {}
virtual void foo() {}

int buffer[1];
int other_field = 0;
};

union U {
S s;
};

struct Derived : S {};

static_assert(!__is_trivially_copyable(S));
#ifdef SANITIZER_ENABLED
// Don't allow memcpy when the struct has poisoned padding bits.
// The sanitizer adds posion padding bits to struct S.
static_assert(sizeof(S) > 16);
static_assert(!__is_bitwise_cloneable(S));
static_assert(sizeof(U) == sizeof(S)); // no padding bit for U.
static_assert(!__is_bitwise_cloneable(U));
static_assert(!__is_bitwise_cloneable(S[2]));
static_assert(!__is_bitwise_cloneable(Derived));
#else
static_assert(sizeof(S) == 16);
static_assert(__is_bitwise_cloneable(S));
static_assert(__is_bitwise_cloneable(U));
static_assert(__is_bitwise_cloneable(S[2]));
static_assert(__is_bitwise_cloneable(Derived));
#endif
8 changes: 8 additions & 0 deletions clang/test/SemaCXX/builtin-is-bitwise-cloneable.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
//
struct DynamicClass { virtual int Foo(); };
static_assert(!__is_trivially_copyable(DynamicClass));
static_assert(__is_bitwise_cloneable(DynamicClass));

struct InComplete; // expected-note{{forward declaration}}
static_assert(!__is_bitwise_cloneable(InComplete)); // expected-error{{incomplete type 'InComplete' used in type trait expression}}
4 changes: 2 additions & 2 deletions clang/test/SemaCXX/constexpr-default-arg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ void test_default_arg2() {
}

// Check that multiple CXXDefaultInitExprs don't cause an assertion failure.
struct A { int &&r = 0; };
struct A { int &&r = 0; }; // expected-note 2{{default member initializer}}
struct B { A x, y; };
B b = {}; // expected-no-diagnostics
B b = {}; // expected-warning 2{{lifetime extension of temporary created by aggregate initialization using a default member initializer is not yet supported}}

}
74 changes: 0 additions & 74 deletions clang/test/SemaCXX/cxx11-default-member-initializers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,80 +27,6 @@ class MemInit {
C m = s;
};

namespace std {
typedef decltype(sizeof(int)) size_t;

// libc++'s implementation
template <class _E> class initializer_list {
const _E *__begin_;
size_t __size_;

initializer_list(const _E *__b, size_t __s) : __begin_(__b), __size_(__s) {}

public:
typedef _E value_type;
typedef const _E &reference;
typedef const _E &const_reference;
typedef size_t size_type;

typedef const _E *iterator;
typedef const _E *const_iterator;

initializer_list() : __begin_(nullptr), __size_(0) {}

size_t size() const { return __size_; }
const _E *begin() const { return __begin_; }
const _E *end() const { return __begin_ + __size_; }
};
} // namespace std

#if __cplusplus >= 201703L
namespace test_rebuild {
template <typename T, int> class C {
public:
C(std::initializer_list<T>);
};

template <typename T> using Ptr = __remove_pointer(T) *;
template <typename T> C(T) -> C<Ptr<T>, sizeof(T)>;

class A {
public:
template <typename T1, typename T2> T1 *some_func(T2 &&);
};

struct B : A {
// Test CXXDefaultInitExpr rebuild issue in
// https://github.com/llvm/llvm-project/pull/87933
int *ar = some_func<int>(C{some_func<int>(0)});
B() {}
};

int TestBody_got;
template <int> class Vector {
public:
Vector(std::initializer_list<int>);
};
template <typename... Ts> Vector(Ts...) -> Vector<sizeof...(Ts)>;
class ProgramBuilder {
public:
template <typename T, typename ARGS> int *create(ARGS);
};

struct TypeTest : ProgramBuilder {
int *str_f16 = create<int>(Vector{0});
TypeTest() {}
};
class TypeTest_Element_Test : TypeTest {
void TestBody();
};
void TypeTest_Element_Test::TestBody() {
int *expect = str_f16;
&TestBody_got != expect; // expected-warning {{inequality comparison result unused}}
}
} // namespace test_rebuild
#endif // __cplusplus >= 201703L

#if __cplusplus >= 202002L
// This test ensures cleanup expressions are correctly produced
// in the presence of default member initializers.
Expand Down
6 changes: 4 additions & 2 deletions clang/test/SemaCXX/eval-crashes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,11 @@ namespace pr33140_0b {
}

namespace pr33140_2 {
struct A { int &&r = 0; };
// FIXME: The declaration of 'b' below should lifetime-extend two int
// temporaries.
struct A { int &&r = 0; }; // expected-note 2{{initializing field 'r' with default member initializer}}
struct B { A x, y; };
B b = {};
B b = {}; // expected-warning 2{{lifetime extension of temporary created by aggregate initialization using a default member initializer is not yet supported}}
}

namespace pr33140_3 {
Expand Down
1 change: 1 addition & 0 deletions clang/test/SemaCXX/nullptr_in_arithmetic_ops.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -Wno-tautological-pointer-compare -fblocks -std=c++11 -verify %s
// RUN: %clang_cc1 -fsyntax-only -Wno-tautological-pointer-compare -fblocks -std=c++11 -verify %s -fexperimental-new-constant-interpreter

void foo() {
int a;
Expand Down
9 changes: 9 additions & 0 deletions clang/test/SemaObjCXX/arc-type-traits.mm
Original file line number Diff line number Diff line change
Expand Up @@ -221,3 +221,12 @@
TRAIT_IS_TRUE(__is_trivially_relocatable, HasStrong);
TRAIT_IS_FALSE(__is_trivially_relocatable, HasWeak);
TRAIT_IS_TRUE(__is_trivially_relocatable, HasUnsafeUnretained);

// __is_bitwise_cloneable
TRAIT_IS_FALSE(__is_bitwise_cloneable, __strong id);
TRAIT_IS_FALSE(__is_bitwise_cloneable, __weak id);
TRAIT_IS_FALSE(__is_bitwise_cloneable, __autoreleasing id);
TRAIT_IS_TRUE(__is_trivial, __unsafe_unretained id);
TRAIT_IS_FALSE(__is_bitwise_cloneable, HasStrong);
TRAIT_IS_FALSE(__is_bitwise_cloneable, HasWeak);
TRAIT_IS_TRUE(__is_bitwise_cloneable, HasUnsafeUnretained);
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ void uses() {
// expected-error@+1{{OpenACC 'present' clause is not valid on 'loop' directive}}
#pragma acc loop auto present(Var)
for(;;);
// expected-warning@+1{{OpenACC clause 'private' not yet implemented}}
#pragma acc loop auto private(Var)
for(;;);
// expected-error@+1{{OpenACC 'copyout' clause is not valid on 'loop' directive}}
Expand Down Expand Up @@ -246,7 +245,6 @@ void uses() {
// expected-error@+1{{OpenACC 'present' clause is not valid on 'loop' directive}}
#pragma acc loop present(Var) auto
for(;;);
// expected-warning@+1{{OpenACC clause 'private' not yet implemented}}
#pragma acc loop private(Var) auto
for(;;);
// expected-error@+1{{OpenACC 'copyout' clause is not valid on 'loop' directive}}
Expand Down Expand Up @@ -387,7 +385,6 @@ void uses() {
// expected-error@+1{{OpenACC 'present' clause is not valid on 'loop' directive}}
#pragma acc loop independent present(Var)
for(;;);
// expected-warning@+1{{OpenACC clause 'private' not yet implemented}}
#pragma acc loop independent private(Var)
for(;;);
// expected-error@+1{{OpenACC 'copyout' clause is not valid on 'loop' directive}}
Expand Down Expand Up @@ -527,7 +524,6 @@ void uses() {
// expected-error@+1{{OpenACC 'present' clause is not valid on 'loop' directive}}
#pragma acc loop present(Var) independent
for(;;);
// expected-warning@+1{{OpenACC clause 'private' not yet implemented}}
#pragma acc loop private(Var) independent
for(;;);
// expected-error@+1{{OpenACC 'copyout' clause is not valid on 'loop' directive}}
Expand Down Expand Up @@ -677,7 +673,6 @@ void uses() {
// expected-error@+1{{OpenACC 'present' clause is not valid on 'loop' directive}}
#pragma acc loop seq present(Var)
for(;;);
// expected-warning@+1{{OpenACC clause 'private' not yet implemented}}
#pragma acc loop seq private(Var)
for(;;);
// expected-error@+1{{OpenACC 'copyout' clause is not valid on 'loop' directive}}
Expand Down Expand Up @@ -826,7 +821,6 @@ void uses() {
// expected-error@+1{{OpenACC 'present' clause is not valid on 'loop' directive}}
#pragma acc loop present(Var) seq
for(;;);
// expected-warning@+1{{OpenACC clause 'private' not yet implemented}}
#pragma acc loop private(Var) seq
for(;;);
// expected-error@+1{{OpenACC 'copyout' clause is not valid on 'loop' directive}}
Expand Down
132 changes: 132 additions & 0 deletions clang/test/SemaOpenACC/loop-construct-private-clause.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
// RUN: %clang_cc1 %s -fopenacc -verify

struct Incomplete;
enum SomeE{ A };
typedef struct IsComplete {
struct S { int A; } CompositeMember;
int ScalarMember;
float ArrayMember[5];
enum SomeE EnumMember;
void *PointerMember;
} Complete;

int GlobalInt;
float GlobalArray[5];
short *GlobalPointer;
Complete GlobalComposite;

void uses(int IntParam, short *PointerParam, float ArrayParam[5], Complete CompositeParam) {
int LocalInt;
short *LocalPointer;
float LocalArray[5];
Complete LocalComposite;

// Check Appertainment:
#pragma acc loop private(LocalInt)
for(;;);

// Valid cases:
#pragma acc loop private(LocalInt, LocalPointer, LocalArray)
for(;;);
#pragma acc loop private(LocalArray)
for(;;);
#pragma acc loop private(LocalArray[:])
for(;;);
#pragma acc loop private(LocalArray[:5])
for(;;);
#pragma acc loop private(LocalArray[2:])
for(;;);
#pragma acc loop private(LocalArray[2:1])
for(;;);
#pragma acc loop private(LocalArray[2])
for(;;);
#pragma acc loop private(LocalComposite)
for(;;);
#pragma acc loop private(LocalComposite.EnumMember)
for(;;);
#pragma acc loop private(LocalComposite.ScalarMember)
for(;;);
#pragma acc loop private(LocalComposite.ArrayMember)
for(;;);
#pragma acc loop private(LocalComposite.ArrayMember[5])
for(;;);
#pragma acc loop private(LocalComposite.PointerMember)
for(;;);
#pragma acc loop private(GlobalInt, GlobalArray, GlobalPointer, GlobalComposite)
for(;;);
#pragma acc loop private(GlobalArray[2], GlobalPointer[2], GlobalComposite.CompositeMember.A)
for(;;);
#pragma acc loop private(LocalComposite, GlobalComposite)
for(;;);
#pragma acc loop private(IntParam, PointerParam, ArrayParam, CompositeParam)
for(;;);
#pragma acc loop private(PointerParam[IntParam], ArrayParam[IntParam], CompositeParam.CompositeMember.A)
for(;;);

#pragma acc loop private(LocalArray) private(LocalArray[2])
for(;;);

#pragma acc loop private(LocalArray, LocalArray[2])
for(;;);

#pragma acc loop private(LocalComposite, LocalComposite.ScalarMember)
for(;;);

#pragma acc loop private(LocalComposite.CompositeMember.A, LocalComposite.ScalarMember)
for(;;);

#pragma acc loop private(LocalComposite.CompositeMember.A) private(LocalComposite.ScalarMember)
for(;;);

Complete LocalComposite2;
#pragma acc loop private(LocalComposite2.ScalarMember, LocalComposite2.ScalarMember)
for(;;);

// Invalid cases, arbitrary expressions.
struct Incomplete *I;
// expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}}
#pragma acc loop private(*I)
for(;;);
// expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}}
#pragma acc loop private(GlobalInt + IntParam)
for(;;);
// expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}}
#pragma acc loop private(+GlobalInt)
for(;;);

// expected-error@+1{{OpenACC sub-array length is unspecified and cannot be inferred because the subscripted value is not an array}}
#pragma acc loop private(PointerParam[:])
for(;;);
#pragma acc loop private(PointerParam[:5])
for(;;);
#pragma acc loop private(PointerParam[:IntParam])
for(;;);
// expected-error@+1{{OpenACC sub-array length is unspecified and cannot be inferred because the subscripted value is not an array}}
#pragma acc loop private(PointerParam[2:])
for(;;);
#pragma acc loop private(PointerParam[2:5])
for(;;);
#pragma acc loop private(PointerParam[2])
for(;;);
#pragma acc loop private(ArrayParam[:])
for(;;);
#pragma acc loop private(ArrayParam[:5])
for(;;);
#pragma acc loop private(ArrayParam[:IntParam])
for(;;);
#pragma acc loop private(ArrayParam[2:])
for(;;);
// expected-error@+1{{OpenACC sub-array specified range [2:5] would be out of the range of the subscripted array size of 5}}
#pragma acc loop private(ArrayParam[2:5])
for(;;);
#pragma acc loop private(ArrayParam[2])
for(;;);

// expected-error@+2{{OpenACC sub-array specified range [2:5] would be out of the range of the subscripted array size of 5}}
// expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}}
#pragma acc loop private((float*)ArrayParam[2:5])
for(;;);
// expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}}
#pragma acc loop private((float)ArrayParam[2])
for(;;);
}
155 changes: 155 additions & 0 deletions clang/test/SemaOpenACC/loop-construct-private-clause.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
// RUN: %clang_cc1 %s -fopenacc -verify

struct Incomplete;
enum SomeE{};
typedef struct IsComplete {
struct S { int A; } CompositeMember;
int ScalarMember;
float ArrayMember[5];
SomeE EnumMember;
char *PointerMember;
} Complete;

int GlobalInt;
float GlobalArray[5];
char *GlobalPointer;
Complete GlobalComposite;

void uses(int IntParam, char *PointerParam, float ArrayParam[5], Complete CompositeParam, int &IntParamRef) {
int LocalInt;
char *LocalPointer;
float LocalArray[5];
Complete LocalComposite;

// Check Appertainment:

#pragma acc loop private(LocalInt)
for(;;);

// Valid cases:
#pragma acc loop private(LocalInt, LocalPointer, LocalArray)
for(;;);
#pragma acc loop private(LocalArray)
for(;;);
#pragma acc loop private(LocalArray[2])
for(;;);
#pragma acc loop private(LocalComposite)
for(;;);
#pragma acc loop private(LocalComposite.EnumMember)
for(;;);
#pragma acc loop private(LocalComposite.ScalarMember)
for(;;);
#pragma acc loop private(LocalComposite.ArrayMember)
for(;;);
#pragma acc loop private(LocalComposite.ArrayMember[5])
for(;;);
#pragma acc loop private(LocalComposite.PointerMember)
for(;;);
#pragma acc loop private(GlobalInt, GlobalArray, GlobalPointer, GlobalComposite)
for(;;);
#pragma acc loop private(GlobalArray[2], GlobalPointer[2], GlobalComposite.CompositeMember.A)
for(;;);
#pragma acc loop private(LocalComposite, GlobalComposite)
for(;;);
#pragma acc loop private(IntParam, PointerParam, ArrayParam, CompositeParam) private(IntParamRef)
for(;;);
#pragma acc loop private(PointerParam[IntParam], ArrayParam[IntParam], CompositeParam.CompositeMember.A)
for(;;);


// Invalid cases, arbitrary expressions.
Incomplete *I;
// expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}}
#pragma acc loop private(*I)
for(;;);
// expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}}
#pragma acc loop private(GlobalInt + IntParam)
for(;;);
// expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}}
#pragma acc loop private(+GlobalInt)
for(;;);
}

template<typename T, unsigned I, typename V>
void TemplUses(T t, T (&arrayT)[I], V TemplComp) {
// expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}}
#pragma acc loop private(+t)
for(;;);

// expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}}
#pragma acc loop private(+I)
for(;;);

// NTTP's are only valid if it is a reference to something.
// expected-error@+2{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}}
// expected-note@#TEMPL_USES_INST{{in instantiation of}}
#pragma acc loop private(I)
for(;;);

// expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}}
#pragma acc loop private(t, I)
for(;;);

#pragma acc loop private(arrayT)
for(;;);

#pragma acc loop private(TemplComp)
for(;;);

#pragma acc loop private(TemplComp.PointerMember[5])
for(;;);

#pragma acc loop private(TemplComp.PointerMember[5]) private(TemplComp)
for(;;);

int *Pointer;
#pragma acc loop private(Pointer[:I])
for(;;);
#pragma acc loop private(Pointer[:t])
for(;;);
// expected-error@+1{{OpenACC sub-array length is unspecified and cannot be inferred because the subscripted value is not an array}}
#pragma acc loop private(Pointer[1:])
for(;;);
}

template<unsigned I, auto &NTTP_REF>
void NTTP() {
// NTTP's are only valid if it is a reference to something.
// expected-error@+2{{OpenACC variable is not a valid variable name, sub-array, array element, member of a composite variable, or composite variable member}}
// expected-note@#NTTP_INST{{in instantiation of}}
#pragma acc loop private(I)
for(;;);

#pragma acc loop private(NTTP_REF)
for(;;);
}

struct S {
int ThisMember;
int ThisMemberArray[5];

void foo();
};

void S::foo() {
#pragma acc loop private(ThisMember, this->ThisMemberArray[1])
for(;;);

#pragma acc loop private(ThisMemberArray[1:2])
for(;;);

#pragma acc loop private(this)
for(;;);

#pragma acc loop private(ThisMember, this->ThisMember)
for(;;);
}

void Inst() {
static constexpr int NTTP_REFed = 1;
int i;
int Arr[5];
Complete C;
TemplUses(i, Arr, C); // #TEMPL_USES_INST
NTTP<5, NTTP_REFed>(); // #NTTP_INST
}
6 changes: 4 additions & 2 deletions clang/test/SemaOpenCL/builtins-amdgcn-gfx940-err.cl
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@

typedef unsigned int u32;

void test_global_load_lds_unsupported_size(global u32* src, local u32 *dst, u32 size) {
__builtin_amdgcn_global_load_lds(src, dst, size, /*offset=*/0, /*aux=*/0); // expected-error{{expression is not an integer constant expression}}
void test_global_load_lds_unsupported_size(global u32* src, local u32 *dst, u32 size, u32 offset, u32 aux) {
__builtin_amdgcn_global_load_lds(src, dst, size, /*offset=*/0, /*aux=*/0); // expected-error{{argument to '__builtin_amdgcn_global_load_lds' must be a constant integer}}
__builtin_amdgcn_global_load_lds(src, dst, /*size=*/4, offset, /*aux=*/0); // expected-error{{argument to '__builtin_amdgcn_global_load_lds' must be a constant integer}}
__builtin_amdgcn_global_load_lds(src, dst, /*size=*/4, /*offset=*/0, aux); // expected-error{{argument to '__builtin_amdgcn_global_load_lds' must be a constant integer}}
__builtin_amdgcn_global_load_lds(src, dst, /*size=*/5, /*offset=*/0, /*aux=*/0); // expected-error{{invalid size value}} expected-note {{size must be 1, 2, or 4}}
__builtin_amdgcn_global_load_lds(src, dst, /*size=*/0, /*offset=*/0, /*aux=*/0); // expected-error{{invalid size value}} expected-note {{size must be 1, 2, or 4}}
__builtin_amdgcn_global_load_lds(src, dst, /*size=*/3, /*offset=*/0, /*aux=*/0); // expected-error{{invalid size value}} expected-note {{size must be 1, 2, or 4}}
Expand Down
46 changes: 46 additions & 0 deletions clang/unittests/AST/Interp/toAPValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,3 +186,49 @@ TEST(ToAPValue, FunctionPointersC) {
ASSERT_EQ(I, 17);
}
}

TEST(ToAPValue, MemberPointers) {
constexpr char Code[] = "struct S {\n"
" int m, n;\n"
"};\n"
"constexpr int S::*pm = &S::m;\n"
"constexpr int S::*nn = nullptr;\n";

auto AST = tooling::buildASTFromCodeWithArgs(
Code, {"-fexperimental-new-constant-interpreter"});

auto &Ctx = AST->getASTContext().getInterpContext();
Program &Prog = Ctx.getProgram();

auto getDecl = [&](const char *Name) -> const ValueDecl * {
auto Nodes =
match(valueDecl(hasName(Name)).bind("var"), AST->getASTContext());
assert(Nodes.size() == 1);
const auto *D = Nodes[0].getNodeAs<ValueDecl>("var");
assert(D);
return D;
};

auto getGlobalPtr = [&](const char *Name) -> Pointer {
const VarDecl *D = cast<VarDecl>(getDecl(Name));
return Prog.getPtrGlobal(*Prog.getGlobal(D));
};

{
const Pointer &GP = getGlobalPtr("pm");
ASSERT_TRUE(GP.isLive());
const MemberPointer &FP = GP.deref<MemberPointer>();
APValue A = FP.toAPValue();
ASSERT_EQ(A.getMemberPointerDecl(), getDecl("m"));
ASSERT_EQ(A.getKind(), APValue::MemberPointer);
}

{
const Pointer &GP = getGlobalPtr("nn");
ASSERT_TRUE(GP.isLive());
const MemberPointer &NP = GP.deref<MemberPointer>();
ASSERT_TRUE(NP.isZero());
APValue A = NP.toAPValue();
ASSERT_EQ(A.getKind(), APValue::MemberPointer);
}
}
11 changes: 10 additions & 1 deletion clang/unittests/Format/FormatTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24879,7 +24879,7 @@ TEST_F(FormatTest, SkipMacroDefinitionBody) {
Style);

// With comments.
verifyFormat("/* */ #define A a // a a", "/* */ # define A a // a a",
verifyFormat("/* */ #define A a // a a", "/* */ # define A a // a a",
Style);
verifyNoChange("/* */ #define A a // a a", Style);

Expand All @@ -24891,6 +24891,15 @@ TEST_F(FormatTest, SkipMacroDefinitionBody) {
"int aaa; // a",
Style);

verifyNoChange(
"#define MACRO_WITH_COMMENTS() \\\n"
" public: \\\n"
" /* Documentation parsed by Doxygen for the following method. */ \\\n"
" static MyType getClassTypeId(); \\\n"
" /** Normal comment for the following method. */ \\\n"
" virtual MyType getTypeId() const;",
Style);

// multiline macro definitions
verifyNoChange("#define A a\\\n"
" A a \\\n "
Expand Down
82 changes: 13 additions & 69 deletions clang/unittests/Lex/DependencyDirectivesScannerTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//

#include "clang/Lex/DependencyDirectivesScanner.h"
#include "clang/Basic/TokenKinds.h"
#include "llvm/ADT/SmallString.h"
#include "gtest/gtest.h"

Expand All @@ -18,11 +17,11 @@ using namespace clang::dependency_directives_scan;
static bool minimizeSourceToDependencyDirectives(
StringRef Input, SmallVectorImpl<char> &Out,
SmallVectorImpl<dependency_directives_scan::Token> &Tokens,
SmallVectorImpl<Directive> &Directives, const LangOptions &LangOpts) {
SmallVectorImpl<Directive> &Directives) {
Out.clear();
Tokens.clear();
Directives.clear();
if (scanSourceForDependencyDirectives(Input, Tokens, Directives, LangOpts))
if (scanSourceForDependencyDirectives(Input, Tokens, Directives))
return true;

raw_svector_ostream OS(Out);
Expand All @@ -39,9 +38,7 @@ static bool minimizeSourceToDependencyDirectives(StringRef Input,
SmallVectorImpl<char> &Out) {
SmallVector<dependency_directives_scan::Token, 16> Tokens;
SmallVector<Directive, 32> Directives;
LangOptions LangOpts;
return minimizeSourceToDependencyDirectives(Input, Out, Tokens, Directives,
LangOpts);
return minimizeSourceToDependencyDirectives(Input, Out, Tokens, Directives);
}

namespace {
Expand All @@ -50,17 +47,16 @@ TEST(MinimizeSourceToDependencyDirectivesTest, Empty) {
SmallVector<char, 128> Out;
SmallVector<dependency_directives_scan::Token, 4> Tokens;
SmallVector<Directive, 4> Directives;
LangOptions LangOpts;

ASSERT_FALSE(minimizeSourceToDependencyDirectives("", Out, Tokens, Directives,
LangOpts));
ASSERT_FALSE(
minimizeSourceToDependencyDirectives("", Out, Tokens, Directives));
EXPECT_TRUE(Out.empty());
EXPECT_TRUE(Tokens.empty());
ASSERT_EQ(1u, Directives.size());
ASSERT_EQ(pp_eof, Directives.back().Kind);

ASSERT_FALSE(minimizeSourceToDependencyDirectives("abc def\nxyz", Out, Tokens,
Directives, LangOpts));
Directives));
EXPECT_STREQ("<TokBeforeEOF>\n", Out.data());
EXPECT_TRUE(Tokens.empty());
ASSERT_EQ(2u, Directives.size());
Expand All @@ -72,7 +68,6 @@ TEST(MinimizeSourceToDependencyDirectivesTest, AllTokens) {
SmallVector<char, 128> Out;
SmallVector<dependency_directives_scan::Token, 4> Tokens;
SmallVector<Directive, 4> Directives;
LangOptions LangOpts;

ASSERT_FALSE(
minimizeSourceToDependencyDirectives("#define A\n"
Expand All @@ -97,7 +92,7 @@ TEST(MinimizeSourceToDependencyDirectivesTest, AllTokens) {
"export module m;\n"
"import m;\n"
"#pragma clang system_header\n",
Out, Tokens, Directives, LangOpts));
Out, Tokens, Directives));
EXPECT_EQ(pp_define, Directives[0].Kind);
EXPECT_EQ(pp_undef, Directives[1].Kind);
EXPECT_EQ(pp_endif, Directives[2].Kind);
Expand Down Expand Up @@ -150,10 +145,9 @@ TEST(MinimizeSourceToDependencyDirectivesTest, Define) {
SmallVector<char, 128> Out;
SmallVector<dependency_directives_scan::Token, 4> Tokens;
SmallVector<Directive, 4> Directives;
LangOptions LangOpts;

ASSERT_FALSE(minimizeSourceToDependencyDirectives(
"#define MACRO", Out, Tokens, Directives, LangOpts));
ASSERT_FALSE(minimizeSourceToDependencyDirectives("#define MACRO", Out,
Tokens, Directives));
EXPECT_STREQ("#define MACRO\n", Out.data());
ASSERT_EQ(4u, Tokens.size());
ASSERT_EQ(2u, Directives.size());
Expand Down Expand Up @@ -844,16 +838,15 @@ TEST(MinimizeSourceToDependencyDirectivesTest, PragmaOnce) {
SmallVector<char, 128> Out;
SmallVector<dependency_directives_scan::Token, 4> Tokens;
SmallVector<Directive, 4> Directives;
LangOptions LangOpts;

StringRef Source = R"(// comment
#pragma once
// another comment
#include <test.h>
_Pragma("once")
)";
ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out, Tokens,
Directives, LangOpts));
ASSERT_FALSE(
minimizeSourceToDependencyDirectives(Source, Out, Tokens, Directives));
EXPECT_STREQ("#pragma once\n#include <test.h>\n_Pragma(\"once\")\n",
Out.data());
ASSERT_EQ(Directives.size(), 4u);
Expand Down Expand Up @@ -933,7 +926,6 @@ TEST(MinimizeSourceToDependencyDirectivesTest, CxxModules) {
SmallVector<char, 128> Out;
SmallVector<dependency_directives_scan::Token, 4> Tokens;
SmallVector<Directive, 4> Directives;
LangOptions LangOpts;

StringRef Source = R"(
module;
Expand Down Expand Up @@ -962,8 +954,8 @@ ort \
import f(->a = 3);
}
)";
ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out, Tokens,
Directives, LangOpts));
ASSERT_FALSE(
minimizeSourceToDependencyDirectives(Source, Out, Tokens, Directives));
EXPECT_STREQ("#include \"textual-header.h\"\nexport module m;"
"exp\\\nort import:l[[rename]];"
"import<<=3;import a b d e d e f e;"
Expand Down Expand Up @@ -1020,52 +1012,4 @@ TEST(MinimizeSourceToDependencyDirectivesTest, TokensBeforeEOF) {
EXPECT_STREQ("#ifndef A\n#define A\n#endif\n<TokBeforeEOF>\n", Out.data());
}

TEST(MinimizeSourceToDependencyDirectivesTest, CPlusPlus14PPNumber) {
SmallVector<char, 128> Out;
SmallVector<dependency_directives_scan::Token, 4> Tokens;
SmallVector<Directive, 4> Directives;
LangOptions LangOpts;

StringRef Source = R"(
#if 123'124
#endif
)";

LangOpts.CPlusPlus14 = true;
ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out, Tokens,
Directives, LangOpts));
EXPECT_STREQ("#if 123'124\n#endif\n", Out.data());
ASSERT_EQ(Directives.size(), 3u);
EXPECT_EQ(Directives[0].Kind, dependency_directives_scan::pp_if);
EXPECT_EQ(Directives[1].Kind, dependency_directives_scan::pp_endif);
EXPECT_EQ(Directives[2].Kind, dependency_directives_scan::pp_eof);
ASSERT_EQ(Tokens.size(), 7u);

ASSERT_TRUE(Tokens[0].is(tok::hash));
ASSERT_TRUE(Tokens[1].is(tok::raw_identifier)); // "if"
ASSERT_TRUE(Tokens[2].is(tok::numeric_constant)); // 123'124
ASSERT_TRUE(Tokens[3].is(tok::eod));
ASSERT_TRUE(Tokens[4].is(tok::hash));
ASSERT_TRUE(Tokens[5].is(tok::raw_identifier)); // #endif
ASSERT_TRUE(Tokens[6].is(tok::eod));

LangOpts.CPlusPlus14 = false;
ASSERT_FALSE(minimizeSourceToDependencyDirectives(Source, Out, Tokens,
Directives, LangOpts));
EXPECT_STREQ("#if 123'124\n#endif\n", Out.data());
ASSERT_EQ(Directives.size(), 3u);
EXPECT_EQ(Directives[0].Kind, dependency_directives_scan::pp_if);
EXPECT_EQ(Directives[1].Kind, dependency_directives_scan::pp_endif);
EXPECT_EQ(Directives[2].Kind, dependency_directives_scan::pp_eof);
ASSERT_EQ(Tokens.size(), 8u);
ASSERT_TRUE(Tokens[0].is(tok::hash));
ASSERT_TRUE(Tokens[1].is(tok::raw_identifier)); // "if"
ASSERT_TRUE(Tokens[2].is(tok::numeric_constant)); // 123
ASSERT_TRUE(Tokens[3].is(tok::unknown)); // '124
ASSERT_TRUE(Tokens[4].is(tok::eod));
ASSERT_TRUE(Tokens[5].is(tok::hash));
ASSERT_TRUE(Tokens[6].is(tok::raw_identifier)); // #endif
ASSERT_TRUE(Tokens[7].is(tok::eod));
}

} // end anonymous namespace
3 changes: 1 addition & 2 deletions clang/unittests/Lex/PPDependencyDirectivesTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,15 +104,14 @@ TEST_F(PPDependencyDirectivesTest, MacroGuard) {
SmallVector<dependency_directives_scan::Directive> Directives;
};
SmallVector<std::unique_ptr<DepDirectives>> DepDirectivesObjects;
LangOptions LangOpts;

auto getDependencyDirectives = [&](FileEntryRef File)
-> std::optional<ArrayRef<dependency_directives_scan::Directive>> {
DepDirectivesObjects.push_back(std::make_unique<DepDirectives>());
StringRef Input = (*FileMgr.getBufferForFile(File))->getBuffer();
bool Err = scanSourceForDependencyDirectives(
Input, DepDirectivesObjects.back()->Tokens,
DepDirectivesObjects.back()->Directives, LangOpts);
DepDirectivesObjects.back()->Directives);
EXPECT_FALSE(Err);
return llvm::ArrayRef(DepDirectivesObjects.back()->Directives);
};
Expand Down
2 changes: 1 addition & 1 deletion clang/www/cxx_dr_status.html
Original file line number Diff line number Diff line change
Expand Up @@ -10698,7 +10698,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2>
<td><a href="https://cplusplus.github.io/CWG/issues/1815.html">1815</a></td>
<td>CD4</td>
<td>Lifetime extension in aggregate initialization</td>
<td class="unreleased" align="center">Clang 19</td>
<td class="none" align="center">No</td>
</tr>
<tr id="1816">
<td><a href="https://cplusplus.github.io/CWG/issues/1816.html">1816</a></td>
Expand Down
31 changes: 13 additions & 18 deletions compiler-rt/lib/builtins/atomic.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,14 +51,6 @@
#endif
static const long SPINLOCK_MASK = SPINLOCK_COUNT - 1;

#ifndef CACHE_LINE_SIZE
#define CACHE_LINE_SIZE 64
#endif

#ifdef __clang__
#pragma clang diagnostic ignored "-Wgnu-designator"
#endif

////////////////////////////////////////////////////////////////////////////////
// Platform-specific lock implementation. Falls back to spinlocks if none is
// defined. Each platform should define the Lock type, and corresponding
Expand Down Expand Up @@ -102,18 +94,21 @@ static Lock locks[SPINLOCK_COUNT]; // initialized to OS_SPINLOCK_INIT which is 0
#else
_Static_assert(__atomic_always_lock_free(sizeof(uintptr_t), 0),
"Implementation assumes lock-free pointer-size cmpxchg");
#include <pthread.h>
#include <stdalign.h>
typedef struct {
alignas(CACHE_LINE_SIZE) pthread_mutex_t m;
} Lock;
typedef _Atomic(uintptr_t) Lock;
/// Unlock a lock. This is a release operation.
__inline static void unlock(Lock *l) { pthread_mutex_unlock(&l->m); }
/// Locks a lock.
__inline static void lock(Lock *l) { pthread_mutex_lock(&l->m); }
__inline static void unlock(Lock *l) {
__c11_atomic_store(l, 0, __ATOMIC_RELEASE);
}
/// Locks a lock. In the current implementation, this is potentially
/// unbounded in the contended case.
__inline static void lock(Lock *l) {
uintptr_t old = 0;
while (!__c11_atomic_compare_exchange_weak(l, &old, 1, __ATOMIC_ACQUIRE,
__ATOMIC_RELAXED))
old = 0;
}
/// locks for atomic operations
static Lock locks[SPINLOCK_COUNT] = {
[0 ... SPINLOCK_COUNT - 1] = {PTHREAD_MUTEX_INITIALIZER}};
static Lock locks[SPINLOCK_COUNT];
#endif

/// Returns a lock to use for a given pointer.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ llvm::MutableArrayRef<int> MutableArrayRef(Array);
llvm::DenseMap<int, int> DenseMap = {{4, 5}, {6, 7}};
llvm::StringMap<int> StringMap = {{"foo", 123}, {"bar", 456}};
llvm::Expected<int> ExpectedValue(8);
llvm::Expected<int> ExpectedError(llvm::createStringError({}, ""));
llvm::Expected<int> ExpectedError(llvm::createStringError(""));
std::optional<int> OptionalValue(9);
std::optional<int> OptionalNone(std::nullopt);
llvm::SmallVector<int, 5> SmallVector = {10, 11, 12};
Expand Down
1 change: 1 addition & 0 deletions flang/cmake/modules/AddFlangOffloadRuntime.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ macro(enable_omp_offload_compilation files)
"gfx908;gfx90a;gfx90c;gfx940;gfx1010;gfx1030"
"gfx1031;gfx1032;gfx1033;gfx1034;gfx1035;gfx1036"
"gfx1100;gfx1101;gfx1102;gfx1103;gfx1150;gfx1151"
"gfx1152"
)
set(all_nvptx_architectures
"sm_35;sm_37;sm_50;sm_52;sm_53;sm_60;sm_61;sm_62"
Expand Down
31 changes: 31 additions & 0 deletions flang/docs/Intrinsics.md
Original file line number Diff line number Diff line change
Expand Up @@ -967,4 +967,35 @@ program test_etime
print *, tarray(1)
print *, tarray(2)
end program test_etime
```

### Non-Standard Intrinsics: GETCWD

#### Description
`GETCWD(C, STATUS)` returns current working directory.

This intrinsic is provided in both subroutine and function forms; however, only one form can be used in any given program unit.

*C* and *STATUS* are `INTENT(OUT)` and provide the following:

| | |
|------------|---------------------------------------------------------------------------------------------------|
| `C` | Current work directory. The type shall be `CHARACTER` and of default kind. |
| `STATUS` | (Optional) Status flag. Returns 0 on success, a system specific and nonzero error code otherwise. The type shall be `INTEGER` and of a kind greater or equal to 4. |

#### Usage and Info

- **Standard:** GNU extension
- **Class:** Subroutine, function
- **Syntax:** `CALL GETCWD(C, STATUS)`, `STATUS = GETCWD(C)`

#### Example
```Fortran
PROGRAM example_getcwd
CHARACTER(len=255) :: cwd
INTEGER :: status
CALL getcwd(cwd, status)
PRINT *, cwd
PRINT *, status
END PROGRAM
```
2 changes: 2 additions & 0 deletions flang/include/flang/Optimizer/Builder/IntrinsicCall.h
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,8 @@ struct IntrinsicLibrary {
mlir::Value genFloor(mlir::Type, llvm::ArrayRef<mlir::Value>);
mlir::Value genFraction(mlir::Type resultType,
mlir::ArrayRef<mlir::Value> args);
fir::ExtendedValue genGetCwd(std::optional<mlir::Type> resultType,
llvm::ArrayRef<fir::ExtendedValue> args);
void genGetCommand(mlir::ArrayRef<fir::ExtendedValue> args);
mlir::Value genGetPID(mlir::Type resultType,
llvm::ArrayRef<mlir::Value> args);
Expand Down
5 changes: 5 additions & 0 deletions flang/include/flang/Optimizer/Builder/Runtime/Command.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,10 @@ mlir::Value genGetEnvVariable(fir::FirOpBuilder &, mlir::Location,
mlir::Value length, mlir::Value trimName,
mlir::Value errmsg);

/// Generate a call to the GetCwd runtime function which implements
/// the GETCWD intrinsic.
mlir::Value genGetCwd(fir::FirOpBuilder &builder, mlir::Location loc,
mlir::Value c);

} // namespace fir::runtime
#endif // FORTRAN_OPTIMIZER_BUILDER_RUNTIME_COMMAND_H
30 changes: 30 additions & 0 deletions flang/include/flang/Optimizer/Dialect/FIRAttr.td
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,36 @@ def fir_BoxFieldAttr : I32EnumAttr<
let cppNamespace = "fir";
}

def fir_ReduceOperationEnum : I32BitEnumAttr<"ReduceOperationEnum",
"intrinsic operations and functions supported by DO CONCURRENT REDUCE",
[
I32BitEnumAttrCaseBit<"Add", 0, "add">,
I32BitEnumAttrCaseBit<"Multiply", 1, "multiply">,
I32BitEnumAttrCaseBit<"AND", 2, "and">,
I32BitEnumAttrCaseBit<"OR", 3, "or">,
I32BitEnumAttrCaseBit<"EQV", 4, "eqv">,
I32BitEnumAttrCaseBit<"NEQV", 5, "neqv">,
I32BitEnumAttrCaseBit<"MAX", 6, "max">,
I32BitEnumAttrCaseBit<"MIN", 7, "min">,
I32BitEnumAttrCaseBit<"IAND", 8, "iand">,
I32BitEnumAttrCaseBit<"IOR", 9, "ior">,
I32BitEnumAttrCaseBit<"EIOR", 10, "eior">
]> {
let separator = ", ";
let cppNamespace = "::fir";
let printBitEnumPrimaryGroups = 1;
}

def fir_ReduceAttr : fir_Attr<"Reduce"> {
let mnemonic = "reduce_attr";

let parameters = (ins
"ReduceOperationEnum":$reduce_operation
);

let assemblyFormat = "`<` $reduce_operation `>`";
}

// mlir::SideEffects::Resource for modelling operations which add debugging information
def DebuggingResource : Resource<"::fir::DebuggingResource">;

Expand Down
35 changes: 27 additions & 8 deletions flang/include/flang/Optimizer/Dialect/FIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -2125,8 +2125,8 @@ class region_Op<string mnemonic, list<Trait> traits = []> :
let hasVerifier = 1;
}

def fir_DoLoopOp : region_Op<"do_loop",
[DeclareOpInterfaceMethods<LoopLikeOpInterface,
def fir_DoLoopOp : region_Op<"do_loop", [AttrSizedOperandSegments,
DeclareOpInterfaceMethods<LoopLikeOpInterface,
["getYieldedValuesMutable"]>]> {
let summary = "generalized loop operation";
let description = [{
Expand Down Expand Up @@ -2156,9 +2156,11 @@ def fir_DoLoopOp : region_Op<"do_loop",
Index:$lowerBound,
Index:$upperBound,
Index:$step,
Variadic<AnyType>:$reduceOperands,
Variadic<AnyType>:$initArgs,
OptionalAttr<UnitAttr>:$unordered,
OptionalAttr<UnitAttr>:$finalValue
OptionalAttr<UnitAttr>:$finalValue,
OptionalAttr<ArrayAttr>:$reduceAttrs
);
let results = (outs Variadic<AnyType>:$results);
let regions = (region SizedRegion<1>:$region);
Expand All @@ -2169,6 +2171,8 @@ def fir_DoLoopOp : region_Op<"do_loop",
"mlir::Value":$step, CArg<"bool", "false">:$unordered,
CArg<"bool", "false">:$finalCountValue,
CArg<"mlir::ValueRange", "std::nullopt">:$iterArgs,
CArg<"mlir::ValueRange", "std::nullopt">:$reduceOperands,
CArg<"llvm::ArrayRef<mlir::Attribute>", "{}">:$reduceAttrs,
CArg<"llvm::ArrayRef<mlir::NamedAttribute>", "{}">:$attributes)>
];

Expand All @@ -2181,11 +2185,12 @@ def fir_DoLoopOp : region_Op<"do_loop",
return getBody()->getArguments().drop_front();
}
mlir::Operation::operand_range getIterOperands() {
return getOperands().drop_front(getNumControlOperands());
return getOperands()
.drop_front(getNumControlOperands() + getNumReduceOperands());
}
llvm::MutableArrayRef<mlir::OpOperand> getInitsMutable() {
return
getOperation()->getOpOperands().drop_front(getNumControlOperands());
return getOperation()->getOpOperands()
.drop_front(getNumControlOperands() + getNumReduceOperands());
}

void setLowerBound(mlir::Value bound) { (*this)->setOperand(0, bound); }
Expand All @@ -2200,11 +2205,25 @@ def fir_DoLoopOp : region_Op<"do_loop",
unsigned getNumControlOperands() { return 3; }
/// Does the operation hold operands for loop-carried values
bool hasIterOperands() {
return (*this)->getNumOperands() > getNumControlOperands();
return getNumIterOperands() > 0;
}
/// Does the operation hold operands for reduction variables
bool hasReduceOperands() {
return getNumReduceOperands() > 0;
}
/// Get Number of variadic operands
unsigned getNumOperands(unsigned idx) {
auto segments = (*this)->getAttrOfType<mlir::DenseI32ArrayAttr>(
getOperandSegmentSizeAttr());
return static_cast<unsigned>(segments[idx]);
}
// Get Number of reduction operands
unsigned getNumReduceOperands() {
return getNumOperands(3);
}
/// Get Number of loop-carried values
unsigned getNumIterOperands() {
return (*this)->getNumOperands() - getNumControlOperands();
return getNumOperands(4);
}

/// Get the body of the loop
Expand Down
3 changes: 0 additions & 3 deletions flang/include/flang/Optimizer/Transforms/Passes.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,6 @@ std::unique_ptr<mlir::Pass> createAffineDemotionPass();
std::unique_ptr<mlir::Pass>
createArrayValueCopyPass(fir::ArrayValueCopyOptions options = {});
std::unique_ptr<mlir::Pass> createCFGConversionPassWithNSW();
std::unique_ptr<mlir::Pass> createExternalNameConversionPass();
std::unique_ptr<mlir::Pass>
createExternalNameConversionPass(bool appendUnderscore);
std::unique_ptr<mlir::Pass> createMemDataFlowOptPass();
std::unique_ptr<mlir::Pass> createPromoteToAffinePass();
std::unique_ptr<mlir::Pass>
Expand Down
1 change: 0 additions & 1 deletion flang/include/flang/Optimizer/Transforms/Passes.td
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,6 @@ def ExternalNameConversion : Pass<"external-name-interop", "mlir::ModuleOp"> {
let description = [{
Demangle FIR internal name and mangle them for external interoperability.
}];
let constructor = "::fir::createExternalNameConversionPass()";
let options = [
Option<"appendUnderscoreOpt", "append-underscore",
"bool", /*default=*/"true",
Expand Down
4 changes: 4 additions & 0 deletions flang/include/flang/Runtime/command.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ std::int32_t RTNAME(GetEnvVariable)(const Descriptor &name,
const Descriptor *value = nullptr, const Descriptor *length = nullptr,
bool trim_name = true, const Descriptor *errmsg = nullptr,
const char *sourceFile = nullptr, int line = 0);

// Calls getcwd()
std::int32_t RTNAME(GetCwd)(
const Descriptor &cwd, const char *sourceFile, int line);
}
} // namespace Fortran::runtime

Expand Down
5 changes: 5 additions & 0 deletions flang/include/flang/Runtime/magic-numbers.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ Additional status code for a bad pointer DEALLOCATE.
#endif
#define FORTRAN_RUNTIME_STAT_BAD_POINTER_DEALLOCATION 110

#if 0
Status codes for GETCWD.
#endif
#define FORTRAN_RUNTIME_STAT_MISSING_CWD 111

#if 0
ieee_class_type values
The sequence is that of F18 Clause 17.2p3, but nothing depends on that.
Expand Down
5 changes: 2 additions & 3 deletions flang/include/flang/Tools/CLOptions.inc
Original file line number Diff line number Diff line change
Expand Up @@ -233,9 +233,8 @@ inline void addBoxedProcedurePass(mlir::PassManager &pm) {

inline void addExternalNameConversionPass(
mlir::PassManager &pm, bool appendUnderscore = true) {
addPassConditionally(pm, disableExternalNameConversion, [&]() {
return fir::createExternalNameConversionPass(appendUnderscore);
});
addPassConditionally(pm, disableExternalNameConversion,
[&]() { return fir::createExternalNameConversion({appendUnderscore}); });
}

// Use inliner extension point callback to register the default inliner pass.
Expand Down
12 changes: 11 additions & 1 deletion flang/lib/Evaluate/intrinsics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -514,6 +514,10 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
{"gamma", {{"x", SameReal}}, SameReal},
{"get_team", {{"level", DefaultInt, Rank::scalar, Optionality::optional}},
TeamType, Rank::scalar, IntrinsicClass::transformationalFunction},
{"getcwd",
{{"c", DefaultChar, Rank::scalar, Optionality::required,
common::Intent::Out}},
TypePattern{IntType, KindCode::greaterOrEqualToKind, 4}},
{"getpid", {}, DefaultInt},
{"huge",
{{"x", SameIntOrReal, Rank::anyOrAssumedRank, Optionality::required,
Expand Down Expand Up @@ -1406,6 +1410,12 @@ static const IntrinsicInterface intrinsicSubroutine[]{
{"errmsg", DefaultChar, Rank::scalar, Optionality::optional,
common::Intent::InOut}},
{}, Rank::elemental, IntrinsicClass::impureSubroutine},
{"getcwd",
{{"c", DefaultChar, Rank::scalar, Optionality::required,
common::Intent::Out},
{"status", TypePattern{IntType, KindCode::greaterOrEqualToKind, 4},
Rank::scalar, Optionality::optional, common::Intent::Out}},
{}, Rank::elemental, IntrinsicClass::impureSubroutine},
{"move_alloc",
{{"from", SameType, Rank::known, Optionality::required,
common::Intent::InOut},
Expand Down Expand Up @@ -2574,7 +2584,7 @@ bool IntrinsicProcTable::Implementation::IsDualIntrinsic(
const std::string &name) const {
// Collection for some intrinsics with function and subroutine form,
// in order to pass the semantic check.
static const std::string dualIntrinsic[]{{"etime"}};
static const std::string dualIntrinsic[]{{"etime"}, {"getcwd"}};

return std::find_if(std::begin(dualIntrinsic), std::end(dualIntrinsic),
[&name](const std::string &dualName) {
Expand Down
16 changes: 8 additions & 8 deletions flang/lib/Lower/OpenMP/ClauseProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ static void addUseDeviceClause(
useDeviceLocs.push_back(operand.getLoc());
}
for (const omp::Object &object : objects)
useDeviceSyms.push_back(object.id());
useDeviceSyms.push_back(object.sym());
}

static void convertLoopBounds(lower::AbstractConverter &converter,
Expand Down Expand Up @@ -525,7 +525,7 @@ bool ClauseProcessor::processCopyin() const {
bool hasCopyin = findRepeatableClause<omp::clause::Copyin>(
[&](const omp::clause::Copyin &clause, const parser::CharBlock &) {
for (const omp::Object &object : clause.v) {
semantics::Symbol *sym = object.id();
semantics::Symbol *sym = object.sym();
assert(sym && "Expecting symbol");
if (const auto *commonDetails =
sym->detailsIf<semantics::CommonBlockDetails>()) {
Expand Down Expand Up @@ -698,7 +698,7 @@ bool ClauseProcessor::processCopyprivate(
bool hasCopyPrivate = findRepeatableClause<clause::Copyprivate>(
[&](const clause::Copyprivate &clause, const parser::CharBlock &) {
for (const Object &object : clause.v) {
semantics::Symbol *sym = object.id();
semantics::Symbol *sym = object.sym();
if (const auto *commonDetails =
sym->detailsIf<semantics::CommonBlockDetails>()) {
for (const auto &mem : commonDetails->objects())
Expand Down Expand Up @@ -739,7 +739,7 @@ bool ClauseProcessor::processDepend(mlir::omp::DependClauseOps &result) const {
"array sections not supported for task depend");
}

semantics::Symbol *sym = object.id();
semantics::Symbol *sym = object.sym();
const mlir::Value variable = converter.getSymbolAddress(*sym);
result.dependVars.push_back(variable);
}
Expand Down Expand Up @@ -870,11 +870,11 @@ bool ClauseProcessor::processMap(
lower::AddrAndBoundsInfo info =
lower::gatherDataOperandAddrAndBounds<mlir::omp::MapBoundsOp,
mlir::omp::MapBoundsType>(
converter, firOpBuilder, semaCtx, stmtCtx, *object.id(),
converter, firOpBuilder, semaCtx, stmtCtx, *object.sym(),
object.ref(), clauseLocation, asFortran, bounds,
treatIndexAsSection);

auto origSymbol = converter.getSymbolAddress(*object.id());
auto origSymbol = converter.getSymbolAddress(*object.sym());
mlir::Value symAddr = info.addr;
if (origSymbol && fir::isTypeWithDescriptor(origSymbol.getType()))
symAddr = origSymbol;
Expand All @@ -894,12 +894,12 @@ bool ClauseProcessor::processMap(
mapTypeBits),
mlir::omp::VariableCaptureKind::ByRef, symAddr.getType());

if (object.id()->owner().IsDerivedType()) {
if (object.sym()->owner().IsDerivedType()) {
addChildIndexAndMapToParent(object, parentMemberIndices, mapOp,
semaCtx);
} else {
result.mapVars.push_back(mapOp);
ptrMapSyms->push_back(object.id());
ptrMapSyms->push_back(object.sym());
if (mapSymTypes)
mapSymTypes->push_back(symAddr.getType());
if (mapSymLocs)
Expand Down
8 changes: 4 additions & 4 deletions flang/lib/Lower/OpenMP/ClauseProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -205,11 +205,11 @@ bool ClauseProcessor::processMotionClauses(lower::StatementContext &stmtCtx,
lower::AddrAndBoundsInfo info =
lower::gatherDataOperandAddrAndBounds<mlir::omp::MapBoundsOp,
mlir::omp::MapBoundsType>(
converter, firOpBuilder, semaCtx, stmtCtx, *object.id(),
converter, firOpBuilder, semaCtx, stmtCtx, *object.sym(),
object.ref(), clauseLocation, asFortran, bounds,
treatIndexAsSection);

auto origSymbol = converter.getSymbolAddress(*object.id());
auto origSymbol = converter.getSymbolAddress(*object.sym());
mlir::Value symAddr = info.addr;
if (origSymbol && fir::isTypeWithDescriptor(origSymbol.getType()))
symAddr = origSymbol;
Expand All @@ -226,12 +226,12 @@ bool ClauseProcessor::processMotionClauses(lower::StatementContext &stmtCtx,
mapTypeBits),
mlir::omp::VariableCaptureKind::ByRef, symAddr.getType());

if (object.id()->owner().IsDerivedType()) {
if (object.sym()->owner().IsDerivedType()) {
addChildIndexAndMapToParent(object, parentMemberIndices, mapOp,
semaCtx);
} else {
result.mapVars.push_back(mapOp);
mapSymbols.push_back(object.id());
mapSymbols.push_back(object.sym());
}
}
});
Expand Down
53 changes: 46 additions & 7 deletions flang/lib/Lower/OpenMP/Clauses.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@
#include <type_traits>
#include <utility>

namespace Fortran::semantics {
class Symbol;
}

namespace Fortran::lower::omp {
using namespace Fortran;
using SomeExpr = semantics::SomeExpr;
Expand All @@ -32,29 +36,64 @@ struct TypeTy : public evaluate::SomeType {
bool operator==(const TypeTy &t) const { return true; }
};

using IdTy = semantics::Symbol *;
template <typename ExprTy>
struct IdTyTemplate {
// "symbol" is always non-null for id's of actual objects.
Fortran::semantics::Symbol *symbol;
std::optional<ExprTy> designator;

bool operator==(const IdTyTemplate &other) const {
// If symbols are different, then the objects are different.
if (symbol != other.symbol)
return false;
if (symbol == nullptr)
return true;
// Equal symbols don't necessarily indicate identical objects,
// for example, a derived object component may use a single symbol,
// which will refer to different objects for different designators,
// e.g. a%c and b%c.
return designator == other.designator;
}

operator bool() const { return symbol != nullptr; }
};

using ExprTy = SomeExpr;

template <typename T>
using List = tomp::ListT<T>;
} // namespace Fortran::lower::omp

// Specialization of the ObjectT template
namespace tomp::type {
template <>
struct ObjectT<Fortran::lower::omp::IdTy, Fortran::lower::omp::ExprTy> {
using IdTy = Fortran::lower::omp::IdTy;
struct ObjectT<Fortran::lower::omp::IdTyTemplate<Fortran::lower::omp::ExprTy>,
Fortran::lower::omp::ExprTy> {
using IdTy = Fortran::lower::omp::IdTyTemplate<Fortran::lower::omp::ExprTy>;
using ExprTy = Fortran::lower::omp::ExprTy;

const IdTy &id() const { return symbol; }
const std::optional<ExprTy> &ref() const { return designator; }
IdTy id() const { return identity; }
Fortran::semantics::Symbol *sym() const { return identity.symbol; }
const std::optional<ExprTy> &ref() const { return identity.designator; }

IdTy symbol;
std::optional<ExprTy> designator;
IdTy identity;
};
} // namespace tomp::type

namespace Fortran::lower::omp {
using IdTy = IdTyTemplate<ExprTy>;
}

namespace std {
template <>
struct hash<Fortran::lower::omp::IdTy> {
size_t operator()(const Fortran::lower::omp::IdTy &id) const {
return static_cast<size_t>(reinterpret_cast<uintptr_t>(id.symbol));
}
};
} // namespace std

namespace Fortran::lower::omp {
using Object = tomp::ObjectT<IdTy, ExprTy>;
using ObjectList = tomp::ObjectListT<IdTy, ExprTy>;

Expand Down
2 changes: 1 addition & 1 deletion flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ void DataSharingProcessor::collectOmpObjectListSymbol(
const omp::ObjectList &objects,
llvm::SetVector<const semantics::Symbol *> &symbolSet) {
for (const omp::Object &object : objects)
symbolSet.insert(object.id());
symbolSet.insert(object.sym());
}

void DataSharingProcessor::collectSymbolsForPrivatization() {
Expand Down
4 changes: 3 additions & 1 deletion flang/lib/Lower/OpenMP/DataSharingProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ class DataSharingProcessor {
void Post(const T &) {}

bool Pre(const parser::OpenMPConstruct &omp) {
currentConstruct = &omp;
// Skip constructs that may not have privatizations.
if (!std::holds_alternative<parser::OpenMPCriticalConstruct>(omp.u))
currentConstruct = &omp;
return true;
}

Expand Down
2 changes: 1 addition & 1 deletion flang/lib/Lower/OpenMP/OpenMP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1434,7 +1434,7 @@ genSectionsOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
mlir::OpBuilder::InsertPoint insp = builder.saveInsertionPoint();
const auto &objList = std::get<ObjectList>(lastp->t);
for (const Object &object : objList) {
semantics::Symbol *sym = object.id();
semantics::Symbol *sym = object.sym();
converter.copyHostAssociateVar(*sym, &insp);
}
}
Expand Down
8 changes: 4 additions & 4 deletions flang/lib/Lower/OpenMP/ReductionProcessor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ namespace omp {
ReductionProcessor::ReductionIdentifier ReductionProcessor::getReductionType(
const omp::clause::ProcedureDesignator &pd) {
auto redType = llvm::StringSwitch<std::optional<ReductionIdentifier>>(
getRealName(pd.v.id()).ToString())
getRealName(pd.v.sym()).ToString())
.Case("max", ReductionIdentifier::MAX)
.Case("min", ReductionIdentifier::MIN)
.Case("iand", ReductionIdentifier::IAND)
Expand Down Expand Up @@ -72,7 +72,7 @@ ReductionProcessor::ReductionIdentifier ReductionProcessor::getReductionType(

bool ReductionProcessor::supportedIntrinsicProcReduction(
const omp::clause::ProcedureDesignator &pd) {
semantics::Symbol *sym = pd.v.id();
semantics::Symbol *sym = pd.v.sym();
if (!sym->GetUltimate().attrs().test(semantics::Attr::INTRINSIC))
return false;
auto redType = llvm::StringSwitch<bool>(getRealName(sym).ToString())
Expand Down Expand Up @@ -707,7 +707,7 @@ void ReductionProcessor::addDeclareReduction(
// should happen byref
fir::FirOpBuilder &builder = converter.getFirOpBuilder();
for (const Object &object : objectList) {
const semantics::Symbol *symbol = object.id();
const semantics::Symbol *symbol = object.sym();
if (reductionSymbols)
reductionSymbols->push_back(symbol);
mlir::Value symVal = converter.getSymbolAddress(*symbol);
Expand Down Expand Up @@ -825,7 +825,7 @@ ReductionProcessor::getRealName(const semantics::Symbol *symbol) {

const semantics::SourceName
ReductionProcessor::getRealName(const omp::clause::ProcedureDesignator &pd) {
return getRealName(pd.v.id());
return getRealName(pd.v.sym());
}

int ReductionProcessor::getOperationIdentity(ReductionIdentifier redId,
Expand Down
8 changes: 4 additions & 4 deletions flang/lib/Lower/OpenMP/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ void genObjectList(const ObjectList &objects,
lower::AbstractConverter &converter,
llvm::SmallVectorImpl<mlir::Value> &operands) {
for (const Object &object : objects) {
const semantics::Symbol *sym = object.id();
const semantics::Symbol *sym = object.sym();
assert(sym && "Expected Symbol");
if (mlir::Value variable = converter.getSymbolAddress(*sym)) {
operands.push_back(variable);
Expand Down Expand Up @@ -107,7 +107,7 @@ void gatherFuncAndVarSyms(
const ObjectList &objects, mlir::omp::DeclareTargetCaptureClause clause,
llvm::SmallVectorImpl<DeclareTargetCapturePair> &symbolAndClause) {
for (const Object &object : objects)
symbolAndClause.emplace_back(clause, *object.id());
symbolAndClause.emplace_back(clause, *object.sym());
}

mlir::omp::MapInfoOp
Expand Down Expand Up @@ -175,7 +175,7 @@ generateMemberPlacementIndices(const Object &object,
semantics::SemanticsContext &semaCtx) {
auto compObj = getComponentObject(object, semaCtx);
while (compObj) {
indices.push_back(getComponentPlacementInParent(compObj->id()));
indices.push_back(getComponentPlacementInParent(compObj->sym()));
compObj =
getComponentObject(getBaseObject(compObj.value(), semaCtx), semaCtx);
}
Expand All @@ -188,7 +188,7 @@ void addChildIndexAndMapToParent(
std::map<const semantics::Symbol *,
llvm::SmallVector<OmpMapMemberIndicesData>> &parentMemberIndices,
mlir::omp::MapInfoOp &mapOp, semantics::SemanticsContext &semaCtx) {
std::optional<evaluate::DataRef> dataRef = ExtractDataRef(object.designator);
std::optional<evaluate::DataRef> dataRef = ExtractDataRef(object.ref());
assert(dataRef.has_value() &&
"DataRef could not be extracted during mapping of derived type "
"cannot proceed");
Expand Down
39 changes: 35 additions & 4 deletions flang/lib/Optimizer/Builder/IntrinsicCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,10 @@ static constexpr IntrinsicHandler handlers[]{
{"trim_name", asAddr, handleDynamicOptional},
{"errmsg", asBox, handleDynamicOptional}}},
/*isElemental=*/false},
{"getcwd",
&I::genGetCwd,
{{{"c", asBox}, {"status", asAddr, handleDynamicOptional}}},
/*isElemental=*/false},
{"getpid", &I::genGetPID},
{"iachar", &I::genIchar},
{"iall",
Expand Down Expand Up @@ -3476,6 +3480,37 @@ mlir::Value IntrinsicLibrary::genFraction(mlir::Type resultType,
fir::runtime::genFraction(builder, loc, fir::getBase(args[0])));
}

// GETCWD
fir::ExtendedValue
IntrinsicLibrary::genGetCwd(std::optional<mlir::Type> resultType,
llvm::ArrayRef<fir::ExtendedValue> args) {
assert((args.size() == 1 && resultType.has_value()) ||
(args.size() >= 1 && !resultType.has_value()));

mlir::Value cwd = fir::getBase(args[0]);
mlir::Value statusValue = fir::runtime::genGetCwd(builder, loc, cwd);

if (resultType.has_value()) {
// Function form, return status.
return statusValue;
} else {
// Subroutine form, store status and return none.
const fir::ExtendedValue &status = args[1];
if (!isStaticallyAbsent(status)) {
mlir::Value statusAddr = fir::getBase(status);
mlir::Value statusIsPresentAtRuntime =
builder.genIsNotNullAddr(loc, statusAddr);
builder.genIfThen(loc, statusIsPresentAtRuntime)
.genThen([&]() {
builder.createStoreWithConvert(loc, statusValue, statusAddr);
})
.end();
}
}

return {};
}

// GET_COMMAND
void IntrinsicLibrary::genGetCommand(llvm::ArrayRef<fir::ExtendedValue> args) {
assert(args.size() == 4);
Expand Down Expand Up @@ -4965,10 +5000,6 @@ fir::ExtendedValue
IntrinsicLibrary::genIsContiguous(mlir::Type resultType,
llvm::ArrayRef<fir::ExtendedValue> args) {
assert(args.size() == 1);
if (const auto *boxValue = args[0].getBoxOf<fir::BoxValue>())
if (boxValue->hasAssumedRank())
TODO(loc, "intrinsic: is_contiguous with assumed rank argument");

return builder.createConvert(
loc, resultType,
fir::runtime::genIsContiguous(builder, loc, fir::getBase(args[0])));
Expand Down
6 changes: 3 additions & 3 deletions flang/lib/Optimizer/Builder/MutableBox.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,8 @@ static bool readToBoxValue(const fir::MutableBoxValue &box,
// Track value as fir.box
if ((box.isDerived() && mayBePolymorphic) || box.isUnlimitedPolymorphic())
return true;
if (box.hasAssumedRank())
return true;
// Intrinsic allocatables are contiguous, no need to track the value by
// fir.box.
if (box.isAllocatable() || box.rank() == 0)
Expand All @@ -409,14 +411,12 @@ fir::factory::genMutableBoxRead(fir::FirOpBuilder &builder, mlir::Location loc,
const fir::MutableBoxValue &box,
bool mayBePolymorphic,
bool preserveLowerBounds) {
if (box.hasAssumedRank())
TODO(loc, "assumed rank allocatables or pointers");
llvm::SmallVector<mlir::Value> lbounds;
llvm::SmallVector<mlir::Value> extents;
llvm::SmallVector<mlir::Value> lengths;
if (readToBoxValue(box, mayBePolymorphic)) {
auto reader = MutablePropertyReader(builder, loc, box);
if (preserveLowerBounds)
if (preserveLowerBounds && !box.hasAssumedRank())
reader.getLowerBounds(lbounds);
return fir::BoxValue{reader.getIrBox(), lbounds,
box.nonDeferredLenParams()};
Expand Down
13 changes: 13 additions & 0 deletions flang/lib/Optimizer/Builder/Runtime/Command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,16 @@ mlir::Value fir::runtime::genGetEnvVariable(fir::FirOpBuilder &builder,
sourceFile, sourceLine);
return builder.create<fir::CallOp>(loc, runtimeFunc, args).getResult(0);
}

mlir::Value fir::runtime::genGetCwd(fir::FirOpBuilder &builder,
mlir::Location loc, mlir::Value cwd) {
mlir::func::FuncOp func =
fir::runtime::getRuntimeFunc<mkRTKey(GetCwd)>(loc, builder);
auto runtimeFuncTy = func.getFunctionType();
mlir::Value sourceFile = fir::factory::locationToFilename(builder, loc);
mlir::Value sourceLine =
fir::factory::locationToLineNo(builder, loc, runtimeFuncTy.getInput(2));
llvm::SmallVector<mlir::Value> args = fir::runtime::createArguments(
builder, loc, runtimeFuncTy, cwd, sourceFile, sourceLine);
return builder.create<fir::CallOp>(loc, func, args).getResult(0);
}
4 changes: 2 additions & 2 deletions flang/lib/Optimizer/Dialect/FIRAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,6 @@ void fir::printFirAttribute(FIROpsDialect *dialect, mlir::Attribute attr,

void FIROpsDialect::registerAttributes() {
addAttributes<ClosedIntervalAttr, ExactTypeAttr, FortranVariableFlagsAttr,
LowerBoundAttr, PointIntervalAttr, RealAttr, SubclassAttr,
UpperBoundAttr>();
LowerBoundAttr, PointIntervalAttr, RealAttr, ReduceAttr,
SubclassAttr, UpperBoundAttr>();
}
73 changes: 66 additions & 7 deletions flang/lib/Optimizer/Dialect/FIROps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2456,9 +2456,16 @@ void fir::DoLoopOp::build(mlir::OpBuilder &builder,
mlir::OperationState &result, mlir::Value lb,
mlir::Value ub, mlir::Value step, bool unordered,
bool finalCountValue, mlir::ValueRange iterArgs,
mlir::ValueRange reduceOperands,
llvm::ArrayRef<mlir::Attribute> reduceAttrs,
llvm::ArrayRef<mlir::NamedAttribute> attributes) {
result.addOperands({lb, ub, step});
result.addOperands(reduceOperands);
result.addOperands(iterArgs);
result.addAttribute(getOperandSegmentSizeAttr(),
builder.getDenseI32ArrayAttr(
{1, 1, 1, static_cast<int32_t>(reduceOperands.size()),
static_cast<int32_t>(iterArgs.size())}));
if (finalCountValue) {
result.addTypes(builder.getIndexType());
result.addAttribute(getFinalValueAttrName(result.name),
Expand All @@ -2477,6 +2484,9 @@ void fir::DoLoopOp::build(mlir::OpBuilder &builder,
if (unordered)
result.addAttribute(getUnorderedAttrName(result.name),
builder.getUnitAttr());
if (!reduceAttrs.empty())
result.addAttribute(getReduceAttrsAttrName(result.name),
builder.getArrayAttr(reduceAttrs));
result.addAttributes(attributes);
}

Expand All @@ -2502,24 +2512,51 @@ mlir::ParseResult fir::DoLoopOp::parse(mlir::OpAsmParser &parser,
if (mlir::succeeded(parser.parseOptionalKeyword("unordered")))
result.addAttribute("unordered", builder.getUnitAttr());

// Parse the reduction arguments.
llvm::SmallVector<mlir::OpAsmParser::UnresolvedOperand> reduceOperands;
llvm::SmallVector<mlir::Type> reduceArgTypes;
if (succeeded(parser.parseOptionalKeyword("reduce"))) {
// Parse reduction attributes and variables.
llvm::SmallVector<ReduceAttr> attributes;
if (failed(parser.parseCommaSeparatedList(
mlir::AsmParser::Delimiter::Paren, [&]() {
if (parser.parseAttribute(attributes.emplace_back()) ||
parser.parseArrow() ||
parser.parseOperand(reduceOperands.emplace_back()) ||
parser.parseColonType(reduceArgTypes.emplace_back()))
return mlir::failure();
return mlir::success();
})))
return mlir::failure();
// Resolve input operands.
for (auto operand_type : llvm::zip(reduceOperands, reduceArgTypes))
if (parser.resolveOperand(std::get<0>(operand_type),
std::get<1>(operand_type), result.operands))
return mlir::failure();
llvm::SmallVector<mlir::Attribute> arrayAttr(attributes.begin(),
attributes.end());
result.addAttribute(getReduceAttrsAttrName(result.name),
builder.getArrayAttr(arrayAttr));
}

// Parse the optional initial iteration arguments.
llvm::SmallVector<mlir::OpAsmParser::Argument> regionArgs;
llvm::SmallVector<mlir::OpAsmParser::UnresolvedOperand> operands;
llvm::SmallVector<mlir::OpAsmParser::UnresolvedOperand> iterOperands;
llvm::SmallVector<mlir::Type> argTypes;
bool prependCount = false;
regionArgs.push_back(inductionVariable);

if (succeeded(parser.parseOptionalKeyword("iter_args"))) {
// Parse assignment list and results type list.
if (parser.parseAssignmentList(regionArgs, operands) ||
if (parser.parseAssignmentList(regionArgs, iterOperands) ||
parser.parseArrowTypeList(result.types))
return mlir::failure();
if (result.types.size() == operands.size() + 1)
if (result.types.size() == iterOperands.size() + 1)
prependCount = true;
// Resolve input operands.
llvm::ArrayRef<mlir::Type> resTypes = result.types;
for (auto operand_type :
llvm::zip(operands, prependCount ? resTypes.drop_front() : resTypes))
for (auto operand_type : llvm::zip(
iterOperands, prependCount ? resTypes.drop_front() : resTypes))
if (parser.resolveOperand(std::get<0>(operand_type),
std::get<1>(operand_type), result.operands))
return mlir::failure();
Expand All @@ -2530,6 +2567,12 @@ mlir::ParseResult fir::DoLoopOp::parse(mlir::OpAsmParser &parser,
prependCount = true;
}

// Set the operandSegmentSizes attribute
result.addAttribute(getOperandSegmentSizeAttr(),
builder.getDenseI32ArrayAttr(
{1, 1, 1, static_cast<int32_t>(reduceOperands.size()),
static_cast<int32_t>(iterOperands.size())}));

if (parser.parseOptionalAttrDictWithKeyword(result.attributes))
return mlir::failure();

Expand Down Expand Up @@ -2606,6 +2649,10 @@ mlir::LogicalResult fir::DoLoopOp::verify() {

i++;
}
auto reduceAttrs = getReduceAttrsAttr();
if (getNumReduceOperands() != (reduceAttrs ? reduceAttrs.size() : 0))
return emitOpError(
"mismatch in number of reduction variables and reduction attributes");
return mlir::success();
}

Expand All @@ -2615,6 +2662,17 @@ void fir::DoLoopOp::print(mlir::OpAsmPrinter &p) {
<< getUpperBound() << " step " << getStep();
if (getUnordered())
p << " unordered";
if (hasReduceOperands()) {
p << " reduce(";
auto attrs = getReduceAttrsAttr();
auto operands = getReduceOperands();
llvm::interleaveComma(llvm::zip(attrs, operands), p, [&](auto it) {
p << std::get<0>(it) << " -> " << std::get<1>(it) << " : "
<< std::get<1>(it).getType();
});
p << ')';
printBlockTerminators = true;
}
if (hasIterOperands()) {
p << " iter_args(";
auto regionArgs = getRegionIterArgs();
Expand All @@ -2628,8 +2686,9 @@ void fir::DoLoopOp::print(mlir::OpAsmPrinter &p) {
p << " -> " << getResultTypes();
printBlockTerminators = true;
}
p.printOptionalAttrDictWithKeyword((*this)->getAttrs(),
{"unordered", "finalValue"});
p.printOptionalAttrDictWithKeyword(
(*this)->getAttrs(),
{"unordered", "finalValue", "reduceAttrs", "operandSegmentSizes"});
p << ' ';
p.printRegion(getRegion(), /*printEntryBlockArgs=*/false,
printBlockTerminators);
Expand Down
23 changes: 4 additions & 19 deletions flang/lib/Optimizer/Transforms/ExternalNameConversion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,25 +45,18 @@ namespace {
class ExternalNameConversionPass
: public fir::impl::ExternalNameConversionBase<ExternalNameConversionPass> {
public:
ExternalNameConversionPass(bool appendUnderscoring)
: appendUnderscores(appendUnderscoring) {}

ExternalNameConversionPass() { usePassOpt = true; }
using ExternalNameConversionBase<
ExternalNameConversionPass>::ExternalNameConversionBase;

mlir::ModuleOp getModule() { return getOperation(); }
void runOnOperation() override;

private:
bool appendUnderscores;
bool usePassOpt = false;
};
} // namespace

void ExternalNameConversionPass::runOnOperation() {
auto op = getOperation();
auto *context = &getContext();

appendUnderscores = (usePassOpt) ? appendUnderscoreOpt : appendUnderscores;
llvm::DenseMap<mlir::StringAttr, mlir::FlatSymbolRefAttr> remappings;
// Update names of external Fortran functions and names of Common Block
// globals.
Expand All @@ -74,7 +67,8 @@ void ExternalNameConversionPass::runOnOperation() {
mlir::SymbolTable::getSymbolAttrName());
auto deconstructedName = fir::NameUniquer::deconstruct(symName);
if (fir::NameUniquer::isExternalFacingUniquedName(deconstructedName)) {
auto newName = mangleExternalName(deconstructedName, appendUnderscores);
auto newName =
mangleExternalName(deconstructedName, appendUnderscoreOpt);
auto newAttr = mlir::StringAttr::get(context, newName);
mlir::SymbolTable::setSymbolName(&funcOrGlobal, newAttr);
auto newSymRef = mlir::FlatSymbolRefAttr::get(newAttr);
Expand All @@ -101,12 +95,3 @@ void ExternalNameConversionPass::runOnOperation() {
nestedOp->setAttr(update.first, update.second);
});
}

std::unique_ptr<mlir::Pass> fir::createExternalNameConversionPass() {
return std::make_unique<ExternalNameConversionPass>();
}

std::unique_ptr<mlir::Pass>
fir::createExternalNameConversionPass(bool appendUnderscoring) {
return std::make_unique<ExternalNameConversionPass>(appendUnderscoring);
}
26 changes: 26 additions & 0 deletions flang/runtime/command.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,19 @@

#ifdef _WIN32
#include "flang/Common/windows-include.h"
#include <direct.h>
#define getcwd _getcwd
#define PATH_MAX MAX_PATH

// On Windows GetCurrentProcessId returns a DWORD aka uint32_t
#include <processthreadsapi.h>
inline pid_t getpid() { return GetCurrentProcessId(); }
#else
#include <unistd.h> //getpid()

#ifndef PATH_MAX
#define PATH_MAX 4096
#endif
#endif

namespace Fortran::runtime {
Expand Down Expand Up @@ -239,4 +246,23 @@ std::int32_t RTNAME(GetEnvVariable)(const Descriptor &name,
return StatOk;
}

std::int32_t RTNAME(GetCwd)(
const Descriptor &cwd, const char *sourceFile, int line) {
Terminator terminator{sourceFile, line};

RUNTIME_CHECK(terminator, IsValidCharDescriptor(&cwd));

char *buf{(char *)AllocateMemoryOrCrash(terminator, PATH_MAX)};

if (!getcwd(buf, PATH_MAX)) {
return StatMissingCurrentWorkDirectory;
}

std::int64_t strLen{StringLength(buf)};
std::int32_t status{CopyCharsToDescriptor(cwd, buf, strLen)};

std::free(buf);
return status;
}

} // namespace Fortran::runtime
1 change: 1 addition & 0 deletions flang/runtime/stat.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ enum Stat {
StatLocked = FORTRAN_RUNTIME_STAT_LOCKED,
StatLockedOtherImage = FORTRAN_RUNTIME_STAT_LOCKED_OTHER_IMAGE,
StatMissingEnvVariable = FORTRAN_RUNTIME_STAT_MISSING_ENV_VAR,
StatMissingCurrentWorkDirectory = FORTRAN_RUNTIME_STAT_MISSING_CWD,
StatStoppedImage = FORTRAN_RUNTIME_STAT_STOPPED_IMAGE,
StatUnlocked = FORTRAN_RUNTIME_STAT_UNLOCKED,
StatUnlockedFailedImage = FORTRAN_RUNTIME_STAT_UNLOCKED_FAILED_IMAGE,
Expand Down
17 changes: 17 additions & 0 deletions flang/test/Fir/loop03.fir
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Test the reduction semantics of fir.do_loop
// RUN: fir-opt %s | FileCheck %s

func.func @reduction() {
%bound = arith.constant 10 : index
%step = arith.constant 1 : index
%sum = fir.alloca i32
// CHECK: %[[VAL_0:.*]] = fir.alloca i32
// CHECK: fir.do_loop %[[VAL_1:.*]] = %[[VAL_2:.*]] to %[[VAL_3:.*]] step %[[VAL_4:.*]] unordered reduce(#fir.reduce_attr<add> -> %[[VAL_0]] : !fir.ref<i32>) {
fir.do_loop %iv = %step to %bound step %step unordered reduce(#fir.reduce_attr<add> -> %sum : !fir.ref<i32>) {
%index = fir.convert %iv : (index) -> i32
%1 = fir.load %sum : !fir.ref<i32>
%2 = arith.addi %index, %1 : i32
fir.store %2 to %sum : !fir.ref<i32>
}
return
}
Loading