Skip to content

Commit e4f1ef8

Browse files
committed
[clang][Interp] Reject bitcasts to atomic types
The current interpreter does this, so follow suit to match its diagnostics.
1 parent 5249379 commit e4f1ef8

File tree

5 files changed

+34
-2
lines changed

5 files changed

+34
-2
lines changed

clang/lib/AST/Interp/ByteCodeExprGen.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,14 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
191191
case CK_NonAtomicToAtomic:
192192
case CK_NoOp:
193193
case CK_UserDefinedConversion:
194+
return this->delegate(SubExpr);
195+
194196
case CK_BitCast:
197+
if (CE->getType()->isAtomicType()) {
198+
if (!this->discard(SubExpr))
199+
return false;
200+
return this->emitInvalidCast(CastKind::Reinterpret, CE);
201+
}
195202
return this->delegate(SubExpr);
196203

197204
case CK_IntegralToBoolean:

clang/lib/AST/Interp/Interp.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2020,8 +2020,11 @@ inline bool Invalid(InterpState &S, CodePtr OpPC) {
20202020
/// Same here, but only for casts.
20212021
inline bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind) {
20222022
const SourceLocation &Loc = S.Current->getLocation(OpPC);
2023-
S.FFDiag(Loc, diag::note_constexpr_invalid_cast)
2024-
<< static_cast<unsigned>(Kind) << S.Current->getRange(OpPC);
2023+
2024+
// FIXME: Support diagnosing other invalid cast kinds.
2025+
if (Kind == CastKind::Reinterpret)
2026+
S.FFDiag(Loc, diag::note_constexpr_invalid_cast)
2027+
<< static_cast<unsigned>(Kind) << S.Current->getRange(OpPC);
20252028
return false;
20262029
}
20272030

clang/lib/AST/Interp/PrimType.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,17 @@ enum PrimType : unsigned {
4848

4949
enum class CastKind : uint8_t {
5050
Reinterpret,
51+
Atomic,
5152
};
5253
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
5354
interp::CastKind CK) {
5455
switch (CK) {
5556
case interp::CastKind::Reinterpret:
5657
OS << "reinterpret_cast";
5758
break;
59+
case interp::CastKind::Atomic:
60+
OS << "atomic";
61+
break;
5862
}
5963
return OS;
6064
}

clang/test/AST/Interp/atomic.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=both,expected %s
2+
// RUN: %clang_cc1 -verify=both,ref %s
3+
4+
/// FIXME: Copied from test/Sema/atomic-expr.c.
5+
/// this expression seems to be rejected for weird reasons,
6+
/// but we imitate the current interpreter's behavior.
7+
_Atomic int ai = 0;
8+
// FIXME: &ai is an address constant, so this should be accepted as an
9+
// initializer, but the bit-cast inserted due to the pointer conversion is
10+
// tripping up the test for whether the initializer is a constant expression.
11+
// The warning is correct but the error is not.
12+
_Atomic(int *) aip3 = &ai; // both-warning {{incompatible pointer types initializing '_Atomic(int *)' with an expression of type '_Atomic(int) *'}} \
13+
// both-error {{initializer element is not a compile-time constant}}

clang/test/Sema/atomic-expr.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22
// RUN: %clang_cc1 %s -std=c2x -verify=expected,access -fsyntax-only
33
// RUN: %clang_cc1 %s -std=c2x -pedantic -verify=expected,access -fsyntax-only
44
// RUN: %clang_cc1 %s -verify -fsyntax-only -Wno-atomic-access
5+
// RUN: %clang_cc1 %s -verify=expected,access -fsyntax-only -fexperimental-new-constant-interpreter
6+
// RUN: %clang_cc1 %s -std=c2x -verify=expected,access -fsyntax-only -fexperimental-new-constant-interpreter
7+
// RUN: %clang_cc1 %s -std=c2x -pedantic -verify=expected,access -fsyntax-only -fexperimental-new-constant-interpreter
8+
// RUN: %clang_cc1 %s -verify -fsyntax-only -Wno-atomic-access -fexperimental-new-constant-interpreter
9+
510

611
_Atomic(unsigned int) data1;
712
int _Atomic data2;

0 commit comments

Comments
 (0)