This is an archive of the discontinued LLVM Phabricator instance.

[libc] Remove global constructor in `getopt` implementation
ClosedPublic

Authored by jhuber6 on Jul 19 2023, 5:12 PM.

Details

Summary

This file required a global constructor due to copying the file stream
and have a non-constexpr constructor for the wrapper type. Also, I
changes the opterr to be a pointer, because it seemed like it wasn't
being set correctly as an externally visibile variable if we just
captured it by value.

Diff Detail

Event Timeline

jhuber6 created this revision.Jul 19 2023, 5:12 PM
Herald added projects: Restricted Project, Restricted Project. · View Herald TranscriptJul 19 2023, 5:12 PM
jhuber6 requested review of this revision.Jul 19 2023, 5:12 PM

I think this is OK but please wait for @abrachet .

Would it make sense to add -Wglobal-constructors here: https://github.com/llvm/llvm-project/blob/main/libc/cmake/modules/LLVMLibCObjectRules.cmake#L36

It's not clear what's different about the impl:: objects and the __llvm_libc::stderr one. [1] If this changes anything it just changes the decision the compiler decided to make, but it is still allowed to use a constructor here. I think to properly remove a global constructor the better route is what we did for atexit and the cmake that goes with it.

The opterr change looks good.

[1] In fact, if there is a difference it would be that __llvm_libc::stderr is (should be if not) a hidden alias to a default visibility stderr, which would make this a relative relocation, while the impl:: objects are symbolic relocations.

libc/src/unistd/getopt.cpp
24–25

This explicit constructor can just be removed instead, I think.

I think this is OK but please wait for @abrachet .

Would it make sense to add -Wglobal-constructors here: https://github.com/llvm/llvm-project/blob/main/libc/cmake/modules/LLVMLibCObjectRules.cmake#L36

This is the patch I had in https://reviews.llvm.org/D155721, but @michaelrj seemed concerned about adding more warnings so I figured I'd fix it first.

It's not clear what's different about the impl:: objects and the __llvm_libc::stderr one. [1] If this changes anything it just changes the decision the compiler decided to make, but it is still allowed to use a constructor here. I think to properly remove a global constructor the better route is what we did for atexit and the cmake that goes with it.

The opterr change looks good.

[1] In fact, if there is a difference it would be that __llvm_libc::stderr is (should be if not) a hidden alias to a default visibility stderr, which would make this a relative relocation, while the impl:: objects are symbolic relocations.

The __llvm_libc::stderr depends on the address of a value that cannot be statically determined, see https://godbolt.org/z/WYjeq3bnK, so it's like you say with the relocations. I don't think there's a way to make this a constant expression without the File API exporting the underlying static variable here.

abrachet accepted this revision.Jul 20 2023, 5:47 AM

The __llvm_libc::stderr depends on the address of a value that cannot be statically determined, see https://godbolt.org/z/WYjeq3bnK, so it's like you say with the relocations. I don't think there's a way to make this a constant expression without the File API exporting the underlying static variable here.

Oh right I see now, we aren't taking the address of __llvm_libc::stderr. I guess then we could hold a FILE** instead and do fprintf(*errstream, ...) or I'm fine with the change as is too.

libc/src/unistd/getopt.cpp
46–50

I think this or something similar is cleaner than conditionals, but up to you.

This revision is now accepted and ready to land.Jul 20 2023, 5:47 AM