Skip to content

Commit

Permalink
[clang][Interp] Reject bitcasts to atomic types
Browse files Browse the repository at this point in the history
The current interpreter does this, so follow suit to match its
diagnostics.
  • Loading branch information
tbaederr committed Feb 5, 2024
1 parent 5249379 commit e4f1ef8
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 2 deletions.
7 changes: 7 additions & 0 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,14 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
case CK_NonAtomicToAtomic:
case CK_NoOp:
case CK_UserDefinedConversion:
return this->delegate(SubExpr);

case CK_BitCast:
if (CE->getType()->isAtomicType()) {
if (!this->discard(SubExpr))
return false;
return this->emitInvalidCast(CastKind::Reinterpret, CE);
}
return this->delegate(SubExpr);

case CK_IntegralToBoolean:
Expand Down
7 changes: 5 additions & 2 deletions clang/lib/AST/Interp/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -2020,8 +2020,11 @@ inline bool Invalid(InterpState &S, CodePtr OpPC) {
/// Same here, but only for casts.
inline bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind) {
const SourceLocation &Loc = S.Current->getLocation(OpPC);
S.FFDiag(Loc, diag::note_constexpr_invalid_cast)
<< static_cast<unsigned>(Kind) << S.Current->getRange(OpPC);

// FIXME: Support diagnosing other invalid cast kinds.
if (Kind == CastKind::Reinterpret)
S.FFDiag(Loc, diag::note_constexpr_invalid_cast)
<< static_cast<unsigned>(Kind) << S.Current->getRange(OpPC);
return false;
}

Expand Down
4 changes: 4 additions & 0 deletions clang/lib/AST/Interp/PrimType.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,17 @@ enum PrimType : unsigned {

enum class CastKind : uint8_t {
Reinterpret,
Atomic,
};
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
interp::CastKind CK) {
switch (CK) {
case interp::CastKind::Reinterpret:
OS << "reinterpret_cast";
break;
case interp::CastKind::Atomic:
OS << "atomic";
break;
}
return OS;
}
Expand Down
13 changes: 13 additions & 0 deletions clang/test/AST/Interp/atomic.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=both,expected %s
// RUN: %clang_cc1 -verify=both,ref %s

/// FIXME: Copied from test/Sema/atomic-expr.c.
/// this expression seems to be rejected for weird reasons,
/// but we imitate the current interpreter's behavior.
_Atomic int ai = 0;
// FIXME: &ai is an address constant, so this should be accepted as an
// initializer, but the bit-cast inserted due to the pointer conversion is
// tripping up the test for whether the initializer is a constant expression.
// The warning is correct but the error is not.
_Atomic(int *) aip3 = &ai; // both-warning {{incompatible pointer types initializing '_Atomic(int *)' with an expression of type '_Atomic(int) *'}} \
// both-error {{initializer element is not a compile-time constant}}
5 changes: 5 additions & 0 deletions clang/test/Sema/atomic-expr.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
// RUN: %clang_cc1 %s -std=c2x -verify=expected,access -fsyntax-only
// RUN: %clang_cc1 %s -std=c2x -pedantic -verify=expected,access -fsyntax-only
// RUN: %clang_cc1 %s -verify -fsyntax-only -Wno-atomic-access
// RUN: %clang_cc1 %s -verify=expected,access -fsyntax-only -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 %s -std=c2x -verify=expected,access -fsyntax-only -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 %s -std=c2x -pedantic -verify=expected,access -fsyntax-only -fexperimental-new-constant-interpreter
// RUN: %clang_cc1 %s -verify -fsyntax-only -Wno-atomic-access -fexperimental-new-constant-interpreter


_Atomic(unsigned int) data1;
int _Atomic data2;
Expand Down

0 comments on commit e4f1ef8

Please sign in to comment.