[PATCH] D153276: [clang][Interp] Reject reinterpret_cast expressions
This revision was landed with ongoing or failed builds. This revision was automatically updated to reflect the committed changes. Closed by commit rG8c0246c7f517: [clang][Interp] Reject reinterpret_casts (authored by tbaeder). Changed prior to commit: https://reviews.llvm.org/D153276?vs=533238&id=544246#toc Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D153276/new/ https://reviews.llvm.org/D153276 Files: clang/lib/AST/Interp/ByteCodeExprGen.cpp clang/lib/AST/Interp/ByteCodeExprGen.h clang/lib/AST/Interp/Disasm.cpp clang/lib/AST/Interp/Interp.h clang/lib/AST/Interp/Opcodes.td clang/lib/AST/Interp/PrimType.h clang/test/AST/Interp/unsupported.cpp Index: clang/test/AST/Interp/unsupported.cpp === --- clang/test/AST/Interp/unsupported.cpp +++ clang/test/AST/Interp/unsupported.cpp @@ -47,3 +47,11 @@ return 0; } } + +namespace Casts { + constexpr int a = reinterpret_cast(12); // expected-error {{must be initialized by a constant expression}} \ + // expected-note {{reinterpret_cast is not allowed}} \ + // ref-error {{must be initialized by a constant expression}} \ + // ref-note {{reinterpret_cast is not allowed}} + +} Index: clang/lib/AST/Interp/PrimType.h === --- clang/lib/AST/Interp/PrimType.h +++ clang/lib/AST/Interp/PrimType.h @@ -13,6 +13,7 @@ #ifndef LLVM_CLANG_AST_INTERP_TYPE_H #define LLVM_CLANG_AST_INTERP_TYPE_H +#include "llvm/Support/raw_ostream.h" #include #include #include @@ -42,6 +43,11 @@ PT_FnPtr, }; +enum class CastKind : uint8_t { + Reinterpret, +}; +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, interp::CastKind CK); + constexpr bool isIntegralType(PrimType T) { return T <= PT_Uint64; } /// Mapping from primitive types to their representation. Index: clang/lib/AST/Interp/Opcodes.td === --- clang/lib/AST/Interp/Opcodes.td +++ clang/lib/AST/Interp/Opcodes.td @@ -51,6 +51,7 @@ def ArgFltSemantics : ArgType { let Name = "const llvm::fltSemantics *"; } def ArgRoundingMode : ArgType { let Name = "llvm::RoundingMode"; } def ArgLETD: ArgType { let Name = "const LifetimeExtendedTemporaryDecl *"; } +def ArgCastKind : ArgType { let Name = "CastKind"; } //===--===// // Classes of types instructions operate on. @@ -604,3 +605,6 @@ // [] -> [] def Invalid : Opcode {} +def InvalidCast : Opcode { + let Args = [ArgCastKind]; +} Index: clang/lib/AST/Interp/Interp.h === --- clang/lib/AST/Interp/Interp.h +++ clang/lib/AST/Interp/Interp.h @@ -1754,6 +1754,14 @@ return false; } +/// 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(Kind) << S.Current->getRange(OpPC); + return false; +} + //===--===// // Read opcode arguments //===--===// Index: clang/lib/AST/Interp/Disasm.cpp === --- clang/lib/AST/Interp/Disasm.cpp +++ clang/lib/AST/Interp/Disasm.cpp @@ -73,3 +73,12 @@ Anon->dump(); } } + +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, interp::CastKind CK) { + switch (CK) { + case interp::CastKind::Reinterpret: +OS << "reinterpret_cast"; +break; + } + return OS; +} Index: clang/lib/AST/Interp/ByteCodeExprGen.h === --- clang/lib/AST/Interp/ByteCodeExprGen.h +++ clang/lib/AST/Interp/ByteCodeExprGen.h @@ -98,6 +98,7 @@ bool VisitLambdaExpr(const LambdaExpr *E); bool VisitPredefinedExpr(const PredefinedExpr *E); bool VisitCXXThrowExpr(const CXXThrowExpr *E); + bool VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr *E); protected: bool visitExpr(const Expr *E) override; Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp === --- clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -997,6 +997,15 @@ return this->emitInvalid(E); } +template +bool ByteCodeExprGen::VisitCXXReinterpretCastExpr( +const CXXReinterpretCastExpr *E) { + if (!this->discard(E->getSubExpr())) +return false; + + return this->emitInvalidCast(CastKind::Reinterpret, E); +} + template bool ByteCodeExprGen::discard(const Expr *E) { if (E->containsErrors()) return fa
[PATCH] D153276: [clang][Interp] Reject reinterpret_cast expressions
jplehr added a comment. Hi, this seems to have broken the OpenMP AMDGPU buildbot (https://lab.llvm.org/buildbot/#/builders/193/builds/35471) I'm happy to help if needed. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D153276/new/ https://reviews.llvm.org/D153276 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D153276: [clang][Interp] Reject reinterpret_cast expressions
tbaeder added a comment. Yeah sorry about that, but should already be fixed by https://github.com/llvm/llvm-project/commit/47446939e0e60cf52ffdd3fa671949ff3183a4c Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D153276/new/ https://reviews.llvm.org/D153276 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D153276: [clang][Interp] Reject reinterpret_cast expressions
jplehr added a comment. Wow, thanks for the quick fix! Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D153276/new/ https://reviews.llvm.org/D153276 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D153276: [clang][Interp] Reject reinterpret_cast expressions
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 `InvalidCast` op for this purpose and emit a diagnostic. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D153276 Files: clang/lib/AST/Interp/ByteCodeExprGen.cpp clang/lib/AST/Interp/ByteCodeExprGen.h clang/lib/AST/Interp/Disasm.cpp clang/lib/AST/Interp/Interp.h clang/lib/AST/Interp/Opcodes.td clang/lib/AST/Interp/PrimType.h clang/test/AST/Interp/unsupported.cpp Index: clang/test/AST/Interp/unsupported.cpp === --- clang/test/AST/Interp/unsupported.cpp +++ clang/test/AST/Interp/unsupported.cpp @@ -47,3 +47,11 @@ return 0; } } + +namespace Casts { + constexpr int a = reinterpret_cast(12); // expected-error {{must be initialized by a constant expression}} \ + // expected-note {{reinterpret_cast is not allowed}} \ + // ref-error {{must be initialized by a constant expression}} \ + // ref-note {{reinterpret_cast is not allowed}} + +} Index: clang/lib/AST/Interp/PrimType.h === --- clang/lib/AST/Interp/PrimType.h +++ clang/lib/AST/Interp/PrimType.h @@ -13,6 +13,7 @@ #ifndef LLVM_CLANG_AST_INTERP_TYPE_H #define LLVM_CLANG_AST_INTERP_TYPE_H +#include "llvm/Support/raw_ostream.h" #include #include #include @@ -42,6 +43,12 @@ PT_FnPtr, }; +enum class CastKind : uint8_t { + Reinterpret, + Dynamic, +}; +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, interp::CastKind CK); + constexpr bool isIntegralType(PrimType T) { return T <= PT_Uint64; } /// Mapping from primitive types to their representation. Index: clang/lib/AST/Interp/Opcodes.td === --- clang/lib/AST/Interp/Opcodes.td +++ clang/lib/AST/Interp/Opcodes.td @@ -51,6 +51,7 @@ def ArgFltSemantics : ArgType { let Name = "const llvm::fltSemantics *"; } def ArgRoundingMode : ArgType { let Name = "llvm::RoundingMode"; } def ArgLETD: ArgType { let Name = "const LifetimeExtendedTemporaryDecl *"; } +def ArgCastKind : ArgType { let Name = "CastKind"; } //===--===// // Classes of types instructions operate on. @@ -636,3 +637,6 @@ // [] -> [] def Invalid : Opcode {} +def InvalidCast : Opcode { + let Args = [ArgCastKind]; +} Index: clang/lib/AST/Interp/Interp.h === --- clang/lib/AST/Interp/Interp.h +++ clang/lib/AST/Interp/Interp.h @@ -1847,6 +1847,14 @@ return false; } +/// 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(Kind) << S.Current->getRange(OpPC); + return false; +} + //===--===// // Read opcode arguments //===--===// Index: clang/lib/AST/Interp/Disasm.cpp === --- clang/lib/AST/Interp/Disasm.cpp +++ clang/lib/AST/Interp/Disasm.cpp @@ -73,3 +73,15 @@ Anon->dump(); } } + +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, interp::CastKind CK) { + switch (CK) { + case interp::CastKind::Reinterpret: +OS << "reinterpret_cast"; +break; + case interp::CastKind::Dynamic: +OS << "dynamic_cast"; +break; + } + return OS; +} Index: clang/lib/AST/Interp/ByteCodeExprGen.h === --- clang/lib/AST/Interp/ByteCodeExprGen.h +++ clang/lib/AST/Interp/ByteCodeExprGen.h @@ -98,6 +98,7 @@ bool VisitLambdaExpr(const LambdaExpr *E); bool VisitPredefinedExpr(const PredefinedExpr *E); bool VisitCXXThrowExpr(const CXXThrowExpr *E); + bool VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr *E); protected: bool visitExpr(const Expr *E) override; Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp === --- clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -1115,6 +1115,15 @@ return this->emitInvalid(E); } +template +bool ByteCodeExprGen::VisitCXXReinterpretCastExpr( +const CXXReinterpretCastExpr *E) { + if (!this->discard(E->getSubExpr())) +return false; + + return this->emitInvalidCast(CastKind::Reinterpret, E); +} + template bool ByteCodeExprGen::discard(const Expr *E) { if (E->contains
[PATCH] D153276: [clang][Interp] Reject reinterpret_cast expressions
aaron.ballman added inline comments. Comment at: clang/lib/AST/Interp/Interp.h:1854 + S.FFDiag(Loc, diag::note_constexpr_invalid_cast) + << static_cast(Kind) << S.Current->getRange(OpPC); + return false; Should this be doing the cast? The overloaded operator accepts an `interp::CastKind` already? Comment at: clang/lib/AST/Interp/PrimType.h:48 + Reinterpret, + Dynamic, +}; Should we bother adding this right now given it's not used or tested? Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D153276/new/ https://reviews.llvm.org/D153276 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D153276: [clang][Interp] Reject reinterpret_cast expressions
tbaeder added inline comments. Comment at: clang/lib/AST/Interp/Interp.h:1854 + S.FFDiag(Loc, diag::note_constexpr_invalid_cast) + << static_cast(Kind) << S.Current->getRange(OpPC); + return false; aaron.ballman wrote: > Should this be doing the cast? The overloaded operator accepts an > `interp::CastKind` already? The streaming operator there is for our `dump()` support, and the `note_constexpr_invalid_cast` diagnostic needs an integer to select the right string. Comment at: clang/lib/AST/Interp/PrimType.h:48 + Reinterpret, + Dynamic, +}; aaron.ballman wrote: > Should we bother adding this right now given it's not used or tested? No strong opinion from my side, I can definitely remove it. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D153276/new/ https://reviews.llvm.org/D153276 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D153276: [clang][Interp] Reject reinterpret_cast expressions
aaron.ballman accepted this revision. aaron.ballman added a comment. This revision is now accepted and ready to land. LGTM with the Dynamic bit pulled. Comment at: clang/lib/AST/Interp/Interp.h:1854 + S.FFDiag(Loc, diag::note_constexpr_invalid_cast) + << static_cast(Kind) << S.Current->getRange(OpPC); + return false; tbaeder wrote: > aaron.ballman wrote: > > Should this be doing the cast? The overloaded operator accepts an > > `interp::CastKind` already? > The streaming operator there is for our `dump()` support, and the > `note_constexpr_invalid_cast` diagnostic needs an integer to select the right > string. Ah, that's right, this isn't calling the diagnostic streaming operator. Nevermind. :-) Comment at: clang/lib/AST/Interp/PrimType.h:48 + Reinterpret, + Dynamic, +}; tbaeder wrote: > aaron.ballman wrote: > > Should we bother adding this right now given it's not used or tested? > No strong opinion from my side, I can definitely remove it. Let's yank it for the moment. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D153276/new/ https://reviews.llvm.org/D153276 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D153276: [clang][Interp] Reject reinterpret_cast expressions
tbaeder updated this revision to Diff 533238. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D153276/new/ https://reviews.llvm.org/D153276 Files: clang/lib/AST/Interp/ByteCodeExprGen.cpp clang/lib/AST/Interp/ByteCodeExprGen.h clang/lib/AST/Interp/Disasm.cpp clang/lib/AST/Interp/Interp.h clang/lib/AST/Interp/Opcodes.td clang/lib/AST/Interp/PrimType.h clang/test/AST/Interp/unsupported.cpp Index: clang/test/AST/Interp/unsupported.cpp === --- clang/test/AST/Interp/unsupported.cpp +++ clang/test/AST/Interp/unsupported.cpp @@ -47,3 +47,11 @@ return 0; } } + +namespace Casts { + constexpr int a = reinterpret_cast(12); // expected-error {{must be initialized by a constant expression}} \ + // expected-note {{reinterpret_cast is not allowed}} \ + // ref-error {{must be initialized by a constant expression}} \ + // ref-note {{reinterpret_cast is not allowed}} + +} Index: clang/lib/AST/Interp/PrimType.h === --- clang/lib/AST/Interp/PrimType.h +++ clang/lib/AST/Interp/PrimType.h @@ -13,6 +13,7 @@ #ifndef LLVM_CLANG_AST_INTERP_TYPE_H #define LLVM_CLANG_AST_INTERP_TYPE_H +#include "llvm/Support/raw_ostream.h" #include #include #include @@ -42,6 +43,11 @@ PT_FnPtr, }; +enum class CastKind : uint8_t { + Reinterpret, +}; +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, interp::CastKind CK); + constexpr bool isIntegralType(PrimType T) { return T <= PT_Uint64; } /// Mapping from primitive types to their representation. Index: clang/lib/AST/Interp/Opcodes.td === --- clang/lib/AST/Interp/Opcodes.td +++ clang/lib/AST/Interp/Opcodes.td @@ -51,6 +51,7 @@ def ArgFltSemantics : ArgType { let Name = "const llvm::fltSemantics *"; } def ArgRoundingMode : ArgType { let Name = "llvm::RoundingMode"; } def ArgLETD: ArgType { let Name = "const LifetimeExtendedTemporaryDecl *"; } +def ArgCastKind : ArgType { let Name = "CastKind"; } //===--===// // Classes of types instructions operate on. @@ -636,3 +637,6 @@ // [] -> [] def Invalid : Opcode {} +def InvalidCast : Opcode { + let Args = [ArgCastKind]; +} Index: clang/lib/AST/Interp/Interp.h === --- clang/lib/AST/Interp/Interp.h +++ clang/lib/AST/Interp/Interp.h @@ -1849,6 +1849,14 @@ return false; } +/// 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(Kind) << S.Current->getRange(OpPC); + return false; +} + //===--===// // Read opcode arguments //===--===// Index: clang/lib/AST/Interp/Disasm.cpp === --- clang/lib/AST/Interp/Disasm.cpp +++ clang/lib/AST/Interp/Disasm.cpp @@ -73,3 +73,15 @@ Anon->dump(); } } + +llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, interp::CastKind CK) { + switch (CK) { + case interp::CastKind::Reinterpret: +OS << "reinterpret_cast"; +break; + case interp::CastKind::Dynamic: +OS << "dynamic_cast"; +break; + } + return OS; +} Index: clang/lib/AST/Interp/ByteCodeExprGen.h === --- clang/lib/AST/Interp/ByteCodeExprGen.h +++ clang/lib/AST/Interp/ByteCodeExprGen.h @@ -98,6 +98,7 @@ bool VisitLambdaExpr(const LambdaExpr *E); bool VisitPredefinedExpr(const PredefinedExpr *E); bool VisitCXXThrowExpr(const CXXThrowExpr *E); + bool VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr *E); protected: bool visitExpr(const Expr *E) override; Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp === --- clang/lib/AST/Interp/ByteCodeExprGen.cpp +++ clang/lib/AST/Interp/ByteCodeExprGen.cpp @@ -1113,6 +1113,15 @@ return this->emitInvalid(E); } +template +bool ByteCodeExprGen::VisitCXXReinterpretCastExpr( +const CXXReinterpretCastExpr *E) { + if (!this->discard(E->getSubExpr())) +return false; + + return this->emitInvalidCast(CastKind::Reinterpret, E); +} + template bool ByteCodeExprGen::discard(const Expr *E) { if (E->containsErrors()) return false; ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D153276: [clang][Interp] Reject reinterpret_cast expressions
probinson added inline comments. Comment at: clang/lib/AST/Interp/Interp.h:1761 + S.FFDiag(Loc, diag::note_constexpr_invalid_cast) + << static_cast(Kind) << S.Current->getRange(OpPC); + return false; Would you mind changing this cast from `uint8_t` to `unsigned`? We have an internal bot using a pickier mode of MSVC and it complains about ambiguous overloads, as the `operator<<` doesn't have anything smaller than `int` and `unsigned`. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D153276/new/ https://reviews.llvm.org/D153276 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D153276: [clang][Interp] Reject reinterpret_cast expressions
tbaeder added inline comments. Comment at: clang/lib/AST/Interp/Interp.h:1761 + S.FFDiag(Loc, diag::note_constexpr_invalid_cast) + << static_cast(Kind) << S.Current->getRange(OpPC); + return false; probinson wrote: > Would you mind changing this cast from `uint8_t` to `unsigned`? We have an > internal bot using a pickier mode of MSVC and it complains about ambiguous > overloads, as the `operator<<` doesn't have anything smaller than `int` and > `unsigned`. Feel free to push that change, I'm currently working on something else. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D153276/new/ https://reviews.llvm.org/D153276 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D153276: [clang][Interp] Reject reinterpret_cast expressions
aaron.ballman added inline comments. Comment at: clang/lib/AST/Interp/Interp.h:1761 + S.FFDiag(Loc, diag::note_constexpr_invalid_cast) + << static_cast(Kind) << S.Current->getRange(OpPC); + return false; tbaeder wrote: > probinson wrote: > > Would you mind changing this cast from `uint8_t` to `unsigned`? We have an > > internal bot using a pickier mode of MSVC and it complains about ambiguous > > overloads, as the `operator<<` doesn't have anything smaller than `int` and > > `unsigned`. > Feel free to push that change, I'm currently working on something else. Yeah, that's a perfectly reasonable NFC commit to make -- go for it! Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D153276/new/ https://reviews.llvm.org/D153276 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[PATCH] D153276: [clang][Interp] Reject reinterpret_cast expressions
probinson added inline comments. Comment at: clang/lib/AST/Interp/Interp.h:1761 + S.FFDiag(Loc, diag::note_constexpr_invalid_cast) + << static_cast(Kind) << S.Current->getRange(OpPC); + return false; aaron.ballman wrote: > tbaeder wrote: > > probinson wrote: > > > Would you mind changing this cast from `uint8_t` to `unsigned`? We have > > > an internal bot using a pickier mode of MSVC and it complains about > > > ambiguous overloads, as the `operator<<` doesn't have anything smaller > > > than `int` and `unsigned`. > > Feel free to push that change, I'm currently working on something else. > Yeah, that's a perfectly reasonable NFC commit to make -- go for it! https://github.com/llvm/llvm-project/commit/4e8cae4aec6590ca13ec65ed38d6da55c6031755 Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D153276/new/ https://reviews.llvm.org/D153276 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits