From c3cd84365e099ab6dfa4b484475ef66f33f16eab Mon Sep 17 00:00:00 2001 From: TB Schardl Date: Sat, 30 Nov 2024 09:13:46 -0500 Subject: [PATCH] [SemaExpr] Fix hyperobject-lookup lvalue conversion involving qualifiers and xvalues. --- clang/lib/AST/Type.cpp | 3 +- clang/lib/Sema/SemaExpr.cpp | 2 +- .../Cilk/hyper-lookup-lvalue-conversion.cpp | 57 +++++++++++++++++++ 3 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 clang/test/Cilk/hyper-lookup-lvalue-conversion.cpp diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp index fee3f1f3319f..8a1253ed17e8 100644 --- a/clang/lib/AST/Type.cpp +++ b/clang/lib/AST/Type.cpp @@ -3416,7 +3416,8 @@ QualType QualType::getNonLValueExprType(const ASTContext &Context) const { QualType QualType::stripHyperobject() const { if (const auto *Hyperobject = getTypePtr()->getAs()) - return Hyperobject->getElementType(); + return Hyperobject->getElementType().withFastQualifiers( + getLocalFastQualifiers()); return *this; } diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 4f99e34d18b5..ca033b097613 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -2279,7 +2279,7 @@ NonOdrUseReason Sema::getNonOdrUseReasonInCurrentContext(ValueDecl *D) { } Expr *Sema::BuildHyperobjectLookup(Expr *E, bool Pointer) { - if (!Pointer && !E->isLValue()) + if (!Pointer && !E->isGLValue()) return E; if (getLangOpts().getCilk() != LangOptions::Cilk_opencilk) diff --git a/clang/test/Cilk/hyper-lookup-lvalue-conversion.cpp b/clang/test/Cilk/hyper-lookup-lvalue-conversion.cpp new file mode 100644 index 000000000000..36ff0ce5af92 --- /dev/null +++ b/clang/test/Cilk/hyper-lookup-lvalue-conversion.cpp @@ -0,0 +1,57 @@ +// Check unusual lvalue conversions involving hyperobject lookups, qualifiers, and xvalues. +// +// RUN: %clang_cc1 %s -x c++ -fopencilk -verify -S -emit-llvm -disable-llvm-passes -o - | FileCheck %s +// expected-no-diagnostics + +// Simplified version of std::move for standalone test. +namespace std { +template +T &&move(T &obj) { + return static_cast(obj); +} +} + +// Reducer definition. +template void sum_init(void *v) { *reinterpret_cast(v) = T{}; } + +template void sum_reduce(void *v, void *v2) { + T *a = reinterpret_cast(v), *b = reinterpret_cast(v2); + *a += *b; +} + +template using SumReducer = T _Hyperobject(sum_init, sum_reduce); + +using Real = double; + +void h(Real arg); + +template +void g(const T &arg) { h(arg); } + +template +void f(T&& arg) { h(std::move(arg)); } + +void run() { + SumReducer sumAParRelError = 0; + // Check handling of hyperobject lookup when result requires extra const qualifier. + g(sumAParRelError); + // Check handling of hyperobject lookup when result treated as xvalue. + f(sumAParRelError); +} + +// CHECK-LABEL: define {{.*}}void @_Z3runv() +// CHECK: %[[SUMAPARRELERROR:.+]] = alloca double +// CHECK: call void @llvm.reducer.register.i64(ptr %[[SUMAPARRELERROR]] +// CHECK-NEXT: call void @_Z1gIHdEvRKT_(ptr {{.*}}%[[SUMAPARRELERROR]]) +// CHECK-NEXT: call void @_Z1fIRHdEvOT_(ptr {{.*}}%[[SUMAPARRELERROR]]) +// CHECK-NEXT: call void @llvm.reducer.unregister(ptr %sumAParRelError) + +// CHECK-LABEL: define {{.*}}void @_Z1gIHdEvRKT_(ptr +// CHECK: %[[LOOKUP:.+]] = call ptr @llvm.hyper.lookup.i64(ptr +// CHECK-NEXT: %[[VIEW:.+]] = load double, ptr %[[LOOKUP]] +// CHECK-NEXT: call void @_Z1hd(double {{.*}}%[[VIEW]]) + +// CHECK-LABEL: define {{.*}}void @_Z1fIRHdEvOT_(ptr +// CHECK: %[[LOOKUP:.+]] = call ptr @llvm.hyper.lookup.i64(ptr +// CHECK-NEXT: %[[VIEW:.+]] = load double, ptr %[[LOOKUP]] +// CHECK-NEXT: call void @_Z1hd(double {{.*}}%[[VIEW]])