]> granicus.if.org Git - clang/commitdiff
Fix an edge case of mangling involving the combination of a lambda and typeid.
authorEli Friedman <eli.friedman@gmail.com>
Wed, 26 Sep 2012 04:34:21 +0000 (04:34 +0000)
committerEli Friedman <eli.friedman@gmail.com>
Wed, 26 Sep 2012 04:34:21 +0000 (04:34 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@164658 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Sema/Sema.h
lib/Parse/ParseDecl.cpp
lib/Parse/ParseExpr.cpp
lib/Parse/ParseExprCXX.cpp
lib/Sema/SemaExpr.cpp
lib/Sema/TreeTransform.h
test/CodeGenCXX/mangle-lambdas.cpp

index 676f52953f376db33a69369a61c4f9599e9d9947..97d425ceaea26becb05055d63fb416b089d6ab1b 100644 (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();
index f8a20c3b532285a073493bbd1560172a5694a7e6..674cd2d22f06ecc53bb9d8319fa73717b7849b3e 100644 (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;
index 37cdd14407f8679b1ea9888eb19cfa96265d638e..90373920c5d1beff90e2ac06f16344f945e47158 100644 (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;
index 3039368cf7b84358263516164e19abb6b8f8ed08..41bf1b623f68a7baaf57c1bbd4b3ba233ca28f6f 100644 (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();
index 41985328bb769a1d3e3798c75dafb4a02271e23e..630281a42426d7ddc5e6f9f3afbc2de587460e33 100644 (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();
 
index 975895dc8e0cbabb1c8c791ace1476fb53901181..e0451c4c49f95ae88a8ef0596603e17f7a5f541f 100644 (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())
index 979760dab9117867dfb99146e2cb0ffc60137149..0bd5ad2a02ca962806d005811aa60dc74d335937 100644 (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;