Linux: -Wincompatible-pointer-types in arch/arm64/lib/xor-neon.c

Created on 8 Dec 2018  Â·  54Comments  Â·  Source: ClangBuiltLinux/linux

Several warnings of this type:

arch/arm64/lib/xor-neon.c:27:28: error: incompatible pointer types assigning to 'const unsigned long *' from 'uint64_t *' (aka 'unsigned long long *') [-Werror,-Wincompatible-pointer-types]
                v0 = veorq_u64(vld1q_u64(dp1 +  0), vld1q_u64(dp2 +  0));
                                         ^~~~~~~~
/home/nathan/cbl/prebuilt/lib/clang/8.0.0/include/arm_neon.h:7538:47: note: expanded from macro 'vld1q_u64'
  __ret = (uint64x2_t) __builtin_neon_vld1q_v(__p0, 51); \
                                              ^~~~

Happens on next-20181207, caused by the commit that introduced the file: https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git/commit/?id=cc9f8349cb33965120a96c12e05d00676162eb7f

Haven't done any triage yet, just filing to make sure it gets noted.

-Wincompatible-pointer-types [ARCH] arm64 [BUG] llvm [FIXED][LINUX] 5.0

Most helpful comment

I left it open because the root cause of the warning is not resolved, even though it is hidden.

All 54 comments

Might be good to see more of vld1q_u64. Maybe that function should take unsigned long * rather than uint64_t *?

Shot in the dark; Clang might expect a const unsigned long * for its __builtin_neon_vld1q_v but gcc might expect unsigned long long *. Or gcc doesn't have this warning.

Looks like vld1q_u64 is defined in the compiler headers, not the kernel.

Clang (not sure how it gets generated because I didn't find vld1q_u64 in the source):

#ifdef __LITTLE_ENDIAN__
#define vld1q_u64(__p0) __extension__ ({ \
  uint64x2_t __ret; \
  __ret = (uint64x2_t) __builtin_neon_vld1q_v(__p0, 51); \
  __ret; \
})
#else
#define vld1q_u64(__p0) __extension__ ({ \
  uint64x2_t __ret; \
  __ret = (uint64x2_t) __builtin_neon_vld1q_v(__p0, 51); \
  __ret = __builtin_shufflevector(__ret, __ret, 1, 0); \
  __ret; \
})
#endif

gcc/config/aarch64/arm_neon.h:

__extension__ extern __inline uint64x2_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vld1q_u64 (const uint64_t *a)
{   
  return (uint64x2_t)
    __builtin_aarch64_ld1v2di ((const __builtin_aarch64_simd_di *) a);
}

This might sound like a stupid question, when I search for __builtin_neon_vld1q_v within Clang, I don't see any function, rather just a couple of references in lib/CodeGen/CGBuiltin.cpp. How would I go about seeing what the expected parameters to that builtin are?

cc @smithp35

CONFIG_XOR_BLOCKS Seeing this now in mainline.

@nathanchance how come our CI isn't reporting this failure? I see it locally for an arm64 defconfig. Is it that our CI's clang is outdated (and thus a regression on the Clang side)?

Ah, CONFIG_XOR_BLOCKS gets selected as a module, which we aren't building on CI. Maybe we should build modules as a separate build target for each build. It would double our matrix size but we would get more coverage.

Hi @nathanchance,

today I stepped on the same problem described in this thread (Linux 5.0-rc2 and clang 8) and after a bit of debugging seems that it is triggered because the arm_neon builtins input parameters are not compliant with what described in ACLE (Arm C Language Extentions): http://infocenter.arm.com/help/topic/com.arm.doc.ecm0665619/acle_sve_100987_0000_00_en.pdf.

I came to this conclusion because if we take for example __builtin_neon_vld1q_v that is defined as:
arm_neon.inc:299 BUILTIN(__builtin_neon_vld1q_v, "V16ScvC*i", "n")
and decode the string V16ScvC*i (based on what described in Builtins.def) we can clearly see that the builtin is expected to return a vector of size 16 (V16) of signed char (Sc) and to take as input a "const void *" (vC*) and an integer (i).

To be compliant with the ACLE the vC* parameter should become UWi (uint64_t).

All the other compilation issues share similar reason. Please let me know what do you think.

Thanks!

@fvincenzo Thanks for the insight!

It looks like that arm_neon.inc file gets generated by clang/utils/TableGen/NeonEmitter.cpp in combination with clang/include/clang/Basic/arm_neon.td, if I am following everything correctly. The parameters you talk about get generated by getBuiltinTypeStr and builtin_str I think.

Have you created a patch yet to change the generation of the arm_neon.inc file? I'm trying to look into it right now but multiple eyes never hurts.

@nathanchance I did not create a patch to target the issue yet. It took me a while to figure out the problem. If you created it in the meantime I am happy to review it.

Thanks.

@fvincenzo I won't be free to seriously look into creating a fix until Monday so if you can beat me to it in that time, please do (especially since you have a basic understanding of the problem).

I can help write a patch (thanks @fvincenzo for the detailed report!).

Hi,
I'm currently fixing a similar issue in clang, https://reviews.llvm.org/D56852 would give you an idea of what the patch would look like. As @fvincenzo says, the fix comes from changing the string to describe the types.

Thanks for the tips. I think the vld1q variants are described in:

include/clang/Basic/arm_neon.td:

 348 def VLD1      : WInst<"vld1", "dc",                                             
 349                       "QUcQUsQUiQUlQcQsQiQlQfQPcQPsUcUsUiUlcsilfPcPs">; 

and can see a breakdown of these codes in include/clang/Basic/arm_neon_incl.td, but I can't say I understand this big long string. Is it defining multiple prototypes at once? How does this work?

These strings are a mad riddle to me, the second string declares a prototype that gets mutated in some way by the third string. But after looking at this a bit closer, I don't think it's where this problem can be solved though. The intrinsics just use void pointers and then there's some manual semantic checking that happens, which is where this warning is coming from (in clang/lib/SemaChecking.cpp Sema::CheckNeonBuiltinFunctionaCall). The variable IsInt64Long is set to true and so we generate an unsigned long.

@sparker-arm I agree with your analisys, I came to similar conclusion. According to me IsInt64Long should not be checked in this case, because ACLE defines the types of the arm_neon builtins input parameters as uint64_t (unsigned long long) hence unless I missed something NeonTypeFlags::Int64 and NeonTypeFlags::Poly64 should always return Signed/Unsigned Long Long.

@nathanchance @nickdesaulniers below the fix that made me build the kernel correctly (Might not be complete, hence I am not submitting a patch):

diff --git a/lib/Sema/SemaChecking.cpp b/lib/Sema/SemaChecking.cpp
index 0598da214e..3f8aec1b69 100644
--- a/lib/Sema/SemaChecking.cpp
+++ b/lib/Sema/SemaChecking.cpp
@@ -1526,9 +1526,6 @@ static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context,
   case NeonTypeFlags::Int32:
     return Flags.isUnsigned() ? Context.UnsignedIntTy : Context.IntTy;
   case NeonTypeFlags::Int64:
-    if (IsInt64Long)
-      return Flags.isUnsigned() ? Context.UnsignedLongTy : Context.LongTy;
-    else
       return Flags.isUnsigned() ? Context.UnsignedLongLongTy
                                 : Context.LongLongTy;
   case NeonTypeFlags::Poly8:
@@ -1536,9 +1533,6 @@ static QualType getNeonEltType(NeonTypeFlags Flags, ASTContext &Context,
   case NeonTypeFlags::Poly16:
     return IsPolyUnsigned ? Context.UnsignedShortTy : Context.ShortTy;
   case NeonTypeFlags::Poly64:
-    if (IsInt64Long)
-      return Context.UnsignedLongTy;
-    else
       return Context.UnsignedLongLongTy;
   case NeonTypeFlags::Poly128:
     break;

Trying to test a patch for this has been a pain because I can't seem to hit the issue when using the clang test driver. Passing -ffreestanding to clang appears to alleviate these stdint issues, does this work for you guys too?

@sparker-arm This translation unit already uses that flag: https://github.com/ClangBuiltLinux/linux/blob/cc9f8349cb33965120a96c12e05d00676162eb7f/arch/arm64/lib/Makefile#L11

@fvincenzo I will test that patch now.

Would the sema checking need to be modified if the definitions in arm_neon.inc were generated with the correct prototype? Something tells me that's the proper solution but I have no idea how to change the couple of functions I mentioned above to do it.

Thanks for pointing that out @nathanchance
But I think there's still something odd going on here, the code in the compiler looks sane to me and it just seems there's a mismatch between a typedef sitting in a header somewhere. I took the xor-neon.c file, removed the headers and just included arm_neon.h instead and the freestanding option then removes all warnings.

The code @fvincenzo commented on was modified by commits 7e0e8ef787107 ("ARM64: initial clang support commit.") r205100, 491dd1c4d1261 ("[AArch64] Change int64_t from 'long long int' to 'long int' for AArch64 target.") r202004, d13c501b4c9d9 ("[AArch64 ACLE] Allow to define poly64_t as 'unsigned long long' on LLP64 system.") r237348.

491dd1c4d1261 ("[AArch64] Change int64_t from 'long long int' to 'long int' for AArch64 target.") r202004

looks the most interesting. If I make those changes @fvincenzo suggests, the following llvm tests fail:

  • CodeGenCXX/aarch64-neon.cpp (only for the poly64x1_t case)

I will contact the author of r202004.

Curious, -ffreestanding is needed to repro, as pointed out by @sparker-arm and @nathanchance . Reproducer:

// clang -ffreestanding -c -target aarch64-linux-gnu neon.c
#include <stdint.h>
#include "arm_neon.h"
void foo(const uint64_t* a) {
  vld1q_u64(a);
}

(aarch64-linux-gnu-gcc -c -ffreestanding neon.c works)

-ffreestanding seems to do something funny with -Wformat:

// uint64_t.c
#include <stdint.h>
#include <stdio.h>
int main () {
  uint64_t x = 42;
  printf("uint64_t is a long int: %lu\n", x);
  printf("uint64_t is a long long int: %llu\n", x);
  return 0;
}
$ clang -ffreestanding -target aarch64-linux-gnu -Wformat uint64_t.c
$ clang -target aarch64-linux-gnu -Wformat uint64_t.c               
uint64_t.c:5:43: warning: format specifies type 'unsigned long' but the argument has
      type 'uint64_t' (aka 'unsigned long long') [-Wformat]
  printf("uint64_t is a long int: %lu\n", x);
                                  ~~~     ^
                                  %llu
1 warning generated.
$ aarch64-linux-gnu-gcc -ffreestanding -Wformat uint64_t.c
$ aarch64-linux-gnu-gcc -Wformat uint64_t.c 
uint64_t.c: In function ‘main’:
uint64_t.c:6:43: warning: format ‘%llu’ expects argument of type ‘long long unsigned int’, but argument 2 has type ‘uint64_t {aka long unsigned int}’ [-Wformat=]
   printf("uint64_t is a long long int: %llu\n", x);
                                        ~~~^
                                        %lu

So -ffreestanding seems to disable -Wformat for both compilers (I hope that's expected). It also seems that clang and gcc disagree on what what uint64_t is for the aarch64-linux-gnu ABI. That sounds bad, very bad.

My teammate, @pirama-arumuga-nainar , points out that -ffreestanding should be used with -nostdinc when cross compiling, otherwise <stdint.h> will be pulled in from your host. When cross compiling from an x86_64 host (as I am), then uint64_t will indeed be different between x86_64-linux-gnu and aarch64-linux-gnu.

Fun, ok, so it looks like Clang incorrectly sets the preprocessor macro __WORDSIZE to 32 for aarch64-linux-gnu. That macro is used in glibc's aarch64 stdint.h to determine what the typedef uint64_t is defined as.

Edit: Filed: https://bugs.llvm.org/show_bug.cgi?id=40415
Edit: NVM that's not a bug, goes back to -nostdinc.
Edit: everything is fine with: clang -target aarch64-linux-gnu -c wordsize.c -nostdinc -isystem /usr/aarch64-linux-gnu/include

/usr/bin/ccache clang -Wp,-MD,arch/arm64/lib/.xor-neon.o.d -nostdinc -isystem /home/nathan/cbl/usr/lib/clang/9.0.0/include -I/home/nathan/cbl/linux-next/arch/arm64/include -I./arch/arm64/include/generated -I/home/nathan/cbl/linux-next/include -I./include -I/home/nathan/cbl/linux-next/arch/arm64/include/uapi -I./arch/arm64/include/generated/uapi -I/home/nathan/cbl/linux-next/include/uapi -I./include/generated/uapi -include /home/nathan/cbl/linux-next/include/linux/kconfig.h -include /home/nathan/cbl/linux-next/include/linux/compiler_types.h -I/home/nathan/cbl/linux-next/arch/arm64/lib -Iarch/arm64/lib -D__KERNEL__ -mlittle-endian -DKASAN_SHADOW_SCALE_SHIFT=3 -Qunused-arguments -Wall -Wundef -Werror=strict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -fshort-wchar -fno-PIE -Werror-implicit-function-declaration -Werror=implicit-int -Wno-format-security -std=gnu89 --target=aarch64-linux-gnu --prefix=/home/nathan/cbl/usr/bin/ --gcc-toolchain=/home/nathan/cbl/usr -no-integrated-as -DCONFIG_AS_LSE=1 -fno-asynchronous-unwind-tables -DKASAN_SHADOW_SCALE_SHIFT=3 -fno-delete-null-pointer-checks -O2 -Wframe-larger-than=2048 -fstack-protector-strong -Wno-format-invalid-specifier -Wno-gnu -Wno-address-of-packed-member -Wno-tautological-compare -mno-global-merge -Wno-unused-const-variable -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -Wdeclaration-after-statement -Wvla -Wno-pointer-sign -fno-strict-overflow -fno-merge-all-constants -fno-stack-check -Werror=date-time -Werror=incompatible-pointer-types -Wno-initializer-overrides -Wno-unused-value -Wno-format -Wno-sign-compare -Wno-format-zero-length -Wno-uninitialized -ffreestanding -DMODULE -DKBUILD_BASENAME='"xor_neon"' -DKBUILD_MODNAME='"xor_neon"' -c -o arch/arm64/lib/xor-neon.o /home/nathan/cbl/linux-next/arch/arm64/lib/xor-neon.c

It does look like -nostdinc and -ffreestanding are provided to this translation unit.

I agree that r202004 seems suspect, I'm curious to see if GCC changed at all after that (since the justification is GCC compatibility).

Apologies to come to this thread very late. From some experiments I can see that there is a problem with pollution from the host header files when cross compiling. However I'm not sure that this is the actual problem or just a tangent. Would it be possible to restate the original problem using all the information we know? I'm not much of a neon expert so may not be able to help much if there is something wrong there.

When I look at the -Wformat example above, when relying on the multiarch support on Ubuntu16.04 the clang driver unfortunately pollutes the include list with a host include. I pick up /usr/include/bits/wordsize.h which selects __WORDSIZE based on if the host is X86_64. If I use a standalone gcc toolchain, in my case a Linaro GCC 7 release and set --gcc-toolchain=/path/to/gcc --sysroot=/path/to/gcc/aarch64-linux-gnu/libc then I get __WORDSIZE set to 64 and GCC matches clang.

For GCC I don't think that there has been any change in the definition of uint64_t. My limited understanding of GCC is that the freestanding uint64_t is defined in stdint-gcc.h by various levels of macro indirection, __UINT64_TYPE_, UINT64_TYPE eventually ending up with LONG_TYPE_SIZE which is 64 for ilp64, and 32 for ilp32 (last change 2013).

A colleague pointed me at https://gcc.gnu.org/ml/gcc-patches/2008-11/msg00305.html which describes some of the GCC freestanding implementation.

After some more digging, something tricky is going on in the kernel with trying to redefine uint64_t.

arch/arm64/include/asm/neon-intrinsics.h:

 14 /*                                                                              
 15  * In the kernel, u64/s64 are [un]signed long long, not [un]signed long.        
 16  * So by redefining these macros to the former, we can force gcc-stdint.h       
 17  * to define uint64_t / in64_t in a compatible manner.                          
 18  */  
 25 #ifdef __UINT64_TYPE__                                                          
 26 #undef __UINT64_TYPE__                                                          
 27 #define __UINT64_TYPE__         unsigned long long                              
 28 #endif 

Suspect commits:
commit 21e28547f613 ("arm64/neon: add workaround for ambiguous C99 stdint.h types")
commit 09096f6a0ee2 ("ARM: 7822/1: add workaround for ambiguous C99 stdint.h types")

I'll bet that llvm/build/lib/clang/9.0.0/include/stdint.h behaves differently from gcc-stdint.h in this regards.

cc @ardbiesheuvel

===

This basic test case shows that the default definition of uint64_t should work:

// clang -c -target aarch64-linux-gnu -nostdinc \
//   -isystem /android1/llvm/build/lib/clang/9.0.0/include \
//   -ffreestanding -O2 neon.c
//
// aarch64-linux-gnu-gcc -ffreestanding -c -O2 neon.c

#include "arm_neon.h"

uint64x2_t foo(uint64_t* a) {
#ifdef __clang__
#ifdef __LITTLE_ENDIAN__
  return __builtin_neon_vld1q_v(a, 51);
#else
#error "BE not implemented"
#endif // __LITTLE_ENDIAN__
#else
  return (uint64x2_t) __builtin_aarch64_ld1v2di ((const __builtin_aarch64_simd_di *) a);
#endif // __clang__
}

ah, adding:

    7 #ifdef __INT64_TYPE__                                                           
    8 #undef __INT64_TYPE__                                                           
    9 #define __INT64_TYPE__          long long                                       
   10 #endif                                                                          
   11 #ifdef __UINT64_TYPE__                                                          
   12 #undef __UINT64_TYPE__                                                          
   13 #define __UINT64_TYPE__         unsigned long long                              
   14 #endif 

to the above test case BEFORE including "arm_neon.h" reproduces this issue exactly.

This solves the issue that the kernel typedefs uint64_t as unsigned long long, which deviates from GCC/glibc.
If it helps to make this GCC specific, then that is fine with me.

This basic test case shows that the default definition of uint64_t should work:

That may be true, but as soon as you include other headers as well, things fall apart, since Linux's types.h header is incompatible.

The root problem is that arm_neon.h includes stdint.h, which is provided either by the system, or by the compiler in case -ffreestanding is passed (which is why that option is included in the first place)

vld1q_u64() on GCC expects a unsigned long long *, but on Clang const unsigned long * is, due to vld1q_u64() passing its arg to __builtin_neon_vld1q_v.

vld1q_u64() on GCC expects a unsigned long long *, but on Clang const unsigned long * is, due to vld1q_u64() passing its arg to __builtin_neon_vld1q_v.

No it doesn't.

__extension__ extern __inline uint64x2_t
__attribute__ ((__always_inline__, __gnu_inline__, __artificial__))
vld1q_u64 (const uint64_t *a)
{
  return (uint64x2_t)
    __builtin_aarch64_ld1v2di ((const __builtin_aarch64_simd_di *) a);
}

The problem is the ambiguity of 'uint64_t' in Linux.

vld1q_u64() on GCC expects a unsigned long long *

No it doesn't.
vld1q_u64 (const uint64_t *a)

Isn't uint64_t defined as typedef unsigned long long for a GCC build? (eventually; there's a few typedefs inbetween).

IIUC, ARMv8-A is LP64 (and I think the kernel shares this data model), which would mean that unsigned long long* and unsigned long* both refer to 64b/8B of memory. (http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0024a/ch08s02.html the row int/long seems to disagree, but I think that's an error and I've contacted @kbeyls ).

So I have a few different ideas:

  • redefine vld1q_u64 and vst1q_u64 to cast their args to const unsigned long* and unsigned long* when defined(__clang__). This works but is kind of a big chunk of code to add to a header. Pro: dont have to touch arch/arm64/lib/xor-neon.c.
  • define wrappers for vld1q_u64 and vst1q_u64 that perform different pointer casts on their parameters. Pros: concise header change, cons: large change to arch/arm64/lib/xor-neon.c.
  • disable -Wincompatible-pointer-types for this file. Due to the above point on data models; there's no bug here. This is always undesirable to me because then that can mask other bugs of that type that might be introduce later.
  • fix clang to not treat unsigned long long* -> unsigned long* casts as -Wincompatible-pointer-types for aarch64. I'm leaning towards this.
  • change clang's definition of vld1q_u64 and vst1q_u64; there seems to be a fair amount of meta programming soup to understand how these are autogenerated...

We cannot change the prototypes of the NEON intrinsics. Not only would this require some kind of versioning scheme, it also means that we are shifting the problem to other users of this header.

All we can reasonably do is fix the issue on the kernel side, which is why we use this hideous #undef/#define sequence in the first place: it reconciles the kernel type system with the GGC/glibc one using a simple targeted change.

If clang permits setting -Wno-incompatible-pointer-types using a #pragma, then let's add it to the neon-instrinsics.h arm64 kernel header, so that anything that includes it will inherit it. Since NEON code can only be used in special source files that have -mgeneral-regs-only removed, this should not leak into other source files (and the diagnostic will remain active for GCC, so we will spot issues with new code as long as we keep building the kernel with GCC as well)

This appears to work on top of v5.0-rc3:

diff --git a/arch/arm64/include/asm/neon-intrinsics.h b/arch/arm64/include/asm/neon-intrinsics.h
index 2ba6c6b9541f..71abfc7612b2 100644
--- a/arch/arm64/include/asm/neon-intrinsics.h
+++ b/arch/arm64/include/asm/neon-intrinsics.h
@@ -36,4 +36,8 @@
 #include <arm_neon.h>
 #endif

+#ifdef CONFIG_CC_IS_CLANG
+#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
+#endif
+
 #endif /* __ASM_NEON_INTRINSICS_H */

Turning off pointer comparisons will only mask more problematic code. Though turning them off via pragma in the effected header is a much much better way than trying to remember to add -Wno-incompatible-pointer-types to each new translation unit that includes arch/arm64/include/asm/neon-intrinsics.h. (Still, header inclusions end up begetting more header inclusions, in a tangled web, then suddenly one of those was turning off warnings and oops! bugs!) (_Pragma helps limit the scope of pragmas, but is not a solution to this particular problem).

We cannot change the prototypes of the NEON intrinsics.

vld1q_u64 in Clang's freestanding arm_neon.h is NOT a static inline function like GCC's, but a autogenerated macro. Its implementation (passing its lone macro arg to the Clang-only builtin __builtin_neon_vld1q_v effectively requires that vld1q_u64 be passed a unsigned long* due to the semantic analysis @fvincenzo pointed out. This is different from GCC's definition of vld1q_u64, which it defines as a static inline function requiring a uint64_t* for it's sole parameter.

The code in arch/arm64/include/asm/neon-intrinsics.h is able to take advantage of implementation details of GCC's freestanding arm_neon.h happening to include stdint.h and thus gcc-stdint.h, redefining uint64_t to be unsigned long long.

Thus, passing a uint64_t* to vld1q_u64 is currently non-portable between compilers. One of them is wrong and needs to change (I think it's Clang). This seems to have been previously reported before. If compilers disagree on what the signature is for a function, we should try to resolve that with compiler vendors, not by turning off warnings.

more experimenting

Thus, passing a uint64_t* to vld1q_u64 is currently non-portable between compilers.

No it is not.

In a sane AArch64 environment, uint64_t == unsigned long, and so this works fine.

It is only in the kernel where we decided that uint64_t == unsigned long long, causing these issues where we want to include compiler headers.

One of them is wrong and needs to change (I think it's Clang). This seems to have been previously reported before. If compilers disagree on what the >signature is for a function, we should try to resolve that with compiler vendors, not by turning off >warnings.

They don't disagree. It is Linux that disagrees with GCC, but in a way that we can easily hack our way around by overriding some CPP macros.

This appears to work on top of v5.0-rc3:

diff --git a/arch/arm64/include/asm/neon-intrinsics.h b/arch/arm64/include/asm/neon-intrinsics.h
index 2ba6c6b9541f..71abfc7612b2 100644
--- a/arch/arm64/include/asm/neon-intrinsics.h
+++ b/arch/arm64/include/asm/neon-intrinsics.h
@@ -36,4 +36,8 @@
 #include <arm_neon.h>
 #endif

+#ifdef CONFIG_CC_IS_CLANG
+#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
+#endif
+
 #endif /* __ASM_NEON_INTRINSICS_H */

Adding the pragma is equivalent to -Wno-incompatible-pointer-types on CFLAGS_xor-neon.o, which means hiding the problem, not solving it. Agree with @nickdesaulniers.

The fundamental problem is that Linux typedefs uint64_t as unsigned long long, and that is unlikely to change. I don't think there is anything wrong with the NEON intrinsics headers of either compiler, so making changes there to accommodate Linux is a bad idea.

@ardbiesheuvel that makes sense. RFC:

```diff
diff --git a/arch/arm64/include/asm/neon-intrinsics.h b/arch/arm64/include/asm/neon-intrinsics.h
index 2ba6c6b9541f..fb02f8f3837e 100644
--- a/arch/arm64/include/asm/neon-intrinsics.h
+++ b/arch/arm64/include/asm/neon-intrinsics.h
@@ -14,7 +14,8 @@
/*

  • In the kernel, u64/s64 are [un]signed long long, not [un]signed long.
  • So by redefining these macros to the former, we can force gcc-stdint.h



      • to define uint64_t / in64_t in a compatible manner.





      • to define uint64_t / in64_t in a compatible manner. Prevents 'conflicting





      • types' errors due to arm_neon.h including stdint.h.


        */



#ifdef __INT64_TYPE__
@@ -36,4 +37,23 @@
#include
#endif

+/*


    • Clang implements these symbols as macros (GCC implements these as static


    • inline functions). Due to include/linux/types.h defining uint64_t as


    • unsigned long long (through u64 (include/asm-generic/int-ll64.h) and __u64


    • (include/uapi/asm-generic/int-ll64.h)), if we want to pass unsigned long*'s


    • to v**1q_u64 for both GCC and Clang, we need to cast the pointers to


    • different types to prevent -Wincompatible-pointer-types warnings. GCC


    • expects uint64_t*'s while Clang depends on the target's int64_t being either


    • long or long long (in the case of arm64, long) (see


    • lib/Sema/SemaChecking.cpp).

  • /
    +#ifdef __clang__
    +#define vld1q_u64_wrapper(x) vld1q_u64((const unsigned long
    )(x))
    +#define vst1q_u64_wrapper(x, y) vst1q_u64((unsigned long)(x), (y))
    +#else
    +#define vld1q_u64_wrapper(x) vld1q_u64((uint64_t
    )(x))
    +#define vst1q_u64_wrapper(x, y) vst1q_u64((uint64_t)(x), (y))
    +#endif
    +
    #endif /
    __ASM_NEON_INTRINSICS_H */
    diff --git a/arch/arm64/lib/xor-neon.c b/arch/arm64/lib/xor-neon.c
    index 131c60c27dff..468b709ba4cf 100644
    --- a/arch/arm64/lib/xor-neon.c
    +++ b/arch/arm64/lib/xor-neon.c
    @@ -16,105 +16,93 @@
    void xor_arm64_neon_2(unsigned long bytes, unsigned long *p1,
    unsigned long *p2)
    {
  • uint64_t *dp1 = (uint64_t *)p1;
  • uint64_t *dp2 = (uint64_t *)p2;
    -
    register uint64x2_t v0, v1, v2, v3;
    long lines = bytes / (sizeof(uint64x2_t) * 4);
do {
    /* p1 ^= p2 */

  • v0 = veorq_u64(vld1q_u64(dp1 + 0), vld1q_u64(dp2 + 0));
  • v1 = veorq_u64(vld1q_u64(dp1 + 2), vld1q_u64(dp2 + 2));
  • v2 = veorq_u64(vld1q_u64(dp1 + 4), vld1q_u64(dp2 + 4));
  • v3 = veorq_u64(vld1q_u64(dp1 + 6), vld1q_u64(dp2 + 6));
  • v0 = veorq_u64(vld1q_u64_wrapper(p1 + 0), vld1q_u64_wrapper(p2 + 0));
  • v1 = veorq_u64(vld1q_u64_wrapper(p1 + 2), vld1q_u64_wrapper(p2 + 2));
  • v2 = veorq_u64(vld1q_u64_wrapper(p1 + 4), vld1q_u64_wrapper(p2 + 4));
  • v3 = veorq_u64(vld1q_u64_wrapper(p1 + 6), vld1q_u64_wrapper(p2 + 6));
    /* store */

  • vst1q_u64(dp1 + 0, v0);
  • vst1q_u64(dp1 + 2, v1);
  • vst1q_u64(dp1 + 4, v2);
  • vst1q_u64(dp1 + 6, v3);
  • vst1q_u64_wrapper(p1 + 0, v0);
  • vst1q_u64_wrapper(p1 + 2, v1);
  • vst1q_u64_wrapper(p1 + 4, v2);
  • vst1q_u64_wrapper(p1 + 6, v3);
  • dp1 += 8;
  • dp2 += 8;
  • p1 += 8;
  • p2 += 8;
    } while (--lines > 0);
    }

    void xor_arm64_neon_3(unsigned long bytes, unsigned long *p1,
    unsigned long *p2, unsigned long *p3)
    {

  • uint64_t *dp1 = (uint64_t *)p1;
  • uint64_t *dp2 = (uint64_t *)p2;
  • uint64_t *dp3 = (uint64_t *)p3;
    -
    register uint64x2_t v0, v1, v2, v3;
    long lines = bytes / (sizeof(uint64x2_t) * 4);

    do {
    /* p1 ^= p2 */

  • v0 = veorq_u64(vld1q_u64(dp1 + 0), vld1q_u64(dp2 + 0));
  • v1 = veorq_u64(vld1q_u64(dp1 + 2), vld1q_u64(dp2 + 2));
  • v2 = veorq_u64(vld1q_u64(dp1 + 4), vld1q_u64(dp2 + 4));
  • v3 = veorq_u64(vld1q_u64(dp1 + 6), vld1q_u64(dp2 + 6));
  • v0 = veorq_u64(vld1q_u64_wrapper(p1 + 0), vld1q_u64_wrapper(p2 + 0));
  • v1 = veorq_u64(vld1q_u64_wrapper(p1 + 2), vld1q_u64_wrapper(p2 + 2));
  • v2 = veorq_u64(vld1q_u64_wrapper(p1 + 4), vld1q_u64_wrapper(p2 + 4));
  • v3 = veorq_u64(vld1q_u64_wrapper(p1 + 6), vld1q_u64_wrapper(p2 + 6));

    /* p1 ^= p3 */
    
  • v0 = veorq_u64(v0, vld1q_u64(dp3 + 0));
  • v1 = veorq_u64(v1, vld1q_u64(dp3 + 2));
  • v2 = veorq_u64(v2, vld1q_u64(dp3 + 4));
  • v3 = veorq_u64(v3, vld1q_u64(dp3 + 6));
  • v0 = veorq_u64(v0, vld1q_u64_wrapper(p3 + 0));
  • v1 = veorq_u64(v1, vld1q_u64_wrapper(p3 + 2));
  • v2 = veorq_u64(v2, vld1q_u64_wrapper(p3 + 4));
  • v3 = veorq_u64(v3, vld1q_u64_wrapper(p3 + 6));

    /* store */
    
  • vst1q_u64(dp1 + 0, v0);
  • vst1q_u64(dp1 + 2, v1);
  • vst1q_u64(dp1 + 4, v2);
  • vst1q_u64(dp1 + 6, v3);
    -
  • dp1 += 8;
  • dp2 += 8;
  • dp3 += 8;
  • vst1q_u64_wrapper(p1 + 0, v0);
  • vst1q_u64_wrapper(p1 + 2, v1);
  • vst1q_u64_wrapper(p1 + 4, v2);
  • vst1q_u64_wrapper(p1 + 6, v3);
    +
  • p1 += 8;
  • p2 += 8;
  • p3 += 8;
    } while (--lines > 0);
    }

    void xor_arm64_neon_4(unsigned long bytes, unsigned long *p1,
    unsigned long *p2, unsigned long *p3, unsigned long *p4)
    {

  • uint64_t *dp1 = (uint64_t *)p1;
  • uint64_t *dp2 = (uint64_t *)p2;
  • uint64_t *dp3 = (uint64_t *)p3;
  • uint64_t *dp4 = (uint64_t *)p4;
    -
    register uint64x2_t v0, v1, v2, v3;
    long lines = bytes / (sizeof(uint64x2_t) * 4);

    do {
    /* p1 ^= p2 */

  • v0 = veorq_u64(vld1q_u64(dp1 + 0), vld1q_u64(dp2 + 0));
  • v1 = veorq_u64(vld1q_u64(dp1 + 2), vld1q_u64(dp2 + 2));
  • v2 = veorq_u64(vld1q_u64(dp1 + 4), vld1q_u64(dp2 + 4));
  • v3 = veorq_u64(vld1q_u64(dp1 + 6), vld1q_u64(dp2 + 6));
  • v0 = veorq_u64(vld1q_u64_wrapper(p1 + 0), vld1q_u64_wrapper(p2 + 0));
  • v1 = veorq_u64(vld1q_u64_wrapper(p1 + 2), vld1q_u64_wrapper(p2 + 2));
  • v2 = veorq_u64(vld1q_u64_wrapper(p1 + 4), vld1q_u64_wrapper(p2 + 4));
  • v3 = veorq_u64(vld1q_u64_wrapper(p1 + 6), vld1q_u64_wrapper(p2 + 6));

    /* p1 ^= p3 */
    
  • v0 = veorq_u64(v0, vld1q_u64(dp3 + 0));
  • v1 = veorq_u64(v1, vld1q_u64(dp3 + 2));
  • v2 = veorq_u64(v2, vld1q_u64(dp3 + 4));
  • v3 = veorq_u64(v3, vld1q_u64(dp3 + 6));
  • v0 = veorq_u64(v0, vld1q_u64_wrapper(p3 + 0));
  • v1 = veorq_u64(v1, vld1q_u64_wrapper(p3 + 2));
  • v2 = veorq_u64(v2, vld1q_u64_wrapper(p3 + 4));
  • v3 = veorq_u64(v3, vld1q_u64_wrapper(p3 + 6));

    /* p1 ^= p4 */
    
  • v0 = veorq_u64(v0, vld1q_u64(dp4 + 0));
  • v1 = veorq_u64(v1, vld1q_u64(dp4 + 2));
  • v2 = veorq_u64(v2, vld1q_u64(dp4 + 4));
  • v3 = veorq_u64(v3, vld1q_u64(dp4 + 6));
  • v0 = veorq_u64(v0, vld1q_u64_wrapper(p4 + 0));
  • v1 = veorq_u64(v1, vld1q_u64_wrapper(p4 + 2));
  • v2 = veorq_u64(v2, vld1q_u64_wrapper(p4 + 4));
  • v3 = veorq_u64(v3, vld1q_u64_wrapper(p4 + 6));

    /* store */
    
  • vst1q_u64(dp1 + 0, v0);
  • vst1q_u64(dp1 + 2, v1);
  • vst1q_u64(dp1 + 4, v2);
  • vst1q_u64(dp1 + 6, v3);
    -
  • dp1 += 8;
  • dp2 += 8;
  • dp3 += 8;
  • dp4 += 8;
  • vst1q_u64_wrapper(p1 + 0, v0);
  • vst1q_u64_wrapper(p1 + 2, v1);
  • vst1q_u64_wrapper(p1 + 4, v2);
  • vst1q_u64_wrapper(p1 + 6, v3);
    +
  • p1 += 8;
  • p2 += 8;
  • p3 += 8;
  • p4 += 8;
    } while (--lines > 0);
    }

@@ -122,51 +110,45 @@ void xor_arm64_neon_5(unsigned long bytes, unsigned long *p1,
unsigned long *p2, unsigned long *p3,
unsigned long *p4, unsigned long *p5)
{

  • uint64_t *dp1 = (uint64_t *)p1;
  • uint64_t *dp2 = (uint64_t *)p2;
  • uint64_t *dp3 = (uint64_t *)p3;
  • uint64_t *dp4 = (uint64_t *)p4;
  • uint64_t *dp5 = (uint64_t *)p5;
    -
    register uint64x2_t v0, v1, v2, v3;
    long lines = bytes / (sizeof(uint64x2_t) * 4);
do {
    /* p1 ^= p2 */

  • v0 = veorq_u64(vld1q_u64(dp1 + 0), vld1q_u64(dp2 + 0));
  • v1 = veorq_u64(vld1q_u64(dp1 + 2), vld1q_u64(dp2 + 2));
  • v2 = veorq_u64(vld1q_u64(dp1 + 4), vld1q_u64(dp2 + 4));
  • v3 = veorq_u64(vld1q_u64(dp1 + 6), vld1q_u64(dp2 + 6));
  • v0 = veorq_u64(vld1q_u64_wrapper(p1 + 0), vld1q_u64_wrapper(p2 + 0));
  • v1 = veorq_u64(vld1q_u64_wrapper(p1 + 2), vld1q_u64_wrapper(p2 + 2));
  • v2 = veorq_u64(vld1q_u64_wrapper(p1 + 4), vld1q_u64_wrapper(p2 + 4));
  • v3 = veorq_u64(vld1q_u64_wrapper(p1 + 6), vld1q_u64_wrapper(p2 + 6));
    /* p1 ^= p3 */

  • v0 = veorq_u64(v0, vld1q_u64(dp3 + 0));
  • v1 = veorq_u64(v1, vld1q_u64(dp3 + 2));
  • v2 = veorq_u64(v2, vld1q_u64(dp3 + 4));
  • v3 = veorq_u64(v3, vld1q_u64(dp3 + 6));
  • v0 = veorq_u64(v0, vld1q_u64_wrapper(p3 + 0));
  • v1 = veorq_u64(v1, vld1q_u64_wrapper(p3 + 2));
  • v2 = veorq_u64(v2, vld1q_u64_wrapper(p3 + 4));
  • v3 = veorq_u64(v3, vld1q_u64_wrapper(p3 + 6));
    /* p1 ^= p4 */

  • v0 = veorq_u64(v0, vld1q_u64(dp4 + 0));
  • v1 = veorq_u64(v1, vld1q_u64(dp4 + 2));
  • v2 = veorq_u64(v2, vld1q_u64(dp4 + 4));
  • v3 = veorq_u64(v3, vld1q_u64(dp4 + 6));
  • v0 = veorq_u64(v0, vld1q_u64_wrapper(p4 + 0));
  • v1 = veorq_u64(v1, vld1q_u64_wrapper(p4 + 2));
  • v2 = veorq_u64(v2, vld1q_u64_wrapper(p4 + 4));
  • v3 = veorq_u64(v3, vld1q_u64_wrapper(p4 + 6));
    /* p1 ^= p5 */

  • v0 = veorq_u64(v0, vld1q_u64(dp5 + 0));
  • v1 = veorq_u64(v1, vld1q_u64(dp5 + 2));
  • v2 = veorq_u64(v2, vld1q_u64(dp5 + 4));
  • v3 = veorq_u64(v3, vld1q_u64(dp5 + 6));
  • v0 = veorq_u64(v0, vld1q_u64_wrapper(p5 + 0));
  • v1 = veorq_u64(v1, vld1q_u64_wrapper(p5 + 2));
  • v2 = veorq_u64(v2, vld1q_u64_wrapper(p5 + 4));
  • v3 = veorq_u64(v3, vld1q_u64_wrapper(p5 + 6));
    /* store */

  • vst1q_u64(dp1 + 0, v0);
  • vst1q_u64(dp1 + 2, v1);
  • vst1q_u64(dp1 + 4, v2);
  • vst1q_u64(dp1 + 6, v3);
    -
  • dp1 += 8;
  • dp2 += 8;
  • dp3 += 8;
  • dp4 += 8;
  • dp5 += 8;
  • vst1q_u64_wrapper(p1 + 0, v0);
  • vst1q_u64_wrapper(p1 + 2, v1);
  • vst1q_u64_wrapper(p1 + 4, v2);
  • vst1q_u64_wrapper(p1 + 6, v3);
    +
  • p1 += 8;
  • p2 += 8;
  • p3 += 8;
  • p4 += 8;
  • p5 += 8;
    } while (--lines > 0);
    }
    ```

Please, no. Just add the #pragma instead.

The pragma is the worst option, since suppressing the warning prevents other bugs from being found. Can we instead remove the redefinition in arch/arm64/include/asm/neon-intrinsics.h?

The pragma is the worst option, since suppressing the warning prevents other bugs from being found. Can we instead remove the redefinition in arch/arm64/include/asm/neon-intrinsics.h?

Unfortunately, removing them adds another error because we'd be redefining uint64_t:

In file included from /home/nathan/cbl/linux-next/arch/arm64/lib/xor-neon.c:14:
In file included from /home/nathan/cbl/linux-next/arch/arm64/include/asm/neon-intrinsics.h:38:
In file included from /home/nathan/cbl/usr/lib/clang/9.0.0/include/arm_neon.h:31:
/home/nathan/cbl/usr/lib/clang/9.0.0/include/stdint.h:107:24: error: typedef redefinition with different types ('long' vs 's64' (aka 'long long'))
typedef __INT64_TYPE__ int64_t;
                       ^
/home/nathan/cbl/linux-next/include/linux/types.h:114:15: note: previous definition is here
typedef s64                     int64_t;
                                ^
In file included from /home/nathan/cbl/linux-next/arch/arm64/lib/xor-neon.c:14:
In file included from /home/nathan/cbl/linux-next/arch/arm64/include/asm/neon-intrinsics.h:38:
In file included from /home/nathan/cbl/usr/lib/clang/9.0.0/include/arm_neon.h:31:
/home/nathan/cbl/usr/lib/clang/9.0.0/include/stdint.h:109:25: error: typedef redefinition with different types ('unsigned long' vs 'u64' (aka 'unsigned long long'))
typedef __UINT64_TYPE__ uint64_t;
                        ^
/home/nathan/cbl/linux-next/include/linux/types.h:112:15: note: previous definition is here
typedef u64                     uint64_t;
                                ^

Another idea: going back to the code @fvincenzo highlighted . Not that function, but its call site.

    bool IsInt64Long =
        Context.getTargetInfo().getInt64Type() == TargetInfo::SignedLong;
    QualType EltTy =
        getNeonEltType(NeonTypeFlags(TV), Context, IsPolyUnsigned, IsInt64Long);

I posit that IsInt64Long is assigned incorrectly here. Sema::CheckNeonBuiltinFunctionCall assumes that an architecture's int64_t being long vs long long is statically defined by the arch. But @ardbiesheuvel 's 09096f6a0ee2f2a26f3f11cf466fab0364405a23 shows that this isn't guaranteed, since you can redefine int64_t at will via __INT64_TYPE__, which is what the kernel does.

(Or, maybe I'm misunderstanding Context.getTargetInfo().getInt64Type(); maybe it should be returning __INT64_TYPE__ at this point in the module context. I don't think I'm misunderstanding though; it looks like the Target's Int64Type is set once during Target construction and does not contain a setter method).

If we changed the initial value of IsInt64Long to be "what does __INT64_TYPE__" mean at this point in the translation unit, then the existing code in the kernel (casting unsigned long* to uint64_t*) should just compile, and we don't have to touch the kernel. (I'm not sure if __INT64_TYPE__ is mentioned in any standard, or is strictly an implementation detail of two separate stdint.h implementations).

so making changes there to accommodate Linux is a bad idea.

It pains me less than disabling a warning. Thoughts?

I did not realize that Clang's builtin stdint.h header also typedefs uint64_t in terms of __UINT64_TYPE__, but in that case, I agree it is a Clang bug to assume elsewhere that __UINT64_TYPE__ is always defined as unsigned long.

@ardbiesheuvel This was the point I was trying to make, hence the modification I proposed above. I came to this conclusion because as a first attempt I tried to modify neon-intrinsics.h redefining __INT64_TYPE__ and __UINT64_TYPE__ in a similar fashion to what gcc does, but they seem ignored by clang.

@nickdesaulniers Not sure of the history behind of __UINT64_TYPE__ but I fully agree with your analysis (not the kernel patch). We should try to make clang work with the __UINT64_TYPE__ defined by the kernel. In a similar way to what happens with gcc.

I continued the investigation based on what @nickdesaulniers suggested above, and I found out that in lib/Basic/Targets/AArch64.cpp the definition of the Int<*>Types (i.e. Int64Type) is defined by operating system, but Linux is missing completely. To address the issue I am using the fix below which seems addressing the general problem (-Wincompatible-pointer-types in arch/arm64/lib/xor-neon.c) as well:

diff --git a/lib/Basic/Targets/AArch64.cpp b/lib/Basic/Targets/AArch64.cpp
index a0885a6981..9c3f379e66 100644
--- a/lib/Basic/Targets/AArch64.cpp
+++ b/lib/Basic/Targets/AArch64.cpp
@@ -36,7 +36,7 @@ const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = {
 AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
                                      const TargetOptions &Opts)
     : TargetInfo(Triple), ABI("aapcs") {
-  if (getTriple().isOSOpenBSD()) {
+  if (getTriple().isOSOpenBSD() || getTriple().isOSLinux()) {
     Int64Type = SignedLongLong;
     IntMaxType = SignedLongLong;
   } else {

Cc: @nathanchance @ardbiesheuvel @nickdesaulniers

With this fix applied linux on arm64 compiles and runs correctly. Thoughts?

On Fri, 1 Feb 2019 at 14:10, Vincenzo Frascino notifications@github.com
wrote:

I continued the investigation based on what @nickdesaulniers
https://github.com/nickdesaulniers suggested above
https://github.com/ClangBuiltLinux/linux/issues/283#issuecomment-457448624,
and I found out that lib/Basic/Targets/AArch64.cpp the definition on the
Int<*>Types (i.e. Int64Type) is defined by operating system, but Linux is
missing completely. To address the issue I am using the fix below which
seems addressing the general problem as well:

diff --git a/lib/Basic/Targets/AArch64.cpp b/lib/Basic/Targets/AArch64.cpp
index a0885a6981..9c3f379e66 100644
--- a/lib/Basic/Targets/AArch64.cpp
+++ b/lib/Basic/Targets/AArch64.cpp
@@ -36,7 +36,7 @@ const Builtin::Info AArch64TargetInfo::BuiltinInfo[] = {
AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: TargetInfo(Triple), ABI("aapcs") {
- if (getTriple().isOSOpenBSD()) {
+ if (getTriple().isOSOpenBSD() || getTriple().isOSLinux()) {
Int64Type = SignedLongLong;
IntMaxType = SignedLongLong;
} else {

Cc: @nathanchance https://github.com/nathanchance @ardbiesheuvel
https://github.com/ardbiesheuvel @nickdesaulniers
https://github.com/nickdesaulniers

With this fix applied linux on arm64 compiles and runs correctly. Thoughts?

Won't this break AArch64 userspace apps that use arm_neon.h, and
[correctly] assume uint64_t == unsigned long?

On Fri, Feb 1, 2019, 10:22 PM Ard Biesheuvel <[email protected]
wrote:

On Fri, 1 Feb 2019 at 14:10, Vincenzo Frascino notifications@github.com
wrote:

I continued the investigation based on what @nickdesaulniers
https://github.com/nickdesaulniers suggested above
<
https://github.com/ClangBuiltLinux/linux/issues/283#issuecomment-457448624
,
and I found out that lib/Basic/Targets/AArch64.cpp the definition on the
Int<*>Types (i.e. Int64Type) is defined by operating system, but Linux is
missing completely. To address the issue I am using the fix below which
seems addressing the general problem as well:

diff --git a/lib/Basic/Targets/AArch64.cpp
b/lib/Basic/Targets/AArch64.cpp
index a0885a6981..9c3f379e66 100644
--- a/lib/Basic/Targets/AArch64.cpp
+++ b/lib/Basic/Targets/AArch64.cpp
@@ -36,7 +36,7 @@ const Builtin::Info AArch64TargetInfo::BuiltinInfo[] =
{
AArch64TargetInfo::AArch64TargetInfo(const llvm::Triple &Triple,
const TargetOptions &Opts)
: TargetInfo(Triple), ABI("aapcs") {
- if (getTriple().isOSOpenBSD()) {
+ if (getTriple().isOSOpenBSD() || getTriple().isOSLinux()) {
Int64Type = SignedLongLong;
IntMaxType = SignedLongLong;
} else {

Cc: @nathanchance https://github.com/nathanchance @ardbiesheuvel
https://github.com/ardbiesheuvel @nickdesaulniers
https://github.com/nickdesaulniers

With this fix applied linux on arm64 compiles and runs correctly.
Thoughts?

Won't this break AArch64 userspace apps that use arm_neon.h, and
[correctly] assume uint64_t == unsigned long?

That's what it looks like to me. We don't want to change the aarch64 ABI.

—

You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/ClangBuiltLinux/linux/issues/283#issuecomment-459888385,
or mute the thread
https://github.com/notifications/unsubscribe-auth/ABvUX1FFSkc98Er7xsaT0jbGwrEgi_30ks5vJL4fgaJpZM4ZJgHM
.

@nickdesaulniers @ardbiesheuvel Agreed. Indeed this changes the ABI and we do not want that. (Looked like too easy :smile:).

I posit that IsInt64Long is assigned incorrectly here.

I've contacted Clang's maintainer to request his thoughts on the matter. Will post once I have an update.

This warning is now hidden on -next to facilitate continuous integration: https://git.kernel.org/next/linux-next/c/0738c8b5915c7eaf1e6007b441008e8f3b460443

The problematic commit was merged in 5.0-rc1 and this commit is in the fixes branch so it should make it into 5.0 final so this release won't regress.

Patch merged into mainline so 5.0 won't regress: https://git.kernel.org/torvalds/c/0738c8b5915c7eaf1e6007b441008e8f3b460443

Shouldn't this be closed?

I left it open because the root cause of the warning is not resolved, even though it is hidden.

Feel free to reopen if you think it's not resolved yet.

Was this page helpful?
0 / 5 - 0 ratings