aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/ByteCode
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/ByteCode')
-rw-r--r--clang/lib/AST/ByteCode/Compiler.cpp22
-rw-r--r--clang/lib/AST/ByteCode/Compiler.h2
-rw-r--r--clang/lib/AST/ByteCode/Interp.h46
-rw-r--r--clang/lib/AST/ByteCode/Opcodes.td2
4 files changed, 52 insertions, 20 deletions
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index 20836f6..f68422c 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -209,19 +209,6 @@ private:
} // namespace clang
template <class Emitter>
-bool Compiler<Emitter>::isValidBitCast(const CastExpr *E) {
- QualType FromTy = E->getSubExpr()->getType()->getPointeeType();
- QualType ToTy = E->getType()->getPointeeType();
-
- if (classify(FromTy) == classify(ToTy))
- return true;
-
- if (FromTy->isVoidType() || ToTy->isVoidType())
- return true;
- return false;
-}
-
-template <class Emitter>
bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
const Expr *SubExpr = CE->getSubExpr();
@@ -506,12 +493,9 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
if (!FromT || !ToT)
return false;
- if (!this->isValidBitCast(CE) &&
- !this->emitInvalidCast(CastKind::ReinterpretLike, /*Fatal=*/false, CE))
- return false;
-
assert(isPtrType(*FromT));
assert(isPtrType(*ToT));
+ bool SrcIsVoidPtr = SubExprTy->isVoidPointerType();
if (FromT == ToT) {
if (CE->getType()->isVoidPointerType() &&
!SubExprTy->isFunctionPointerType()) {
@@ -520,6 +504,10 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) {
if (!this->visit(SubExpr))
return false;
+ if (!this->emitCheckBitCast(CETy->getPointeeType().getTypePtr(),
+ SrcIsVoidPtr, CE))
+ return false;
+
if (CE->getType()->isFunctionPointerType() ||
SubExprTy->isFunctionPointerType()) {
return this->emitFnPtrCast(CE);
diff --git a/clang/lib/AST/ByteCode/Compiler.h b/clang/lib/AST/ByteCode/Compiler.h
index fac0a7f..5c46f75 100644
--- a/clang/lib/AST/ByteCode/Compiler.h
+++ b/clang/lib/AST/ByteCode/Compiler.h
@@ -425,8 +425,6 @@ private:
bool refersToUnion(const Expr *E);
- bool isValidBitCast(const CastExpr *E);
-
protected:
/// Variable to storage mapping.
llvm::DenseMap<const ValueDecl *, Scope::Local> Locals;
diff --git a/clang/lib/AST/ByteCode/Interp.h b/clang/lib/AST/ByteCode/Interp.h
index c16408c..cbd60c9 100644
--- a/clang/lib/AST/ByteCode/Interp.h
+++ b/clang/lib/AST/ByteCode/Interp.h
@@ -3290,6 +3290,52 @@ inline bool SideEffect(InterpState &S, CodePtr OpPC) {
return S.noteSideEffect();
}
+inline bool CheckBitCast(InterpState &S, CodePtr OpPC, const Type *TargetType,
+ bool SrcIsVoidPtr) {
+ const auto &Ptr = S.Stk.peek<Pointer>();
+ if (Ptr.isZero())
+ return true;
+ if (!Ptr.isBlockPointer())
+ return true;
+
+ if (TargetType->isIntegerType())
+ return true;
+
+ if (SrcIsVoidPtr && S.getLangOpts().CPlusPlus) {
+ bool HasValidResult = !Ptr.isZero();
+
+ if (HasValidResult) {
+ if (S.getStdAllocatorCaller("allocate"))
+ return true;
+
+ const auto &E = cast<CastExpr>(S.Current->getExpr(OpPC));
+ if (S.getLangOpts().CPlusPlus26 &&
+ S.getASTContext().hasSimilarType(Ptr.getType(),
+ QualType(TargetType, 0)))
+ return true;
+
+ S.CCEDiag(E, diag::note_constexpr_invalid_void_star_cast)
+ << E->getSubExpr()->getType() << S.getLangOpts().CPlusPlus26
+ << Ptr.getType().getCanonicalType() << E->getType()->getPointeeType();
+ } else if (!S.getLangOpts().CPlusPlus26) {
+ const SourceInfo &E = S.Current->getSource(OpPC);
+ S.CCEDiag(E, diag::note_constexpr_invalid_cast)
+ << diag::ConstexprInvalidCastKind::CastFrom << "'void *'"
+ << S.Current->getRange(OpPC);
+ }
+ }
+
+ QualType PtrType = Ptr.getType();
+ if (PtrType->isRecordType() &&
+ PtrType->getAsRecordDecl() != TargetType->getAsRecordDecl()) {
+ S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_invalid_cast)
+ << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
+ << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
+ return false;
+ }
+ return true;
+}
+
/// Same here, but only for casts.
inline bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind,
bool Fatal) {
diff --git a/clang/lib/AST/ByteCode/Opcodes.td b/clang/lib/AST/ByteCode/Opcodes.td
index a2eaa61..1785fcf 100644
--- a/clang/lib/AST/ByteCode/Opcodes.td
+++ b/clang/lib/AST/ByteCode/Opcodes.td
@@ -422,8 +422,8 @@ def CheckLiteralType : Opcode {
}
def CheckArraySize : Opcode { let Args = [ArgUint64]; }
-
def CheckFunctionDecl : Opcode { let Args = [ArgFunctionDecl]; }
+def CheckBitCast : Opcode { let Args = [ArgTypePtr, ArgBool]; }
// [] -> [Value]
def GetGlobal : AccessOpcode;