Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions clang/lib/AST/ExprConstant.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18606,12 +18606,15 @@ bool IntExprEvaluator::VisitCastExpr(const CastExpr *E) {

if (!Result.isInt()) {
// Allow casts of address-of-label differences if they are no-ops
// or narrowing. (The narrowing case isn't actually guaranteed to
// or narrowing, if the result is at least 32 bits wide.
// (The narrowing case isn't actually guaranteed to
// be constant-evaluatable except in some narrow cases which are hard
// to detect here. We let it through on the assumption the user knows
// what they are doing.)
if (Result.isAddrLabelDiff())
return Info.Ctx.getTypeSize(DestType) <= Info.Ctx.getTypeSize(SrcType);
if (Result.isAddrLabelDiff()) {
unsigned DestBits = Info.Ctx.getTypeSize(DestType);
return DestBits >= 32 && DestBits <= Info.Ctx.getTypeSize(SrcType);
}
// Only allow casts of lvalues if they are lossless.
return Info.Ctx.getTypeSize(DestType) == Info.Ctx.getTypeSize(SrcType);
}
Expand Down
2 changes: 1 addition & 1 deletion clang/test/AST/ast-dump-APValue-addrlabeldiff.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@

// CHECK: | |-value: AddrLabelDiff &&l2 - &&l1
int Test(void) {
constexpr char ar = &&l2 - &&l1;
constexpr long long ar = &&l2 - &&l1;
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can we keep a test where the result is narrowed to show that we reject those, or is that already covered elsewhere?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, in clang/test/CodeGen/const-label-addr.c for example:

int b(void) {
  static int ar = &&l2 - &&l1;
l1:
  return 10;
l2:
  return 11;
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

That's not what I was after, I meant a Sema test showing we diagnose:

int b(void) {
  static unsigned char ar = &&l2 - &&l1; // error
l1:
  return 10;
l2:
  return 11;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Oh, I guess we don't?
We also don't reject widening casts in sema today:

int b(void) {
  static unsigned __int128 ar = &&l2 - &&l1; // error
l1:
  return 10;
l2:
  return 11;
}

but we don't constant fold them.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I was basing this off the patch description saying: Reject integral casts of addr-label-diffs if the result is narrower than 32 bits. ;-)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This patch rejects those casts in the same way we've always rejected widening casts :P

l1:
return 10;
l2:
Expand Down
4 changes: 4 additions & 0 deletions clang/test/CodeGenCXX/const-init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ __int128_t PR11705 = (__int128_t)&PR11705;
// CHECK: @_ZZ23UnfoldableAddrLabelDiffvE1x = internal global i128 0
void UnfoldableAddrLabelDiff() { static __int128_t x = (long)&&a-(long)&&b; a:b:return;}

// CHECK: @_ZZ24UnfoldableAddrLabelDiff2vE1x = internal global i16 0
void UnfoldableAddrLabelDiff2() { static short x = (long)&&a-(long)&&b; a:b:return;}


// But make sure we do fold this.
// CHECK: @_ZZ21FoldableAddrLabelDiffvE1x = internal global i64 sub (i64 ptrtoint (ptr blockaddress(@_Z21FoldableAddrLabelDiffv
void FoldableAddrLabelDiff() { static long x = (long)&&a-(long)&&b; a:b:return;}
Expand Down