diff --git a/clang/docs/LanguageExtensions.rst b/clang/docs/LanguageExtensions.rst --- a/clang/docs/LanguageExtensions.rst +++ b/clang/docs/LanguageExtensions.rst @@ -2354,13 +2354,13 @@ under bpf compile-once run-everywhere framework. Debuginfo (typically with ``-g``) is needed, otherwise, the compiler will exit with an error. The return type for the intrinsic is the same as the type of the -argument, and must be a pointer type. +argument. **Syntax**: .. code-block:: c - PointerT __builtin_preserve_access_index(PointerT ptr) + type __builtin_preserve_access_index(type arg) **Example of Use**: @@ -2375,7 +2375,8 @@ } c[4]; }; struct t *v = ...; - const void *pb =__builtin_preserve_access_index(&v->c[3].b); + int *pb =__builtin_preserve_access_index(&v->c[3].b); + __builtin_preserve_access_index(v->j); Multiprecision Arithmetic Builtins ---------------------------------- diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9916,7 +9916,4 @@ "__builtin_bit_cast %select{source|destination}0 type must be trivially copyable">; def err_bit_cast_type_size_mismatch : Error< "__builtin_bit_cast source size does not equal destination size (%0 vs %1)">; - -def err_builtin_preserve_access_index_invalid_arg : Error< - "__builtin_preserve_access_index argument must a pointer type instead of %0">; } // end of sema component. diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -191,22 +191,12 @@ return false; } -/// Check the number of arguments and arg type, and set the result type to +/// Check the number of arguments and set the result type to /// the argument type. static bool SemaBuiltinPreserveAI(Sema &S, CallExpr *TheCall) { if (checkArgCount(S, TheCall, 1)) return true; - // The argument type must be a pointer - ExprResult Arg = TheCall->getArg(0); - QualType Ty = Arg.get()->getType(); - if (!Ty->isPointerType()) { - S.Diag(Arg.get()->getBeginLoc(), - diag::err_builtin_preserve_access_index_invalid_arg) - << Ty << Arg.get()->getSourceRange(); - return true; - } - TheCall->setType(TheCall->getArg(0)->getType()); return false; } diff --git a/clang/test/CodeGen/builtin-preserve-access-index-nonptr.c b/clang/test/CodeGen/builtin-preserve-access-index-nonptr.c new file mode 100644 --- /dev/null +++ b/clang/test/CodeGen/builtin-preserve-access-index-nonptr.c @@ -0,0 +1,18 @@ +// RUN: %clang -target x86_64 -emit-llvm -S -g %s -o - | FileCheck %s + +#define _(x) (__builtin_preserve_access_index(x)) + +struct s1 { + char a; + int b[4]; +}; + +int unit1(struct s1 *arg) { + return _(arg->b[2]); +} +// CHECK: define dso_local i32 @unit1 +// CHECK: call [4 x i32]* @llvm.preserve.struct.access.index.p0a4i32.p0s_struct.s1s(%struct.s1* %{{[0-9a-z]+}}, i32 1, i32 1), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[STRUCT_S1:[0-9]+]] +// CHECK: call i32* @llvm.preserve.array.access.index.p0i32.p0a4i32([4 x i32]* %{{[0-9a-z]+}}, i32 1, i32 2), !dbg !{{[0-9]+}}, !llvm.preserve.access.index ![[ARRAY:[0-9]+]] +// +// CHECK: ![[ARRAY]] = !DICompositeType(tag: DW_TAG_array_type +// CHECK: ![[STRUCT_S1]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s1" diff --git a/clang/test/Sema/builtin-preserve-access-index.c b/clang/test/Sema/builtin-preserve-access-index.c --- a/clang/test/Sema/builtin-preserve-access-index.c +++ b/clang/test/Sema/builtin-preserve-access-index.c @@ -4,8 +4,8 @@ return __builtin_preserve_access_index(&arg[1], 1); // expected-error {{too many arguments to function call, expected 1, have 2}} } -const void *invalid2(const int *arg) { - return __builtin_preserve_access_index(1); // expected-error {{__builtin_preserve_access_index argument must a pointer type instead of 'int'}} +int valid2(void) { + return __builtin_preserve_access_index(1); } void *invalid3(const int *arg) { @@ -29,3 +29,11 @@ int valid7(struct s *arg) { return *__builtin_preserve_access_index(&arg->b); } + +int valid8(struct s *arg) { + return __builtin_preserve_access_index(arg->a + arg->b); +} + +int valid9(struct s *arg) { + return __builtin_preserve_access_index(({arg->a = 2; arg->b = 3; })); +}