]> granicus.if.org Git - clang/commitdiff
A quick fix to PR17877 that was introduced by r194188 (generic-lambda-capturing)...
authorFaisal Vali <faisalv@yahoo.com>
Tue, 12 Nov 2013 03:48:27 +0000 (03:48 +0000)
committerFaisal Vali <faisalv@yahoo.com>
Tue, 12 Nov 2013 03:48:27 +0000 (03:48 +0000)
See http://lists.cs.uiuc.edu/pipermail/cfe-dev/2013-November/033369.html for discussion on cfe-dev.

This fix explicitly checks whether we are within the declcontext of a lambda's call operator - which is what I had intended to be true (and assumed would be true if getCurLambda returns a valid pointer) before checking whether a lambda can capture the potential-captures of the innermost lambda.

A deeper fix (that addresses why getCurLambda() returns a valid pointer when perhaps it shouldn't?) - as proposed by Richard Smith in http://llvm.org/bugs/show_bug.cgi?id=17877 - has been suggested as a FIXME.

Patch was LGTM'd by Richard (just barely :)

http://llvm-reviews.chandlerc.com/D2144

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

lib/Sema/SemaExprCXX.cpp
test/SemaCXX/cxx1y-generic-lambdas.cpp

index 84220f7c9c70072eba5bed1769e3f939c9d1a3c0..e27bfd80505433f67a53d0ac1e4cd0e8f6371b2b 100644 (file)
@@ -5988,9 +5988,24 @@ ExprResult Sema::ActOnFinishFullExpr(Expr *FE, SourceLocation CC,
   //   full-expression +n + ({ 0; }); ends, but it's too late for us to see that 
   //   we need to capture n after all.
 
-  LambdaScopeInfo *const CurrentLSI = getCurLambda(); 
-  if (CurrentLSI && CurrentLSI->hasPotentialCaptures() && 
-      !FullExpr.isInvalid())
+  LambdaScopeInfo *const CurrentLSI = getCurLambda();
+  // FIXME: PR 17877 showed that getCurLambda() can return a valid pointer 
+  // even if CurContext is not a lambda call operator. Refer to that Bug Report
+  // for an example of the code that might cause this asynchrony.  
+  // By ensuring we are in the context of a lambda's call operator
+  // we can fix the bug (we only need to check whether we need to capture
+  // if we are within a lambda's body); but per the comments in that 
+  // PR, a proper fix would entail :
+  //   "Alternative suggestion:
+  //   - Add to Sema an integer holding the smallest (outermost) scope 
+  //     index that we are *lexically* within, and save/restore/set to 
+  //     FunctionScopes.size() in InstantiatingTemplate's 
+  //     constructor/destructor.
+  //  - Teach the handful of places that iterate over FunctionScopes to 
+  //    stop at the outermost enclosing lexical scope." 
+  const bool IsInLambdaDeclContext = isLambdaCallOperator(CurContext); 
+  if (IsInLambdaDeclContext && CurrentLSI && 
+      CurrentLSI->hasPotentialCaptures() && !FullExpr.isInvalid())
     CheckLambdaCaptures(FE, CurrentLSI, *this);
   return MaybeCreateExprWithCleanups(FullExpr);
 }
index 4d0e27ec1cd6dbe9586ab154b5ec337516a1a5ef..a8518a3a40b35677454edad8940d1c1c6c7533e8 100644 (file)
@@ -824,4 +824,25 @@ void finalizeDefaultAtomValues() {
 
 void f() { finalizeDefaultAtomValues<char>(); }
 
-} 
\ No newline at end of file
+} 
+
+namespace PR17877_lambda_declcontext_and_get_cur_lambda_disconnect {
+
+
+template<class T> struct U {
+  int t = 0;
+};
+
+template<class T>
+struct V { 
+  U<T> size() const { return U<T>{}; }
+};
+
+template<typename T>
+void Do() {
+  V<int> v{};
+  [=] { v.size(); };
+}
+
+
+}
\ No newline at end of file