Avoid __builtin_assume_aligned crash when the 1st arg is array type(or string literal).
Open issue: https://github.com/llvm/llvm-project/issues/57169
Differential D133202
[Clang] Avoid __builtin_assume_aligned crash when the 1st arg is array type yronglin on Sep 2 2022, 6:22 AM. Authored by
Details Avoid __builtin_assume_aligned crash when the 1st arg is array type(or string literal). Open issue: https://github.com/llvm/llvm-project/issues/57169
Diff Detail
Event TimelineThis comment was removed by yronglin. Comment Actions Other than the one thing, this looks good.
This comment was removed by yronglin. Comment Actions Thanks @vitalybuka , seems intrin0.inl.h have a forward declaration __MACHINE(void * __cdecl __builtin_assume_aligned(const void *, size_t, ...) noexcept), should we use nc in BUILTIN(__builtin_assume_aligned, "v*vC*z.", "nct") but not nct ? Comment Actions Fix windows build bolt broken https://lab.llvm.org/buildbot/#/builders/127/builds/35304 Comment Actions LGTM, but can you add a release note to clang/docs/ReleaseNotes.rst for the fix? Also, do you need someone to commit this on your behalf? If so, what name and email address would you like used for patch attribution? Comment Actions Thanks for your review @aaron.ballman , I've updated ReleaseNotes. I don’t have commit access, can you land this patch for me?Please use 'yronglin <yronglin777@gmail.com>' to commit the change. Comment Actions I've pushed the changes up for you, thanks! Something to keep in mind for the future: we typically only "ping" a review after about a week of no activity on it (just because folks end up being busy, taking vacation, want to contemplate the review for a while, etc).
Comment Actions Thanks a lot for your comments @rsmith @rjmccall . Firstly, as far as I know, turning on the -fsanitizer=alignment options and calling __builtin_assume_aligned, Clang will emit call void @__ubsan_handle_alignment_assumption(...) in CodeGen, and CodeGen need user-written-type for 1st arg to generate correct TypeDescriptor (this class in compiler-rt/UBSan). Secondly, before this patch, clang::CodeGen::CodeGenFunction::emitAlignmentAssumption use CastExpr->getSubExprAsWritten to get user-written-type in CodeGen. In Diff 457643 , we use custom sema checking.and just do DefaultFunctionArrayLvalueConversion on 1st arg, but not implicit cast 1st arg to const void *(We expect pass user-written-type to CodeGen). Unfortunately, Diff 457643 broken windows sanitize test, because there have a forward declaration __MACHINE(void * __cdecl __builtin_assume_aligned(const void *, size_t, ...) noexcept)in intrin0.inl.h, I think the reason for this problem is we use nct in BUILTIN(__builtin_assume_aligned, "v*vC*z.", "nct"), I try to find a solution based on Diff 457643, what do you all think about?
Comment Actions Reproduce windows broken test: ignore.cpp #include <stddef.h> void *__builtin_assume_aligned(const void *, size_t, ...) noexcept; void foo() { int a; (void) __builtin_assume_aligned(&a, 4); } FunctionDecl 0x14a80e480 <./ignore.cpp:3:1, col:7> col:7 __builtin_assume_aligned 'void *(const void *, size_t, ...) noexcept' |-ParmVarDecl 0x14a80df80 <col:32, col:43> col:44 'const void *' `-ParmVarDecl 0x14a80e050 <col:46> col:52 'size_t':'unsigned long' FunctionDecl 0x14a80e210 <./ignore.cpp:3:7> col:7 implicit __builtin_assume_aligned 'void *(const void *, unsigned long, ...) noexcept' extern |-ParmVarDecl 0x14a80e308 <<invalid sloc>> <invalid sloc> 'const void *' |-ParmVarDecl 0x14a80e370 <<invalid sloc>> <invalid sloc> 'unsigned long' |-BuiltinAttr 0x14a80e2b0 <<invalid sloc>> Implicit 402 |-NoThrowAttr 0x14a80e3e8 <col:7> Implicit `-ConstAttr 0x14a80e410 <col:7> Implicit ./ignore.cpp:3:7: error: cannot redeclare builtin function '__builtin_assume_aligned' void *__builtin_assume_aligned(const void *, size_t, ...) noexcept; ^ ./ignore.cpp:3:7: note: '__builtin_assume_aligned' is a builtin with type 'void *(const void *, unsigned long, ...) noexcept' 1 error generated. Comment Actions Seems that a builtin can't be redeclared which has custom type checking bool Builtin::Context::canBeRedeclared(unsigned ID) const { return ID == Builtin::NotBuiltin || ID == Builtin::BI__va_start || (!hasReferenceArgsOrResult(ID) && !hasCustomTypechecking(ID)) || isInStdNamespace(ID); } Comment Actions Please look into the history of that test case to see why we're specifically testing for the ability to redeclare this builtin. We could certainly allow this builtin to be redeclared using the const void* type — that doesn't really reflect the generic nature of the builtin, but it would work for compatibility with other compilers in the vast preponderance of code — but if we don't really need to do it, let's not go down that road.
Comment Actions Thanks very much for your comments @rjmccall @rsmith , I've take a look at D45383, I believe that user code isn't allowed to declare __builtin_*, but seems intrin0.inl.h is a system header on windows, should we keep compatibility(like __va_start in D45383) with it? or breaking it, but I'd like some further guidance. can you help me make that decision? I think you guys are experts in this area and have more experience than me, I'll see if I can accomplish soon! (maybe I should submit a new patch).
|
This looks very suspicious to me: this will remove a cast expression that was written in the source code from the AST. That loses source fidelity, can give the wrong answer if the cast changed the value (such as a C++ derived-to-base conversion to a non-primary base class), and in any case this is only done once where there could be multiple explicit casts written on an argument to the builtin, so if it's necessary, then it's not being done fully.
Can this be removed?