tbaeder created this revision.
tbaeder added reviewers: aaron.ballman, erichkeane, tahonermann, shafik.
Herald added a project: All.
tbaeder requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.
Add a new opcode doing the cast and emit a diagnostic in case we're in a
constant context.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D150946
Files:
clang/lib/AST/Interp/ByteCodeExprGen.cpp
clang/lib/AST/Interp/Interp.cpp
clang/lib/AST/Interp/Interp.h
clang/lib/AST/Interp/Opcodes.td
clang/lib/AST/Interp/Pointer.h
clang/test/AST/Interp/literals.cpp
Index: clang/test/AST/Interp/literals.cpp
===================================================================
--- clang/test/AST/Interp/literals.cpp
+++ clang/test/AST/Interp/literals.cpp
@@ -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}}
@@ -1008,3 +1010,15 @@
static_assert(heh(2) == 'h', "");
#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}}
+}
Index: clang/lib/AST/Interp/Pointer.h
===================================================================
--- clang/lib/AST/Interp/Pointer.h
+++ clang/lib/AST/Interp/Pointer.h
@@ -82,6 +82,10 @@
/// 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;
+ }
+
/// Converts the pointer to an APValue that is an rvalue.
APValue toRValue(const Context &Ctx) const;
Index: clang/lib/AST/Interp/Opcodes.td
===================================================================
--- clang/lib/AST/Interp/Opcodes.td
+++ clang/lib/AST/Interp/Opcodes.td
@@ -590,6 +590,12 @@
let HasGroup = 1;
}
+def CastPointerIntegral : Opcode {
+ let Types = [AluTypeClass];
+ let Args = [];
+ let HasGroup = 1;
+}
+
//===----------------------------------------------------------------------===//
// Comparison opcodes.
//===----------------------------------------------------------------------===//
Index: clang/lib/AST/Interp/Interp.h
===================================================================
--- clang/lib/AST/Interp/Interp.h
+++ clang/lib/AST/Interp/Interp.h
@@ -108,6 +108,10 @@
/// 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,
@@ -1571,6 +1575,17 @@
}
}
+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
//===----------------------------------------------------------------------===//
Index: clang/lib/AST/Interp/Interp.cpp
===================================================================
--- clang/lib/AST/Interp/Interp.cpp
+++ clang/lib/AST/Interp/Interp.cpp
@@ -519,6 +519,17 @@
return true;
}
+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 CastFP(InterpState &S, CodePtr OpPC, const llvm::fltSemantics *Sem,
llvm::RoundingMode RM) {
Floating F = S.Stk.pop<Floating>();
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -192,6 +192,15 @@
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:
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits