Skip to content

Commit

Permalink
[clang][Interp] PointerToIntegral casts
Browse files Browse the repository at this point in the history
Differential Revision: https://reviews.llvm.org/D150946
  • Loading branch information
tbaederr committed Jul 26, 2023
1 parent c52ab9e commit ae4849f
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 0 deletions.
9 changes: 9 additions & 0 deletions clang/lib/AST/Interp/ByteCodeExprGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,15 @@ bool ByteCodeExprGen<Emitter>::VisitCastExpr(const CastExpr *CE) {
return true;
return this->emitNull(classifyPrim(CE->getType()), CE);

case CK_PointerToIntegral: {
// TODO: Discard handling.
if (!this->visit(SubExpr))
return false;

PrimType T = classifyPrim(CE->getType());
return this->emitCastPointerIntegral(T, CE);
}

case CK_ArrayToPointerDecay:
case CK_AtomicToNonAtomic:
case CK_ConstructorConversion:
Expand Down
11 changes: 11 additions & 0 deletions clang/lib/AST/Interp/Interp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -462,6 +462,17 @@ bool CheckCtorCall(InterpState &S, CodePtr OpPC, const Pointer &This) {
return CheckArrayInitialized(S, OpPC, This, CAT);
}

bool CheckPotentialReinterpretCast(InterpState &S, CodePtr OpPC,
const Pointer &Ptr) {
if (!S.inConstantContext())
return true;

const SourceInfo &E = S.Current->getSource(OpPC);
S.CCEDiag(E, diag::note_constexpr_invalid_cast)
<< 2 << S.getLangOpts().CPlusPlus;
return false;
}

bool CheckFloatResult(InterpState &S, CodePtr OpPC, APFloat::opStatus Status) {
// In a constant context, assume that any dynamic rounding mode or FP
// exception state matches the default floating-point environment.
Expand Down
15 changes: 15 additions & 0 deletions clang/lib/AST/Interp/Interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,10 @@ bool CheckPure(InterpState &S, CodePtr OpPC, const CXXMethodDecl *MD);
/// Checks that all fields are initialized after a constructor call.
bool CheckCtorCall(InterpState &S, CodePtr OpPC, const Pointer &This);

/// Checks if reinterpret casts are legal in the current context.
bool CheckPotentialReinterpretCast(InterpState &S, CodePtr OpPC,
const Pointer &Ptr);

/// Checks if the shift operation is legal.
template <typename LT, typename RT>
bool CheckShift(InterpState &S, CodePtr OpPC, const LT &LHS, const RT &RHS,
Expand Down Expand Up @@ -1493,6 +1497,17 @@ bool CastFloatingIntegral(InterpState &S, CodePtr OpPC) {
}
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool CastPointerIntegral(InterpState &S, CodePtr OpPC) {
const Pointer &Ptr = S.Stk.pop<Pointer>();

if (!CheckPotentialReinterpretCast(S, OpPC, Ptr))
return false;

S.Stk.push<T>(T::from(Ptr.getIntegerRepresentation()));
return true;
}

//===----------------------------------------------------------------------===//
// Zero, Nullptr
//===----------------------------------------------------------------------===//
Expand Down
6 changes: 6 additions & 0 deletions clang/lib/AST/Interp/Opcodes.td
Original file line number Diff line number Diff line change
Expand Up @@ -565,6 +565,12 @@ def CastFloatingIntegral : Opcode {
let HasGroup = 1;
}

def CastPointerIntegral : Opcode {
let Types = [AluTypeClass];
let Args = [];
let HasGroup = 1;
}

//===----------------------------------------------------------------------===//
// Comparison opcodes.
//===----------------------------------------------------------------------===//
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/AST/Interp/Pointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,13 @@ class Pointer {
/// Converts the pointer to an APValue.
APValue toAPValue() const;

/// Converts the pointer to a string usable in diagnostics.
std::string toDiagnosticString(const ASTContext &Ctx) const;

unsigned getIntegerRepresentation() const {
return reinterpret_cast<uintptr_t>(Pointee) + Offset;
}

/// Offsets a pointer inside an array.
Pointer atIndex(unsigned Idx) const {
if (Base == RootPtrMark)
Expand Down
14 changes: 14 additions & 0 deletions clang/test/AST/Interp/literals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
#define INT_MIN (~__INT_MAX__)
#define INT_MAX __INT_MAX__

typedef __INTPTR_TYPE__ intptr_t;


static_assert(true, "");
static_assert(false, ""); // expected-error{{failed}} ref-error{{failed}}
Expand Down Expand Up @@ -932,3 +934,15 @@ namespace NE {
static_assert(a() == 0, "");
#endif
}

namespace PointerCasts {
constexpr int M = 10;
constexpr const int *P = &M;
constexpr intptr_t A = (intptr_t)P; // ref-error {{must be initialized by a constant expression}} \
// ref-note {{cast that performs the conversions of a reinterpret_cast}} \
// expected-error {{must be initialized by a constant expression}} \
// expected-note {{cast that performs the conversions of a reinterpret_cast}}

int array[(long)(char*)0]; // ref-warning {{variable length array folded to constant array}} \
// expected-warning {{variable length array folded to constant array}}
}

0 comments on commit ae4849f

Please sign in to comment.