]> granicus.if.org Git - clang/commitdiff
Handle errors in lambda prototype instantiation correctly
authorReid Kleckner <reid@kleckner.net>
Mon, 15 Dec 2014 21:07:16 +0000 (21:07 +0000)
committerReid Kleckner <reid@kleckner.net>
Mon, 15 Dec 2014 21:07:16 +0000 (21:07 +0000)
Previously we would attempt to build a TypeSourceInfo for a null type,
and then we would forget to pop the function scope before returning an
error.

Reviewers: rsmith

Differential Revision: http://reviews.llvm.org/D6665

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

include/clang/Sema/Sema.h
lib/Sema/TreeTransform.h
test/SemaCXX/lambda-expressions.cpp

index b0d9be449a4d3d9ccfe77d5250d21f5c8295fb37..a6010944aabb17460e2848754f411605f0cbca5f 100644 (file)
@@ -3107,6 +3107,18 @@ public:
     Sema &S;
   };
 
+  /// An RAII helper that pops function a function scope on exit.
+  struct FunctionScopeRAII {
+    Sema &S;
+    bool Active;
+    FunctionScopeRAII(Sema &S) : Active(true), S(S) {}
+    ~FunctionScopeRAII() {
+      if (Active)
+        S.PopFunctionScopeInfo();
+    }
+    void disable() { Active = false; }
+  };
+
   StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl,
                                    SourceLocation StartLoc,
                                    SourceLocation EndLoc);
index 295d208edfc5ad5692388d4afda749816cbb71bf..36abbb624af76fb143603db1c6009695d0fa99e4 100644 (file)
@@ -9121,6 +9121,8 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
   }
 
   LambdaScopeInfo *LSI = getSema().PushLambdaScope();
+  Sema::FunctionScopeRAII FuncScopeCleanup(getSema());
+
   // Transform the template parameters, and add them to the current
   // instantiation scope. The null case is handled correctly.
   LSI->GLTemplateParameterList = getDerived().TransformTemplateParameterList(
@@ -9145,10 +9147,10 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
           return This->TransformExceptionSpec(OldCallOpFPTL.getBeginLoc(), ESI,
                                               ExceptionStorage, Changed);
         });
+    if (NewCallOpType.isNull())
+      return ExprError();
     NewCallOpTSI = NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context,
                                                         NewCallOpType);
-    if (!NewCallOpTSI)
-      return ExprError();
   }
 
   // Create the local class that will describe the lambda.
@@ -9168,6 +9170,10 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
 
   getDerived().transformAttrs(E->getCallOperator(), NewCallOperator);
 
+  // TransformLambdaScope will manage the function scope, so we can disable the
+  // cleanup.
+  FuncScopeCleanup.disable();
+
   return getDerived().TransformLambdaScope(E, NewCallOperator, 
       InitCaptureExprsAndTypes);
 }
index 1346c3da912b220fe6cb1bb65462280cc0870030..62208959ae10e153b2be7d04813be6c98892a121 100644 (file)
@@ -425,3 +425,17 @@ namespace lambda_in_default_mem_init {
   }
   template void g<int>();
 }
+
+namespace error_in_transform_prototype {
+  template<class T>
+  void f(T t) {
+    // expected-error@+2 {{type 'int' cannot be used prior to '::' because it has no members}}
+    // expected-error@+1 {{no member named 'ns' in 'error_in_transform_prototype::S'}}
+    auto x = [](typename T::ns::type &k) {};
+  }
+  class S {};
+  void foo() {
+    f(5); // expected-note {{requested here}}
+    f(S()); // expected-note {{requested here}}
+  }
+}