[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2019-05-04 Thread Hamza Sood via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL359967: [c++20] Implement P0428R2 - Familiar template syntax 
for generic lambdas (authored by hamzasood, committed by ).
Herald added a project: LLVM.
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D36527?vs=177221&id=198134#toc

Repository:
  rL LLVM

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

https://reviews.llvm.org/D36527

Files:
  cfe/trunk/include/clang/AST/DeclCXX.h
  cfe/trunk/include/clang/AST/DeclTemplate.h
  cfe/trunk/include/clang/AST/ExprCXX.h
  cfe/trunk/include/clang/AST/RecursiveASTVisitor.h
  cfe/trunk/include/clang/Basic/DiagnosticParseKinds.td
  cfe/trunk/include/clang/Parse/Parser.h
  cfe/trunk/include/clang/Sema/ScopeInfo.h
  cfe/trunk/include/clang/Sema/Sema.h
  cfe/trunk/lib/AST/DeclCXX.cpp
  cfe/trunk/lib/AST/DeclPrinter.cpp
  cfe/trunk/lib/AST/ExprCXX.cpp
  cfe/trunk/lib/AST/ItaniumMangle.cpp
  cfe/trunk/lib/AST/StmtPrinter.cpp
  cfe/trunk/lib/AST/TypePrinter.cpp
  cfe/trunk/lib/Parse/ParseExprCXX.cpp
  cfe/trunk/lib/Sema/Sema.cpp
  cfe/trunk/lib/Sema/SemaLambda.cpp
  cfe/trunk/lib/Sema/SemaType.cpp
  cfe/trunk/test/CXX/temp/temp.decls/temp.variadic/p4.cpp
  cfe/trunk/test/CodeGenCXX/mangle-lambda-explicit-template-params.cpp
  cfe/trunk/test/Index/print-display-names.cpp
  cfe/trunk/test/PCH/cxx11-lambdas.mm
  cfe/trunk/test/PCH/cxx1y-lambdas.mm
  cfe/trunk/test/PCH/cxx2a-template-lambdas.cpp
  cfe/trunk/test/Parser/cxx2a-template-lambdas.cpp
  cfe/trunk/test/SemaCXX/cxx2a-template-lambdas.cpp
  cfe/trunk/unittests/AST/StmtPrinterTest.cpp
  cfe/trunk/unittests/Tooling/RecursiveASTVisitorTests/LambdaTemplateParams.cpp
  cfe/trunk/www/cxx_status.html

Index: cfe/trunk/test/PCH/cxx2a-template-lambdas.cpp
===
--- cfe/trunk/test/PCH/cxx2a-template-lambdas.cpp
+++ cfe/trunk/test/PCH/cxx2a-template-lambdas.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -std=c++2a -emit-pch %s -o %t
+// RUN: %clang_cc1 -std=c++2a -include-pch %t -verify %s
+
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+auto l1 = []() constexpr -> int {
+return I;
+};
+
+auto l2 = []() constexpr -> decltype(I) {
+return I;
+};
+
+auto l3 = [](auto i) constexpr -> T {
+  return T(i);
+};
+
+auto l4 = [] class T, class U>(T, auto i) constexpr -> U {
+  return U(i);
+};
+
+#else /*included pch*/
+
+static_assert(l1.operator()<5>() == 5);
+static_assert(l1.operator()<6>() == 6);
+
+static_assert(l2.operator()<7>() == 7);
+static_assert(l2.operator()() == nullptr);
+
+static_assert(l3.operator()(8.4) == 8);
+static_assert(l3.operator()(9.9) == 9);
+
+template
+struct DummyTemplate { };
+
+static_assert(l4(DummyTemplate(), 12) == 12.0);
+static_assert(l4(DummyTemplate(), 19.8) == 19);
+
+#endif // HEADER
Index: cfe/trunk/test/PCH/cxx11-lambdas.mm
===
--- cfe/trunk/test/PCH/cxx11-lambdas.mm
+++ cfe/trunk/test/PCH/cxx11-lambdas.mm
@@ -54,7 +54,7 @@
 }
 
 // CHECK-PRINT: inline int add_int_slowly_twice 
-// CHECK-PRINT: lambda = [&] (int z)
+// CHECK-PRINT: lambda = [&](int z)
 
 // CHECK-PRINT: init_capture
 // CHECK-PRINT: [&, x(t)]
Index: cfe/trunk/test/PCH/cxx1y-lambdas.mm
===
--- cfe/trunk/test/PCH/cxx1y-lambdas.mm
+++ cfe/trunk/test/PCH/cxx1y-lambdas.mm
@@ -50,7 +50,7 @@
 }
 
 // CHECK-PRINT: inline int add_int_slowly_twice 
-// CHECK-PRINT: lambda = [] (type-parameter-0-0 z
+// CHECK-PRINT: lambda = [](auto z
 
 // CHECK-PRINT: init_capture
 // CHECK-PRINT: [&, x(t)]
Index: cfe/trunk/test/SemaCXX/cxx2a-template-lambdas.cpp
===
--- cfe/trunk/test/SemaCXX/cxx2a-template-lambdas.cpp
+++ cfe/trunk/test/SemaCXX/cxx2a-template-lambdas.cpp
@@ -0,0 +1,45 @@
+// RUN: %clang_cc1 -std=c++2a -verify %s
+
+template
+constexpr bool is_same = false;
+
+template
+constexpr bool is_same = true;
+
+template
+struct DummyTemplate { };
+
+void func() {
+  auto L0 = [](T arg) {
+static_assert(is_same); // expected-error {{static_assert failed}}
+  };
+  L0(0);
+  L0(0.0); // expected-note {{in instantiation}}
+
+  auto L1 = [] {
+static_assert(I == 5); // expected-error {{static_assert failed}}
+  };
+  L1.operator()<5>();
+  L1.operator()<6>(); // expected-note {{in instantiation}}
+
+  auto L2 = [] class T, class U>(T &&arg) {
+static_assert(is_same, DummyTemplate>); // // expected-error {{static_assert failed}}
+  };
+  L2(DummyTemplate());
+  L2(DummyTemplate()); // expected-note {{in instantiation}}
+}
+
+template // expected-note {{declared here}}
+struct ShadowMe {
+  void member_func() {
+auto L = [] { }; // expected-error {{'T' shadows template parameter}}
+  }
+};
+
+template
+constexpr T outer() {
+  return []() { return x; }.template operator()<123>(); // expected-error {{no matching 

[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2019-05-04 Thread Richard Smith - zygoloid via Phabricator via cfe-commits
rsmith accepted this revision.
rsmith marked an inline comment as done.
rsmith added a comment.
This revision is now accepted and ready to land.

Thank you, please go ahead and land this! (We'll need to parse and handle 
//requires-clause//s here too, but that can wait for another patch.)

(Please feel free to send ~weekly pings if you're not getting code review 
feedback; it's easy for things to get missed.)




Comment at: lib/AST/DeclPrinter.cpp:107-108
 
-void printTemplateParameters(const TemplateParameterList *Params);
+void printTemplateParameters(const TemplateParameterList *Params,
+ bool OmitTemplateKW = false);
 void printTemplateArguments(const TemplateArgumentList &Args,

hamzasood wrote:
> rsmith wrote:
> > Nit: I'd prefer splitting this into two functions (one that prints 
> > 'template', calls the other, then prints a space, and the other to print 
> > the actual template parameters) rather than passing a boolean flag.
> Do you reckon that the boolean flag is okay for 
> `TemplateParameterList::print`? I've left this change for now until that has 
> been decided.
This seems fine.


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

https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2018-12-07 Thread Hamza Sood via Phabricator via cfe-commits
hamzasood marked 6 inline comments as done.
hamzasood added inline comments.



Comment at: lib/AST/DeclPrinter.cpp:107-108
 
-void printTemplateParameters(const TemplateParameterList *Params);
+void printTemplateParameters(const TemplateParameterList *Params,
+ bool OmitTemplateKW = false);
 void printTemplateArguments(const TemplateArgumentList &Args,

rsmith wrote:
> Nit: I'd prefer splitting this into two functions (one that prints 
> 'template', calls the other, then prints a space, and the other to print the 
> actual template parameters) rather than passing a boolean flag.
Do you reckon that the boolean flag is okay for `TemplateParameterList::print`? 
I've left this change for now until that has been decided.


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

https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2018-12-07 Thread Hamza Sood via Phabricator via cfe-commits
hamzasood updated this revision to Diff 177221.
hamzasood added a comment.

- Committed the test framework changes separately as r348589 and  r348603.
- Correctly cleanup the lambda scope if an error in encountered while parsing 
the template parameters.
- Replaced getExplicitTemplateParameterCount with 
getExplicitTemplateParameters, which returns an ArrayRef. This simplifies the 
handling of the parameters in a few places.
- Replaced a linear search over the template parameters with a binary search.
- Added expected error cases to the template lambda usage tests to ensure that 
the static assertions are correctly instantiated.
- Added a test for templated lambdas that're used within another template; 
TreeTransform already transforms the template parameter list so no change was 
needed to make the test pass.


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

https://reviews.llvm.org/D36527

Files:
  include/clang/AST/DeclCXX.h
  include/clang/AST/DeclTemplate.h
  include/clang/AST/ExprCXX.h
  include/clang/AST/RecursiveASTVisitor.h
  include/clang/Basic/DiagnosticParseKinds.td
  include/clang/Parse/Parser.h
  include/clang/Sema/ScopeInfo.h
  include/clang/Sema/Sema.h
  lib/AST/DeclCXX.cpp
  lib/AST/DeclPrinter.cpp
  lib/AST/ExprCXX.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/StmtPrinter.cpp
  lib/AST/TypePrinter.cpp
  lib/Parse/ParseExprCXX.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaLambda.cpp
  lib/Sema/SemaType.cpp
  test/CXX/temp/temp.decls/temp.variadic/p4.cpp
  test/CodeGenCXX/mangle-lambda-explicit-template-params.cpp
  test/Index/print-display-names.cpp
  test/PCH/cxx11-lambdas.mm
  test/PCH/cxx1y-lambdas.mm
  test/PCH/cxx2a-template-lambdas.cpp
  test/Parser/cxx2a-template-lambdas.cpp
  test/SemaCXX/cxx2a-template-lambdas.cpp
  unittests/AST/StmtPrinterTest.cpp
  unittests/Tooling/RecursiveASTVisitorTests/LambdaTemplateParams.cpp
  www/cxx_status.html

Index: www/cxx_status.html
===
--- www/cxx_status.html
+++ www/cxx_status.html
@@ -860,7 +860,7 @@
 
   template-parameter-list for generic lambdas
   http://wg21.link/p0428r2";>P0428R2
-  No
+  SVN
 
 
   Concepts
Index: unittests/Tooling/RecursiveASTVisitorTests/LambdaTemplateParams.cpp
===
--- unittests/Tooling/RecursiveASTVisitorTests/LambdaTemplateParams.cpp
+++ unittests/Tooling/RecursiveASTVisitorTests/LambdaTemplateParams.cpp
@@ -0,0 +1,53 @@
+//===- unittest/Tooling/RecursiveASTVisitorTests/LambdaTemplateParams.cpp -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#include "TestVisitor.h"
+
+using namespace clang;
+
+namespace {
+
+// Matches (optional) explicit template parameters.
+class LambdaTemplateParametersVisitor
+  : public ExpectedLocationVisitor {
+public:
+  bool shouldVisitImplicitCode() const { return false; }
+
+  bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
+EXPECT_FALSE(D->isImplicit());
+Match(D->getName(), D->getLocStart());
+return true;
+  }
+
+  bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
+EXPECT_FALSE(D->isImplicit());
+Match(D->getName(), D->getLocStart());
+return true;
+  }
+
+  bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
+EXPECT_FALSE(D->isImplicit());
+Match(D->getName(), D->getLocStart());
+return true;
+  }
+};
+
+TEST(RecursiveASTVisitor, VisitsLambdaExplicitTemplateParameters) {
+  LambdaTemplateParametersVisitor Visitor;
+  Visitor.ExpectMatch("T",  2, 15);
+  Visitor.ExpectMatch("I",  2, 24);
+  Visitor.ExpectMatch("TT", 2, 31);
+  EXPECT_TRUE(Visitor.runOver(
+  "void f() { \n"
+  "  auto l = [] class TT>(auto p) { }; \n"
+  "}",
+  LambdaTemplateParametersVisitor::Lang_CXX2a));
+}
+
+} // end anonymous namespace
Index: unittests/AST/StmtPrinterTest.cpp
===
--- unittests/AST/StmtPrinterTest.cpp
+++ unittests/AST/StmtPrinterTest.cpp
@@ -232,6 +232,43 @@
 // WRONG; Should be: (a & b).operator void *()
 }
 
+TEST(StmtPrinter, TestCXXLamda) {
+  ASSERT_TRUE(PrintedStmtCXXMatches(StdVer::CXX11,
+"void A() {"
+"  auto l = [] { };"
+"}",
+lambdaExpr(anything()).bind("id"),
+"[] {\n"
+"}"));
+
+  ASSERT_TRUE(PrintedStmtCXXMatches(StdVer::CXX11,
+"void A() {"
+"  int a = 0, b = 1;"
+"  auto l = [a,b](int c, float d) { };"
+"}",
+lambdaExpr(anything()).bind("id"),
+"[a, b](int c, float d) {\n"
+"}"));
+
+  ASSERT_TRUE(PrintedStmtCXXMatches(StdVer::CXX14,
+"void A() {"
+"  auto l = [](auto a, int b, auto c, int, auto) { };"
+"}",
+lambdaExpr(anything()).bind("id"),
+"[](auto a, int b

[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2018-11-19 Thread Erich Keane via Phabricator via cfe-commits
erichkeane added a comment.

Submitter: Any update on the status?  It seems that Richard's feedback should 
be trivial enough, so I was wondering if you need this taken up?


https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2018-10-10 Thread Richard Smith - zygoloid via Phabricator via cfe-commits
rsmith added a comment.
Herald added a subscriber: arphaman.

This looks great, thanks!

In https://reviews.llvm.org/D36527#892395, @hamzasood wrote:

> Could you expand on your first point a bit more? Do you have an example that 
> shows the issue?


You have very little test coverage for the case where a lambda with explicit 
template parameters is used within another template. Eg, something like 
(untested):

  template constexpr T f() {
return []() { return V; }.operator()<12345>(); // expected-error {{no 
viable function}} expected-note {{candidate}}
  }
  static_assert(f() == 12345); // ok
  int *p = f(); // expected-note {{in instantiation of}}




Comment at: lib/AST/DeclCXX.cpp:1396-1397
+
+  return std::count_if(List->begin(), List->end(),
+   [](const NamedDecl *D) { return !D->isImplicit(); });
+}

Given that you've already assert-checked `is_partitioned`, maybe use a binary 
search here (eg, `lower_bound`)?



Comment at: lib/AST/DeclPrinter.cpp:107-108
 
-void printTemplateParameters(const TemplateParameterList *Params);
+void printTemplateParameters(const TemplateParameterList *Params,
+ bool OmitTemplateKW = false);
 void printTemplateArguments(const TemplateArgumentList &Args,

Nit: I'd prefer splitting this into two functions (one that prints 'template', 
calls the other, then prints a space, and the other to print the actual 
template parameters) rather than passing a boolean flag.



Comment at: lib/AST/ItaniumMangle.cpp:1710
+Out << "Ty";
+  }
+  else if (auto *Tn = dyn_cast(Decl)) {

No newline between `}` and `else`, please.



Comment at: lib/AST/ItaniumMangle.cpp:1752-1757
+const auto *List = Lambda->getGenericLambdaTemplateParameterList();
+assert(List && "Lambda says it has explicit template parameters, "
+   "but it doesn't have a template parameter list");
+for (auto It = List->begin(), End = It + ExplcitTemplateParamCount;
+ It != End;
+ ++It)

Might be nice to add an accessor that returns the range of explicit parameters. 
(The `if` surrounding this code would then also be redundant.)



Comment at: lib/Parse/ParseExprCXX.cpp:1139
+TemplateParams, LAngleLoc, RAngleLoc)) {
+  return ExprError();
+}

You need to do something here to leave the lambda scope that was pushed near 
the start of this function.



Comment at: unittests/AST/StmtPrinterTest.cpp:109
 
-::testing::AssertionResult
-PrintedStmtCXX98Matches(StringRef Code, const StatementMatcher &NodeMatch,
-StringRef ExpectedPrinted) {
-  std::vector Args;
-  Args.push_back("-std=c++98");
-  Args.push_back("-Wno-unused-value");
-  return PrintedStmtMatches(Code, Args, NodeMatch, ExpectedPrinted);
-}
-
-::testing::AssertionResult PrintedStmtCXX98Matches(
-  StringRef Code,
-  StringRef ContainingFunction,
-  StringRef ExpectedPrinted) {
-  std::vector Args;
-  Args.push_back("-std=c++98");
-  Args.push_back("-Wno-unused-value");
-  return PrintedStmtMatches(Code,
-Args,
-functionDecl(hasName(ContainingFunction),
- 
has(compoundStmt(has(stmt().bind("id"),
-ExpectedPrinted);
+enum class StdVer { CXX98, CXX11, CXX14, CXX17, CXX2a };
+

Please commit the refactoring portion of the changes to this file separately.


https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2018-07-21 Thread Hamza Sood via Phabricator via cfe-commits
hamzasood updated this revision to Diff 156693.
hamzasood added a comment.

- Resolved merge conflicts


https://reviews.llvm.org/D36527

Files:
  include/clang/AST/DeclCXX.h
  include/clang/AST/DeclTemplate.h
  include/clang/AST/ExprCXX.h
  include/clang/AST/RecursiveASTVisitor.h
  include/clang/Basic/DiagnosticParseKinds.td
  include/clang/Parse/Parser.h
  include/clang/Sema/ScopeInfo.h
  include/clang/Sema/Sema.h
  lib/AST/DeclCXX.cpp
  lib/AST/DeclPrinter.cpp
  lib/AST/ExprCXX.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/StmtPrinter.cpp
  lib/AST/TypePrinter.cpp
  lib/Parse/ParseExprCXX.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaLambda.cpp
  lib/Sema/SemaType.cpp
  test/CXX/temp/temp.decls/temp.variadic/p4.cpp
  test/CodeGenCXX/mangle-lambda-explicit-template-params.cpp
  test/Index/print-display-names.cpp
  test/PCH/cxx11-lambdas.mm
  test/PCH/cxx1y-lambdas.mm
  test/PCH/cxx2a-template-lambdas.cpp
  test/Parser/cxx2a-template-lambdas.cpp
  test/SemaCXX/cxx2a-template-lambdas.cpp
  unittests/AST/StmtPrinterTest.cpp
  unittests/Tooling/RecursiveASTVisitorTests/LambdaTemplateParams.cpp
  unittests/Tooling/TestVisitor.h
  www/cxx_status.html

Index: www/cxx_status.html
===
--- www/cxx_status.html
+++ www/cxx_status.html
@@ -860,7 +860,7 @@
 
   template-parameter-list for generic lambdas
   http://wg21.link/p0428r2";>P0428R2
-  No
+  SVN
 
 
   Concepts
Index: unittests/Tooling/TestVisitor.h
===
--- unittests/Tooling/TestVisitor.h
+++ unittests/Tooling/TestVisitor.h
@@ -44,6 +44,8 @@
 Lang_CXX98,
 Lang_CXX11,
 Lang_CXX14,
+Lang_CXX17,
+Lang_CXX2a,
 Lang_OBJC,
 Lang_OBJCXX11,
 Lang_CXX = Lang_CXX98
@@ -60,6 +62,8 @@
   case Lang_CXX98: Args.push_back("-std=c++98"); break;
   case Lang_CXX11: Args.push_back("-std=c++11"); break;
   case Lang_CXX14: Args.push_back("-std=c++14"); break;
+  case Lang_CXX17: Args.push_back("-std=c++17"); break;
+  case Lang_CXX2a: Args.push_back("-std=c++2a"); break;
   case Lang_OBJC:
 Args.push_back("-ObjC");
 Args.push_back("-fobjc-runtime=macosx-10.12.0");
Index: unittests/Tooling/RecursiveASTVisitorTests/LambdaTemplateParams.cpp
===
--- unittests/Tooling/RecursiveASTVisitorTests/LambdaTemplateParams.cpp
+++ unittests/Tooling/RecursiveASTVisitorTests/LambdaTemplateParams.cpp
@@ -0,0 +1,53 @@
+//===- unittest/Tooling/RecursiveASTVisitorTests/LambdaTemplateParams.cpp -===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===--===//
+
+#include "TestVisitor.h"
+
+using namespace clang;
+
+namespace {
+
+// Matches (optional) explicit template parameters.
+class LambdaTemplateParametersVisitor
+  : public ExpectedLocationVisitor {
+public:
+  bool shouldVisitImplicitCode() const { return false; }
+
+  bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
+EXPECT_FALSE(D->isImplicit());
+Match(D->getName(), D->getLocStart());
+return true;
+  }
+
+  bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
+EXPECT_FALSE(D->isImplicit());
+Match(D->getName(), D->getLocStart());
+return true;
+  }
+
+  bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
+EXPECT_FALSE(D->isImplicit());
+Match(D->getName(), D->getLocStart());
+return true;
+  }
+};
+
+TEST(RecursiveASTVisitor, VisitsLambdaExplicitTemplateParameters) {
+  LambdaTemplateParametersVisitor Visitor;
+  Visitor.ExpectMatch("T",  2, 15);
+  Visitor.ExpectMatch("I",  2, 24);
+  Visitor.ExpectMatch("TT", 2, 31);
+  EXPECT_TRUE(Visitor.runOver(
+  "void f() { \n"
+  "  auto l = [] class TT>(auto p) { }; \n"
+  "}",
+  LambdaTemplateParametersVisitor::Lang_CXX2a));
+}
+
+} // end anonymous namespace
Index: unittests/AST/StmtPrinterTest.cpp
===
--- unittests/AST/StmtPrinterTest.cpp
+++ unittests/AST/StmtPrinterTest.cpp
@@ -106,78 +106,73 @@
   return ::testing::AssertionSuccess();
 }
 
-::testing::AssertionResult
-PrintedStmtCXX98Matches(StringRef Code, const StatementMatcher &NodeMatch,
-StringRef ExpectedPrinted) {
-  std::vector Args;
-  Args.push_back("-std=c++98");
-  Args.push_back("-Wno-unused-value");
-  return PrintedStmtMatches(Code, Args, NodeMatch, ExpectedPrinted);
-}
-
-::testing::AssertionResult PrintedStmtCXX98Matches(
-  StringRef Code,
-  StringRef ContainingFunction,
-  StringRef ExpectedPrinted) {
-  std::vector Args;
-  Args.push

[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-11-15 Thread Hamza Sood via Phabricator via cfe-commits
hamzasood updated this revision to Diff 123015.
hamzasood added a comment.

Resolved merge conflicts from the last month of changes 
(`unittests/AST/StmtPrinterTest.cpp` and `lib/AST/DeclCXX.cpp`)


https://reviews.llvm.org/D36527

Files:
  include/clang/AST/DeclCXX.h
  include/clang/AST/DeclTemplate.h
  include/clang/AST/ExprCXX.h
  include/clang/AST/RecursiveASTVisitor.h
  include/clang/Basic/DiagnosticParseKinds.td
  include/clang/Parse/Parser.h
  include/clang/Sema/ScopeInfo.h
  include/clang/Sema/Sema.h
  lib/AST/DeclCXX.cpp
  lib/AST/DeclPrinter.cpp
  lib/AST/ExprCXX.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/StmtPrinter.cpp
  lib/AST/TypePrinter.cpp
  lib/Parse/ParseExprCXX.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaLambda.cpp
  lib/Sema/SemaType.cpp
  test/CXX/temp/temp.decls/temp.variadic/p4.cpp
  test/CodeGenCXX/mangle-lambda-explicit-template-params.cpp
  test/PCH/cxx11-lambdas.mm
  test/PCH/cxx1y-lambdas.mm
  test/PCH/cxx2a-template-lambdas.cpp
  test/Parser/cxx2a-template-lambdas.cpp
  test/SemaCXX/cxx2a-template-lambdas.cpp
  unittests/AST/StmtPrinterTest.cpp
  unittests/Tooling/RecursiveASTVisitorTest.cpp
  unittests/Tooling/TestVisitor.h
  www/cxx_status.html

Index: www/cxx_status.html
===
--- www/cxx_status.html
+++ www/cxx_status.html
@@ -823,7 +823,7 @@
 
   template-parameter-list for generic lambdas
   http://wg21.link/p0428r2";>P0428R2
-  No
+  SVN
 
 
   Initializer list constructors in class template argument deduction
Index: unittests/Tooling/TestVisitor.h
===
--- unittests/Tooling/TestVisitor.h
+++ unittests/Tooling/TestVisitor.h
@@ -44,6 +44,8 @@
 Lang_CXX98,
 Lang_CXX11,
 Lang_CXX14,
+Lang_CXX17,
+Lang_CXX2a,
 Lang_OBJC,
 Lang_OBJCXX11,
 Lang_CXX = Lang_CXX98
@@ -60,6 +62,8 @@
   case Lang_CXX98: Args.push_back("-std=c++98"); break;
   case Lang_CXX11: Args.push_back("-std=c++11"); break;
   case Lang_CXX14: Args.push_back("-std=c++14"); break;
+  case Lang_CXX17: Args.push_back("-std=c++17"); break;
+  case Lang_CXX2a: Args.push_back("-std=c++2a"); break;
   case Lang_OBJC:
 Args.push_back("-ObjC");
 Args.push_back("-fobjc-runtime=macosx-10.12.0");
Index: unittests/Tooling/RecursiveASTVisitorTest.cpp
===
--- unittests/Tooling/RecursiveASTVisitorTest.cpp
+++ unittests/Tooling/RecursiveASTVisitorTest.cpp
@@ -79,6 +79,41 @@
   LambdaDefaultCaptureVisitor::Lang_CXX11));
 }
 
+// Matches (optional) explicit template parameters.
+class LambdaTemplateParametersVisitor
+  : public ExpectedLocationVisitor {
+public:
+  bool shouldVisitImplicitCode() const { return false; }
+
+  bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
+EXPECT_FALSE(D->isImplicit());
+Match(D->getName(), D->getLocStart());
+return true;
+  }
+  bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
+EXPECT_FALSE(D->isImplicit());
+Match(D->getName(), D->getLocStart());
+return true;
+  }
+  bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
+EXPECT_FALSE(D->isImplicit());
+Match(D->getName(), D->getLocStart());
+return true;
+  }
+};
+
+TEST(RecursiveASTVisitor, VisitsLambdaExplicitTemplateParameters) {
+  LambdaTemplateParametersVisitor Visitor;
+  Visitor.ExpectMatch("T",  2, 15);
+  Visitor.ExpectMatch("I",  2, 24);
+  Visitor.ExpectMatch("TT", 2, 31);
+  EXPECT_TRUE(Visitor.runOver(
+  "void f() { \n"
+  "  auto l = [] class TT>(auto p) { }; \n"
+  "}",
+  LambdaTemplateParametersVisitor::Lang_CXX2a));
+}
+
 // Checks for lambda classes that are not marked as implicitly-generated.
 // (There should be none.)
 class ClassVisitor : public ExpectedLocationVisitor {
Index: unittests/AST/StmtPrinterTest.cpp
===
--- unittests/AST/StmtPrinterTest.cpp
+++ unittests/AST/StmtPrinterTest.cpp
@@ -106,78 +106,73 @@
   return ::testing::AssertionSuccess();
 }
 
-::testing::AssertionResult
-PrintedStmtCXX98Matches(StringRef Code, const StatementMatcher &NodeMatch,
-StringRef ExpectedPrinted) {
-  std::vector Args;
-  Args.push_back("-std=c++98");
-  Args.push_back("-Wno-unused-value");
-  return PrintedStmtMatches(Code, Args, NodeMatch, ExpectedPrinted);
-}
-
-::testing::AssertionResult PrintedStmtCXX98Matches(
-  StringRef Code,
-  StringRef ContainingFunction,
-  StringRef ExpectedPrinted) {
-  std::vector Args;
-  Args.push_back("-std=c++98");
-  Args.push_back("-Wno-unused-value");
-  return PrintedStmtMatches(Code,
-Args,
-functionDecl(hasName(Contain

[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-10-09 Thread Hamza Sood via Phabricator via cfe-commits
hamzasood updated this revision to Diff 118261.
hamzasood added a comment.

- Updated lambda mangling to include explicit template parameters
- Allow explicit template parameter lists on lambdas pre-c++2a as an extension.
- Improved the somewhat fragile template depth handling.
- Reformatted some asserts.

Could you expand on your first point a bit more? Do you have an example that 
shows the issue?


https://reviews.llvm.org/D36527

Files:
  include/clang/AST/DeclCXX.h
  include/clang/AST/DeclTemplate.h
  include/clang/AST/ExprCXX.h
  include/clang/AST/RecursiveASTVisitor.h
  include/clang/Basic/DiagnosticParseKinds.td
  include/clang/Parse/Parser.h
  include/clang/Sema/ScopeInfo.h
  include/clang/Sema/Sema.h
  lib/AST/DeclCXX.cpp
  lib/AST/DeclPrinter.cpp
  lib/AST/ExprCXX.cpp
  lib/AST/ItaniumMangle.cpp
  lib/AST/StmtPrinter.cpp
  lib/AST/TypePrinter.cpp
  lib/Parse/ParseExprCXX.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaLambda.cpp
  lib/Sema/SemaType.cpp
  test/CXX/temp/temp.decls/temp.variadic/p4.cpp
  test/CodeGenCXX/mangle-lambda-explicit-template-params.cpp
  test/PCH/cxx11-lambdas.mm
  test/PCH/cxx1y-lambdas.mm
  test/PCH/cxx2a-template-lambdas.cpp
  test/Parser/cxx2a-template-lambdas.cpp
  test/SemaCXX/cxx2a-template-lambdas.cpp
  unittests/AST/StmtPrinterTest.cpp
  unittests/Tooling/RecursiveASTVisitorTest.cpp
  unittests/Tooling/TestVisitor.h
  www/cxx_status.html

Index: www/cxx_status.html
===
--- www/cxx_status.html
+++ www/cxx_status.html
@@ -823,7 +823,7 @@
 
   template-parameter-list for generic lambdas
   http://wg21.link/p0428r2";>P0428R2
-  No
+  SVN
 
 
   Initializer list constructors in class template argument deduction
Index: unittests/Tooling/TestVisitor.h
===
--- unittests/Tooling/TestVisitor.h
+++ unittests/Tooling/TestVisitor.h
@@ -44,6 +44,8 @@
 Lang_CXX98,
 Lang_CXX11,
 Lang_CXX14,
+Lang_CXX17,
+Lang_CXX2a,
 Lang_OBJC,
 Lang_OBJCXX11,
 Lang_CXX = Lang_CXX98
@@ -60,6 +62,8 @@
   case Lang_CXX98: Args.push_back("-std=c++98"); break;
   case Lang_CXX11: Args.push_back("-std=c++11"); break;
   case Lang_CXX14: Args.push_back("-std=c++14"); break;
+  case Lang_CXX17: Args.push_back("-std=c++17"); break;
+  case Lang_CXX2a: Args.push_back("-std=c++2a"); break;
   case Lang_OBJC:
 Args.push_back("-ObjC");
 Args.push_back("-fobjc-runtime=macosx-10.12.0");
Index: unittests/Tooling/RecursiveASTVisitorTest.cpp
===
--- unittests/Tooling/RecursiveASTVisitorTest.cpp
+++ unittests/Tooling/RecursiveASTVisitorTest.cpp
@@ -79,6 +79,41 @@
   LambdaDefaultCaptureVisitor::Lang_CXX11));
 }
 
+// Matches (optional) explicit template parameters.
+class LambdaTemplateParametersVisitor
+  : public ExpectedLocationVisitor {
+public:
+  bool shouldVisitImplicitCode() const { return false; }
+
+  bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
+EXPECT_FALSE(D->isImplicit());
+Match(D->getName(), D->getLocStart());
+return true;
+  }
+  bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
+EXPECT_FALSE(D->isImplicit());
+Match(D->getName(), D->getLocStart());
+return true;
+  }
+  bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
+EXPECT_FALSE(D->isImplicit());
+Match(D->getName(), D->getLocStart());
+return true;
+  }
+};
+
+TEST(RecursiveASTVisitor, VisitsLambdaExplicitTemplateParameters) {
+  LambdaTemplateParametersVisitor Visitor;
+  Visitor.ExpectMatch("T",  2, 15);
+  Visitor.ExpectMatch("I",  2, 24);
+  Visitor.ExpectMatch("TT", 2, 31);
+  EXPECT_TRUE(Visitor.runOver(
+  "void f() { \n"
+  "  auto l = [] class TT>(auto p) { }; \n"
+  "}",
+  LambdaTemplateParametersVisitor::Lang_CXX2a));
+}
+
 // Checks for lambda classes that are not marked as implicitly-generated.
 // (There should be none.)
 class ClassVisitor : public ExpectedLocationVisitor {
Index: unittests/AST/StmtPrinterTest.cpp
===
--- unittests/AST/StmtPrinterTest.cpp
+++ unittests/AST/StmtPrinterTest.cpp
@@ -67,9 +67,8 @@
 
 template 
 ::testing::AssertionResult
-PrintedStmtMatches(StringRef Code, const std::vector &Args,
-   const T &NodeMatch, StringRef ExpectedPrinted) {
-
+PrintedStmtMatchesInternal(StringRef Code, const std::vector &Args,
+   const T &NodeMatch, StringRef ExpectedPrinted) {
   PrintMatch Printer;
   MatchFinder Finder;
   Finder.addMatcher(NodeMatch, &Printer);
@@ -97,65 +96,52 @@
   return ::testing::AssertionSuccess();
 }
 
+enum class StdVer { CXX98, CXX11, CXX14, CXX17, CXX2a };
+
+DeclarationMatcher FunctionBodyMatcher(StringRef ContainingFunction) {
+  return functionDecl(hasName(ContainingFunction),
+  

[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-09-29 Thread Richard Smith - zygoloid via Phabricator via cfe-commits
rsmith added a comment.

A couple of remaining pieces that I think are missing:

- Tests for instantiation of templates containing one of these lambdas. I would 
expect you'll find you need to change Sema/TreeTransform.h to make that work.
- Updates to Itanium mangling (AST/ItaniumMangle.cpp) for the mangling changes 
described in https://github.com/itanium-cxx-abi/cxx-abi/issues/31




Comment at: lib/Parse/ParseExprCXX.cpp:1117
+/*EnteredScope=*/HasExplicitTemplateParams);
+  if (HasExplicitTemplateParams) {
+SmallVector TemplateParams;

Please add a pre-C++2a-compat warning along this code path, and permit this in 
pre-C++2a modes with an extension warning. (You can look at other C++2a 
features for examples of how to do this.)



Comment at: lib/Parse/ParseExprCXX.cpp:1151-1165
+  // Record the template parameter depth for auto parameters.
+  // Subtract 1 from the current depth if we've parsed an explicit template
+  // parameter list, because that will have increased the depth.
+  Actions.RecordParsingTemplateParameterDepth(HasExplicitTemplateParams
+? TemplateParameterDepth - 
1
+: TemplateParameterDepth);
+

This handling of the template depth is more subtle / error-prone than I'd like. 
Maybe you could add a `TemplateParameterDepthRAII::setAddedDepth(1)` to replace 
the conditional increment, and a 
`TemplateParameterDepthRAII::getOriginalDepth()` to replace the conditional 
subtraction of 1?



Comment at: lib/Sema/SemaLambda.cpp:484-490
+  assert(LSI->NumExplicitTemplateParams == 0
+ && "Already acted on explicit template parameters");
+  assert(LSI->TemplateParams.size() == 0
+ && "Explicit template parameters should come "
+"before invented (auto) ones");
+  assert(TParams.size() > 0
+ && "No template parameters to act on");

Please put the `&&` on the previous line.


https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-09-11 Thread Hamza Sood via Phabricator via cfe-commits
hamzasood updated this revision to Diff 114550.
hamzasood added a comment.

- Replaced an unneeded `STLExtras.h` include with ``.
- Assert that the lambda template scope has a parent before accessing it.
- Added an equals in a braced init as per the LLVM coding standards.

Thanks @Rakete


https://reviews.llvm.org/D36527

Files:
  include/clang/AST/DeclTemplate.h
  include/clang/AST/ExprCXX.h
  include/clang/AST/RecursiveASTVisitor.h
  include/clang/Basic/DiagnosticParseKinds.td
  include/clang/Sema/ScopeInfo.h
  include/clang/Sema/Sema.h
  lib/AST/DeclPrinter.cpp
  lib/AST/ExprCXX.cpp
  lib/AST/StmtPrinter.cpp
  lib/AST/TypePrinter.cpp
  lib/Parse/ParseExprCXX.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaLambda.cpp
  lib/Sema/SemaType.cpp
  test/CXX/temp/temp.decls/temp.variadic/p4.cpp
  test/PCH/cxx11-lambdas.mm
  test/PCH/cxx1y-lambdas.mm
  test/PCH/cxx2a-template-lambdas.cpp
  test/Parser/cxx2a-template-lambdas.cpp
  test/SemaCXX/cxx2a-template-lambdas.cpp
  unittests/AST/StmtPrinterTest.cpp
  unittests/Tooling/RecursiveASTVisitorTest.cpp
  unittests/Tooling/TestVisitor.h
  www/cxx_status.html

Index: www/cxx_status.html
===
--- www/cxx_status.html
+++ www/cxx_status.html
@@ -823,7 +823,7 @@
 
   template-parameter-list for generic lambdas
   http://wg21.link/p0428r2";>P0428R2
-  No
+  SVN
 
 
   Initializer list constructors in class template argument deduction
Index: unittests/Tooling/TestVisitor.h
===
--- unittests/Tooling/TestVisitor.h
+++ unittests/Tooling/TestVisitor.h
@@ -44,6 +44,8 @@
 Lang_CXX98,
 Lang_CXX11,
 Lang_CXX14,
+Lang_CXX17,
+Lang_CXX2a,
 Lang_OBJC,
 Lang_OBJCXX11,
 Lang_CXX = Lang_CXX98
@@ -60,6 +62,8 @@
   case Lang_CXX98: Args.push_back("-std=c++98"); break;
   case Lang_CXX11: Args.push_back("-std=c++11"); break;
   case Lang_CXX14: Args.push_back("-std=c++14"); break;
+  case Lang_CXX17: Args.push_back("-std=c++17"); break;
+  case Lang_CXX2a: Args.push_back("-std=c++2a"); break;
   case Lang_OBJC:
 Args.push_back("-ObjC");
 Args.push_back("-fobjc-runtime=macosx-10.12.0");
Index: unittests/Tooling/RecursiveASTVisitorTest.cpp
===
--- unittests/Tooling/RecursiveASTVisitorTest.cpp
+++ unittests/Tooling/RecursiveASTVisitorTest.cpp
@@ -79,6 +79,41 @@
   LambdaDefaultCaptureVisitor::Lang_CXX11));
 }
 
+// Matches (optional) explicit template parameters.
+class LambdaTemplateParametersVisitor
+  : public ExpectedLocationVisitor {
+public:
+  bool shouldVisitImplicitCode() const { return false; }
+
+  bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
+EXPECT_FALSE(D->isImplicit());
+Match(D->getName(), D->getLocStart());
+return true;
+  }
+  bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
+EXPECT_FALSE(D->isImplicit());
+Match(D->getName(), D->getLocStart());
+return true;
+  }
+  bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
+EXPECT_FALSE(D->isImplicit());
+Match(D->getName(), D->getLocStart());
+return true;
+  }
+};
+
+TEST(RecursiveASTVisitor, VisitsLambdaExplicitTemplateParameters) {
+  LambdaTemplateParametersVisitor Visitor;
+  Visitor.ExpectMatch("T",  2, 15);
+  Visitor.ExpectMatch("I",  2, 24);
+  Visitor.ExpectMatch("TT", 2, 31);
+  EXPECT_TRUE(Visitor.runOver(
+  "void f() { \n"
+  "  auto l = [] class TT>(auto p) { }; \n"
+  "}",
+  LambdaTemplateParametersVisitor::Lang_CXX2a));
+}
+
 // Checks for lambda classes that are not marked as implicitly-generated.
 // (There should be none.)
 class ClassVisitor : public ExpectedLocationVisitor {
Index: unittests/AST/StmtPrinterTest.cpp
===
--- unittests/AST/StmtPrinterTest.cpp
+++ unittests/AST/StmtPrinterTest.cpp
@@ -67,9 +67,8 @@
 
 template 
 ::testing::AssertionResult
-PrintedStmtMatches(StringRef Code, const std::vector &Args,
-   const T &NodeMatch, StringRef ExpectedPrinted) {
-
+PrintedStmtMatchesInternal(StringRef Code, const std::vector &Args,
+   const T &NodeMatch, StringRef ExpectedPrinted) {
   PrintMatch Printer;
   MatchFinder Finder;
   Finder.addMatcher(NodeMatch, &Printer);
@@ -97,65 +96,52 @@
   return ::testing::AssertionSuccess();
 }
 
+enum class StdVer { CXX98, CXX11, CXX14, CXX17, CXX2a };
+
+DeclarationMatcher FunctionBodyMatcher(StringRef ContainingFunction) {
+  return functionDecl(hasName(ContainingFunction),
+  has(compoundStmt(has(stmt().bind("id");
+}
+
+template 
 ::testing::AssertionResult
-PrintedStmtCXX98Matches(StringRef Code, const StatementMatcher &NodeMatch,
-StringRef ExpectedPrinted) {
-  std::vector Args;
-  Args.push_back("-std

[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-09-09 Thread Blitz Rakete via Phabricator via cfe-commits
Rakete added a comment.

> Is that a problem?

I don't think so, because `shouldVisitImplicitCode()` doesn't mean that it only 
visits implicit code, it's not `onlyVisitImplicitCode()` :) In fact, I would be 
surprised if the template parameters were only visited once.




Comment at: lib/AST/ExprCXX.cpp:21
 #include "clang/Basic/IdentifierTable.h"
+#include "llvm/ADT/STLExtras.h"
 using namespace clang;

You don't need this header.



Comment at: lib/AST/ExprCXX.cpp:1010
+  return std::count_if(List->begin(), List->end(),
+   [](const NamedDecl *D) { return !D->isImplicit(); });
 }

You could store the lambda in a variable instead of having two times the same 
exact lambda expression.



Comment at: lib/Sema/SemaLambda.cpp:840
+  "template param scope");
+KnownDependent = TemplateParamScope->getParent()
+   ->getTemplateParamParent() != nullptr;

I think you should add an `assert` to verify that `getParent()` doesn't return 
`nullptr`, just to be safe from UB.



Comment at: unittests/AST/StmtPrinterTest.cpp:126
+ const T &NodeMatch, StringRef ExpectedPrinted) {
+  std::vector Args {
+"-std=c++98",

LLVM style guide says that if you are using a braced-init-list to initialize an 
object, you have to use an `=`.


https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-09-06 Thread Hamza Sood via Phabricator via cfe-commits
hamzasood added a comment.

Ping


https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-30 Thread Hamza Sood via Phabricator via cfe-commits
hamzasood updated this revision to Diff 113271.
hamzasood added a comment.
Herald added a subscriber: klimek.

Implemented pretty printing and recursive AST visiting (both with appropriate 
unit tests).

The pretty printing implementation includes fixing a few printing bugs (which I 
needed fixed to write decent tests);

- Unnamed template parameters now print without a trailing space (e.g.  
instead of ).
- C++14 generic lambda parameters are now printed as `auto` as opposed to 
`typeparameter-depth-index`.

RecursiveASTVisitor now visits each explicit template parameter, and also the 
implicit ones if shouldVisitImplicitCode is set.
However there is a problem with this implementation that I'm not sure about.
Consider a TU that is simply: `auto l = []() { };`
If shouldVisitImplicitCode is set, the template parameter will be visited 
twice, Once when visiting the lambda (which is what I added) and once when 
visiting the implicit lambda class type (existing behaviour). Is that a problem?

With regards to serialisation, I don't think any changes are needed. However 
I've added a PCH test to be sure (which passes).


https://reviews.llvm.org/D36527

Files:
  include/clang/AST/DeclTemplate.h
  include/clang/AST/ExprCXX.h
  include/clang/AST/RecursiveASTVisitor.h
  include/clang/Basic/DiagnosticParseKinds.td
  include/clang/Sema/ScopeInfo.h
  include/clang/Sema/Sema.h
  lib/AST/DeclPrinter.cpp
  lib/AST/ExprCXX.cpp
  lib/AST/StmtPrinter.cpp
  lib/AST/TypePrinter.cpp
  lib/Parse/ParseExprCXX.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaLambda.cpp
  lib/Sema/SemaType.cpp
  test/CXX/temp/temp.decls/temp.variadic/p4.cpp
  test/PCH/cxx11-lambdas.mm
  test/PCH/cxx1y-lambdas.mm
  test/PCH/cxx2a-template-lambdas.cpp
  test/Parser/cxx2a-template-lambdas.cpp
  test/SemaCXX/cxx2a-template-lambdas.cpp
  unittests/AST/StmtPrinterTest.cpp
  unittests/Tooling/RecursiveASTVisitorTest.cpp
  unittests/Tooling/TestVisitor.h
  www/cxx_status.html

Index: www/cxx_status.html
===
--- www/cxx_status.html
+++ www/cxx_status.html
@@ -822,7 +822,7 @@
 
   template-parameter-list for generic lambdas
   http://wg21.link/p0428r2";>P0428R2
-  No
+  SVN
 
 
   Initializer list constructors in class template argument deduction
Index: unittests/Tooling/TestVisitor.h
===
--- unittests/Tooling/TestVisitor.h
+++ unittests/Tooling/TestVisitor.h
@@ -44,6 +44,8 @@
 Lang_CXX98,
 Lang_CXX11,
 Lang_CXX14,
+Lang_CXX17,
+Lang_CXX2a,
 Lang_OBJC,
 Lang_OBJCXX11,
 Lang_CXX = Lang_CXX98
@@ -60,6 +62,8 @@
   case Lang_CXX98: Args.push_back("-std=c++98"); break;
   case Lang_CXX11: Args.push_back("-std=c++11"); break;
   case Lang_CXX14: Args.push_back("-std=c++14"); break;
+  case Lang_CXX17: Args.push_back("-std=c++17"); break;
+  case Lang_CXX2a: Args.push_back("-std=c++2a"); break;
   case Lang_OBJC:
 Args.push_back("-ObjC");
 Args.push_back("-fobjc-runtime=macosx-10.12.0");
Index: unittests/Tooling/RecursiveASTVisitorTest.cpp
===
--- unittests/Tooling/RecursiveASTVisitorTest.cpp
+++ unittests/Tooling/RecursiveASTVisitorTest.cpp
@@ -79,6 +79,41 @@
   LambdaDefaultCaptureVisitor::Lang_CXX11));
 }
 
+// Matches (optional) explicit template parameters.
+class LambdaTemplateParametersVisitor
+  : public ExpectedLocationVisitor {
+public:
+  bool shouldVisitImplicitCode() const { return false; }
+
+  bool VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) {
+EXPECT_FALSE(D->isImplicit());
+Match(D->getName(), D->getLocStart());
+return true;
+  }
+  bool VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) {
+EXPECT_FALSE(D->isImplicit());
+Match(D->getName(), D->getLocStart());
+return true;
+  }
+  bool VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) {
+EXPECT_FALSE(D->isImplicit());
+Match(D->getName(), D->getLocStart());
+return true;
+  }
+};
+
+TEST(RecursiveASTVisitor, VisitsLambdaExplicitTemplateParameters) {
+  LambdaTemplateParametersVisitor Visitor;
+  Visitor.ExpectMatch("T",  2, 15);
+  Visitor.ExpectMatch("I",  2, 24);
+  Visitor.ExpectMatch("TT", 2, 31);
+  EXPECT_TRUE(Visitor.runOver(
+  "void f() { \n"
+  "  auto l = [] class TT>(auto p) { }; \n"
+  "}",
+  LambdaTemplateParametersVisitor::Lang_CXX2a));
+}
+
 // Checks for lambda classes that are not marked as implicitly-generated.
 // (There should be none.)
 class ClassVisitor : public ExpectedLocationVisitor {
Index: unittests/AST/StmtPrinterTest.cpp
===
--- unittests/AST/StmtPrinterTest.cpp
+++ unittests/AST/StmtPrinterTest.cpp
@@ -67,9 +67,8 @@
 
 template 
 ::testing::AssertionResult
-PrintedStmtMatches(StringRef Code, const std::vector &Args,
-  

[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-28 Thread Faisal Vali via Phabricator via cfe-commits
faisalv added a comment.

In https://reviews.llvm.org/D36527#854883, @faisalv wrote:

>




> Interestingly we don't (explicitly) visit the lambda's function parameters?

This is obviously false - sorry :)


https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-28 Thread Faisal Vali via Phabricator via cfe-commits
faisalv added a comment.

In https://reviews.llvm.org/D36527#854600, @rsmith wrote:

> This patch appears to be missing some necessary changes in the following 
> places:
>
> - lib/Serialization -- round-trip the new information through PCH / modules


Shouldn't the explicit template parameter information be automatically 
serialized within the non-implicitness of the corresponding template parameter 
decls within our TemplateParameterList?

> - lib/AST/StmtPrinter.cpp -- pretty-printing lambdas with explicit template 
> parameters

yes - this would be nice.

> - lib/Sema/TreeTransform.h -- template instantiation of lambdas with explicit 
> template arguments

yes - i had wondered about TreeTransform - I had hoped that the transformation 
of the template parameter list (for all generic lambdas) would be sufficient 
(perhaps only need to be tweaked to maintain the implicit flag on template 
parameters, if that's not transferred through?) - but I agree this does need to 
be tested well (substitution into default template arguments, non-type-template 
parameters for e.g.).

> - lib/AST/RecursiveASTVisitor.h -- recursive AST visitation should visit 
> explicit template parameters

Would we also want to (explicitly) visit the implicit template parameters?
Interestingly we don't (explicitly) visit the lambda's function parameters?

> We'll also need to agree within the cxx-abi-dev list how to mangle lambda 
> closure types for this form and lib/AST/ItaniumMangle.cpp's `mangleLambda` 
> will need to be updated to match. (The MS mangling is not based on the type 
> of the lambda call operator, so we probably don't need changes there.)




https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-28 Thread Richard Smith - zygoloid via Phabricator via cfe-commits
rsmith added a comment.

In https://reviews.llvm.org/D36527#854600, @rsmith wrote:

> We'll also need to agree within the cxx-abi-dev list how to mangle lambda 
> closure types for this form


I filed https://github.com/itanium-cxx-abi/cxx-abi/issues/31 for this.


https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-28 Thread Richard Smith - zygoloid via Phabricator via cfe-commits
rsmith added a comment.

This patch appears to be missing some necessary changes in the following places:

- lib/Serialization -- round-trip the new information through PCH / modules
- lib/AST/StmtPrinter.cpp -- pretty-printing lambdas with explicit template 
parameters
- lib/Sema/TreeTransform.h -- template instantiation of lambdas with explicit 
template arguments
- lib/AST/RecursiveASTVisitor.h -- recursive AST visitation should visit 
explicit template parameters

We'll also need to agree within the cxx-abi-dev list how to mangle lambda 
closure types for this form and lib/AST/ItaniumMangle.cpp's `mangleLambda` will 
need to be updated to match. (The MS mangling is not based on the type of the 
lambda call operator, so we probably don't need changes there.)


https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-28 Thread Hamza Sood via Phabricator via cfe-commits
hamzasood updated this revision to Diff 112867.
hamzasood added a comment.

Hi Richard, thanks for your feedback. This update makes the changes that you 
requested.
It turns out that the casting is no longer an issue since 
`ParseTemplateParameters` has been refactored to use `NamedDecl`.


https://reviews.llvm.org/D36527

Files:
  include/clang/AST/ExprCXX.h
  include/clang/Basic/DiagnosticParseKinds.td
  include/clang/Sema/ScopeInfo.h
  include/clang/Sema/Sema.h
  lib/AST/ExprCXX.cpp
  lib/Parse/ParseExprCXX.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaLambda.cpp
  lib/Sema/SemaType.cpp
  test/CXX/temp/temp.decls/temp.variadic/p4.cpp
  test/Parser/cxx2a-template-lambdas.cpp
  test/SemaCXX/cxx2a-template-lambdas.cpp
  www/cxx_status.html

Index: www/cxx_status.html
===
--- www/cxx_status.html
+++ www/cxx_status.html
@@ -822,7 +822,7 @@
 
   template-parameter-list for generic lambdas
   http://wg21.link/p0428r2";>P0428R2
-  No
+  SVN
 
 
   Initializer list constructors in class template argument deduction
Index: test/SemaCXX/cxx2a-template-lambdas.cpp
===
--- test/SemaCXX/cxx2a-template-lambdas.cpp
+++ test/SemaCXX/cxx2a-template-lambdas.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -std=c++2a -verify %s
+
+template
+constexpr bool is_same = false;
+
+template
+constexpr bool is_same = true;
+
+template
+struct DummyTemplate { };
+
+void func() {
+  auto L0 = [](T arg) {
+static_assert(is_same);
+  };
+  L0(0);
+
+  auto L1 = [] {
+static_assert(I == 5);
+  };
+  L1.operator()<5>();
+
+  auto L2 = [] class T, class U>(T &&arg) {
+static_assert(is_same, DummyTemplate>);
+  };
+  L2(DummyTemplate());
+}
+
+template // expected-note {{declared here}}
+struct ShadowMe {
+  void member_func() {
+auto L = [] { }; // expected-error {{'T' shadows template parameter}}
+  }
+};
Index: test/Parser/cxx2a-template-lambdas.cpp
===
--- test/Parser/cxx2a-template-lambdas.cpp
+++ test/Parser/cxx2a-template-lambdas.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -std=c++2a %s -verify
+
+auto L0 = []<> { }; //expected-error {{cannot be empty}}
+
+auto L1 = [] { };
+auto L2 = [](T1 arg1, T2 arg2) -> T1 { };
+auto L3 = [](auto arg) { T t; };
+auto L4 = []() { };
Index: test/CXX/temp/temp.decls/temp.variadic/p4.cpp
===
--- test/CXX/temp/temp.decls/temp.variadic/p4.cpp
+++ test/CXX/temp/temp.decls/temp.variadic/p4.cpp
@@ -213,8 +213,10 @@
   };
 #endif
 
+#if __cplusplus > 201703L
   //- in a template parameter pack that is a pack expansion
-  // FIXME: We do not support any way to reach this case yet.
+  swallow([] typename ...W>(W ...wv) { });
+#endif
 
   //- in an initializer-list
   int arr[] = {T().x...};
@@ -279,11 +281,6 @@
   struct T { int x; using U = int; };
   void g() { f(1, 2, 3); }
 
-  template void pack_in_lambda(U ...u) { // expected-note {{here}}
-// FIXME: Move this test into 'f' above once we support this syntax.
-[] typename ...U>(U ...uv) {}; // expected-error {{expected body of lambda}} expected-error {{does not refer to a value}}
-  }
-
   template void pack_expand_attr() {
 // FIXME: Move this test into 'f' above once we support this.
 [[gnu::aligned(alignof(T))...]] int x; // expected-error {{cannot be used as an attribute pack}} expected-error {{unexpanded}}
Index: lib/Sema/SemaType.cpp
===
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -2790,7 +2790,7 @@
 sema::LambdaScopeInfo *LSI = SemaRef.getCurLambda();
 assert(LSI && "No LambdaScopeInfo on the stack!");
 const unsigned TemplateParameterDepth = LSI->AutoTemplateParameterDepth;
-const unsigned AutoParameterPosition = LSI->AutoTemplateParams.size();
+const unsigned AutoParameterPosition = LSI->TemplateParams.size();
 const bool IsParameterPack = D.hasEllipsis();
 
 // Create the TemplateTypeParmDecl here to retrieve the corresponding
@@ -2802,7 +2802,8 @@
 /*KeyLoc*/SourceLocation(), /*NameLoc*/D.getLocStart(),
 TemplateParameterDepth, AutoParameterPosition,
 /*Identifier*/nullptr, false, IsParameterPack);
-LSI->AutoTemplateParams.push_back(CorrespondingTemplateParam);
+CorrespondingTemplateParam->setImplicit();
+LSI->TemplateParams.push_back(CorrespondingTemplateParam);
 // Replace the 'auto' in the function parameter with this invented 
 // template type parameter.
 // FIXME: Retain some type sugar to indicate that this was written
Index: lib/Sema/SemaLambda.cpp
===
--- lib/Sema/SemaLambda.cpp
+++ lib/Sema/SemaLambda.cpp
@@ -21,6 +21,

[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-27 Thread Richard Smith - zygoloid via Phabricator via cfe-commits
rsmith added inline comments.



Comment at: lib/Parse/ParseExprCXX.cpp:638
 /// lambda-introducer lambda-declarator[opt] compound-statement
+/// lambda-introducer  lambda-declarator[opt]
+/// compound-statement

We generally put terminals in single quotes in these grammar excerpts:
```
  lambda-introducer '<' template-parameter-list '>' lambda-declarator[opt]
```



Comment at: lib/Parse/ParseExprCXX.cpp:1126-1127
+   diag::err_lambda_template_parameter_list_empty);
+}
+else {
+  Actions.ActOnLambdaExplicitTemplateParameterList(

No linebreak between `}` and `else`.



Comment at: lib/Sema/SemaLambda.cpp:495
+  reinterpret_cast(TParams.begin()),
+  reinterpret_cast(TParams.end()));
+  LSI->NumExplicitTemplateParams = TParams.size();

hamzasood wrote:
> faisalv wrote:
> > ack - avoid reinterpret cast please - why not just stick to Decl* for 
> > TemplateParams for now  - and add some fixme's that suggest we should 
> > consider refactoring ParseTemplateParameterList to accept a vector of 
> > nameddecls - and update this when that gets updated ?
> > 
> > Perhaps add an assert here that iterates through and checks to make sure 
> > each item in this list is some form of a template parameter decl - within 
> > an #ifndef NDEBUG block (or your conversion check to NameDecl should 
> > suffice?)
> Unfortunately `TemplateParameterList::Create` expects an array of 
> `NamedDecl`, so there’ll need to be a forced downcast somewhere. By getting 
> that over with as soon as possible, any errors will be caught straight away 
> by that assertion instead of moving the problem down the line somewhere and 
> making it more difficult to see where it went wrong.
OK, but please cast them one by one rather than type-punning the array (which 
results in UB).



Comment at: lib/Sema/SemaLambda.cpp:845-846
+   ->getTemplateParamParent() != nullptr;
+  }
+  else {
+KnownDependent = CurScope->getTemplateParamParent() != nullptr;

No linebreak between `}` and `else`.



Comment at: test/CXX/temp/temp.decls/temp.variadic/p4.cpp:216
 
+#if __cplusplus >= 201707L
   //- in a template parameter pack that is a pack expansion

Please use `__cplusplus > 201703L` rather than a number that will become 
meaningless once we have a real value for C++2a.


https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-26 Thread Hamza Sood via Phabricator via cfe-commits
hamzasood added a comment.

Thanks for all of your feedback! It’s really helped to improve this patch.




Comment at: lib/AST/ExprCXX.cpp:979
 
+SourceRange LambdaExpr::getExplicitTemplateParameterListRange() const {
+  TemplateParameterList *List = getTemplateParameterList();

faisalv wrote:
> hamzasood wrote:
> > faisalv wrote:
> > > I think this should return an invalid range if getExplicitCount is 0.
> > > might assert that when not 0, langleloc does not equal rangleloc.
> > > 
> > I think it does return an invalid range in that case. Without explicit 
> > template parameters, getLAngleLoc and getRAngleLoc return invalid 
> > locations. And a range of invalid locations is an invalid range. But I 
> > suppose that could be asserted to make sure.
> fyi - Since getGenericLambdaTPL sets the LAngleLoc and RAngleLoc to the 
> introducer range - unless one handles that case spearately- those funcs won't 
> return an invalid loc?  
That’s changed in this patch. LAngleLoc and RAngleLoc are invalid unless 
there’s an explicit template parameter list.



Comment at: lib/Parse/ParseExprCXX.cpp:1116
+  if (HasExplicitTemplateParams) {
+SmallVector TemplateParams;
+SourceLocation LAngleLoc, RAngleLoc;

faisalv wrote:
> hamzasood wrote:
> > faisalv wrote:
> > > hamzasood wrote:
> > > > faisalv wrote:
> > > > > Why not Just use/pass LSI->TemplateParams?
> > > > I thought that Parser and Sema stay separate, and communicate through 
> > > > various ActOn functions? Directly accessing LSI would violate that.
> > > Aah yes - you're right.  Still it does seem a little wasteful to create 
> > > two of those (and then append).  What are your thoughts about passing the 
> > > argument by (moved from) value, and then swapping their guts within ActOn 
> > > (i..e value-semantics) ?  (I suppose the only concern would be the small 
> > > array case - but i think that would be quite easy for any optimizer to 
> > > inline).   
> > > 
> > I don't think a SmallVectorImpl can be passed by value.
> > 
> > So to make that work, the function would either needed to be templated 
> > (SmallVector) or only accept a SmallVector. And I don't 
> > think either of those options are worthwhile.
> OK - add a FIXME that alerts folks that we currently make two copies of this 
> and ideally we shouldn't need to.
I disagree with this. I don’t think that needing to copy a few pointers is a 
big deal; it happens all the time. E.g. a few lines below this is a vector of 
ParamInfo that’s filled locally and then copied to its destination. The 
performance gain from eliminating that copy isn’t worth making the code more 
confusing, especially since the small case will be hit most of the time.


https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-25 Thread Faisal Vali via Phabricator via cfe-commits
faisalv added inline comments.



Comment at: lib/AST/ExprCXX.cpp:979
 
+SourceRange LambdaExpr::getExplicitTemplateParameterListRange() const {
+  TemplateParameterList *List = getTemplateParameterList();

hamzasood wrote:
> faisalv wrote:
> > I think this should return an invalid range if getExplicitCount is 0.
> > might assert that when not 0, langleloc does not equal rangleloc.
> > 
> I think it does return an invalid range in that case. Without explicit 
> template parameters, getLAngleLoc and getRAngleLoc return invalid locations. 
> And a range of invalid locations is an invalid range. But I suppose that 
> could be asserted to make sure.
fyi - Since getGenericLambdaTPL sets the LAngleLoc and RAngleLoc to the 
introducer range - unless one handles that case spearately- those funcs won't 
return an invalid loc?  


https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-25 Thread Faisal Vali via Phabricator via cfe-commits
faisalv added a comment.

OK - I'll commit this on sunday if no one blocks it by then.  (I'll add the 
fixme's).

Nice Work!


https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-25 Thread Hamza Sood via Phabricator via cfe-commits
hamzasood added inline comments.



Comment at: lib/AST/ExprCXX.cpp:979
 
+SourceRange LambdaExpr::getExplicitTemplateParameterListRange() const {
+  TemplateParameterList *List = getTemplateParameterList();

faisalv wrote:
> I think this should return an invalid range if getExplicitCount is 0.
> might assert that when not 0, langleloc does not equal rangleloc.
> 
I think it does return an invalid range in that case. Without explicit template 
parameters, getLAngleLoc and getRAngleLoc return invalid locations. And a range 
of invalid locations is an invalid range. But I suppose that could be asserted 
to make sure.



Comment at: lib/Sema/SemaLambda.cpp:495
+  reinterpret_cast(TParams.begin()),
+  reinterpret_cast(TParams.end()));
+  LSI->NumExplicitTemplateParams = TParams.size();

faisalv wrote:
> ack - avoid reinterpret cast please - why not just stick to Decl* for 
> TemplateParams for now  - and add some fixme's that suggest we should 
> consider refactoring ParseTemplateParameterList to accept a vector of 
> nameddecls - and update this when that gets updated ?
> 
> Perhaps add an assert here that iterates through and checks to make sure each 
> item in this list is some form of a template parameter decl - within an 
> #ifndef NDEBUG block (or your conversion check to NameDecl should suffice?)
Unfortunately `TemplateParameterList::Create` expects an array of `NamedDecl`, 
so there’ll need to be a forced downcast somewhere. By getting that over with 
as soon as possible, any errors will be caught straight away by that assertion 
instead of moving the problem down the line somewhere and making it more 
difficult to see where it went wrong.


https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-25 Thread Faisal Vali via Phabricator via cfe-commits
faisalv added inline comments.



Comment at: lib/AST/ExprCXX.cpp:979
 
+SourceRange LambdaExpr::getExplicitTemplateParameterListRange() const {
+  TemplateParameterList *List = getTemplateParameterList();

I think this should return an invalid range if getExplicitCount is 0.
might assert that when not 0, langleloc does not equal rangleloc.




Comment at: lib/Sema/SemaLambda.cpp:486
+ && "Already acted on explicit template parameters");
+  assert(LSI->TemplateParams.size() == 0
+ && "Explicit template parameters should come "

Perhaps also assert TParams.size should not be 0?



Comment at: lib/Sema/SemaLambda.cpp:495
+  reinterpret_cast(TParams.begin()),
+  reinterpret_cast(TParams.end()));
+  LSI->NumExplicitTemplateParams = TParams.size();

ack - avoid reinterpret cast please - why not just stick to Decl* for 
TemplateParams for now  - and add some fixme's that suggest we should consider 
refactoring ParseTemplateParameterList to accept a vector of nameddecls - and 
update this when that gets updated ?

Perhaps add an assert here that iterates through and checks to make sure each 
item in this list is some form of a template parameter decl - within an #ifndef 
NDEBUG block (or your conversion check to NameDecl should suffice?)


https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-21 Thread Hamza Sood via Phabricator via cfe-commits
hamzasood updated this revision to Diff 112018.
hamzasood added a comment.

- Info about a lambda's explicit template parameters is now exposed in the AST 
(see changes to LambdaExpr). It turns out that no extra storage was actually 
needed to achieve this.
- Removed remnants of a previous implementation (unused 
getExplicitTemplateParams function, creation of a TemplateParameterList in 
ActOnLambdaTemplateParameterList).
- Renamed ActOnLambdaTemplateParameterList -> 
ActOnLambdaExplicitTemplateParameterList (which is a bit more clear).
- Changed LambdaScopeInfo::TemplateParams from a vector of Decl* to a vector of 
NamedDecl*.


https://reviews.llvm.org/D36527

Files:
  include/clang/AST/ExprCXX.h
  include/clang/Basic/DiagnosticParseKinds.td
  include/clang/Sema/ScopeInfo.h
  include/clang/Sema/Sema.h
  lib/AST/ExprCXX.cpp
  lib/Parse/ParseExprCXX.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaLambda.cpp
  lib/Sema/SemaType.cpp
  test/CXX/temp/temp.decls/temp.variadic/p4.cpp
  test/Parser/cxx2a-template-lambdas.cpp
  test/SemaCXX/cxx2a-template-lambdas.cpp
  www/cxx_status.html

Index: www/cxx_status.html
===
--- www/cxx_status.html
+++ www/cxx_status.html
@@ -822,7 +822,7 @@
 
   template-parameter-list for generic lambdas
   http://wg21.link/p0428r2";>P0428R2
-  No
+  SVN
 
 
   Initializer list constructors in class template argument deduction
Index: test/SemaCXX/cxx2a-template-lambdas.cpp
===
--- test/SemaCXX/cxx2a-template-lambdas.cpp
+++ test/SemaCXX/cxx2a-template-lambdas.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -std=c++2a -verify %s
+
+template
+constexpr bool is_same = false;
+
+template
+constexpr bool is_same = true;
+
+template
+struct DummyTemplate { };
+
+void func() {
+  auto L0 = [](T arg) {
+static_assert(is_same);
+  };
+  L0(0);
+
+  auto L1 = [] {
+static_assert(I == 5);
+  };
+  L1.operator()<5>();
+
+  auto L2 = [] class T, class U>(T &&arg) {
+static_assert(is_same, DummyTemplate>);
+  };
+  L2(DummyTemplate());
+}
+
+template // expected-note {{declared here}}
+struct ShadowMe {
+  void member_func() {
+auto L = [] { }; // expected-error {{'T' shadows template parameter}}
+  }
+};
Index: test/Parser/cxx2a-template-lambdas.cpp
===
--- test/Parser/cxx2a-template-lambdas.cpp
+++ test/Parser/cxx2a-template-lambdas.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -std=c++2a %s -verify
+
+auto L0 = []<> { }; //expected-error {{cannot be empty}}
+
+auto L1 = [] { };
+auto L2 = [](T1 arg1, T2 arg2) -> T1 { };
+auto L3 = [](auto arg) { T t; };
+auto L4 = []() { };
Index: test/CXX/temp/temp.decls/temp.variadic/p4.cpp
===
--- test/CXX/temp/temp.decls/temp.variadic/p4.cpp
+++ test/CXX/temp/temp.decls/temp.variadic/p4.cpp
@@ -213,8 +213,10 @@
   };
 #endif
 
+#if __cplusplus >= 201707L
   //- in a template parameter pack that is a pack expansion
-  // FIXME: We do not support any way to reach this case yet.
+  swallow([] typename ...W>(W ...wv) { });
+#endif
 
   //- in an initializer-list
   int arr[] = {T().x...};
@@ -279,11 +281,6 @@
   struct T { int x; using U = int; };
   void g() { f(1, 2, 3); }
 
-  template void pack_in_lambda(U ...u) { // expected-note {{here}}
-// FIXME: Move this test into 'f' above once we support this syntax.
-[] typename ...U>(U ...uv) {}; // expected-error {{expected body of lambda}} expected-error {{does not refer to a value}}
-  }
-
   template void pack_expand_attr() {
 // FIXME: Move this test into 'f' above once we support this.
 [[gnu::aligned(alignof(T))...]] int x; // expected-error {{cannot be used as an attribute pack}} expected-error {{unexpanded}}
Index: lib/Sema/SemaType.cpp
===
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -2790,7 +2790,7 @@
 sema::LambdaScopeInfo *LSI = SemaRef.getCurLambda();
 assert(LSI && "No LambdaScopeInfo on the stack!");
 const unsigned TemplateParameterDepth = LSI->AutoTemplateParameterDepth;
-const unsigned AutoParameterPosition = LSI->AutoTemplateParams.size();
+const unsigned AutoParameterPosition = LSI->TemplateParams.size();
 const bool IsParameterPack = D.hasEllipsis();
 
 // Create the TemplateTypeParmDecl here to retrieve the corresponding
@@ -2802,7 +2802,8 @@
 /*KeyLoc*/SourceLocation(), /*NameLoc*/D.getLocStart(),
 TemplateParameterDepth, AutoParameterPosition,
 /*Identifier*/nullptr, false, IsParameterPack);
-LSI->AutoTemplateParams.push_back(CorrespondingTemplateParam);
+CorrespondingTemplateParam->setImplicit();
+LSI->TemplateParams.push_back(CorrespondingTemplateParam);
 //

[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-21 Thread Faisal Vali via Phabricator via cfe-commits
faisalv added inline comments.



Comment at: lib/Parse/ParseExprCXX.cpp:1116
+  if (HasExplicitTemplateParams) {
+SmallVector TemplateParams;
+SourceLocation LAngleLoc, RAngleLoc;

hamzasood wrote:
> faisalv wrote:
> > hamzasood wrote:
> > > faisalv wrote:
> > > > Why not Just use/pass LSI->TemplateParams?
> > > I thought that Parser and Sema stay separate, and communicate through 
> > > various ActOn functions? Directly accessing LSI would violate that.
> > Aah yes - you're right.  Still it does seem a little wasteful to create two 
> > of those (and then append).  What are your thoughts about passing the 
> > argument by (moved from) value, and then swapping their guts within ActOn 
> > (i..e value-semantics) ?  (I suppose the only concern would be the small 
> > array case - but i think that would be quite easy for any optimizer to 
> > inline).   
> > 
> I don't think a SmallVectorImpl can be passed by value.
> 
> So to make that work, the function would either needed to be templated 
> (SmallVector) or only accept a SmallVector. And I don't 
> think either of those options are worthwhile.
OK - add a FIXME that alerts folks that we currently make two copies of this 
and ideally we shouldn't need to.


https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-21 Thread Faisal Vali via Phabricator via cfe-commits
faisalv added inline comments.



Comment at: lib/Sema/SemaLambda.cpp:858
+KnownDependent = CurScope->getTemplateParamParent() != nullptr;
+  }
 

hamzasood wrote:
> faisalv wrote:
> > Hmm - now that you drew my attention to this ;) - I'm pretty sure this is 
> > broken - but (embarrassingly) it broke back when i implemented generic 
> > lambdas (and interestingly is less broken w generic lambdas w explicit 
> > TPLs) - could I ask you to add a FIXME here that states something along the 
> > lines of:  
> > 
> > When parsing default arguments that contain lambdas, it seems necessary to 
> > know whether the containing parameter-declaration clause is that of a 
> > template to mark the closure type created in the default-argument as 
> > dependent.  Using template params to detect dependence is not enough for 
> > all generic lambdas since you can have generic lambdas without explicit 
> > template parameters, and whose default arguments contain lambdas that 
> > should be dependent - and you can not rely on the existence of a template 
> > parameter scope to detect those cases.  Consider:
> >auto L = [](int I = [] { return 5; }(), auto a) { };  
> > The above nested closure type (of the default argument) occurs within a 
> > dependent context and is therefore dependent - but we won't know that until 
> > we parse the second parameter.  
> > 
> > p.s. I'll try and get around to fixing this if no one else does.
> > 
> Good point. Now you mention it, isn't it even more broken than than?
> E.g:
> 
> ```
>  auto L = [](auto A, int I = [] { return 5; }());
> ```
> 
> L is known to be generic before we parse the nested lambda, but template 
> param scopes aren't established for auto parameters (I think), so the nested 
> lambda won't get marked as dependent
I was aware of that - but I think that's the easier case to fix (where you see 
the auto first - hence i reversed it in my example).


https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-21 Thread Hamza Sood via Phabricator via cfe-commits
hamzasood added inline comments.



Comment at: lib/Parse/ParseExprCXX.cpp:1116
+  if (HasExplicitTemplateParams) {
+SmallVector TemplateParams;
+SourceLocation LAngleLoc, RAngleLoc;

faisalv wrote:
> hamzasood wrote:
> > faisalv wrote:
> > > Why not Just use/pass LSI->TemplateParams?
> > I thought that Parser and Sema stay separate, and communicate through 
> > various ActOn functions? Directly accessing LSI would violate that.
> Aah yes - you're right.  Still it does seem a little wasteful to create two 
> of those (and then append).  What are your thoughts about passing the 
> argument by (moved from) value, and then swapping their guts within ActOn 
> (i..e value-semantics) ?  (I suppose the only concern would be the small 
> array case - but i think that would be quite easy for any optimizer to 
> inline).   
> 
I don't think a SmallVectorImpl can be passed by value.

So to make that work, the function would either needed to be templated 
(SmallVector) or only accept a SmallVector. And I don't 
think either of those options are worthwhile.



Comment at: lib/Sema/SemaLambda.cpp:858
+KnownDependent = CurScope->getTemplateParamParent() != nullptr;
+  }
 

faisalv wrote:
> Hmm - now that you drew my attention to this ;) - I'm pretty sure this is 
> broken - but (embarrassingly) it broke back when i implemented generic 
> lambdas (and interestingly is less broken w generic lambdas w explicit TPLs) 
> - could I ask you to add a FIXME here that states something along the lines 
> of:  
> 
> When parsing default arguments that contain lambdas, it seems necessary to 
> know whether the containing parameter-declaration clause is that of a 
> template to mark the closure type created in the default-argument as 
> dependent.  Using template params to detect dependence is not enough for all 
> generic lambdas since you can have generic lambdas without explicit template 
> parameters, and whose default arguments contain lambdas that should be 
> dependent - and you can not rely on the existence of a template parameter 
> scope to detect those cases.  Consider:
>auto L = [](int I = [] { return 5; }(), auto a) { };  
> The above nested closure type (of the default argument) occurs within a 
> dependent context and is therefore dependent - but we won't know that until 
> we parse the second parameter.  
> 
> p.s. I'll try and get around to fixing this if no one else does.
> 
Good point. Now you mention it, isn't it even more broken than than?
E.g:

```
 auto L = [](auto A, int I = [] { return 5; }());
```

L is known to be generic before we parse the nested lambda, but template param 
scopes aren't established for auto parameters (I think), so the nested lambda 
won't get marked as dependent


https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-21 Thread Faisal Vali via Phabricator via cfe-commits
faisalv added inline comments.



Comment at: lib/Parse/ParseExprCXX.cpp:1116
+  if (HasExplicitTemplateParams) {
+SmallVector TemplateParams;
+SourceLocation LAngleLoc, RAngleLoc;

hamzasood wrote:
> faisalv wrote:
> > Why not Just use/pass LSI->TemplateParams?
> I thought that Parser and Sema stay separate, and communicate through various 
> ActOn functions? Directly accessing LSI would violate that.
Aah yes - you're right.  Still it does seem a little wasteful to create two of 
those (and then append).  What are your thoughts about passing the argument by 
(moved from) value, and then swapping their guts within ActOn (i..e 
value-semantics) ?  (I suppose the only concern would be the small array case - 
but i think that would be quite easy for any optimizer to inline).   



https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-21 Thread Hamza Sood via Phabricator via cfe-commits
hamzasood marked 5 inline comments as done.
hamzasood added a comment.

So to clarify: NumExplicitTemplateParams should be stored in 
LambdaDefinitionData (with an accessor in LambdaExpr) and 
ExplicitTemplateParamRange (SourceRange) should be stored in LambdaExpr?
That makes sense, but doesn't seem consistent with how things are currently 
stored. E.g. NumCaptures is stored in both LambdaDefinitionData and LambdaExpr.




Comment at: lib/Parse/ParseExprCXX.cpp:1116
+  if (HasExplicitTemplateParams) {
+SmallVector TemplateParams;
+SourceLocation LAngleLoc, RAngleLoc;

faisalv wrote:
> Why not Just use/pass LSI->TemplateParams?
I thought that Parser and Sema stay separate, and communicate through various 
ActOn functions? Directly accessing LSI would violate that.


https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-21 Thread Faisal Vali via Phabricator via cfe-commits
faisalv added a comment.

In regards to representing this in the AST - I think (based on precedence) that 
the number of explicit template parameters should be stored in 
LambdaDefinitionData - and the interface exposed through LambdaExpr (where the 
source information of the template parameter list should be stored too i think 
- Richard you agree?).

Also can you add examples of such generic lambdas that are nested within either 
other generic lambdas or templates - and make sure that they 
instantiate/substitute correctly - and that we really don't have to touch the 
template instantiation machinery?

Thanks!




Comment at: include/clang/Sema/ScopeInfo.h:955
+  }
+
   // When passed the index, returns the VarDecl and Expr associated

This function doesn't seem to be called anywhere?



Comment at: lib/Parse/ParseExprCXX.cpp:1116
+  if (HasExplicitTemplateParams) {
+SmallVector TemplateParams;
+SourceLocation LAngleLoc, RAngleLoc;

Why not Just use/pass LSI->TemplateParams?



Comment at: lib/Sema/SemaLambda.cpp:501
+  LAngleLoc, TParams, RAngleLoc,
+  /*RequiresClause=*/nullptr);
+

I'm not sure i see the point in creating the template parameter list here and 
returning it, when it's not used anywhere?  The TPL is created and cached in 
GLTemplateParameterList when needed it seems.




Comment at: lib/Sema/SemaLambda.cpp:858
+KnownDependent = CurScope->getTemplateParamParent() != nullptr;
+  }
 

Hmm - now that you drew my attention to this ;) - I'm pretty sure this is 
broken - but (embarrassingly) it broke back when i implemented generic lambdas 
(and interestingly is less broken w generic lambdas w explicit TPLs) - could I 
ask you to add a FIXME here that states something along the lines of:  

When parsing default arguments that contain lambdas, it seems necessary to know 
whether the containing parameter-declaration clause is that of a template to 
mark the closure type created in the default-argument as dependent.  Using 
template params to detect dependence is not enough for all generic lambdas 
since you can have generic lambdas without explicit template parameters, and 
whose default arguments contain lambdas that should be dependent - and you can 
not rely on the existence of a template parameter scope to detect those cases.  
Consider:
   auto L = [](int I = [] { return 5; }(), auto a) { };  
The above nested closure type (of the default argument) occurs within a 
dependent context and is therefore dependent - but we won't know that until we 
parse the second parameter.  

p.s. I'll try and get around to fixing this if no one else does.



https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-20 Thread Hamza Sood via Phabricator via cfe-commits
hamzasood updated this revision to Diff 111892.
hamzasood added a comment.

Sorry, I've just spotted a small mistake in how the auto parameter depth is 
recorded.
This update fixes it.


https://reviews.llvm.org/D36527

Files:
  include/clang/Basic/DiagnosticParseKinds.td
  include/clang/Sema/ScopeInfo.h
  include/clang/Sema/Sema.h
  lib/Parse/ParseExprCXX.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaLambda.cpp
  lib/Sema/SemaType.cpp
  test/CXX/temp/temp.decls/temp.variadic/p4.cpp
  test/Parser/cxx2a-template-lambdas.cpp
  test/SemaCXX/cxx2a-template-lambdas.cpp
  www/cxx_status.html

Index: www/cxx_status.html
===
--- www/cxx_status.html
+++ www/cxx_status.html
@@ -822,7 +822,7 @@
 
   template-parameter-list for generic lambdas
   http://wg21.link/p0428r2";>P0428R2
-  No
+  SVN
 
 
   Initializer list constructors in class template argument deduction
Index: test/SemaCXX/cxx2a-template-lambdas.cpp
===
--- test/SemaCXX/cxx2a-template-lambdas.cpp
+++ test/SemaCXX/cxx2a-template-lambdas.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -std=c++2a -verify %s
+
+template
+constexpr bool is_same = false;
+
+template
+constexpr bool is_same = true;
+
+template
+struct DummyTemplate { };
+
+void func() {
+  auto L0 = [](T arg) {
+static_assert(is_same);
+  };
+  L0(0);
+
+  auto L1 = [] {
+static_assert(I == 5);
+  };
+  L1.operator()<5>();
+
+  auto L2 = [] class T, class U>(T &&arg) {
+static_assert(is_same, DummyTemplate>);
+  };
+  L2(DummyTemplate());
+}
+
+template // expected-note {{declared here}}
+struct ShadowMe {
+  void member_func() {
+auto L = [] { }; // expected-error {{'T' shadows template parameter}}
+  }
+};
Index: test/Parser/cxx2a-template-lambdas.cpp
===
--- test/Parser/cxx2a-template-lambdas.cpp
+++ test/Parser/cxx2a-template-lambdas.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -std=c++2a %s -verify
+
+auto L0 = []<> { }; //expected-error {{cannot be empty}}
+
+auto L1 = [] { };
+auto L2 = [](T1 arg1, T2 arg2) -> T1 { };
+auto L3 = [](auto arg) { T t; };
+auto L4 = []() { };
Index: test/CXX/temp/temp.decls/temp.variadic/p4.cpp
===
--- test/CXX/temp/temp.decls/temp.variadic/p4.cpp
+++ test/CXX/temp/temp.decls/temp.variadic/p4.cpp
@@ -213,8 +213,10 @@
   };
 #endif
 
+#if __cplusplus >= 201707L
   //- in a template parameter pack that is a pack expansion
-  // FIXME: We do not support any way to reach this case yet.
+  swallow([] typename ...W>(W ...wv) { });
+#endif
 
   //- in an initializer-list
   int arr[] = {T().x...};
@@ -279,11 +281,6 @@
   struct T { int x; using U = int; };
   void g() { f(1, 2, 3); }
 
-  template void pack_in_lambda(U ...u) { // expected-note {{here}}
-// FIXME: Move this test into 'f' above once we support this syntax.
-[] typename ...U>(U ...uv) {}; // expected-error {{expected body of lambda}} expected-error {{does not refer to a value}}
-  }
-
   template void pack_expand_attr() {
 // FIXME: Move this test into 'f' above once we support this.
 [[gnu::aligned(alignof(T))...]] int x; // expected-error {{cannot be used as an attribute pack}} expected-error {{unexpanded}}
Index: lib/Sema/SemaType.cpp
===
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -2790,7 +2790,7 @@
 sema::LambdaScopeInfo *LSI = SemaRef.getCurLambda();
 assert(LSI && "No LambdaScopeInfo on the stack!");
 const unsigned TemplateParameterDepth = LSI->AutoTemplateParameterDepth;
-const unsigned AutoParameterPosition = LSI->AutoTemplateParams.size();
+const unsigned AutoParameterPosition = LSI->TemplateParams.size();
 const bool IsParameterPack = D.hasEllipsis();
 
 // Create the TemplateTypeParmDecl here to retrieve the corresponding
@@ -2802,7 +2802,7 @@
 /*KeyLoc*/SourceLocation(), /*NameLoc*/D.getLocStart(),
 TemplateParameterDepth, AutoParameterPosition,
 /*Identifier*/nullptr, false, IsParameterPack);
-LSI->AutoTemplateParams.push_back(CorrespondingTemplateParam);
+LSI->TemplateParams.push_back(CorrespondingTemplateParam);
 // Replace the 'auto' in the function parameter with this invented 
 // template type parameter.
 // FIXME: Retain some type sugar to indicate that this was written
Index: lib/Sema/SemaLambda.cpp
===
--- lib/Sema/SemaLambda.cpp
+++ lib/Sema/SemaLambda.cpp
@@ -229,15 +229,17 @@
   if (LSI->GLTemplateParameterList)
 return LSI->GLTemplateParameterList;
 
-  if (!LSI->AutoTemplateParams.empty()) {
-SourceRange IntroRange = LSI->IntroducerRange;
-SourceLocation LAn

[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-20 Thread Hamza Sood via Phabricator via cfe-commits
hamzasood updated this revision to Diff 111887.
hamzasood added a comment.

- Corrected a typo.
- Made HasExplicitTemplateParams const.
- Reverted the change in where template depth is incremented and recorded.
- Fixed the broken test.
- Keep the template scope active instead of exiting it and manually introducing 
the template parameters into scope. I think this works fine now; you can see 
the fix in line 847 of SemaLambda.cpp. Basically having a template scope active 
resulted in the lambda being incorrectly marked as dependent, which broke a lot 
of stuff.

One question I have is how to expose explicit template params in the AST (if at 
all)? I was thinking of adding an int representing the number of template 
params that were explicitly specified. But do I add that to LambdaExpr or 
CXXRecordDecl::LambdaDefinitionData (or both)?


https://reviews.llvm.org/D36527

Files:
  include/clang/Basic/DiagnosticParseKinds.td
  include/clang/Sema/ScopeInfo.h
  include/clang/Sema/Sema.h
  lib/Parse/ParseExprCXX.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaLambda.cpp
  lib/Sema/SemaType.cpp
  test/CXX/temp/temp.decls/temp.variadic/p4.cpp
  test/Parser/cxx2a-template-lambdas.cpp
  test/SemaCXX/cxx2a-template-lambdas.cpp
  www/cxx_status.html

Index: www/cxx_status.html
===
--- www/cxx_status.html
+++ www/cxx_status.html
@@ -822,7 +822,7 @@
 
   template-parameter-list for generic lambdas
   http://wg21.link/p0428r2";>P0428R2
-  No
+  SVN
 
 
   Initializer list constructors in class template argument deduction
Index: test/SemaCXX/cxx2a-template-lambdas.cpp
===
--- test/SemaCXX/cxx2a-template-lambdas.cpp
+++ test/SemaCXX/cxx2a-template-lambdas.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -std=c++2a -verify %s
+
+template
+constexpr bool is_same = false;
+
+template
+constexpr bool is_same = true;
+
+template
+struct DummyTemplate { };
+
+void func() {
+  auto L0 = [](T arg) {
+static_assert(is_same);
+  };
+  L0(0);
+
+  auto L1 = [] {
+static_assert(I == 5);
+  };
+  L1.operator()<5>();
+
+  auto L2 = [] class T, class U>(T &&arg) {
+static_assert(is_same, DummyTemplate>);
+  };
+  L2(DummyTemplate());
+}
+
+template // expected-note {{declared here}}
+struct ShadowMe {
+  void member_func() {
+auto L = [] { }; // expected-error {{'T' shadows template parameter}}
+  }
+};
Index: test/Parser/cxx2a-template-lambdas.cpp
===
--- test/Parser/cxx2a-template-lambdas.cpp
+++ test/Parser/cxx2a-template-lambdas.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -std=c++2a %s -verify
+
+auto L0 = []<> { }; //expected-error {{cannot be empty}}
+
+auto L1 = [] { };
+auto L2 = [](T1 arg1, T2 arg2) -> T1 { };
+auto L3 = [](auto arg) { T t; };
+auto L4 = []() { };
Index: test/CXX/temp/temp.decls/temp.variadic/p4.cpp
===
--- test/CXX/temp/temp.decls/temp.variadic/p4.cpp
+++ test/CXX/temp/temp.decls/temp.variadic/p4.cpp
@@ -213,8 +213,10 @@
   };
 #endif
 
+#if __cplusplus >= 201707L
   //- in a template parameter pack that is a pack expansion
-  // FIXME: We do not support any way to reach this case yet.
+  swallow([] typename ...W>(W ...wv) { });
+#endif
 
   //- in an initializer-list
   int arr[] = {T().x...};
@@ -279,11 +281,6 @@
   struct T { int x; using U = int; };
   void g() { f(1, 2, 3); }
 
-  template void pack_in_lambda(U ...u) { // expected-note {{here}}
-// FIXME: Move this test into 'f' above once we support this syntax.
-[] typename ...U>(U ...uv) {}; // expected-error {{expected body of lambda}} expected-error {{does not refer to a value}}
-  }
-
   template void pack_expand_attr() {
 // FIXME: Move this test into 'f' above once we support this.
 [[gnu::aligned(alignof(T))...]] int x; // expected-error {{cannot be used as an attribute pack}} expected-error {{unexpanded}}
Index: lib/Sema/SemaType.cpp
===
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -2790,7 +2790,7 @@
 sema::LambdaScopeInfo *LSI = SemaRef.getCurLambda();
 assert(LSI && "No LambdaScopeInfo on the stack!");
 const unsigned TemplateParameterDepth = LSI->AutoTemplateParameterDepth;
-const unsigned AutoParameterPosition = LSI->AutoTemplateParams.size();
+const unsigned AutoParameterPosition = LSI->TemplateParams.size();
 const bool IsParameterPack = D.hasEllipsis();
 
 // Create the TemplateTypeParmDecl here to retrieve the corresponding
@@ -2802,7 +2802,7 @@
 /*KeyLoc*/SourceLocation(), /*NameLoc*/D.getLocStart(),
 TemplateParameterDepth, AutoParameterPosition,
 /*Identifier*/nullptr, false, IsParameterPack);
-LSI->AutoTemplateParams.push_back(Co

[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-20 Thread Faisal Vali via Phabricator via cfe-commits
faisalv added inline comments.



Comment at: lib/Parse/ParseExprCXX.cpp:1090
+  TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
+  Actions.RecordParsingTemplateParameterDepth(TemplateParameterDepth);
+

hamzasood wrote:
> faisalv wrote:
> > Since you only really need to pass this information on for computing the 
> > depth of the 'auto' parameters - why not just leave the 
> > RecordParsingTEmplateParameterDepth call where it was, increment the 
> > template depth once we parse the TPL, and just pass in the right depth 
> > (minus one if ExplicitTemplateParameters) and increment the tracker if we 
> > getGenericLambda but no explicit TPL?
> > 
> > I wonder if that might be the safer way to do it - especially if you have 
> > generic lambdas in default arguments of generic lambdas - each of which 
> > have explicit template parameters also??
> > 
> > thoughts?
> > 
> While the depth is currently only used for auto parameters, that could change 
> in the future (especially since the function name is quite general. I.e. 
> record depth instead of record auto depth or whatever). Because of that, it 
> wouldn't seem right to not record it in the case where there's an explicit 
> template param list but no function parameters. So the options were to record 
> it twice (parsing the explicit TPL and function parameters) or just do it 
> once for every lambda. Since it's a cheap operation (pretty much just setting 
> a variable), I went for the latter.
> 
> Good point about incrementing after seeing an explicit template param list. 
> I'll change that in the next update.
I think If the depth will be needed in the future for something other than 
determining the depth of the auto parameter - then that change (of moving the 
call outside) should occur in that 'future' patch.  I don't see why you say 
that it would ever need to be called twice in your patch?

Just like we localize our variable declarations and limit their scope (to ease 
comprehension) similarly, i think changes to state should be as local to the 
part of the program that uses that state (once again for comprehension:  If you 
move the call, folks now might have to put in more effort when trying to 
comprehend the effects of that call, since the set of potential operations 
relying on that set grows).




Comment at: lib/Parse/ParseExprCXX.cpp:1305
 
+  TemplateParamScope.Exit();
+

hamzasood wrote:
> faisalv wrote:
> > Why do you exit the scope here, and then re-add the template parameters to 
> > the current scope?  What confusion (if any) occurs if you leave this scope 
> > on?
> > 
> That was my original attempt, but I just couldn't get it to work.
> 
> E.g.
> 
> ```
> auto l = [](T t) { };
> ```
> 
> triggers an assertion:
> 
> ```
> (!A->getDeducedType().isNull() && "cannot request the size of an undeduced or 
> dependent auto type"), function getTypeInfoImpl, file 
> /Users/hamzasood/LLVM/src/tools/clang/lib/AST/ASTContext.cpp, line 1883.
> ```
> 
> A lot of other things broke too.
> 
> I figured since function parameters are explicitly added to scope, it would 
> make sense to introduce explicit template parameters in the same place.
Hmm - I think at the very least we should understand exactly what assumptions 
are being violated - and then decide whether we wish to temporarily 
bypass/shortcut the way scopes are supposed to 'seamlessly' work (w a fixme or 
comment prior to the 'false exit' that explains why we are doing so) or adjust 
the assumptions...


https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-20 Thread Hamza Sood via Phabricator via cfe-commits
hamzasood added inline comments.



Comment at: lib/Parse/ParseExprCXX.cpp:1090
+  TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
+  Actions.RecordParsingTemplateParameterDepth(TemplateParameterDepth);
+

faisalv wrote:
> Since you only really need to pass this information on for computing the 
> depth of the 'auto' parameters - why not just leave the 
> RecordParsingTEmplateParameterDepth call where it was, increment the template 
> depth once we parse the TPL, and just pass in the right depth (minus one if 
> ExplicitTemplateParameters) and increment the tracker if we getGenericLambda 
> but no explicit TPL?
> 
> I wonder if that might be the safer way to do it - especially if you have 
> generic lambdas in default arguments of generic lambdas - each of which have 
> explicit template parameters also??
> 
> thoughts?
> 
While the depth is currently only used for auto parameters, that could change 
in the future (especially since the function name is quite general. I.e. record 
depth instead of record auto depth or whatever). Because of that, it wouldn't 
seem right to not record it in the case where there's an explicit template 
param list but no function parameters. So the options were to record it twice 
(parsing the explicit TPL and function parameters) or just do it once for every 
lambda. Since it's a cheap operation (pretty much just setting a variable), I 
went for the latter.

Good point about incrementing after seeing an explicit template param list. 
I'll change that in the next update.



Comment at: lib/Parse/ParseExprCXX.cpp:1305
 
+  TemplateParamScope.Exit();
+

faisalv wrote:
> Why do you exit the scope here, and then re-add the template parameters to 
> the current scope?  What confusion (if any) occurs if you leave this scope on?
> 
That was my original attempt, but I just couldn't get it to work.

E.g.

```
auto l = [](T t) { };
```

triggers an assertion:

```
(!A->getDeducedType().isNull() && "cannot request the size of an undeduced or 
dependent auto type"), function getTypeInfoImpl, file 
/Users/hamzasood/LLVM/src/tools/clang/lib/AST/ASTContext.cpp, line 1883.
```

A lot of other things broke too.

I figured since function parameters are explicitly added to scope, it would 
make sense to introduce explicit template parameters in the same place.


https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-19 Thread Faisal Vali via Phabricator via cfe-commits
faisalv added a comment.

In regards to that failing test (that was added since review began) - could you 
fix that test pls (i.e. rename the nested ttp 'U' to something else) and move 
it into the function 'f' as requested by the author?
Might want to include a similar (but not same) example of matching complexity 
to your tests too.

Thanks!


https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-19 Thread Faisal Vali via Phabricator via cfe-commits
faisalv added inline comments.



Comment at: include/clang/Sema/ScopeInfo.h:774
+  /// \brief The number of parameters in the template parameter list that were
+  /// explicitely specified by the user, as opposed to being invented by use
+  /// of an auto parameter.

typo: explicitly



Comment at: lib/Parse/ParseExprCXX.cpp:1090
+  TemplateParameterDepthRAII CurTemplateDepthTracker(TemplateParameterDepth);
+  Actions.RecordParsingTemplateParameterDepth(TemplateParameterDepth);
+

Since you only really need to pass this information on for computing the depth 
of the 'auto' parameters - why not just leave the 
RecordParsingTEmplateParameterDepth call where it was, increment the template 
depth once we parse the TPL, and just pass in the right depth (minus one if 
ExplicitTemplateParameters) and increment the tracker if we getGenericLambda 
but no explicit TPL?

I wonder if that might be the safer way to do it - especially if you have 
generic lambdas in default arguments of generic lambdas - each of which have 
explicit template parameters also??

thoughts?




Comment at: lib/Parse/ParseExprCXX.cpp:1113
+  // FIXME: Consider allowing this as an extension for GCC compatibiblity.
+  bool HasExplicitTemplateParams = getLangOpts().CPlusPlus2a
+   && Tok.is(tok::less);

make this const pls.



Comment at: lib/Parse/ParseExprCXX.cpp:1305
 
+  TemplateParamScope.Exit();
+

Why do you exit the scope here, and then re-add the template parameters to the 
current scope?  What confusion (if any) occurs if you leave this scope on?



https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-19 Thread Hamza Sood via Phabricator via cfe-commits
hamzasood updated this revision to Diff 111812.
hamzasood added a comment.

Changed a documentation comment to use \brief instead of stating the function 
name.
Only enter the template parameter scope if needed.
Changed the phrasing of the diagnostic when an empty template parameter list is 
encountered.

Since submitting this patch for review, a test 

 has been added which fails with this patch. The test has a FIXME comment about 
moving the test somewhere when template lambda syntax is supported, but I'm not 
sure what needs to be done. Any ideas?


https://reviews.llvm.org/D36527

Files:
  include/clang/Basic/DiagnosticParseKinds.td
  include/clang/Sema/ScopeInfo.h
  include/clang/Sema/Sema.h
  lib/Parse/ParseExprCXX.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaLambda.cpp
  lib/Sema/SemaType.cpp
  test/Parser/cxx2a-template-lambdas.cpp
  test/SemaCXX/cxx2a-template-lambdas.cpp
  www/cxx_status.html

Index: www/cxx_status.html
===
--- www/cxx_status.html
+++ www/cxx_status.html
@@ -822,7 +822,7 @@
 
   template-parameter-list for generic lambdas
   http://wg21.link/p0428r2";>P0428R2
-  No
+  SVN
 
 
   Initializer list constructors in class template argument deduction
Index: test/SemaCXX/cxx2a-template-lambdas.cpp
===
--- test/SemaCXX/cxx2a-template-lambdas.cpp
+++ test/SemaCXX/cxx2a-template-lambdas.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -std=c++2a -verify %s
+
+template
+constexpr bool is_same = false;
+
+template
+constexpr bool is_same = true;
+
+template
+struct DummyTemplate { };
+
+void func() {
+  auto L0 = [](T arg) {
+static_assert(is_same);
+  };
+  L0(0);
+
+  auto L1 = [] {
+static_assert(I == 5);
+  };
+  L1.operator()<5>();
+
+  auto L2 = [] class T, class U>(T &&arg) {
+static_assert(is_same, DummyTemplate>);
+  };
+  L2(DummyTemplate());
+}
+
+template // expected-note {{declared here}}
+struct ShadowMe {
+  void member_func() {
+auto L = [] { }; // expected-error {{'T' shadows template parameter}}
+  }
+};
Index: test/Parser/cxx2a-template-lambdas.cpp
===
--- test/Parser/cxx2a-template-lambdas.cpp
+++ test/Parser/cxx2a-template-lambdas.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -std=c++2a %s -verify
+
+auto L0 = []<> { }; //expected-error {{cannot be empty}}
+
+auto L1 = [] { };
+auto L2 = [](T1 arg1, T2 arg2) -> T1 { };
+auto L3 = [](auto arg) { T t; };
+auto L4 = []() { };
Index: lib/Sema/SemaType.cpp
===
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -2789,8 +2789,8 @@
 // template parameter type.
 sema::LambdaScopeInfo *LSI = SemaRef.getCurLambda();
 assert(LSI && "No LambdaScopeInfo on the stack!");
-const unsigned TemplateParameterDepth = LSI->AutoTemplateParameterDepth;
-const unsigned AutoParameterPosition = LSI->AutoTemplateParams.size();
+const unsigned TemplateParameterDepth = LSI->TemplateParameterDepth;
+const unsigned AutoParameterPosition = LSI->TemplateParams.size();
 const bool IsParameterPack = D.hasEllipsis();
 
 // Create the TemplateTypeParmDecl here to retrieve the corresponding
@@ -2802,7 +2802,7 @@
 /*KeyLoc*/SourceLocation(), /*NameLoc*/D.getLocStart(),
 TemplateParameterDepth, AutoParameterPosition,
 /*Identifier*/nullptr, false, IsParameterPack);
-LSI->AutoTemplateParams.push_back(CorrespondingTemplateParam);
+LSI->TemplateParams.push_back(CorrespondingTemplateParam);
 // Replace the 'auto' in the function parameter with this invented 
 // template type parameter.
 // FIXME: Retain some type sugar to indicate that this was written
Index: lib/Sema/SemaLambda.cpp
===
--- lib/Sema/SemaLambda.cpp
+++ lib/Sema/SemaLambda.cpp
@@ -229,15 +229,17 @@
   if (LSI->GLTemplateParameterList)
 return LSI->GLTemplateParameterList;
 
-  if (!LSI->AutoTemplateParams.empty()) {
-SourceRange IntroRange = LSI->IntroducerRange;
-SourceLocation LAngleLoc = IntroRange.getBegin();
-SourceLocation RAngleLoc = IntroRange.getEnd();
+  if (!LSI->TemplateParams.empty()) {
+SourceRange ListRange = LSI->ExplicitTemplateParamsRange.isValid()
+  ? LSI->ExplicitTemplateParamsRange
+  : LSI->IntroducerRange;
+SourceLocation LAngleLoc = ListRange.getBegin();
+SourceLocation RAngleLoc = ListRange.getEnd();
 LSI->GLTemplateParameterList = TemplateParameterList::Create(
 SemaRef.Context,
 /*Template kw loc*/ SourceLocation(), LAngleLoc,
-   

[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-18 Thread Faisal Vali via Phabricator via cfe-commits
faisalv added inline comments.



Comment at: lib/Parse/ParseExprCXX.cpp:1112
 
+  ParseScope TemplateParamScope(this, Scope::TemplateParamScope);
+  if (getLangOpts().CPlusPlus2a && Tok.is(tok::less)) {

hamzasood wrote:
> faisalv wrote:
> > We always create a template parameter scope here - but it's only the right 
> > scope if we have explicit template parameters, correct?
> > 
> > What I think we should do here is :
> >   - factor out (preferably as a separate patch) the post 
> > explicit-template-parameter-list parsing into a separate function (F1) 
> > which is then called from here.
> >   - then in this patch factor out the explicit template-parameter-list 
> > parsing also into a separate function that then either calls the function 
> > above ('F1'), or sequenced these statements before a call to 'F1'
> >   - also since gcc has had explicit template parameters on their generic 
> > lambdas for a while, can we find out under what options they have it 
> > enabled, and consider enabling it under those options for our gcc emulation 
> > mode? (or add a fixme for it?)
> >   - should we enable these explicit template parameters for pre-C++2a modes 
> > and emit extension/compatibility warnings where appropriate?
> > 
> Good point. It isn’t the “wrong” scope in the sense that is breaks anything, 
> but it is a bit wasteful to unconditionally push a potentially unneeded scope.
> 
> I have another idea that could be less intrusive, which is to replace this 
> line and the start of the if statement with:
> 
>   bool HasExplicitTemplateParams = getLangOpts().CPlusPlus2a && 
> Tok.is(tok::less);
>   ParseScope TemplateParamScope(this, Scope::TemplateParamScope, 
> HasExplicitTemplateParams);
>   if (HasExplicitTemplateParams) {
> // same code as before
>   }
> 
> That way the scope is only entered when needed, but no restructuring is 
> required (which I personally think would make things a bit harder to follow). 
> Could that work?
good idea - i think that should work too.  (Although i do still like the idea 
of refactoring this long function via extract-method - but i can always do that 
refactoring post this patch). 


https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-18 Thread Hamza Sood via Phabricator via cfe-commits
hamzasood added inline comments.



Comment at: lib/Parse/ParseExprCXX.cpp:1112
 
+  ParseScope TemplateParamScope(this, Scope::TemplateParamScope);
+  if (getLangOpts().CPlusPlus2a && Tok.is(tok::less)) {

faisalv wrote:
> We always create a template parameter scope here - but it's only the right 
> scope if we have explicit template parameters, correct?
> 
> What I think we should do here is :
>   - factor out (preferably as a separate patch) the post 
> explicit-template-parameter-list parsing into a separate function (F1) which 
> is then called from here.
>   - then in this patch factor out the explicit template-parameter-list 
> parsing also into a separate function that then either calls the function 
> above ('F1'), or sequenced these statements before a call to 'F1'
>   - also since gcc has had explicit template parameters on their generic 
> lambdas for a while, can we find out under what options they have it enabled, 
> and consider enabling it under those options for our gcc emulation mode? (or 
> add a fixme for it?)
>   - should we enable these explicit template parameters for pre-C++2a modes 
> and emit extension/compatibility warnings where appropriate?
> 
Good point. It isn’t the “wrong” scope in the sense that is breaks anything, 
but it is a bit wasteful to unconditionally push a potentially unneeded scope.

I have another idea that could be less intrusive, which is to replace this line 
and the start of the if statement with:

  bool HasExplicitTemplateParams = getLangOpts().CPlusPlus2a && 
Tok.is(tok::less);
  ParseScope TemplateParamScope(this, Scope::TemplateParamScope, 
HasExplicitTemplateParams);
  if (HasExplicitTemplateParams) {
// same code as before
  }

That way the scope is only entered when needed, but no restructuring is 
required (which I personally think would make things a bit harder to follow). 
Could that work?


https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-17 Thread Faisal Vali via Phabricator via cfe-commits
faisalv added inline comments.



Comment at: include/clang/Sema/Sema.h:5466
 
+  /// ActOnLambdaTemplateParameterList - This is called after parsing
+  /// the explicit template parameter list (if it exists) in C++2a.

Avoid listing the name of the function: replace a w a \brief comment.



Comment at: lib/Parse/ParseExprCXX.cpp:1112
 
+  ParseScope TemplateParamScope(this, Scope::TemplateParamScope);
+  if (getLangOpts().CPlusPlus2a && Tok.is(tok::less)) {

We always create a template parameter scope here - but it's only the right 
scope if we have explicit template parameters, correct?

What I think we should do here is :
  - factor out (preferably as a separate patch) the post 
explicit-template-parameter-list parsing into a separate function (F1) which is 
then called from here.
  - then in this patch factor out the explicit template-parameter-list parsing 
also into a separate function that then either calls the function above ('F1'), 
or sequenced these statements before a call to 'F1'
  - also since gcc has had explicit template parameters on their generic 
lambdas for a while, can we find out under what options they have it enabled, 
and consider enabling it under those options for our gcc emulation mode? (or 
add a fixme for it?)
  - should we enable these explicit template parameters for pre-C++2a modes and 
emit extension/compatibility warnings where appropriate?




Comment at: lib/Parse/ParseExprCXX.cpp:1123
+  Diag(RAngleLoc,
+   diag::err_expected_lambda_template_parameter_list);
+}

I think it might be more user friendly if you used a different error message 
for the <> case here - along the lines of: empty template parameter list is not 
allowed 


https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-16 Thread Faisal Vali via Phabricator via cfe-commits
faisalv added a comment.

I'll try and get you some feedback on this over the next couple of days (unless 
someone else jumps in).

Thanks for working on this!


https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-16 Thread John McCall via Phabricator via cfe-commits
rjmccall resigned from this revision.
rjmccall added a comment.

I don't think I'm best-equipped to review this, sorry.


https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-16 Thread Hamza Sood via Phabricator via cfe-commits
hamzasood added a comment.

Ping


https://reviews.llvm.org/D36527



___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36527: Implemented P0428R2 - Familiar template syntax for generic lambdas

2017-08-09 Thread Hamza Sood via Phabricator via cfe-commits
hamzasood created this revision.

This patch provides an implementation for P0428R2 .


https://reviews.llvm.org/D36527

Files:
  include/clang/Basic/DiagnosticParseKinds.td
  include/clang/Sema/ScopeInfo.h
  include/clang/Sema/Sema.h
  lib/Parse/ParseExprCXX.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaLambda.cpp
  lib/Sema/SemaType.cpp
  test/Parser/cxx2a-template-lambdas.cpp
  test/SemaCXX/cxx2a-template-lambdas.cpp
  www/cxx_status.html

Index: www/cxx_status.html
===
--- www/cxx_status.html
+++ www/cxx_status.html
@@ -777,13 +777,12 @@
 
 C++2a implementation status
 
-Clang does not yet support any of the proposed features of
-
+Clang has experimental support for some proposed features of
 the C++ standard following C++17, provisionally named C++2a.
 Note that support for these features may change or be removed without notice,
 as the draft C++2a standard evolves.
 
-
+You can use Clang in C++2a mode with the -std=c++2a option.
 
 
 List of features and minimum Clang version with support
@@ -823,7 +822,7 @@
 
   template-parameter-list for generic lambdas
   http://wg21.link/p0428r2";>P0428R2
-  No
+  SVN
 
 
   Initializer list constructors in class template argument deduction
Index: test/SemaCXX/cxx2a-template-lambdas.cpp
===
--- test/SemaCXX/cxx2a-template-lambdas.cpp
+++ test/SemaCXX/cxx2a-template-lambdas.cpp
@@ -0,0 +1,34 @@
+// RUN: %clang_cc1 -std=c++2a -verify %s
+
+template
+constexpr bool is_same = false;
+
+template
+constexpr bool is_same = true;
+
+template
+struct DummyTemplate { };
+
+void func() {
+  auto L0 = [](T arg) {
+static_assert(is_same);
+  };
+  L0(0);
+
+  auto L1 = [] {
+static_assert(I == 5);
+  };
+  L1.operator()<5>();
+
+  auto L2 = [] class T, class U>(T &&arg) {
+static_assert(is_same, DummyTemplate>);
+  };
+  L2(DummyTemplate());
+}
+
+template // expected-note {{declared here}}
+struct ShadowMe {
+  void member_func() {
+auto L = [] { }; // expected-error {{'T' shadows template parameter}}
+  }
+};
Index: test/Parser/cxx2a-template-lambdas.cpp
===
--- test/Parser/cxx2a-template-lambdas.cpp
+++ test/Parser/cxx2a-template-lambdas.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -std=c++2a %s -verify
+
+auto L0 = []<> { }; //expected-error {{expected template parameter list}}
+
+auto L1 = [] { };
+auto L2 = [](T1 arg1, T2 arg2) -> T1 { };
+auto L3 = [](auto arg) { T t; };
+auto L4 = []() { };
Index: lib/Sema/SemaType.cpp
===
--- lib/Sema/SemaType.cpp
+++ lib/Sema/SemaType.cpp
@@ -2789,8 +2789,8 @@
 // template parameter type.
 sema::LambdaScopeInfo *LSI = SemaRef.getCurLambda();
 assert(LSI && "No LambdaScopeInfo on the stack!");
-const unsigned TemplateParameterDepth = LSI->AutoTemplateParameterDepth;
-const unsigned AutoParameterPosition = LSI->AutoTemplateParams.size();
+const unsigned TemplateParameterDepth = LSI->TemplateParameterDepth;
+const unsigned AutoParameterPosition = LSI->TemplateParams.size();
 const bool IsParameterPack = D.hasEllipsis();
 
 // Create the TemplateTypeParmDecl here to retrieve the corresponding
@@ -2802,7 +2802,7 @@
 /*KeyLoc*/SourceLocation(), /*NameLoc*/D.getLocStart(),
 TemplateParameterDepth, AutoParameterPosition,
 /*Identifier*/nullptr, false, IsParameterPack);
-LSI->AutoTemplateParams.push_back(CorrespondingTemplateParam);
+LSI->TemplateParams.push_back(CorrespondingTemplateParam);
 // Replace the 'auto' in the function parameter with this invented 
 // template type parameter.
 // FIXME: Retain some type sugar to indicate that this was written
Index: lib/Sema/SemaLambda.cpp
===
--- lib/Sema/SemaLambda.cpp
+++ lib/Sema/SemaLambda.cpp
@@ -229,15 +229,17 @@
   if (LSI->GLTemplateParameterList)
 return LSI->GLTemplateParameterList;
 
-  if (!LSI->AutoTemplateParams.empty()) {
-SourceRange IntroRange = LSI->IntroducerRange;
-SourceLocation LAngleLoc = IntroRange.getBegin();
-SourceLocation RAngleLoc = IntroRange.getEnd();
+  if (!LSI->TemplateParams.empty()) {
+SourceRange ListRange = LSI->ExplicitTemplateParamsRange.isValid()
+  ? LSI->ExplicitTemplateParamsRange
+  : LSI->IntroducerRange;
+SourceLocation LAngleLoc = ListRange.getBegin();
+SourceLocation RAngleLoc = ListRange.getEnd();
 LSI->GLTemplateParameterList = TemplateParameterList::Create(
 SemaRef.Context,
 /*Template kw loc*/ SourceLocation(), LAngleLoc,
-llvm::makeArrayRef((NamedDecl *const *)LSI->AutoTemplateParams.data(),
-