forked from OSchip/llvm-project
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:
parent
81406f692f
commit
15681d6852
|
@ -2721,7 +2721,10 @@ public:
|
||||||
void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
|
void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
|
||||||
Decl *LambdaContextDecl = 0,
|
Decl *LambdaContextDecl = 0,
|
||||||
bool IsDecltype = false);
|
bool IsDecltype = false);
|
||||||
|
enum ReuseLambdaContextDecl_t { ReuseLambdaContextDecl };
|
||||||
|
void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
|
||||||
|
ReuseLambdaContextDecl_t,
|
||||||
|
bool IsDecltype = false);
|
||||||
void PopExpressionEvaluationContext();
|
void PopExpressionEvaluationContext();
|
||||||
|
|
||||||
void DiscardCleanupsInEvaluationContext();
|
void DiscardCleanupsInEvaluationContext();
|
||||||
|
@ -7295,6 +7298,15 @@ public:
|
||||||
Actions.PushExpressionEvaluationContext(NewContext, LambdaContextDecl,
|
Actions.PushExpressionEvaluationContext(NewContext, LambdaContextDecl,
|
||||||
IsDecltype);
|
IsDecltype);
|
||||||
}
|
}
|
||||||
|
EnterExpressionEvaluationContext(Sema &Actions,
|
||||||
|
Sema::ExpressionEvaluationContext NewContext,
|
||||||
|
Sema::ReuseLambdaContextDecl_t,
|
||||||
|
bool IsDecltype = false)
|
||||||
|
: Actions(Actions) {
|
||||||
|
Actions.PushExpressionEvaluationContext(NewContext,
|
||||||
|
Sema::ReuseLambdaContextDecl,
|
||||||
|
IsDecltype);
|
||||||
|
}
|
||||||
|
|
||||||
~EnterExpressionEvaluationContext() {
|
~EnterExpressionEvaluationContext() {
|
||||||
Actions.PopExpressionEvaluationContext();
|
Actions.PopExpressionEvaluationContext();
|
||||||
|
|
|
@ -5078,7 +5078,8 @@ void Parser::ParseTypeofSpecifier(DeclSpec &DS) {
|
||||||
|
|
||||||
const bool hasParens = Tok.is(tok::l_paren);
|
const bool hasParens = Tok.is(tok::l_paren);
|
||||||
|
|
||||||
EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
|
EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated,
|
||||||
|
Sema::ReuseLambdaContextDecl);
|
||||||
|
|
||||||
bool isCastExpr;
|
bool isCastExpr;
|
||||||
ParsedType CastTy;
|
ParsedType CastTy;
|
||||||
|
|
|
@ -1723,7 +1723,8 @@ ExprResult Parser::ParseUnaryExprOrTypeTraitExpression() {
|
||||||
if (OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw__Alignof))
|
if (OpTok.is(tok::kw_alignof) || OpTok.is(tok::kw__Alignof))
|
||||||
Diag(OpTok, diag::warn_cxx98_compat_alignof);
|
Diag(OpTok, diag::warn_cxx98_compat_alignof);
|
||||||
|
|
||||||
EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
|
EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated,
|
||||||
|
Sema::ReuseLambdaContextDecl);
|
||||||
|
|
||||||
bool isCastExpr;
|
bool isCastExpr;
|
||||||
ParsedType CastTy;
|
ParsedType CastTy;
|
||||||
|
|
|
@ -1001,7 +1001,8 @@ ExprResult Parser::ParseCXXTypeid() {
|
||||||
// We enter the unevaluated context before trying to determine whether we
|
// We enter the unevaluated context before trying to determine whether we
|
||||||
// have a type-id, because the tentative parse logic will try to resolve
|
// have a type-id, because the tentative parse logic will try to resolve
|
||||||
// names, and must treat them as unevaluated.
|
// names, and must treat them as unevaluated.
|
||||||
EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated);
|
EnterExpressionEvaluationContext Unevaluated(Actions, Sema::Unevaluated,
|
||||||
|
Sema::ReuseLambdaContextDecl);
|
||||||
|
|
||||||
if (isTypeIdInParens()) {
|
if (isTypeIdInParens()) {
|
||||||
TypeResult Ty = ParseTypeName();
|
TypeResult Ty = ParseTypeName();
|
||||||
|
|
|
@ -10135,6 +10135,14 @@ Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
|
||||||
std::swap(MaybeODRUseExprs, ExprEvalContexts.back().SavedMaybeODRUseExprs);
|
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() {
|
void Sema::PopExpressionEvaluationContext() {
|
||||||
ExpressionEvaluationContextRecord& Rec = ExprEvalContexts.back();
|
ExpressionEvaluationContextRecord& Rec = ExprEvalContexts.back();
|
||||||
|
|
||||||
|
|
|
@ -4275,7 +4275,8 @@ template<typename Derived>
|
||||||
QualType TreeTransform<Derived>::TransformTypeOfExprType(TypeLocBuilder &TLB,
|
QualType TreeTransform<Derived>::TransformTypeOfExprType(TypeLocBuilder &TLB,
|
||||||
TypeOfExprTypeLoc TL) {
|
TypeOfExprTypeLoc TL) {
|
||||||
// typeof expressions are not potentially evaluated contexts
|
// 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());
|
ExprResult E = getDerived().TransformExpr(TL.getUnderlyingExpr());
|
||||||
if (E.isInvalid())
|
if (E.isInvalid())
|
||||||
|
@ -6266,7 +6267,8 @@ TreeTransform<Derived>::TransformUnaryExprOrTypeTraitExpr(
|
||||||
// C++0x [expr.sizeof]p1:
|
// C++0x [expr.sizeof]p1:
|
||||||
// The operand is either an expression, which is an unevaluated operand
|
// 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());
|
ExprResult SubExpr = getDerived().TransformExpr(E->getArgumentExpr());
|
||||||
if (SubExpr.isInvalid())
|
if (SubExpr.isInvalid())
|
||||||
|
@ -7002,7 +7004,8 @@ TreeTransform<Derived>::TransformCXXTypeidExpr(CXXTypeidExpr *E) {
|
||||||
// after we perform semantic analysis. We speculatively assume it is
|
// after we perform semantic analysis. We speculatively assume it is
|
||||||
// unevaluated; it will get fixed later if the subexpression is in fact
|
// unevaluated; it will get fixed later if the subexpression is in fact
|
||||||
// potentially evaluated.
|
// potentially evaluated.
|
||||||
EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated);
|
EnterExpressionEvaluationContext Unevaluated(SemaRef, Sema::Unevaluated,
|
||||||
|
Sema::ReuseLambdaContextDecl);
|
||||||
|
|
||||||
ExprResult SubExpr = getDerived().TransformExpr(E->getExprOperand());
|
ExprResult SubExpr = getDerived().TransformExpr(E->getExprOperand());
|
||||||
if (SubExpr.isInvalid())
|
if (SubExpr.isInvalid())
|
||||||
|
|
|
@ -172,6 +172,19 @@ template<typename...T> int PR12917<T...>::n[3] = {
|
||||||
PR12917<int, char, double> pr12917;
|
PR12917<int, char, double> pr12917;
|
||||||
int *pr12917_p = PR12917<int, int>::n;
|
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 {
|
namespace PR12808 {
|
||||||
template <typename> struct B {
|
template <typename> struct B {
|
||||||
int a;
|
int a;
|
||||||
|
|
Loading…
Reference in New Issue