mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-21 23:10:54 +00:00
[c++20] P1327R1: Support for typeid applied to objects of polymorphic
class type in constant evaluation. This reinstates r360977, reverted in r360987, now that its rerequisite patch is reinstated and fixed. llvm-svn: 361067
This commit is contained in:
parent
144291e14c
commit
a933030f84
@ -12,7 +12,8 @@ let Component = "AST" in {
|
||||
def note_expr_divide_by_zero : Note<"division by zero">;
|
||||
def note_constexpr_invalid_cast : Note<
|
||||
"%select{reinterpret_cast|dynamic_cast|cast that performs the conversions of"
|
||||
" a reinterpret_cast|cast from %1}0 is not allowed in a constant expression">;
|
||||
" a reinterpret_cast|cast from %1}0 is not allowed in a constant expression"
|
||||
"%select{| in C++ standards before C++2a||}0">;
|
||||
def note_constexpr_invalid_downcast : Note<
|
||||
"cannot cast object of dynamic type %0 to type %1">;
|
||||
def note_constexpr_overflow : Note<
|
||||
@ -31,12 +32,13 @@ def note_constexpr_invalid_inhctor : Note<
|
||||
def note_constexpr_no_return : Note<
|
||||
"control reached end of constexpr function">;
|
||||
def note_constexpr_virtual_call : Note<
|
||||
"cannot evaluate call to virtual function in a constant expression">;
|
||||
"cannot evaluate call to virtual function in a constant expression "
|
||||
"in C++ standards before C++2a">;
|
||||
def note_constexpr_pure_virtual_call : Note<
|
||||
"pure virtual function %q0 called">;
|
||||
def note_constexpr_polymorphic_unknown_dynamic_type : Note<
|
||||
"%select{||||virtual function called on|dynamic_cast applied to}0 "
|
||||
"object '%1' whose dynamic type is not constant">;
|
||||
"%select{||||virtual function called on|dynamic_cast applied to|"
|
||||
"typeid applied to}0 object '%1' whose dynamic type is not constant">;
|
||||
def note_constexpr_dynamic_cast_to_reference_failed : Note<
|
||||
"reference dynamic_cast failed: %select{"
|
||||
"static type %1 of operand is a non-public base class of dynamic type %2|"
|
||||
@ -90,7 +92,7 @@ def note_constexpr_var_init_non_constant : Note<
|
||||
"initializer of %0 is not a constant expression">;
|
||||
def note_constexpr_typeid_polymorphic : Note<
|
||||
"typeid applied to expression of polymorphic type %0 is "
|
||||
"not allowed in a constant expression">;
|
||||
"not allowed in a constant expression in C++ standards before C++2a">;
|
||||
def note_constexpr_void_comparison : Note<
|
||||
"comparison between unequal pointers to void has unspecified result">;
|
||||
def note_constexpr_temporary_here : Note<"temporary created here">;
|
||||
@ -108,11 +110,11 @@ def note_constexpr_this : Note<
|
||||
"evaluation of a call to a 'constexpr' member function">;
|
||||
def note_constexpr_lifetime_ended : Note<
|
||||
"%select{read of|assignment to|increment of|decrement of|member call on|"
|
||||
"dynamic_cast of}0 "
|
||||
"dynamic_cast of|typeid applied to}0 "
|
||||
"%select{temporary|variable}1 whose lifetime has ended">;
|
||||
def note_constexpr_access_uninit : Note<
|
||||
"%select{read of|assignment to|increment of|decrement of|member call on|"
|
||||
"dynamic_cast of}0 "
|
||||
"dynamic_cast of|typeid applied to}0 "
|
||||
"object outside its lifetime is not allowed in a constant expression">;
|
||||
def note_constexpr_use_uninit_reference : Note<
|
||||
"use of reference outside its lifetime "
|
||||
@ -139,30 +141,30 @@ def note_constexpr_ltor_incomplete_type : Note<
|
||||
"read of incomplete type %0 is not allowed in a constant expression">;
|
||||
def note_constexpr_access_null : Note<
|
||||
"%select{read of|assignment to|increment of|decrement of|member call on|"
|
||||
"dynamic_cast of}0 "
|
||||
"dynamic_cast of|typeid applied to}0 "
|
||||
"dereferenced null pointer is not allowed in a constant expression">;
|
||||
def note_constexpr_access_past_end : Note<
|
||||
"%select{read of|assignment to|increment of|decrement of|member call on|"
|
||||
"dynamic_cast of}0 "
|
||||
"dynamic_cast of|typeid applied to}0 "
|
||||
"dereferenced one-past-the-end pointer is not allowed in a constant expression">;
|
||||
def note_constexpr_access_unsized_array : Note<
|
||||
"%select{read of|assignment to|increment of|decrement of|member call on|"
|
||||
"dynamic_cast of}0 "
|
||||
"dynamic_cast of|typeid applied to}0 "
|
||||
"element of array without known bound "
|
||||
"is not allowed in a constant expression">;
|
||||
def note_constexpr_access_inactive_union_member : Note<
|
||||
"%select{read of|assignment to|increment of|decrement of|member call on|"
|
||||
"dynamic_cast of}0 "
|
||||
"dynamic_cast of|typeid applied to}0 "
|
||||
"member %1 of union with %select{active member %3|no active member}2 "
|
||||
"is not allowed in a constant expression">;
|
||||
def note_constexpr_access_static_temporary : Note<
|
||||
"%select{read of|assignment to|increment of|decrement of|member call on|"
|
||||
"dynamic_cast of}0 temporary "
|
||||
"dynamic_cast of|typeid applied to}0 temporary "
|
||||
"is not allowed in a constant expression outside the expression that "
|
||||
"created the temporary">;
|
||||
def note_constexpr_access_unreadable_object : Note<
|
||||
"%select{read of|assignment to|increment of|decrement of|member call on|"
|
||||
"dynamic_cast of}0 object '%1' whose value is not known">;
|
||||
"dynamic_cast of|typeid applied to}0 object '%1' whose value is not known">;
|
||||
def note_constexpr_modify_global : Note<
|
||||
"a constant expression cannot modify an object that is visible outside "
|
||||
"that expression">;
|
||||
|
@ -1349,6 +1349,7 @@ enum AccessKinds {
|
||||
AK_Decrement,
|
||||
AK_MemberCall,
|
||||
AK_DynamicCast,
|
||||
AK_TypeId,
|
||||
};
|
||||
|
||||
static bool isModification(AccessKinds AK) {
|
||||
@ -1356,6 +1357,7 @@ static bool isModification(AccessKinds AK) {
|
||||
case AK_Read:
|
||||
case AK_MemberCall:
|
||||
case AK_DynamicCast:
|
||||
case AK_TypeId:
|
||||
return false;
|
||||
case AK_Assign:
|
||||
case AK_Increment:
|
||||
@ -6034,19 +6036,33 @@ LValueExprEvaluator::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
|
||||
}
|
||||
|
||||
bool LValueExprEvaluator::VisitCXXTypeidExpr(const CXXTypeidExpr *E) {
|
||||
TypeInfoLValue TypeInfo;
|
||||
|
||||
if (!E->isPotentiallyEvaluated()) {
|
||||
TypeInfoLValue TypeInfo;
|
||||
if (E->isTypeOperand())
|
||||
TypeInfo = TypeInfoLValue(E->getTypeOperand(Info.Ctx).getTypePtr());
|
||||
else
|
||||
TypeInfo = TypeInfoLValue(E->getExprOperand()->getType().getTypePtr());
|
||||
return Success(APValue::LValueBase::getTypeInfo(TypeInfo, E->getType()));
|
||||
} else {
|
||||
if (!Info.Ctx.getLangOpts().CPlusPlus2a) {
|
||||
Info.CCEDiag(E, diag::note_constexpr_typeid_polymorphic)
|
||||
<< E->getExprOperand()->getType()
|
||||
<< E->getExprOperand()->getSourceRange();
|
||||
}
|
||||
|
||||
if (!Visit(E->getExprOperand()))
|
||||
return false;
|
||||
|
||||
Optional<DynamicType> DynType =
|
||||
ComputeDynamicType(Info, E, Result, AK_TypeId);
|
||||
if (!DynType)
|
||||
return false;
|
||||
|
||||
TypeInfo =
|
||||
TypeInfoLValue(Info.Ctx.getRecordType(DynType->Type).getTypePtr());
|
||||
}
|
||||
|
||||
Info.FFDiag(E, diag::note_constexpr_typeid_polymorphic)
|
||||
<< E->getExprOperand()->getType()
|
||||
<< E->getExprOperand()->getSourceRange();
|
||||
return false;
|
||||
return Success(APValue::LValueBase::getTypeInfo(TypeInfo, E->getType()));
|
||||
}
|
||||
|
||||
bool LValueExprEvaluator::VisitCXXUuidofExpr(const CXXUuidofExpr *E) {
|
||||
|
@ -2,6 +2,10 @@
|
||||
|
||||
#include "Inputs/std-compare.h"
|
||||
|
||||
namespace std {
|
||||
struct type_info;
|
||||
};
|
||||
|
||||
namespace ThreeWayComparison {
|
||||
struct A {
|
||||
int n;
|
||||
@ -354,3 +358,58 @@ namespace DynamicCast {
|
||||
// expected-note@+1 {{reference dynamic_cast failed: dynamic type 'DynamicCast::G' of operand does not have a base class of type 'DynamicCast::Unrelated'}}
|
||||
constexpr int e_unrelated = (dynamic_cast<Unrelated&>((E&)g), 0); // expected-error {{}}
|
||||
}
|
||||
|
||||
namespace TypeId {
|
||||
struct A {
|
||||
const std::type_info &ti = typeid(*this);
|
||||
};
|
||||
struct A2 : A {};
|
||||
static_assert(&A().ti == &typeid(A));
|
||||
static_assert(&typeid((A2())) == &typeid(A2));
|
||||
extern A2 extern_a2;
|
||||
static_assert(&typeid(extern_a2) == &typeid(A2));
|
||||
|
||||
constexpr A2 a2;
|
||||
constexpr const A &a1 = a2;
|
||||
static_assert(&typeid(a1) == &typeid(A));
|
||||
|
||||
struct B {
|
||||
virtual void f();
|
||||
const std::type_info &ti1 = typeid(*this);
|
||||
};
|
||||
struct B2 : B {
|
||||
const std::type_info &ti2 = typeid(*this);
|
||||
};
|
||||
static_assert(&B2().ti1 == &typeid(B));
|
||||
static_assert(&B2().ti2 == &typeid(B2));
|
||||
extern B2 extern_b2;
|
||||
// expected-note@+1 {{typeid applied to object 'extern_b2' whose dynamic type is not constant}}
|
||||
static_assert(&typeid(extern_b2) == &typeid(B2)); // expected-error {{constant expression}}
|
||||
|
||||
constexpr B2 b2;
|
||||
constexpr const B &b1 = b2;
|
||||
static_assert(&typeid(b1) == &typeid(B2));
|
||||
|
||||
constexpr bool side_effects() {
|
||||
// Not polymorphic nor a glvalue.
|
||||
bool OK = true;
|
||||
(void)typeid(OK = false, A2()); // expected-warning {{has no effect}}
|
||||
if (!OK) return false;
|
||||
|
||||
// Not polymorphic.
|
||||
A2 a2;
|
||||
(void)typeid(OK = false, a2); // expected-warning {{has no effect}}
|
||||
if (!OK) return false;
|
||||
|
||||
// Not a glvalue.
|
||||
(void)typeid(OK = false, B2()); // expected-warning {{has no effect}}
|
||||
if (!OK) return false;
|
||||
|
||||
// Polymorphic glvalue: operand evaluated.
|
||||
OK = false;
|
||||
B2 b2;
|
||||
(void)typeid(OK = true, b2); // expected-warning {{will be evaluated}}
|
||||
return OK;
|
||||
}
|
||||
static_assert(side_effects());
|
||||
}
|
||||
|
@ -973,10 +973,11 @@ as the draft C++2a standard evolves.
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="http://wg21.link/p1327r1">P1327R1</a></td>
|
||||
<td rowspan=2 class="none" align="center">No</td>
|
||||
<td class="svn" align="center">SVN</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><a href="http://wg21.link/p1330r0">P1330R0</a></td>
|
||||
<td class="none" align="center">No</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Prohibit aggregates with user-declared constructors</td>
|
||||
|
Loading…
Reference in New Issue
Block a user