[cfe-dev] CheckConstantExpression issue
Serge Preis via cfe-dev
cfe-dev at lists.llvm.org
Wed Jul 5 01:42:31 PDT 2017
Hello,
I encountered the following issue in lib/AST/ExprConstant.cpp:
In function CheckConstantExpr there is a code:
if (Value.isUnion() && Value.getUnionField()) {
return CheckConstantExpression(Info, DiagLoc,
Value.getUnionField()->getType(),
Value.getUnionValue());
}
if (Value.isStruct()) {
RecordDecl *RD = Type->castAs<RecordType>()->getDecl(); //// <<<<<< The problematic line
if (const CXXRecordDecl *CD = dyn_cast<CXXRecordDecl>(RD)) {
unsigned BaseIndex = 0;
for (CXXRecordDecl::base_class_const_iterator I = CD->bases_begin(),
End = CD->bases_end(); I != End; ++I, ++BaseIndex) {
if (!CheckConstantExpression(Info, DiagLoc, I->getType(),
Value.getStructBase(BaseIndex)))
return false;
The problematic line causes a crash because Type cannot be cast to RecordType.
This looks like an issue in clang to me, but the question is what's wrong: Value.isStruct() returning true for constant of template parameter type (see below) or absence of check for Type to be RecordType.
I will definitely impelement workaround in my code, but I would also like to investingate and fix this issue in clang.
Regards,
Serge.
----- useful info ----
The code which triggering this behavior looks like the following:
...
template<class T>
void DoTestMax() {
const T max = Max();
...
I am trying to access and print constant initializer for 'max' variable under following checks:
} else if (auto* varDecl = llvm::dyn_cast<clang::VarDecl>(decl)) {
if (!clang::isa<clang::ParmVarDecl>(varDecl) && (varDecl->isConstexpr() || varDecl->getType().isConstQualified())) {
const clang::Expr* init = varDecl->getAnyInitializer();
if (init != nullptr &&
!init->getType().isNull() &&
!init->isValueDependent() &&
varDecl->ensureEvaluatedStmt() != nullptr &&
varDecl->ensureEvaluatedStmt()->Value != nullptr)
{
const clang::APValue* val = varDecl->evaluateValue(); /// <<< Problem is here
The relevant stack for debug clang (trunk) looks like below:
#3 0x00007ffff6bb2ca2 in __GI___assert_fail (assertion=0x2661ae0 "isa<X>(Val) && \"cast<Ty>() argument of incompatible type!\"", file=0x2661aa0 "/home/spreis/LLVM/latest/llvm/include/llvm/Support/Casting.h", line=241,
function=0x2663de0 <std::enable_if<!llvm::is_simple_type<clang::QualType>::value, llvm::cast_retty<clang::RecordType, clang::QualType const>::ret_type>::type llvm::cast<clang::RecordType, clang::QualType>(clang::QualType const&)::__PRETTY_FUNCTION__> "typename std::enable_if<(! llvm::is_simple_type<Y>::value), typename llvm::cast_retty<X, const Y>::ret_type>::type llvm::cast(const Y&) [with X = clang::RecordType; Y = clang::QualType; typename std::"...)
at assert.c:101
#4 0x00000000010cf75e in llvm::cast<clang::RecordType, clang::QualType> (Val=...)
at /home/spreis/LLVM/latest/llvm/include/llvm/Support/Casting.h:241
#5 0x00000000010ce4fa in clang::Type::castAs<clang::RecordType> (this=0x554a880)
at /home/spreis/LLVM/latest/llvm/tools/clang/include/clang/AST/TypeNodes.def:122
#6 0x0000000001c0b810 in CheckConstantExpression (Info=..., DiagLoc=..., Type=..., Value=...)
at /home/spreis/LLVM/latest/llvm/tools/clang/lib/AST/ExprConstant.cpp:1737
#7 0x0000000001c2f1b0 in clang::Expr::EvaluateAsInitializer (this=0x554ab50, Value=..., Ctx=..., VD=0x554a9d8, Notes=...)
at /home/spreis/LLVM/latest/llvm/tools/clang/lib/AST/ExprConstant.cpp:10079
#8 0x0000000001b923fa in clang::VarDecl::evaluateValue (this=0x554a9d8, Notes=...)
at /home/spreis/LLVM/latest/llvm/tools/clang/lib/AST/Decl.cpp:2172
#9 0x0000000001b9229c in clang::VarDecl::evaluateValue (this=0x554a9d8)
at /home/spreis/LLVM/latest/llvm/tools/clang/lib/AST/Decl.cpp:2146
The var:
(gdb) frame 9
2146 return evaluateValue(Notes);
(gdb) call this->dump()
VarDecl 0x554a9d8 <..snip..snip> referenced max 'const T' cinit
`-CallExpr 0x554ab50 <col:23, col:27> '::NPrivate::TMax':'struct NPrivate::TMax'
`-ImplicitCastExpr 0x554ab38 <col:23> '::NPrivate::TMax (*)(void) noexcept' <FunctionToPointerDecay>
`-DeclRefExpr 0x554aab8 <col:23> '::NPrivate::TMax (void) noexcept' lvalue Function 0x3f82c28 'Max' '::NPrivate::TMax (void) noexcept'
The type:
(gdb) frame 6
1737 RecordDecl *RD = Type->castAs<RecordType>()->getDecl();
(gdb) call Type.dump()
QualType 0x554a881 'const T' const
`-TemplateTypeParmType 0x554a880 'T' dependent depth 0 index 0
`-TemplateTypeParm 0x554a840 'T'
More information about the cfe-dev
mailing list