This is an archive of the discontinued LLVM Phabricator instance.

[FunctionAttrs] allow weak functions to propagate noreturn
AbandonedPublic

Authored by nickdesaulniers on Mar 29 2023, 12:15 PM.

Details

Summary

I noticed that FunctionAttrs would propagate noreturn for various
functions, but stopped unexpectedly for a very simple weak definition.

While functions with weak linkage may be redefined, that should not
prevent us from propagating noreturn for this particular definition.

Link: https://github.com/ClangBuiltLinux/linux/issues/1815

Diff Detail

Event Timeline

Herald added a project: Restricted Project. · View Herald TranscriptMar 29 2023, 12:15 PM
nickdesaulniers requested review of this revision.Mar 29 2023, 12:15 PM
Herald added a project: Restricted Project. · View Herald TranscriptMar 29 2023, 12:15 PM

I don't think this is sound. Refinement again:

static I = 0;
__attribute__((weak)) void weak() {
  unspecified_order(++I, UB_if_I_is_non_zero());
}

Order 1:

static I = 0;
__attribute__((weak)) void weak() {
  auto _T1 = ++I;
  auto _T2 = UB_if_I_is_non_zero();
  unspecified_order(_T1, _T2);
  // weak is now noreturn because we hit UB computing _T2.
}

Order 2:

static I = 0;
__attribute__((weak)) void weak() {
  auto _T1 = UB_if_I_is_non_zero();
  auto _T2 = ++I;
  unspecified_order(_T2, _T1);
  // weak is not noreturn and optimizing call sites with it will cause problems if we pick this version.
}

Right, the callers is what we have to worry about.

If the weak function was declared as being noreturn, even the strong definitions should be noreturn, and optimizations should hold the code to that contract.

But if the weak function wasn't declared as noreturn, inferring it for one definition says nothing about the strong definition, so such optimizations might be surprising!

nickdesaulniers abandoned this revision.Mar 29 2023, 2:53 PM