Skip to content

Conversation

@localspook
Copy link
Contributor

The first parameter of the builtin is const void *, and function pointers aren't convertible to that. GCC diagnoses this.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Aug 14, 2025
@llvmbot
Copy link
Member

llvmbot commented Aug 14, 2025

@llvm/pr-subscribers-clang

Author: Victor Chernyakin (localspook)

Changes

The first parameter of the builtin is const void *, and function pointers aren't convertible to that. GCC diagnoses this.


Full diff: https://github.com/llvm/llvm-project/pull/153552.diff

3 Files Affected:

  • (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+2-1)
  • (modified) clang/lib/Sema/SemaChecking.cpp (+3-2)
  • (modified) clang/test/Sema/builtin-assume-aligned.c (+9-8)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 116341f4b66d5..f7f26ed6062b3 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -12829,7 +12829,8 @@ def err_builtin_launder_invalid_arg : Error< "%select{non-pointer|function pointer|void pointer}0 argument to " "'__builtin_launder' is not allowed">; def err_builtin_assume_aligned_invalid_arg : Error< - "non-pointer argument to '__builtin_assume_aligned' is not allowed">; + "%select{non-pointer|function pointer}0 argument to " + "'__builtin_assume_aligned' is not allowed">; def err_builtin_is_within_lifetime_invalid_arg : Error< "%select{non-|function }0pointer argument to '__builtin_is_within_lifetime' " diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp index 9ecee18661340..d8ad9f65c1995 100644 --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -5660,9 +5660,10 @@ bool Sema::BuiltinAssumeAligned(CallExpr *TheCall) { { ExprResult FirstArgResult = DefaultFunctionArrayLvalueConversion(FirstArg); - if (!FirstArgResult.get()->getType()->isPointerType()) { + QualType FirstArgType = FirstArgResult.get()->getType(); + if (!FirstArgType->isObjectPointerType()) { Diag(TheCall->getBeginLoc(), diag::err_builtin_assume_aligned_invalid_arg) - << TheCall->getSourceRange(); + << FirstArgType->isFunctionPointerType() << TheCall->getSourceRange(); return true; } TheCall->setArg(0, FirstArgResult.get()); diff --git a/clang/test/Sema/builtin-assume-aligned.c b/clang/test/Sema/builtin-assume-aligned.c index 57378a3426524..c6d1197fe8ab4 100644 --- a/clang/test/Sema/builtin-assume-aligned.c +++ b/clang/test/Sema/builtin-assume-aligned.c @@ -77,18 +77,19 @@ int test14(int *a, int b) { a = (int *)__builtin_assume_aligned(b, 32); // expected-error {{non-pointer argument to '__builtin_assume_aligned' is not allowed}} } -int test15(int *b) { - int arr[3] = {1, 2, 3}; - b = (int *)__builtin_assume_aligned(arr, 32); - return b[0]; +void test15(void (*f)()) { + f = (void (*)())__builtin_assume_aligned(f, 32); // expected-error {{function pointer argument to '__builtin_assume_aligned' is not allowed}} } -int val(int x) { - return x; +void foo(); + +void test16(void (*f)()) { + f = (void (*)())__builtin_assume_aligned(foo, 32); // expected-error {{function pointer argument to '__builtin_assume_aligned' is not allowed}} } -int test16(int *b) { - b = (int *)__builtin_assume_aligned(val, 32); +int test17(int *b) { + int arr[3] = {1, 2, 3}; + b = (int *)__builtin_assume_aligned(arr, 32); return b[0]; } 
Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for working on this! However, this isn't quite the correct change IMO. GCC diagnoses function pointer to void * conversions in C++ mode in general. Clang does as well: https://godbolt.org/z/jcW718EY6

I think you should be calling checkBuiltinArgument() to initialize the parameter. That should go through the usual initialization sequence logic and emit the correct diagnostics in both C++ and C.

Also, the changes should come with a release note in clang/docs/ReleaseNotes.rst so users know about the fix.

@localspook
Copy link
Contributor Author

localspook commented Aug 15, 2025

I've switched to checkBuiltinArgument, but it causes an issue that I'd like input on before I continue. clang/test/CodeGen/catch-alignment-assumption-ignorelist.c tests that UBSan doesn't validate the alignment of pointers to volatile. Several UBSan checks have this exception, but I don't understand the motivation behind it. With this change, the volatile-ness of the pointer is lost when passed into __builtin_assume_aligned, so the UBSan checks are generated. To me this seems like an improvement; after all, checking alignment does not dereference the pointer, so why does it matter if it points to volatile?

@@ -1,9 +0,0 @@
// RUN: %clang_cc1 -fsyntax-only -Wno-int-conversion -triple x86_64-linux -verify %s
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The pointer is now always converted to const void *, so we no longer need to disallow these integer conversions.

@AaronBallman
Copy link
Collaborator

I've switched to checkBuiltinArgument, but it causes an issue that I'd like input on before I continue. clang/test/CodeGen/catch-alignment-assumption-ignorelist.c tests that UBSan doesn't validate the alignment of pointers to volatile. Several UBSan checks have this exception, but I don't understand the motivation behind it. With this change, the volatile-ness of the pointer is lost when passed into __builtin_assume_aligned, so the UBSan checks are generated. To me this seems like an improvement; after all, checking alignment does not dereference the pointer, so why does it matter if it points to volatile?

CC @zygoloid @vitalybuka for opinions

Copy link
Collaborator

@AaronBallman AaronBallman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! The changes LGTM but I'd like to hear from @zygoloid or @vitalybuka about the change in sanitizer before before we land the changes.

@AaronBallman
Copy link
Collaborator

It looks like precommit CI found relevant failures though:

 ******************** Failed Tests (40): UBSan-AddressSanitizer-lld-x86_64 :: TestCases/Pointer/align-assume-builtin_assume_aligned-three-params-variable.cpp UBSan-AddressSanitizer-lld-x86_64 :: TestCases/Pointer/align-assume-builtin_assume_aligned-three-params.cpp UBSan-AddressSanitizer-lld-x86_64 :: TestCases/Pointer/align-assume-builtin_assume_aligned-two-params.cpp UBSan-AddressSanitizer-lld-x86_64 :: TestCases/Pointer/align-assume-ignorelist.cpp UBSan-AddressSanitizer-lld-x86_64 :: TestCases/Pointer/align-assume-summary.cpp UBSan-AddressSanitizer-x86_64 :: TestCases/Pointer/align-assume-builtin_assume_aligned-three-params-variable.cpp UBSan-AddressSanitizer-x86_64 :: TestCases/Pointer/align-assume-builtin_assume_aligned-three-params.cpp UBSan-AddressSanitizer-x86_64 :: TestCases/Pointer/align-assume-builtin_assume_aligned-two-params.cpp UBSan-AddressSanitizer-x86_64 :: TestCases/Pointer/align-assume-ignorelist.cpp UBSan-AddressSanitizer-x86_64 :: TestCases/Pointer/align-assume-summary.cpp UBSan-MemorySanitizer-lld-x86_64 :: TestCases/Pointer/align-assume-builtin_assume_aligned-three-params-variable.cpp UBSan-MemorySanitizer-lld-x86_64 :: TestCases/Pointer/align-assume-builtin_assume_aligned-three-params.cpp UBSan-MemorySanitizer-lld-x86_64 :: TestCases/Pointer/align-assume-builtin_assume_aligned-two-params.cpp UBSan-MemorySanitizer-lld-x86_64 :: TestCases/Pointer/align-assume-ignorelist.cpp UBSan-MemorySanitizer-lld-x86_64 :: TestCases/Pointer/align-assume-summary.cpp UBSan-MemorySanitizer-x86_64 :: TestCases/Pointer/align-assume-builtin_assume_aligned-three-params-variable.cpp UBSan-MemorySanitizer-x86_64 :: TestCases/Pointer/align-assume-builtin_assume_aligned-three-params.cpp UBSan-MemorySanitizer-x86_64 :: TestCases/Pointer/align-assume-builtin_assume_aligned-two-params.cpp UBSan-MemorySanitizer-x86_64 :: TestCases/Pointer/align-assume-ignorelist.cpp UBSan-MemorySanitizer-x86_64 :: TestCases/Pointer/align-assume-summary.cpp UBSan-Standalone-lld-x86_64 :: TestCases/Pointer/align-assume-builtin_assume_aligned-three-params-variable.cpp UBSan-Standalone-lld-x86_64 :: TestCases/Pointer/align-assume-builtin_assume_aligned-three-params.cpp UBSan-Standalone-lld-x86_64 :: TestCases/Pointer/align-assume-builtin_assume_aligned-two-params.cpp UBSan-Standalone-lld-x86_64 :: TestCases/Pointer/align-assume-ignorelist.cpp UBSan-Standalone-lld-x86_64 :: TestCases/Pointer/align-assume-summary.cpp UBSan-Standalone-x86_64 :: TestCases/Pointer/align-assume-builtin_assume_aligned-three-params-variable.cpp UBSan-Standalone-x86_64 :: TestCases/Pointer/align-assume-builtin_assume_aligned-three-params.cpp UBSan-Standalone-x86_64 :: TestCases/Pointer/align-assume-builtin_assume_aligned-two-params.cpp UBSan-Standalone-x86_64 :: TestCases/Pointer/align-assume-ignorelist.cpp UBSan-Standalone-x86_64 :: TestCases/Pointer/align-assume-summary.cpp UBSan-ThreadSanitizer-lld-x86_64 :: TestCases/Pointer/align-assume-builtin_assume_aligned-three-params-variable.cpp UBSan-ThreadSanitizer-lld-x86_64 :: TestCases/Pointer/align-assume-builtin_assume_aligned-three-params.cpp UBSan-ThreadSanitizer-lld-x86_64 :: TestCases/Pointer/align-assume-builtin_assume_aligned-two-params.cpp UBSan-ThreadSanitizer-lld-x86_64 :: TestCases/Pointer/align-assume-ignorelist.cpp UBSan-ThreadSanitizer-lld-x86_64 :: TestCases/Pointer/align-assume-summary.cpp UBSan-ThreadSanitizer-x86_64 :: TestCases/Pointer/align-assume-builtin_assume_aligned-three-params-variable.cpp UBSan-ThreadSanitizer-x86_64 :: TestCases/Pointer/align-assume-builtin_assume_aligned-three-params.cpp UBSan-ThreadSanitizer-x86_64 :: TestCases/Pointer/align-assume-builtin_assume_aligned-two-params.cpp UBSan-ThreadSanitizer-x86_64 :: TestCases/Pointer/align-assume-ignorelist.cpp UBSan-ThreadSanitizer-x86_64 :: TestCases/Pointer/align-assume-summary.cpp Testing Time: 61.89s Total Discovered Tests: 7681 Skipped : 18 (0.23%) Unsupported : 1286 (16.74%) Passed : 6273 (81.67%) Expectedly Failed: 64 (0.83%) Failed : 40 (0.52%) 
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category

3 participants