comex created this revision.
comex added reviewers: rsmith, faisalv, Mordante.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

When first parsing a lambda expression, `BuildDeclRefExpr` is called on the 
parameter declarations with the lambda scope already pushed.  But when 
transforming a lambda expression as part of instantiating an outer template, 
`BuildDeclRefExpr` is called again without the scope pushed.  This causes 
`tryCaptureVariable` to get confused when a lambda parameter references an 
earlier parameter, e.g.:

  [](auto c, int x = sizeof(decltype(c))) {}

Fix this by moving up the call to `PushLambdaScope` in 
`TreeTransform::TransformLambdaExpr` to match 
`Parser::ParseLambdaExpressionAfterIntroducer`.

(Note: I do not have commit access.)


Repository:
  rC Clang

https://reviews.llvm.org/D66067

Files:
  clang/lib/Sema/TreeTransform.h
  clang/test/SemaTemplate/default-arguments-cxx0x.cpp


Index: clang/test/SemaTemplate/default-arguments-cxx0x.cpp
===================================================================
--- clang/test/SemaTemplate/default-arguments-cxx0x.cpp
+++ clang/test/SemaTemplate/default-arguments-cxx0x.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
 // expected-no-diagnostics
 
 // Test default template arguments for function templates.
@@ -114,3 +114,13 @@
     S<int> _a{};
   };
 }
+
+namespace lambda {
+template <class T>
+void bar() {
+  (void) [](auto c, int x = sizeof(decltype(c))) {};
+}
+void foo() {
+  bar<int>();
+}
+} // namespace lambda
Index: clang/lib/Sema/TreeTransform.h
===================================================================
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -11318,6 +11318,10 @@
     }
   }
 
+  LambdaScopeInfo *LSI = getSema().PushLambdaScope();
+  Sema::FunctionScopeRAII FuncScopeCleanup(getSema());
+  LSI->GLTemplateParameterList = TPL;
+
   // Transform the template parameters, and add them to the current
   // instantiation scope. The null case is handled correctly.
   auto TPL = getDerived().TransformTemplateParameterList(
@@ -11348,10 +11352,6 @@
                                                         NewCallOpType);
   }
 
-  LambdaScopeInfo *LSI = getSema().PushLambdaScope();
-  Sema::FunctionScopeRAII FuncScopeCleanup(getSema());
-  LSI->GLTemplateParameterList = TPL;
-
   // Create the local class that will describe the lambda.
   CXXRecordDecl *OldClass = E->getLambdaClass();
   CXXRecordDecl *Class


Index: clang/test/SemaTemplate/default-arguments-cxx0x.cpp
===================================================================
--- clang/test/SemaTemplate/default-arguments-cxx0x.cpp
+++ clang/test/SemaTemplate/default-arguments-cxx0x.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
 // expected-no-diagnostics
 
 // Test default template arguments for function templates.
@@ -114,3 +114,13 @@
     S<int> _a{};
   };
 }
+
+namespace lambda {
+template <class T>
+void bar() {
+  (void) [](auto c, int x = sizeof(decltype(c))) {};
+}
+void foo() {
+  bar<int>();
+}
+} // namespace lambda
Index: clang/lib/Sema/TreeTransform.h
===================================================================
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -11318,6 +11318,10 @@
     }
   }
 
+  LambdaScopeInfo *LSI = getSema().PushLambdaScope();
+  Sema::FunctionScopeRAII FuncScopeCleanup(getSema());
+  LSI->GLTemplateParameterList = TPL;
+
   // Transform the template parameters, and add them to the current
   // instantiation scope. The null case is handled correctly.
   auto TPL = getDerived().TransformTemplateParameterList(
@@ -11348,10 +11352,6 @@
                                                         NewCallOpType);
   }
 
-  LambdaScopeInfo *LSI = getSema().PushLambdaScope();
-  Sema::FunctionScopeRAII FuncScopeCleanup(getSema());
-  LSI->GLTemplateParameterList = TPL;
-
   // Create the local class that will describe the lambda.
   CXXRecordDecl *OldClass = E->getLambdaClass();
   CXXRecordDecl *Class
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to