cor3ntin updated this revision to Diff 423671.
cor3ntin added a comment.


- Get rid of buildLambdaScopeCaptures
- Set the call operator inner loc in CompleteLambdaCallOperator (+ tests)


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D124012/new/

https://reviews.llvm.org/D124012

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaLambda.cpp
  clang/lib/Sema/TreeTransform.h
  clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp
  clang/test/SemaCXX/lambda-capture-type-deduction.cpp

Index: clang/test/SemaCXX/lambda-capture-type-deduction.cpp
===================================================================
--- clang/test/SemaCXX/lambda-capture-type-deduction.cpp
+++ clang/test/SemaCXX/lambda-capture-type-deduction.cpp
@@ -163,6 +163,35 @@
   [&]() requires is_same<decltype(u), T> {}();
 }
 
+template <typename T>
+void dependent_init_capture(T x = 0) {
+  [ y = x + 1, x ]() mutable -> decltype(y + x) requires(is_same<decltype((y)), int &> && is_same<decltype((x)), int &>) {
+    return y;
+  }
+  ();
+  [ y = x + 1, x ]() -> decltype(y + x) requires(is_same<decltype((y)), const int &> && is_same<decltype((x)), const int &>) {
+    return y;
+  }
+  ();
+}
+
+template <typename T, typename...>
+struct extract_type {
+  using type = T;
+};
+
+template <typename... T>
+void dependent_variadic_capture(T... x) {
+  [... y = x, x... ](auto...) mutable -> typename extract_type<decltype(y)...>::type requires((is_same<decltype((y)), int &> && ...) && (is_same<decltype((x)), int &> && ...)) {
+    return 0;
+  }
+  (x...);
+  [... y = x, x... ](auto...) -> typename extract_type<decltype(y)...>::type requires((is_same<decltype((y)), const int &> && ...) && (is_same<decltype((x)), const int &> && ...)) {
+    return 0;
+  }
+  (x...);
+}
+
 void test_dependent() {
   int v   = 0;
   int & r = v;
@@ -170,6 +199,8 @@
   dependent<int&>(v);
   dependent<int&>(r);
   dependent<const int&>(cr);
+  dependent_init_capture(0);
+  dependent_variadic_capture(1, 2, 3, 4);
 }
 
 void test_CWG2569_tpl(auto a) {
Index: clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp
===================================================================
--- clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp
+++ clang/test/CXX/expr/expr.prim/expr.prim.lambda/p4.cpp
@@ -43,10 +43,21 @@
   }(5);
 }
 
-struct Incomplete; // expected-note{{forward declaration of 'Incomplete'}}
+struct Incomplete; // expected-note 2{{forward declaration of 'Incomplete'}}
 void test_result_type(int N) {
   auto l1 = [] () -> Incomplete { }; // expected-error{{incomplete result type 'Incomplete' in lambda expression}}
 
   typedef int vla[N];
   auto l2 = [] () -> vla { }; // expected-error{{function cannot return array type 'vla' (aka 'int[N]')}}
 }
+
+template <typename T>
+void test_result_type_tpl(int N) {
+  auto l1 = []() -> T {}; // expected-error{{incomplete result type 'Incomplete' in lambda expression}}
+  typedef int vla[N];
+  auto l2 = []() -> vla {}; // expected-error{{function cannot return array type 'vla' (aka 'int[N]')}}
+}
+
+void test_result_type_call() {
+  test_result_type_tpl<Incomplete>(10); // expected-note {{requested here}}
+}
Index: clang/lib/Sema/TreeTransform.h
===================================================================
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -12966,44 +12966,6 @@
   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.
-  auto TPL = getDerived().TransformTemplateParameterList(
-      E->getTemplateParameterList());
-  LSI->GLTemplateParameterList = TPL;
-
-  // Transform the type of the original lambda's call operator.
-  // The transformation MUST be done in the CurrentInstantiationScope since
-  // it introduces a mapping of the original to the newly created
-  // transformed parameters.
-  TypeSourceInfo *NewCallOpTSI = nullptr;
-  {
-    TypeSourceInfo *OldCallOpTSI = E->getCallOperator()->getTypeSourceInfo();
-    FunctionProtoTypeLoc OldCallOpFPTL =
-        OldCallOpTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>();
-
-    TypeLocBuilder NewCallOpTLBuilder;
-    SmallVector<QualType, 4> ExceptionStorage;
-    TreeTransform *This = this; // Work around gcc.gnu.org/PR56135.
-    QualType NewCallOpType = TransformFunctionProtoType(
-        NewCallOpTLBuilder, OldCallOpFPTL, nullptr, Qualifiers(),
-        [&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) {
-          return This->TransformExceptionSpec(OldCallOpFPTL.getBeginLoc(), ESI,
-                                              ExceptionStorage, Changed);
-        });
-    if (NewCallOpType.isNull())
-      return ExprError();
-    NewCallOpTSI = NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context,
-                                                        NewCallOpType);
-  }
-
-  // Transform the trailing requires clause
-  ExprResult NewTrailingRequiresClause;
-  if (Expr *TRC = E->getCallOperator()->getTrailingRequiresClause())
-    // FIXME: Concepts: Substitution into requires clause should only happen
-    //                  when checking satisfaction.
-    NewTrailingRequiresClause = getDerived().TransformExpr(TRC);
-
   // Create the local class that will describe the lambda.
 
   // FIXME: DependencyKind below is wrong when substituting inside a templated
@@ -13019,10 +12981,8 @@
     DependencyKind = CXXRecordDecl::LDK_NeverDependent;
 
   CXXRecordDecl *OldClass = E->getLambdaClass();
-  CXXRecordDecl *Class =
-      getSema().createLambdaClosureType(E->getIntroducerRange(), NewCallOpTSI,
-                                        DependencyKind, E->getCaptureDefault());
-
+  CXXRecordDecl *Class = getSema().createLambdaClosureType(
+      E->getIntroducerRange(), nullptr, DependencyKind, E->getCaptureDefault());
   getDerived().transformedLocalDecl(OldClass, {Class});
 
   Optional<std::tuple<bool, unsigned, unsigned, Decl *>> Mangling;
@@ -13032,35 +12992,19 @@
                                OldClass->getDeviceLambdaManglingNumber(),
                                OldClass->getLambdaContextDecl());
 
-  // Build the call operator.
-  CXXMethodDecl *NewCallOperator = getSema().startLambdaDefinition(
-      Class, E->getIntroducerRange(), NewCallOpTSI,
-      E->getCallOperator()->getEndLoc(),
-      NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>().getParams(),
-      E->getCallOperator()->getConstexprKind(),
-      NewTrailingRequiresClause.get());
-
-  LSI->CallOperator = NewCallOperator;
+  CXXMethodDecl *NewCallOperator =
+      getSema().CreateLambdaCallOperator(E->getIntroducerRange(), Class);
+  NewCallOperator->setLexicalDeclContext(getSema().CurContext);
 
-  getDerived().transformAttrs(E->getCallOperator(), NewCallOperator);
-  getDerived().transformedLocalDecl(E->getCallOperator(), {NewCallOperator});
-
-  // Number the lambda for linkage purposes if necessary.
-  getSema().handleLambdaNumbering(Class, NewCallOperator, Mangling);
+  // Enter the scope of the lambda.
+  getSema().buildLambdaScope(LSI, NewCallOperator, E->getIntroducerRange(),
+                             E->getCaptureDefault(), E->getCaptureDefaultLoc(),
+                             E->hasExplicitParameters(), E->isMutable());
 
   // Introduce the context of the call operator.
   Sema::ContextRAII SavedContext(getSema(), NewCallOperator,
                                  /*NewThisContext*/false);
 
-  // Enter the scope of the lambda.
-  getSema().buildLambdaScope(LSI, NewCallOperator,
-                             E->getIntroducerRange(),
-                             E->getCaptureDefault(),
-                             E->getCaptureDefaultLoc(),
-                             E->hasExplicitParameters(),
-                             E->hasExplicitResultType(),
-                             E->isMutable());
-
   bool Invalid = false;
 
   // Transform captures.
@@ -13182,6 +13126,60 @@
   }
   getSema().finishLambdaExplicitCaptures(LSI);
 
+  // Transform the template parameters, and add them to the current
+  // instantiation scope. The null case is handled correctly.
+  auto TPL = getDerived().TransformTemplateParameterList(
+      E->getTemplateParameterList());
+  LSI->GLTemplateParameterList = TPL;
+
+  // Transform the type of the original lambda's call operator.
+  // The transformation MUST be done in the CurrentInstantiationScope since
+  // it introduces a mapping of the original to the newly created
+  // transformed parameters.
+  TypeSourceInfo *NewCallOpTSI = nullptr;
+  {
+    TypeSourceInfo *OldCallOpTSI = E->getCallOperator()->getTypeSourceInfo();
+    FunctionProtoTypeLoc OldCallOpFPTL =
+        OldCallOpTSI->getTypeLoc().getAs<FunctionProtoTypeLoc>();
+
+    TypeLocBuilder NewCallOpTLBuilder;
+    SmallVector<QualType, 4> ExceptionStorage;
+    TreeTransform *This = this; // Work around gcc.gnu.org/PR56135.
+    QualType NewCallOpType = TransformFunctionProtoType(
+        NewCallOpTLBuilder, OldCallOpFPTL, nullptr, Qualifiers(),
+        [&](FunctionProtoType::ExceptionSpecInfo &ESI, bool &Changed) {
+          return This->TransformExceptionSpec(OldCallOpFPTL.getBeginLoc(), ESI,
+                                              ExceptionStorage, Changed);
+        });
+    if (NewCallOpType.isNull())
+      return ExprError();
+    NewCallOpTSI =
+        NewCallOpTLBuilder.getTypeSourceInfo(getSema().Context, NewCallOpType);
+  }
+
+  // Transform the trailing requires clause
+  ExprResult NewTrailingRequiresClause;
+  if (Expr *TRC = E->getCallOperator()->getTrailingRequiresClause())
+    // FIXME: Concepts: Substitution into requires clause should only happen
+    //                  when checking satisfaction.
+    NewTrailingRequiresClause = getDerived().TransformExpr(TRC);
+
+  getSema().CompleteLambdaCallOperator(
+      NewCallOperator, E->getCallOperator()->getLocation(),
+      E->getCallOperator()->getInnerLocStart(), NewTrailingRequiresClause.get(),
+      NewCallOpTSI, E->getCallOperator()->getConstexprKind(),
+      NewCallOpTSI->getTypeLoc().castAs<FunctionProtoTypeLoc>().getParams(),
+      E->hasExplicitResultType());
+
+  getDerived().transformAttrs(E->getCallOperator(), NewCallOperator);
+  getDerived().transformedLocalDecl(E->getCallOperator(), {NewCallOperator});
+
+  {
+    // Number the lambda for linkage purposes if necessary.
+    Sema::ContextRAII ManglingContext(getSema(), Class->getDeclContext());
+    getSema().handleLambdaNumbering(Class, NewCallOperator, Mangling);
+  }
+
   // FIXME: Sema's lambda-building mechanism expects us to push an expression
   // evaluation context even if we're not transforming the function body.
   getSema().PushExpressionEvaluationContext(
Index: clang/lib/Sema/SemaLambda.cpp
===================================================================
--- clang/lib/Sema/SemaLambda.cpp
+++ clang/lib/Sema/SemaLambda.cpp
@@ -517,12 +517,11 @@
   }
 }
 
-static void buildLambdaScopeCaptures(LambdaScopeInfo *LSI,
-                                     CXXMethodDecl *CallOperator,
-                                     SourceRange IntroducerRange,
-                                     LambdaCaptureDefault CaptureDefault,
-                                     SourceLocation CaptureDefaultLoc,
-                                     bool ExplicitParams, bool Mutable) {
+void Sema::buildLambdaScope(LambdaScopeInfo *LSI, CXXMethodDecl *CallOperator,
+                            SourceRange IntroducerRange,
+                            LambdaCaptureDefault CaptureDefault,
+                            SourceLocation CaptureDefaultLoc,
+                            bool ExplicitParams, bool Mutable) {
   LSI->CallOperator = CallOperator;
   CXXRecordDecl *LambdaClass = CallOperator->getParent();
   LSI->Lambda = LambdaClass;
@@ -536,17 +535,6 @@
   LSI->Mutable = Mutable;
 }
 
-void Sema::buildLambdaScope(LambdaScopeInfo *LSI, CXXMethodDecl *CallOperator,
-                            SourceRange IntroducerRange,
-                            LambdaCaptureDefault CaptureDefault,
-                            SourceLocation CaptureDefaultLoc,
-                            bool ExplicitParams, bool ExplicitResultType,
-                            bool Mutable) {
-  buildLambdaScopeCaptures(LSI, CallOperator, IntroducerRange, CaptureDefault,
-                           CaptureDefaultLoc, ExplicitParams, Mutable);
-  buildLambdaScopeReturnType(*this, LSI, CallOperator, ExplicitResultType);
-}
-
 void Sema::finishLambdaExplicitCaptures(LambdaScopeInfo *LSI) {
   LSI->finishedExplicitCaptures();
 }
@@ -953,28 +941,76 @@
   return MethodTyInfo;
 }
 
-static CXXMethodDecl *CreateMethod(Sema &S, SourceRange IntroducerRange,
-                                   CXXRecordDecl *Class) {
+CXXMethodDecl *Sema::CreateLambdaCallOperator(SourceRange IntroducerRange,
+                                              CXXRecordDecl *Class) {
+
   // C++11 [expr.prim.lambda]p5:
   //   The closure type for a lambda-expression has a public inline function
   //   call operator (13.5.4) whose parameters and return type are described
   //   by the lambda-expression's parameter-declaration-clause and
   //   trailing-return-type respectively.
   DeclarationName MethodName =
-      S.Context.DeclarationNames.getCXXOperatorName(OO_Call);
+      Context.DeclarationNames.getCXXOperatorName(OO_Call);
   DeclarationNameLoc MethodNameLoc =
       DeclarationNameLoc::makeCXXOperatorNameLoc(IntroducerRange.getBegin());
   CXXMethodDecl *Method = CXXMethodDecl::Create(
-      S.Context, Class, SourceLocation(),
+      Context, Class, SourceLocation(),
       DeclarationNameInfo(MethodName, IntroducerRange.getBegin(),
                           MethodNameLoc),
-      QualType(), nullptr, SC_None, S.getCurFPFeatures().isFPConstrained(),
+      QualType(), nullptr, SC_None, getCurFPFeatures().isFPConstrained(),
       /*isInline=*/true, ConstexprSpecKind::Unspecified, SourceLocation(),
       nullptr);
   Method->setAccess(AS_public);
   return Method;
 }
 
+void Sema::CompleteLambdaCallOperator(
+    CXXMethodDecl *Method, SourceLocation LambdaLoc,
+    SourceLocation CallOperatorLoc, Expr *TrailingRequiresClause,
+    TypeSourceInfo *MethodTyInfo, ConstexprSpecKind ConstexprKind,
+    ArrayRef<ParmVarDecl *> Params, bool HasExplicitResultType) {
+
+  LambdaScopeInfo *const LSI = getCurrentLambdaScopeUnsafe(*this);
+
+  if (TrailingRequiresClause)
+    Method->setTrailingRequiresClause(TrailingRequiresClause);
+
+  TemplateParameterList *TemplateParams =
+      getGenericLambdaTemplateParameterList(LSI, *this);
+
+  auto DC = Method->getLexicalDeclContext();
+  Method->setLexicalDeclContext(LSI->Lambda);
+  if (TemplateParams) {
+    FunctionTemplateDecl *const TemplateMethod = FunctionTemplateDecl::Create(
+        Context, LSI->Lambda, Method->getLocation(), Method->getDeclName(),
+        TemplateParams, Method);
+    TemplateMethod->setAccess(AS_public);
+    Method->setDescribedFunctionTemplate(TemplateMethod);
+    LSI->Lambda->addDecl(TemplateMethod);
+    TemplateMethod->setLexicalDeclContext(DC);
+  } else {
+    LSI->Lambda->addDecl(Method);
+  }
+  LSI->Lambda->setLambdaIsGeneric(TemplateParams);
+  LSI->Lambda->setLambdaTypeInfo(MethodTyInfo);
+
+  Method->setLexicalDeclContext(DC);
+  Method->setLocation(LambdaLoc);
+  Method->setInnerLocStart(CallOperatorLoc);
+  Method->setTypeSourceInfo(MethodTyInfo);
+  Method->setType(buildTypeForLambdaCallOperator(*this, LSI->Lambda,
+                                                 TemplateParams, MethodTyInfo));
+  Method->setConstexprKind(ConstexprKind);
+  if (!Params.empty()) {
+    CheckParmsForFunctionDef(Params, /*CheckParameterNames=*/false);
+    Method->setParams(Params);
+    for (auto P : Method->parameters())
+      P->setOwningFunction(Method);
+  }
+
+  buildLambdaScopeReturnType(*this, LSI, Method, HasExplicitResultType);
+}
+
 void Sema::ActOnLambdaIntroducer(LambdaIntroducer &Intro, Scope *CurrentScope) {
 
   LambdaScopeInfo *const LSI = getCurLambda();
@@ -1016,7 +1052,7 @@
   //   by the lambda-expression's parameter-declaration-clause and
   //   trailing-return-type respectively.
 
-  CXXMethodDecl *Method = CreateMethod(*this, Intro.Range, Class);
+  CXXMethodDecl *Method = CreateLambdaCallOperator(Intro.Range, Class);
   LSI->CallOperator = Method;
   Method->setLexicalDeclContext(CurContext);
 
@@ -1297,55 +1333,24 @@
   SmallVector<ParmVarDecl *, 8> Params;
   bool ExplicitResultType;
 
-  SourceLocation TypeLoc, LambdaLoc;
+  SourceLocation TypeLoc, CallOperatorLoc;
   if (ParamInfo.getNumTypeObjects() == 0) {
-    LambdaLoc = TypeLoc = Intro.Range.getEnd();
+    CallOperatorLoc = TypeLoc = Intro.Range.getEnd();
   } else {
     unsigned index;
     ParamInfo.isFunctionDeclarator(index);
     const auto &Object = ParamInfo.getTypeObject(index);
     TypeLoc =
         Object.Loc.isValid() ? Object.Loc : ParamInfo.getSourceRange().getEnd();
-    LambdaLoc = ParamInfo.getSourceRange().getEnd();
+    CallOperatorLoc = ParamInfo.getSourceRange().getEnd();
   }
 
   CXXRecordDecl *Class = LSI->Lambda;
   CXXMethodDecl *Method = LSI->CallOperator;
 
-  if (auto *C = ParamInfo.getTrailingRequiresClause())
-    Method->setTrailingRequiresClause(C);
-
-  TemplateParameterList *TemplateParams =
-      getGenericLambdaTemplateParameterList(LSI, *this);
-
-  auto DC = Method->getLexicalDeclContext();
-  Method->setLexicalDeclContext(Class);
-  if (TemplateParams) {
-    FunctionTemplateDecl *const TemplateMethod = FunctionTemplateDecl::Create(
-        Context, Class, Method->getLocation(), Method->getDeclName(),
-        TemplateParams, Method);
-    TemplateMethod->setAccess(AS_public);
-    Method->setDescribedFunctionTemplate(TemplateMethod);
-    Class->addDecl(TemplateMethod);
-    TemplateMethod->setLexicalDeclContext(DC);
-  } else {
-    Class->addDecl(Method);
-  }
-  Method->setLexicalDeclContext(DC);
-  Class->setLambdaIsGeneric(TemplateParams);
-
   TypeSourceInfo *MethodTyInfo = getLambdaType(
       *this, Intro, ParamInfo, getCurScope(), TypeLoc, ExplicitResultType);
 
-  Class->setLambdaTypeInfo(MethodTyInfo);
-  Method->setInnerLocStart(LambdaLoc);
-  Method->setLocation(Intro.Range.getBegin());
-  Method->setTypeSourceInfo(MethodTyInfo);
-  Method->setType(buildTypeForLambdaCallOperator(*this, Class, TemplateParams,
-                                                 MethodTyInfo));
-  Method->setConstexprKind(ParamInfo.getDeclSpec().getConstexprSpecifier());
-  buildLambdaScopeReturnType(*this, LSI, Method, ExplicitResultType);
-
   LSI->ExplicitParams = ParamInfo.getNumTypeObjects() != 0;
 
   if (ParamInfo.isFunctionDeclarator() != 0 &&
@@ -1359,14 +1364,15 @@
     }
   }
 
-  ContextRAII ManglingContext(*this, Class->getDeclContext());
+  CompleteLambdaCallOperator(Method, Intro.Range.getBegin(), CallOperatorLoc,
+                             ParamInfo.getTrailingRequiresClause(),
+                             MethodTyInfo,
+                             ParamInfo.getDeclSpec().getConstexprSpecifier(),
+                             Params, ExplicitResultType);
 
-  CheckParmsForFunctionDef(Params, /*CheckParameterNames=*/false);
+  ContextRAII ManglingContext(*this, Class->getDeclContext());
 
-  if (LSI->ExplicitParams) {
-    Method->setParams(Params);
-    CheckCXXDefaultArguments(Method);
-  }
+  CheckCXXDefaultArguments(Method);
 
   // This represents the function body for the lambda function, check if we
   // have to apply optnone due to a pragma.
Index: clang/include/clang/Sema/Sema.h
===================================================================
--- clang/include/clang/Sema/Sema.h
+++ clang/include/clang/Sema/Sema.h
@@ -6849,9 +6849,16 @@
                         LambdaCaptureDefault CaptureDefault,
                         SourceLocation CaptureDefaultLoc,
                         bool ExplicitParams,
-                        bool ExplicitResultType,
                         bool Mutable);
 
+  CXXMethodDecl *CreateLambdaCallOperator(SourceRange IntroducerRange,
+                                          CXXRecordDecl *Class);
+  void CompleteLambdaCallOperator(
+      CXXMethodDecl *Method, SourceLocation LambdaLoc,
+      SourceLocation CallOperatorLoc, Expr *TrailingRequiresClause,
+      TypeSourceInfo *MethodTyInfo, ConstexprSpecKind ConstexprKind,
+      ArrayRef<ParmVarDecl *> Params, bool HasExplicitResultType);
+
   /// Perform initialization analysis of the init-capture and perform
   /// any implicit conversions such as an lvalue-to-rvalue conversion if
   /// not being used to initialize a reference.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to