Fix an edge case of mangling involving the combination of a lambda and typeid.

typeid (and a couple other non-standard places where we can transform an
unevaluated expression into an evaluated expression) is special
because it introduces an an expression evaluation context,
which conflicts with the mechanism to compute the current
lambda mangling context.  PR12123.

I would appreciate if someone would double-check that we get the mangling
correct with this patch.

llvm-svn: 164658
This commit is contained in:
Eli Friedman 2012-09-26 04:34:21 +00:00
parent 81406f692f
commit 15681d6852
7 changed files with 46 additions and 7 deletions

View File

@ -2721,7 +2721,10 @@ public:
void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
Decl *LambdaContextDecl = 0,
bool IsDecltype = false);
enum ReuseLambdaContextDecl_t { ReuseLambdaContextDecl };
void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
ReuseLambdaContextDecl_t,
bool IsDecltype = false);
void PopExpressionEvaluationContext();
void DiscardCleanupsInEvaluationContext();
@ -7295,6 +7298,15 @@ public:
Actions.PushExpressionEvaluationContext(NewContext, LambdaContextDecl,
IsDecltype);
}
EnterExpressionEvaluationContext(Sema &Actions,
Sema::ExpressionEvaluationContext NewContext,
Sema::ReuseLambdaContextDecl_t,
bool IsDecltype = false)
: Actions(Actions) {
Actions.PushExpressionEvaluationContext(NewContext,
Sema::ReuseLambdaContextDecl,
IsDecltype);
}
~EnterExpressionEvaluationContext() {
Actions.PopExpressionEvaluationContext();

View File

@ -5078,7 +5078,8 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
const bool hasParens = Tok.is(tok::l_paren);
EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated,
Sema::ReuseLambdaContextDecl);
bool isCastExpr;
ParsedType CastTy;

View File

@ -1723,7 +1723,8 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
if (OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw__Alignof))
Diag(OpTok, diag::warn_cxx98_compat_alignof);
EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated,
Sema::ReuseLambdaContextDecl);
bool isCastExpr;
ParsedType CastTy;

View File

@ -1001,7 +1001,8 @@ ExprResult Parser::ParseCXXTypeid() {
// We enter the unevaluated context before trying to determine whether we
// have a type-id, because the tentative parse logic will try to resolve
// names, and must treat them as unevaluated.
EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated,
Sema::ReuseLambdaContextDecl);
if (isTypeIdInParens()) {
TypeResult Ty = ParseTypeName();

View File

@ -10135,6 +10135,14 @@ Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
std::swap(MaybeODRUseExprs, ExprEvalContexts.back().SavedMaybeODRUseExprs);
}
void
Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
ReuseLambdaContextDecl_t,
bool IsDecltype) {
Decl *LambdaContextDecl = ExprEvalContexts.back().LambdaContextDecl;
PushExpressionEvaluationContext(NewContext, LambdaContextDecl, IsDecltype);
}
void Sema::PopExpressionEvaluationContext() {
ExpressionEvaluationContextRecord& Rec = ExprEvalContexts.back();

View File

@ -4275,7 +4275,8 @@ template<typename Derived>
QualType TreeTransform<Derived>::TransformTypeOfExprType(TypeLocBuilder &TLB,
TypeOfExprTypeLoc TL) {
// typeof expressions are not potentially evaluated contexts
EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated,
Sema::ReuseLambdaContextDecl);
ExprResult E = getDerived().TransformExpr(TL.getUnderlyingExpr());
if (E.isInvalid())
@ -6266,7 +6267,8 @@ TreeTransform<Derived>::TransformUnaryExprOrTypeTraitExpr(
// C++0x [expr.sizeof]p1:
// The operand is either an expression, which is an unevaluated operand
// [...]
EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated,
Sema::ReuseLambdaContextDecl);
ExprResult SubExpr = getDerived().TransformExpr(E->getArgumentExpr());
if (SubExpr.isInvalid())
@ -7002,7 +7004,8 @@ TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E) {
// after we perform semantic analysis. We speculatively assume it is
// unevaluated; it will get fixed later if the subexpression is in fact
// potentially evaluated.
EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated,
Sema::ReuseLambdaContextDecl);
ExprResult SubExpr = getDerived().TransformExpr(E->getExprOperand());
if (SubExpr.isInvalid())

View File

@ -172,6 +172,19 @@ template<typename...T> int PR12917<T...>::n[3] = {
PR12917<int, char, double> pr12917;
int *pr12917_p = PR12917<int, int>::n;
namespace std {
struct type_info;
}
namespace PR12123 {
struct A { virtual ~A(); } g;
struct B {
void f(const std::type_info& x = typeid([]()->A& { return g; }()));
void h();
};
void B::h() { f(); }
}
// CHECK: define linkonce_odr %"struct.PR12123::A"* @_ZZN7PR121231B1fERKSt9type_infoEd_NKUlvE_clEv
namespace PR12808 {
template <typename> struct B {
int a;