<div dir="ltr">It looks like you're trying to evaluate a variable with a dependent type. I think that `evaluateValue` function is not intended for such variables. I think that it might be a good idea to put an assertion into that function that checks if the variables or its type is dependent, to complement the assertion for the dependent initializer in that function.<div><div><div><div><div class="gmail_extra"><br><div class="gmail_quote">On 5 July 2017 at 09:42, Serge Preis via cfe-dev <span dir="ltr"><<a href="mailto:cfe-dev@lists.llvm.org" target="_blank">cfe-dev@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-style:solid;border-left-color:rgb(204,204,204);padding-left:1ex">Hello,<br>
<br>
I encountered the following issue in lib/AST/ExprConstant.cpp:<br>
<br>
In function CheckConstantExpr there is a code:<br>
<br>
if (Value.isUnion() && Value.getUnionField()) {<br>
return CheckConstantExpression(Info, DiagLoc,<br>
Value.getUnionField()-><wbr>getType(),<br>
Value.getUnionValue());<br>
}<br>
if (Value.isStruct()) {<br>
RecordDecl *RD = Type->castAs<RecordType>()-><wbr>getDecl(); //// <<<<<< The problematic line<br>
if (const CXXRecordDecl *CD = dyn_cast<CXXRecordDecl>(RD)) {<br>
unsigned BaseIndex = 0;<br>
for (CXXRecordDecl::base_class_<wbr>const_iterator I = CD->bases_begin(),<br>
End = CD->bases_end(); I != End; ++I, ++BaseIndex) {<br>
if (!CheckConstantExpression(<wbr>Info, DiagLoc, I->getType(),<br>
Value.getStructBase(BaseIndex)<wbr>))<br>
return false;<br>
<br>
<br>
The problematic line causes a crash because Type cannot be cast to RecordType.<br>
<br>
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.<br>
I will definitely impelement workaround in my code, but I would also like to investingate and fix this issue in clang.<br>
<br>
Regards,<br>
Serge.<br>
<br>
<br>
----- useful info ----<br>
<br>
The code which triggering this behavior looks like the following:<br>
...<br>
template<class T><br>
void DoTestMax() {<br>
const T max = Max();<br>
...<br>
<br>
I am trying to access and print constant initializer for 'max' variable under following checks:<br>
} else if (auto* varDecl = llvm::dyn_cast<clang::VarDecl><wbr>(decl)) {<br>
if (!clang::isa<clang::<wbr>ParmVarDecl>(varDecl) && (varDecl->isConstexpr() || varDecl->getType().<wbr>isConstQualified())) {<br>
const clang::Expr* init = varDecl->getAnyInitializer();<br>
if (init != nullptr &&<br>
!init->getType().isNull() &&<br>
!init->isValueDependent() &&<br>
varDecl->ensureEvaluatedStmt() != nullptr &&<br>
varDecl->ensureEvaluatedStmt()<wbr>->Value != nullptr)<br>
{<br>
const clang::APValue* val = varDecl->evaluateValue(); /// <<< Problem is here<br>
<br>
The relevant stack for debug clang (trunk) looks like below:<br>
#3 0x00007ffff6bb2ca2 in __GI___assert_fail (assertion=0x2661ae0 "isa<X>(Val) && \"cast<Ty>() argument of incompatible type!\"", file=0x2661aa0 "/home/spreis/LLVM/latest/<wbr>llvm/include/llvm/Support/<wbr>Casting.h", line=241,<br>
function=0x2663de0 <std::enable_if<!llvm::is_<wbr>simple_type<clang::QualType>::<wbr>value, llvm::cast_retty<clang::<wbr>RecordType, clang::QualType const>::ret_type>::type llvm::cast<clang::RecordType, clang::QualType>(clang::<wbr>QualType const&)::__PRETTY_FUNCTION__> "typename std::enable_if<(! llvm::is_simple_type<Y>::<wbr>value), typename llvm::cast_retty<X, const Y>::ret_type>::type llvm::cast(const Y&) [with X = clang::RecordType; Y = clang::QualType; typename std::"...)<br>
at assert.c:101<br>
#4 0x00000000010cf75e in llvm::cast<clang::RecordType, clang::QualType> (Val=...)<br>
at /home/spreis/LLVM/latest/llvm/<wbr>include/llvm/Support/Casting.<wbr>h:241<br>
#5 0x00000000010ce4fa in clang::Type::castAs<clang::<wbr>RecordType> (this=0x554a880)<br>
at /home/spreis/LLVM/latest/llvm/<wbr>tools/clang/include/clang/AST/<wbr>TypeNodes.def:122<br>
#6 0x0000000001c0b810 in CheckConstantExpression (Info=..., DiagLoc=..., Type=..., Value=...)<br>
at /home/spreis/LLVM/latest/llvm/<wbr>tools/clang/lib/AST/<wbr>ExprConstant.cpp:1737<br>
#7 0x0000000001c2f1b0 in clang::Expr::<wbr>EvaluateAsInitializer (this=0x554ab50, Value=..., Ctx=..., VD=0x554a9d8, Notes=...)<br>
at /home/spreis/LLVM/latest/llvm/<wbr>tools/clang/lib/AST/<wbr>ExprConstant.cpp:10079<br>
#8 0x0000000001b923fa in clang::VarDecl::evaluateValue (this=0x554a9d8, Notes=...)<br>
at /home/spreis/LLVM/latest/llvm/<wbr>tools/clang/lib/AST/Decl.cpp:<wbr>2172<br>
#9 0x0000000001b9229c in clang::VarDecl::evaluateValue (this=0x554a9d8)<br>
at /home/spreis/LLVM/latest/llvm/<wbr>tools/clang/lib/AST/Decl.cpp:<wbr>2146<br>
<br>
The var:<br>
(gdb) frame 9<br>
2146 return evaluateValue(Notes);<br>
(gdb) call this->dump()<br>
VarDecl 0x554a9d8 <..snip..snip> referenced max 'const T' cinit<br>
`-CallExpr 0x554ab50 <col:23, col:27> '::NPrivate::TMax':'struct NPrivate::TMax'<br>
`-ImplicitCastExpr 0x554ab38 <col:23> '::NPrivate::TMax (*)(void) noexcept' <FunctionToPointerDecay><br>
`-DeclRefExpr 0x554aab8 <col:23> '::NPrivate::TMax (void) noexcept' lvalue Function 0x3f82c28 'Max' '::NPrivate::TMax (void) noexcept'<br>
<br>
The type:<br>
(gdb) frame 6<br>
1737 RecordDecl *RD = Type->castAs<RecordType>()-><wbr>getDecl();<br>
(gdb) call Type.dump()<br>
QualType 0x554a881 'const T' const<br>
`-TemplateTypeParmType 0x554a880 'T' dependent depth 0 index 0<br>
`-TemplateTypeParm 0x554a840 'T'<br>
<br>
______________________________<wbr>_________________<br>
cfe-dev mailing list<br>
<a href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-dev</a><br>
</blockquote></div><br></div></div></div></div></div></div>