Skip to content

Commit a50269e

Browse files
authored
[clang][bytecode] Diagnose dynamic_cast before C++20 (llvm#137442)
Emit a CCE diagnostic.
1 parent b81947e commit a50269e

File tree

5 files changed

+32
-2
lines changed

5 files changed

+32
-2
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3011,6 +3011,17 @@ bool Compiler<Emitter>::VisitCXXReinterpretCastExpr(
30113011
return this->VisitCastExpr(E);
30123012
}
30133013

3014+
template <class Emitter>
3015+
bool Compiler<Emitter>::VisitCXXDynamicCastExpr(const CXXDynamicCastExpr *E) {
3016+
3017+
if (!Ctx.getLangOpts().CPlusPlus20) {
3018+
if (!this->emitInvalidCast(CastKind::Dynamic, /*Fatal=*/false, E))
3019+
return false;
3020+
}
3021+
3022+
return this->VisitCastExpr(E);
3023+
}
3024+
30143025
template <class Emitter>
30153026
bool Compiler<Emitter>::VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) {
30163027
assert(E->getType()->isBooleanType());

clang/lib/AST/ByteCode/Compiler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,6 +180,7 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
180180
bool VisitPredefinedExpr(const PredefinedExpr *E);
181181
bool VisitCXXThrowExpr(const CXXThrowExpr *E);
182182
bool VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr *E);
183+
bool VisitCXXDynamicCastExpr(const CXXDynamicCastExpr *E);
183184
bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E);
184185
bool VisitCXXConstructExpr(const CXXConstructExpr *E);
185186
bool VisitSourceLocExpr(const SourceLocExpr *E);

clang/lib/AST/ByteCode/Interp.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2935,6 +2935,11 @@ inline bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind,
29352935
S.FFDiag(E);
29362936

29372937
return false;
2938+
} else if (Kind == CastKind::Dynamic) {
2939+
assert(!S.getLangOpts().CPlusPlus20);
2940+
S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_invalid_cast)
2941+
<< diag::ConstexprInvalidCastKind::Dynamic;
2942+
return true;
29382943
}
29392944

29402945
return false;

clang/lib/AST/ByteCode/PrimType.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ inline constexpr bool isPtrType(PrimType T) {
5656
enum class CastKind : uint8_t {
5757
Reinterpret,
5858
Volatile,
59+
Dynamic,
5960
};
6061

6162
inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
@@ -67,6 +68,9 @@ inline llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
6768
case interp::CastKind::Volatile:
6869
OS << "volatile";
6970
break;
71+
case interp::CastKind::Dynamic:
72+
OS << "dynamic";
73+
break;
7074
}
7175
return OS;
7276
}

clang/test/AST/ByteCode/cxx11-pedantic.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify=both,expected -std=c++11 -triple x86_64-linux -pedantic %s
2-
// RUN: %clang_cc1 -verify=both,ref -std=c++11 -triple x86_64-linux -pedantic %s
1+
// RUN: %clang_cc1 -verify=both,expected -std=c++11 -triple x86_64-linux -pedantic %s -fexperimental-new-constant-interpreter
2+
// RUN: %clang_cc1 -verify=both,ref -std=c++11 -triple x86_64-linux -pedantic %s
33

44
struct T { int n; };
55
const T t = { 42 }; // both-note 2{{declared here}}
@@ -11,3 +11,12 @@ struct S {
1111

1212
static_assert(t.n == 42, ""); // both-error {{expression is not an integral constant expression}} \
1313
// both-note {{read of non-constexpr variable 't' is not allowed}}
14+
15+
namespace DynamicCast {
16+
struct S { int n; };
17+
constexpr S s { 16 };
18+
struct T {
19+
int n : dynamic_cast<const S*>(&s)->n; // both-warning {{constant expression}} \
20+
// both-note {{dynamic_cast}}
21+
};
22+
}

0 commit comments

Comments
 (0)