[clang] Fix ICE with typeid & polymorphic class (pr50497)
authorNathan Sidwell <nathan@acm.org>
Thu, 27 May 2021 14:34:39 +0000 (07:34 -0700)
committerNathan Sidwell <nathan@acm.org>
Tue, 1 Jun 2021 19:55:29 +0000 (12:55 -0700)
commitc138f3ce5c70ff87a35d77e11f77a77d9d539b49
tree3dadf42e7d386c6d333e7dc0bd5d9a3cf5ea5c6f
parente9f82e9e1b6851ff66010a0e500346379b1ef572
[clang] Fix ICE with typeid & polymorphic class (pr50497)

This addresses pr50497. The argument of a typeid expression is
unevaluated, *except* when it's a polymorphic type. We handle this by
parsing as unevaluated and then transforming to evaluated if we
discover it should have been an evaluated context.

We do the same in TreeTransform<Derived>::TransformCXXTypeidExpr,
entering unevaluated context before transforming and rebuilding the
typeid. But that's incorrect and can lead us to converting to
evaluated context twice -- and hitting an assert.

During normal template instantiation we're always cloning the
expression, but during generic lambda processing we do not necessarily
AlwaysRebuild, and end up with TransformDeclRefExpr unconditionally
calling MarkDeclRefReferenced around line 10226. That triggers the
assert.

// Mark it referenced in the new context regardless.
// FIXME: this is a bit instantiation-specific.
SemaRef.MarkDeclRefReferenced(E);

This patch makes 2 changes.

a) TreeTransform<Derived>::TransformCXXTypeidExpr only enters
unevaluated context if the typeid's operand is not a polymorphic
glvalue. If it is, it keeps the same evaluation context.

b) Sema::BuildCXXTypeId is altered to only transform to evaluated, if
the current context is unevaluated.

Differential Revision: https://reviews.llvm.org/D103258
clang/lib/Sema/SemaExprCXX.cpp
clang/lib/Sema/TreeTransform.h
clang/test/SemaCXX/pr50497-crash-typeid.cpp [new file with mode: 0644]