[PATCH] D36357: Added a better diagnostic when using the delete operator with lambdas

2018-08-08 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 159832.
Rakete added a comment.

Rebase + friendly ping :)


Repository:
  rC Clang

https://reviews.llvm.org/D36357

Files:
  include/clang/Basic/DiagnosticParseKinds.td
  lib/Parse/ParseExprCXX.cpp
  test/FixIt/fixit-cxx0x.cpp
  test/Parser/cxx0x-lambda-expressions.cpp
  test/SemaCXX/new-delete-0x.cpp

Index: test/SemaCXX/new-delete-0x.cpp
===
--- test/SemaCXX/new-delete-0x.cpp
+++ test/SemaCXX/new-delete-0x.cpp
@@ -34,6 +34,6 @@
 void bad_deletes()
 {
   // 'delete []' is always array delete, per [expr.delete]p1.
-  // FIXME: Give a better diagnostic.
-  delete []{ return (int*)0; }(); // expected-error {{expected expression}}
+  delete []{ return (int*)0; }(); // expected-error {{'[]' after delete interpreted as 'delete[]'}}
 }
+
Index: test/Parser/cxx0x-lambda-expressions.cpp
===
--- test/Parser/cxx0x-lambda-expressions.cpp
+++ test/Parser/cxx0x-lambda-expressions.cpp
@@ -53,8 +53,11 @@
   void delete_lambda(int *p) {
 delete [] p;
 delete [] (int*) { new int }; // ok, compound-literal, not lambda
-delete [] { return new int; } (); // expected-error{{expected expression}}
+delete [] { return new int; } (); // expected-error {{'[]' after delete interpreted as 'delete[]'}}
 delete [&] { return new int; } (); // ok, lambda
+
+delete []() { return new int; }(); // expected-error{{'[]' after delete interpreted as 'delete[]'}}
+delete [](E Enum) { return new int((int)Enum); }(e); // expected-error{{'[]' after delete interpreted as 'delete[]'}}
   }
 
   // We support init-captures in C++11 as an extension.
Index: test/FixIt/fixit-cxx0x.cpp
===
--- test/FixIt/fixit-cxx0x.cpp
+++ test/FixIt/fixit-cxx0x.cpp
@@ -58,6 +58,9 @@
   (void)[&, i, i]{ }; // expected-error{{'i' can appear only once in a capture list}}
   (void)[] mutable { }; // expected-error{{lambda requires '()' before 'mutable'}}
   (void)[] -> int { }; // expected-error{{lambda requires '()' before return type}}
+
+  delete []() { return new int; }(); // expected-error{{'[]' after delete interpreted as 'delete[]'}}
+  delete [] { return new int; }(); // expected-error{{'[]' after delete interpreted as 'delete[]'}}
 }
 
 #define bar "bar"
Index: lib/Parse/ParseExprCXX.cpp
===
--- lib/Parse/ParseExprCXX.cpp
+++ lib/Parse/ParseExprCXX.cpp
@@ -2946,8 +2946,38 @@
 //   [Footnote: A lambda expression with a lambda-introducer that consists
 //  of empty square brackets can follow the delete keyword if
 //  the lambda expression is enclosed in parentheses.]
-// FIXME: Produce a better diagnostic if the '[]' is unambiguously a
-//lambda-introducer.
+
+const Token Next = GetLookAheadToken(2);
+
+// Basic lookahead to check if we have a lambda expression.
+if (Next.isOneOf(tok::l_brace, tok::less) ||
+(Next.is(tok::l_paren) &&
+ (GetLookAheadToken(3).is(tok::r_paren) ||
+  (GetLookAheadToken(3).is(tok::identifier) &&
+   GetLookAheadToken(4).is(tok::identifier) {
+  SourceLocation RightBracketLock = NextToken().getLocation();
+  // Warn if the non-capturing lambda isn't surrounded by parenthesis
+  // to disambiguate it from 'delete[]'.
+  ExprResult Lambda = ParseLambdaExpression();
+  if (Lambda.isInvalid())
+return ExprError();
+
+  SourceLocation StartLoc = Lambda.get()->getLocStart();
+  Diag(Start, diag::err_lambda_after_delete)
+  << SourceRange(Start, RightBracketLock)
+  << FixItHint::CreateInsertion(StartLoc, "(")
+  << FixItHint::CreateInsertion(
+ Lexer::getLocForEndOfToken(Lambda.get()->getLocEnd(), 0,
+Actions.getSourceManager(),
+getLangOpts()),
+ ")");
+
+  // Evaluate any postfix expressions used on the lambda.
+  Lambda = ParsePostfixExpressionSuffix(Lambda);
+  return Actions.ActOnCXXDelete(Start, UseGlobal, /*ArrayForm=*/false,
+Lambda.get());
+}
+
 ArrayDelete = true;
 BalancedDelimiterTracker T(*this, tok::l_square);
 
Index: include/clang/Basic/DiagnosticParseKinds.td
===
--- include/clang/Basic/DiagnosticParseKinds.td
+++ include/clang/Basic/DiagnosticParseKinds.td
@@ -99,6 +99,8 @@
   InGroup, DefaultIgnore;
 def ext_alignof_expr : ExtWarn<
   "%0 applied to an expression is a GNU extension">, InGroup;
+def err_lambda_after_delete : Error<
+  "'[]' after delete interpreted as 'delete[]'">;
 
 def warn_microsoft_dependent_exists : Warning<
   "dependent %select{__if_not_exists|__if_exists}0 declarations are ignored

[PATCH] D50119: Compiler support for P1144R0 "__is_trivially_relocatable(T)"

2018-08-16 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added a comment.

It would be nice to be able to diagnose `X`:

  template 
  struct Foo {
struct [[trivially_relocatable]] X { // no warning
  X(X &&) = delete;
};
  };
  
  Foo f; // no warning
  static_assert(!__is_trivially_relocatable(Foo::X)); // ok

But otherwise, you might want to put the attribute in the `clang` namespace. 
LGTM then, but you'll want to wait for someone more senior than me to review 
(and possibly accept) it.


Repository:
  rC Clang

https://reviews.llvm.org/D50119



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


[PATCH] D50766: Fix false positive unsequenced access and modification warning in array subscript expression.

2018-08-16 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete requested changes to this revision.
Rakete added a comment.
This revision now requires changes to proceed.

Your patch breaks a lot of stuff in the test suite. For example:

  void f() {
int A = 0;
(A++, A) = 1; // warning from this patch, but this is perfectly valid since 
forever.
  }

Also, you don't take into account the fact that the rule you mention was added 
in C++17. In versions prior to that (and C!), the warning is not a false 
positive.


https://reviews.llvm.org/D50766



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


[PATCH] D41284: [Concepts] Associated constraints infrastructure.

2018-08-18 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added inline comments.



Comment at: 
test/CXX/concepts-ts/temp/temp.constr/temp.constr.decl/var-template-decl.cpp:10
+
+template  requires bool(U())
+int B::A = int(U());

Quuxplusone wrote:
> saar.raz wrote:
> > Quuxplusone wrote:
> > > For my own edification, could you explain whether, given
> > > 
> > > #define BOOL bool
> > > using typedef_for_bool = bool;
> > > 
> > > you'd expect to diagnose a redeclaration of `B::A` with associated 
> > > constraint
> > > 
> > > requires bool( U() )  // extra whitespace
> > > 
> > > or
> > > 
> > > requires BOOL(U())  // different spelling of `bool`
> > > 
> > > or
> > > 
> > > requires typedef_for_bool(U())  // different spelling of `bool`
> > > 
> > > ? My naive reading of N4762 temp.constr.atomic/2 says that none of these 
> > > constraints (on line 10) would be "identical" to the constraint on line 
> > > 6... but then I don't understand what's the salient difference between 
> > > line 10 (which apparently gives no error) and line 22 (which apparently 
> > > gives an error).
> > Line 22 has a not (!) operator in front of the bool(), I guess you missed 
> > that? 
> I saw the `!`... but I don't understand how the compiler "knows" that 
> `!bool(U())` is "different" from `bool(T())` in a way that doesn't equally 
> apply to `bool(U())`.
> 
> Or suppose the constraint on line 10 was `requires bool(U())==true`... would 
> that give a diagnostic?
`bool(T())` and `bool(U())` are identical because they have the same parameter 
mappings.

The "identical" requirement applies to the actual grammar composition of the 
expression, so `bool(T())` would be different to `bool(T()) == true`.

At least that's how I understand it.


Repository:
  rC Clang

https://reviews.llvm.org/D41284



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


[PATCH] D37442: [C++17] Disallow lambdas in template parameters (PR33696).

2018-05-25 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 148555.
Rakete added a comment.

Rebase and friendly ping :)


https://reviews.llvm.org/D37442

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/Parse/ParseDecl.cpp
  lib/Parse/ParseDeclCXX.cpp
  lib/Parse/ParseStmt.cpp
  lib/Parse/ParseTemplate.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaExprCXX.cpp
  lib/Sema/TreeTransform.h
  test/CXX/expr/expr.prim/expr.prim.lambda/p2-template-parameter.cpp

Index: test/CXX/expr/expr.prim/expr.prim.lambda/p2-template-parameter.cpp
===
--- test/CXX/expr/expr.prim/expr.prim.lambda/p2-template-parameter.cpp
+++ test/CXX/expr/expr.prim/expr.prim.lambda/p2-template-parameter.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -std=c++17 %s -verify
+
+template struct Nothing {};
+
+void pr33696() {
+Nothing<[]() { return 0; }()> nothing; // expected-error{{a lambda expression cannot appear in this context}}
+}
Index: lib/Sema/TreeTransform.h
===
--- lib/Sema/TreeTransform.h
+++ lib/Sema/TreeTransform.h
@@ -5494,7 +5494,7 @@
   // decltype expressions are not potentially evaluated contexts
   EnterExpressionEvaluationContext Unevaluated(
   SemaRef, Sema::ExpressionEvaluationContext::Unevaluated, nullptr,
-  /*IsDecltype=*/true);
+  Sema::ExpressionEvaluationContextRecord::EK_Decltype);
 
   ExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr());
   if (E.isInvalid())
Index: lib/Sema/SemaExprCXX.cpp
===
--- lib/Sema/SemaExprCXX.cpp
+++ lib/Sema/SemaExprCXX.cpp
@@ -6363,7 +6363,8 @@
   if (RD->isInvalidDecl() || RD->isDependentContext())
 return E;
 
-  bool IsDecltype = ExprEvalContexts.back().IsDecltype;
+  bool IsDecltype = ExprEvalContexts.back().ExprContext ==
+ExpressionEvaluationContextRecord::EK_Decltype;
   CXXDestructorDecl *Destructor = IsDecltype ? nullptr : LookupDestructor(RD);
 
   if (Destructor) {
@@ -6445,7 +6446,9 @@
 /// are omitted for the 'topmost' call in the decltype expression. If the
 /// topmost call bound a temporary, strip that temporary off the expression.
 ExprResult Sema::ActOnDecltypeExpression(Expr *E) {
-  assert(ExprEvalContexts.back().IsDecltype && "not in a decltype expression");
+  assert(ExprEvalContexts.back().ExprContext ==
+ ExpressionEvaluationContextRecord::EK_Decltype &&
+ "not in a decltype expression");
 
   // C++11 [expr.call]p11:
   //   If a function call is a prvalue of object type,
@@ -6487,7 +6490,8 @@
 TopBind = nullptr;
 
   // Disable the special decltype handling now.
-  ExprEvalContexts.back().IsDecltype = false;
+  ExprEvalContexts.back().ExprContext =
+  ExpressionEvaluationContextRecord::EK_Other;
 
   // In MS mode, don't perform any extra checking of call return types within a
   // decltype expression.
Index: lib/Sema/SemaExpr.cpp
===
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -14038,11 +14038,11 @@
 }
 
 void
-Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
-  Decl *LambdaContextDecl,
-  bool IsDecltype) {
+Sema::PushExpressionEvaluationContext(
+ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl,
+ExpressionEvaluationContextRecord::ExpressionKind ExprContext) {
   ExprEvalContexts.emplace_back(NewContext, ExprCleanupObjects.size(), Cleanup,
-LambdaContextDecl, IsDecltype);
+LambdaContextDecl, ExprContext);
   Cleanup.reset();
   if (!MaybeODRUseExprs.empty())
 std::swap(MaybeODRUseExprs, ExprEvalContexts.back().SavedMaybeODRUseExprs);
@@ -14049,11 +14049,11 @@
 }
 
 void
-Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
-  ReuseLambdaContextDecl_t,
-  bool IsDecltype) {
+Sema::PushExpressionEvaluationContext(
+ExpressionEvaluationContext NewContext, ReuseLambdaContextDecl_t,
+ExpressionEvaluationContextRecord::ExpressionKind ExprContext) {
   Decl *ClosureContextDecl = ExprEvalContexts.back().ManglingContextDecl;
-  PushExpressionEvaluationContext(NewContext, ClosureContextDecl, IsDecltype);
+  PushExpressionEvaluationContext(NewContext, ClosureContextDecl, ExprContext);
 }
 
 void Sema::PopExpressionEvaluationContext() {
@@ -14061,7 +14061,9 @@
   unsigned NumTypos = Rec.NumTypos;
 
   if (!Rec.Lambdas.empty()) {
-if (Rec.isUnevaluated() || Rec.isConstantEvaluated()) {
+using ExpressionKind = ExpressionEvaluationContextRecord::ExpressionKind;
+if (Rec.ExprContext == ExpressionKind::EK_TemplateParameter || Rec.isUnevaluated() ||
+(Rec.isConstantEvaluated() && !getLangO

[PATCH] D39679: [C++11] Fix warning when dropping cv-qualifiers when assigning to a reference with a braced initializer list

2018-05-25 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 148564.
Rakete added a comment.

Rebased + friendly ping :)


https://reviews.llvm.org/D39679

Files:
  lib/Sema/SemaInit.cpp
  test/SemaCXX/references.cpp

Index: test/SemaCXX/references.cpp
===
--- test/SemaCXX/references.cpp
+++ test/SemaCXX/references.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s 
 int g(int);
 
 void f() {
@@ -55,6 +55,24 @@
   //  const double& rcd2 = 2; // rcd2 refers to temporary with value 2.0
   const volatile int cvi = 1;
   const int& r = cvi; // expected-error{{binding value of type 'const volatile int' to reference to type 'const int' drops 'volatile' qualifier}}
+
+#if __cplusplus >= 201103L
+  const int& r2{cvi}; // expected-error{{binding value of type 'const volatile int' to reference to type 'const int' drops 'volatile' qualifier}}
+
+  const int a = 2;
+  int& r3{a}; // expected-error{{binding value of type 'const int' to reference to type 'int' drops 'const'}}
+
+  const int&& r4{a}; // expected-error{{rvalue reference to type 'const int' cannot bind to lvalue of type 'const int'}}
+
+  void func();
+  void func(int);
+  int &ptr1 = {func}; // expected-error{{address of overloaded function 'func' does not match required type 'int'}}
+  int &&ptr2{func}; // expected-error{{address of overloaded function 'func' does not match required type 'int'}}
+  // expected-note@-4{{candidate function}}
+  // expected-note@-4{{candidate function}}
+  // expected-note@-6{{candidate function}}
+  // expected-note@-6{{candidate function}}
+#endif
 }
 
 // C++ [dcl.init.ref]p3
Index: lib/Sema/SemaInit.cpp
===
--- lib/Sema/SemaInit.cpp
+++ lib/Sema/SemaInit.cpp
@@ -7571,6 +7571,18 @@
   if (!Failed())
 return false;
 
+  // When we want to diagnose only one element of a braced-init-list, we need to factor it out.
+  Expr *OnlyArg;
+  if (Args.size() == 1) {
+auto *List = dyn_cast(Args[0]);
+if (List && List->getNumInits() == 1)
+  OnlyArg = List->getInit(0);
+else
+  OnlyArg = Args[0];
+  }
+  else
+OnlyArg = nullptr;
+
   QualType DestType = Entity.getType();
   switch (Failure) {
   case FK_TooManyInitsForReference:
@@ -7631,7 +7643,7 @@
   ? diag::err_array_init_different_type
   : diag::err_array_init_non_constant_array))
   << DestType.getNonReferenceType()
-  << Args[0]->getType()
+  << OnlyArg->getType()
   << Args[0]->getSourceRange();
 break;
 
@@ -7642,7 +7654,7 @@
 
   case FK_AddressOfOverloadFailed: {
 DeclAccessPair Found;
-S.ResolveAddressOfOverloadedFunction(Args[0],
+S.ResolveAddressOfOverloadedFunction(OnlyArg,
  DestType.getNonReferenceType(),
  true,
  Found);
@@ -7662,11 +7674,11 @@
 case OR_Ambiguous:
   if (Failure == FK_UserConversionOverloadFailed)
 S.Diag(Kind.getLocation(), diag::err_typecheck_ambiguous_condition)
-  << Args[0]->getType() << DestType
+  << OnlyArg->getType() << DestType
   << Args[0]->getSourceRange();
   else
 S.Diag(Kind.getLocation(), diag::err_ref_init_ambiguous)
-  << DestType << Args[0]->getType()
+  << DestType << OnlyArg->getType()
   << Args[0]->getSourceRange();
 
   FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, Args);
@@ -7676,10 +7688,10 @@
   if (!S.RequireCompleteType(Kind.getLocation(),
  DestType.getNonReferenceType(),
   diag::err_typecheck_nonviable_condition_incomplete,
-   Args[0]->getType(), Args[0]->getSourceRange()))
+   OnlyArg->getType(), Args[0]->getSourceRange()))
 S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition)
   << (Entity.getKind() == InitializedEntity::EK_Result)
-  << Args[0]->getType() << Args[0]->getSourceRange()
+  << OnlyArg->getType() << Args[0]->getSourceRange()
   << DestType.getNonReferenceType();
 
   FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args);
@@ -7687,7 +7699,7 @@
 
 case OR_Deleted: {
   S.Diag(Kind.getLocation(), diag::err_typecheck_deleted_function)
-<< Args[0]->getType() << DestType.getNonReferenceType()
+<< OnlyArg->getType() << DestType.getNonReferenceType()
 << Args[0]->getSourceRange();
   OverloadCandidateSet::iterator Best;
   OverloadingResult Ovl
@@ -7723,7 +7735,7 @@
  : diag::err_lvalue_reference_bind_to_unrelated)
   << DestType.getNonReferenceType().isVolatileQualified()
   << DestType.getNonReferenceType()
-  << Args[0]->getType()
+  << OnlyArg->getType()
   << Args[0]->getSourceRange

[PATCH] D38342: [C++] Parse (sub) postfix expression after boolean literal

2017-09-27 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete created this revision.
Rakete added a project: clang.

Parsers a postfix expression after a boolean literal:

This fixes PR34273 .


https://reviews.llvm.org/D38342

Files:
  lib/Parse/ParseExpr.cpp
  test/CXX/expr/expr.post/expr.sub/p1.cpp


Index: test/CXX/expr/expr.post/expr.sub/p1.cpp
===
--- test/CXX/expr/expr.post/expr.sub/p1.cpp
+++ test/CXX/expr/expr.post/expr.sub/p1.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+void pr34273() {
+  char Normal = "clang"[true]; // expected-no-diagnostics
+  char Special = true["clang"]; // expected-no-diagnostics
+}
+
Index: lib/Parse/ParseExpr.cpp
===
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -798,7 +798,8 @@
 
   case tok::kw_true:
   case tok::kw_false:
-return ParseCXXBoolLiteral();
+Res = ParseCXXBoolLiteral();
+break;
   
   case tok::kw___objc_yes:
   case tok::kw___objc_no:


Index: test/CXX/expr/expr.post/expr.sub/p1.cpp
===
--- test/CXX/expr/expr.post/expr.sub/p1.cpp
+++ test/CXX/expr/expr.post/expr.sub/p1.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+void pr34273() {
+  char Normal = "clang"[true]; // expected-no-diagnostics
+  char Special = true["clang"]; // expected-no-diagnostics
+}
+
Index: lib/Parse/ParseExpr.cpp
===
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -798,7 +798,8 @@
 
   case tok::kw_true:
   case tok::kw_false:
-return ParseCXXBoolLiteral();
+Res = ParseCXXBoolLiteral();
+break;
   
   case tok::kw___objc_yes:
   case tok::kw___objc_no:
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D38342: [C++] Parse (sub) postfix expression after boolean literal

2017-09-28 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 117051.
Rakete added a comment.

- Moved test to test/CXX/

Do I actually need to -verify the test if no diagnostics are expected?

Thanks @aaron.ballman


https://reviews.llvm.org/D38342

Files:
  lib/Parse/ParseExpr.cpp
  test/Parser/cxx-bool.cpp


Index: test/Parser/cxx-bool.cpp
===
--- test/Parser/cxx-bool.cpp
+++ test/Parser/cxx-bool.cpp
@@ -2,3 +2,9 @@
 
 bool a = true;
 bool b = false;
+
+namespace pr34273 {
+  char c = "clang"[true];
+  char d = true["clang"];
+}
+
Index: lib/Parse/ParseExpr.cpp
===
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -798,7 +798,8 @@
 
   case tok::kw_true:
   case tok::kw_false:
-return ParseCXXBoolLiteral();
+Res = ParseCXXBoolLiteral();
+break;
   
   case tok::kw___objc_yes:
   case tok::kw___objc_no:


Index: test/Parser/cxx-bool.cpp
===
--- test/Parser/cxx-bool.cpp
+++ test/Parser/cxx-bool.cpp
@@ -2,3 +2,9 @@
 
 bool a = true;
 bool b = false;
+
+namespace pr34273 {
+  char c = "clang"[true];
+  char d = true["clang"];
+}
+
Index: lib/Parse/ParseExpr.cpp
===
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -798,7 +798,8 @@
 
   case tok::kw_true:
   case tok::kw_false:
-return ParseCXXBoolLiteral();
+Res = ParseCXXBoolLiteral();
+break;
   
   case tok::kw___objc_yes:
   case tok::kw___objc_no:
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D38342: [C++] Parse (sub) postfix expression after boolean literal

2017-09-28 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 117054.
Rakete added a comment.

- Fixed test case for bools

Ah got it! Thanks!!


https://reviews.llvm.org/D38342

Files:
  lib/Parse/ParseExpr.cpp
  test/Parser/cxx-bool.cpp


Index: test/Parser/cxx-bool.cpp
===
--- test/Parser/cxx-bool.cpp
+++ test/Parser/cxx-bool.cpp
@@ -1,4 +1,11 @@
-// RUN: %clang_cc1 -fsyntax-only %s
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
 
 bool a = true;
 bool b = false;
+
+namespace pr34273 {
+  char c = "clang"[true];
+  char d = true["clang"];
+}
+
Index: lib/Parse/ParseExpr.cpp
===
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -798,7 +798,8 @@
 
   case tok::kw_true:
   case tok::kw_false:
-return ParseCXXBoolLiteral();
+Res = ParseCXXBoolLiteral();
+break;
   
   case tok::kw___objc_yes:
   case tok::kw___objc_no:


Index: test/Parser/cxx-bool.cpp
===
--- test/Parser/cxx-bool.cpp
+++ test/Parser/cxx-bool.cpp
@@ -1,4 +1,11 @@
-// RUN: %clang_cc1 -fsyntax-only %s
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
 
 bool a = true;
 bool b = false;
+
+namespace pr34273 {
+  char c = "clang"[true];
+  char d = true["clang"];
+}
+
Index: lib/Parse/ParseExpr.cpp
===
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -798,7 +798,8 @@
 
   case tok::kw_true:
   case tok::kw_false:
-return ParseCXXBoolLiteral();
+Res = ParseCXXBoolLiteral();
+break;
   
   case tok::kw___objc_yes:
   case tok::kw___objc_no:
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D38342: [C++] Parse (sub) postfix expression after boolean literal

2017-09-28 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added a comment.

Yes please :) Thanks @aaron.ballman


https://reviews.llvm.org/D38342



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


[PATCH] D37442: [C++17] Disallow lambdas in template parameters (PR33696).

2017-10-03 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 117568.
Rakete added a comment.

- rebased

Does anyone have a better name than `ExpressionType`? I don't really like it.


https://reviews.llvm.org/D37442

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/Parse/ParseDecl.cpp
  lib/Parse/ParseDeclCXX.cpp
  lib/Parse/ParseStmt.cpp
  lib/Parse/ParseTemplate.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaExprCXX.cpp
  lib/Sema/TreeTransform.h
  test/CXX/expr/expr.prim/expr.prim.lambda/p2-template-parameter.cpp

Index: test/CXX/expr/expr.prim/expr.prim.lambda/p2-template-parameter.cpp
===
--- test/CXX/expr/expr.prim/expr.prim.lambda/p2-template-parameter.cpp
+++ test/CXX/expr/expr.prim/expr.prim.lambda/p2-template-parameter.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -std=c++17 %s -verify
+
+template struct Nothing {};
+
+void pr33696() {
+Nothing<[]() { return 0; }()> nothing; // expected-error{{a lambda expression cannot appear in this context}}
+}
Index: lib/Sema/TreeTransform.h
===
--- lib/Sema/TreeTransform.h
+++ lib/Sema/TreeTransform.h
@@ -5508,7 +5508,7 @@
   // decltype expressions are not potentially evaluated contexts
   EnterExpressionEvaluationContext Unevaluated(
   SemaRef, Sema::ExpressionEvaluationContext::Unevaluated, nullptr,
-  /*IsDecltype=*/true);
+  Sema::ExpressionType::Decltype);
 
   ExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr());
   if (E.isInvalid())
Index: lib/Sema/SemaExprCXX.cpp
===
--- lib/Sema/SemaExprCXX.cpp
+++ lib/Sema/SemaExprCXX.cpp
@@ -6146,7 +6146,7 @@
   if (RD->isInvalidDecl() || RD->isDependentContext())
 return E;
 
-  bool IsDecltype = ExprEvalContexts.back().IsDecltype;
+  bool IsDecltype = ExprEvalContexts.back().Type == ExpressionType::Decltype;
   CXXDestructorDecl *Destructor = IsDecltype ? nullptr : LookupDestructor(RD);
 
   if (Destructor) {
@@ -6229,7 +6229,8 @@
 /// are omitted for the 'topmost' call in the decltype expression. If the
 /// topmost call bound a temporary, strip that temporary off the expression.
 ExprResult Sema::ActOnDecltypeExpression(Expr *E) {
-  assert(ExprEvalContexts.back().IsDecltype && "not in a decltype expression");
+  assert(ExprEvalContexts.back().Type == ExpressionType::Decltype &&
+ "not in a decltype expression");
 
   // C++11 [expr.call]p11:
   //   If a function call is a prvalue of object type,
@@ -6271,7 +6272,7 @@
 TopBind = nullptr;
 
   // Disable the special decltype handling now.
-  ExprEvalContexts.back().IsDecltype = false;
+  ExprEvalContexts.back().Type = ExpressionType::Other;
 
   // In MS mode, don't perform any extra checking of call return types within a
   // decltype expression.
Index: lib/Sema/SemaExpr.cpp
===
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -13690,9 +13690,9 @@
 void
 Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
   Decl *LambdaContextDecl,
-  bool IsDecltype) {
+  ExpressionType Type) {
   ExprEvalContexts.emplace_back(NewContext, ExprCleanupObjects.size(), Cleanup,
-LambdaContextDecl, IsDecltype);
+LambdaContextDecl, Type);
   Cleanup.reset();
   if (!MaybeODRUseExprs.empty())
 std::swap(MaybeODRUseExprs, ExprEvalContexts.back().SavedMaybeODRUseExprs);
@@ -13701,9 +13701,9 @@
 void
 Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
   ReuseLambdaContextDecl_t,
-  bool IsDecltype) {
+  ExpressionType Type) {
   Decl *ClosureContextDecl = ExprEvalContexts.back().ManglingContextDecl;
-  PushExpressionEvaluationContext(NewContext, ClosureContextDecl, IsDecltype);
+  PushExpressionEvaluationContext(NewContext, ClosureContextDecl, Type);
 }
 
 void Sema::PopExpressionEvaluationContext() {
@@ -13711,7 +13711,8 @@
   unsigned NumTypos = Rec.NumTypos;
 
   if (!Rec.Lambdas.empty()) {
-if (Rec.isUnevaluated() || Rec.isConstantEvaluated()) {
+if (Rec.Type == ExpressionType::TemplateParameter || Rec.isUnevaluated() ||
+(Rec.isConstantEvaluated() && !getLangOpts().CPlusPlus1z)) {
   unsigned D;
   if (Rec.isUnevaluated()) {
 // C++11 [expr.prim.lambda]p2:
@@ -13718,23 +13719,21 @@
 //   A lambda-expression shall not appear in an unevaluated operand
 //   (Clause 5).
 D = diag::err_lambda_unevaluated_operand;
-  } else {
+  } else if (Rec.isConstantEvaluated() && !getLangOpts().CPlusPlus1z) {
 // C++1y [expr.const]p2:
 //   A condit

[PATCH] D36918: [Sema] Take into account the current context when checking the accessibility of a member function pointer

2017-10-06 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added inline comments.



Comment at: lib/Sema/SemaAccess.cpp:1798
+  EffectiveContext EC(CurScope->getEntity());
+  if (IsAccessible(*this, EC, Entity) == ::AR_accessible)
+return AR_accessible;

You don't need that scope resolution operator there. Also, I guess you don't 
have to create `EC`, you can just pass 
`EffectiveContext(CurScope->getEntity())` directly to `IsAccessible`.


https://reviews.llvm.org/D36918



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


[PATCH] D38216: [C++17] Fix class template argument deduction for default constructors without an initializer

2017-10-14 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 119035.
Rakete added a comment.

Rebased and friendly ping :)


https://reviews.llvm.org/D38216

Files:
  lib/Sema/SemaDecl.cpp
  test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
  test/Parser/cxx1z-class-template-argument-deduction.cpp


Index: test/Parser/cxx1z-class-template-argument-deduction.cpp
===
--- test/Parser/cxx1z-class-template-argument-deduction.cpp
+++ test/Parser/cxx1z-class-template-argument-deduction.cpp
@@ -52,7 +52,7 @@
 
   operator A(); // expected-error {{requires template arguments; argument 
deduction not allowed in conversion function type}}
 
-  static A x; // expected-error {{declaration of variable 'x' with deduced 
type 'A' requires an initializer}}
+  static A x;
   static constexpr A y = 0;
 };
 
@@ -114,7 +114,6 @@
 (void)A{n};
 (void)new A(n);
 (void)new A{n};
-// FIXME: We should diagnose the lack of an initializer here.
 (void)new A;
   }
 }
@@ -127,7 +126,7 @@
 
   auto k() -> A; // expected-error{{requires template arguments}}
 
-  A a; // expected-error {{declaration of variable 'a' with deduced type 'A' 
requires an initializer}}
+  A a;
   A b = 0;
   const A c = 0;
   A (parens) = 0; // expected-error {{cannot use parentheses when declaring 
variable with deduced class template specialization type}}
Index: test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
===
--- test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
+++ test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
@@ -5,8 +5,7 @@
 A(int) -> A;
 
 static constexpr inline const volatile A a = {}; // ok, specifiers are 
permitted
-// FIXME: There isn't really a good reason to reject this.
-A b; // expected-error {{requires an initializer}}
+A b;
 A c [[]] {};
 
 A d = {}, e = {};
@@ -13,6 +12,6 @@
 A f(0), g{}; // expected-error {{template arguments deduced as 'A' in 
declaration of 'f' and deduced as 'A' in declaration of 'g'}}
 
 struct B {
-  static A a; // expected-error {{requires an initializer}}
+  static A a;
 };
-extern A x; // expected-error {{requires an initializer}}
+extern A x;
Index: lib/Sema/SemaDecl.cpp
===
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -10174,7 +10174,8 @@
   assert(Deduced && "deduceVarTypeFromInitializer for non-deduced type");
 
   // C++11 [dcl.spec.auto]p3
-  if (!Init) {
+  // Except for class argument deduction.
+  if (!Init && !isa(Deduced)) {
 assert(VDecl && "no init for init capture deduction?");
 Diag(VDecl->getLocation(), diag::err_auto_var_requires_init)
   << VDecl->getDeclName() << Type;
@@ -10193,7 +10194,10 @@
 InitializationKind Kind = InitializationKind::CreateForInit(
 VDecl->getLocation(), DirectInit, Init);
 // FIXME: Initialization should not be taking a mutable list of inits. 
-SmallVector InitsCopy(DeduceInits.begin(), DeduceInits.end());
+SmallVector InitsCopy;
+if (Init)
+  InitsCopy = {DeduceInits.begin(), DeduceInits.end()};
+
 return DeduceTemplateSpecializationFromInitializer(TSI, Entity, Kind,
InitsCopy);
   }


Index: test/Parser/cxx1z-class-template-argument-deduction.cpp
===
--- test/Parser/cxx1z-class-template-argument-deduction.cpp
+++ test/Parser/cxx1z-class-template-argument-deduction.cpp
@@ -52,7 +52,7 @@
 
   operator A(); // expected-error {{requires template arguments; argument deduction not allowed in conversion function type}}
 
-  static A x; // expected-error {{declaration of variable 'x' with deduced type 'A' requires an initializer}}
+  static A x;
   static constexpr A y = 0;
 };
 
@@ -114,7 +114,6 @@
 (void)A{n};
 (void)new A(n);
 (void)new A{n};
-// FIXME: We should diagnose the lack of an initializer here.
 (void)new A;
   }
 }
@@ -127,7 +126,7 @@
 
   auto k() -> A; // expected-error{{requires template arguments}}
 
-  A a; // expected-error {{declaration of variable 'a' with deduced type 'A' requires an initializer}}
+  A a;
   A b = 0;
   const A c = 0;
   A (parens) = 0; // expected-error {{cannot use parentheses when declaring variable with deduced class template specialization type}}
Index: test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
===
--- test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
+++ test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
@@ -5,8 +5,7 @@
 A(int) -> A;
 
 static constexpr inline const volatile A a = {}; // ok, specifiers are permitted
-// FIXME: There isn't really a good reason to reject this.
-A b; // expected-error {{requires an initializer}}
+A b;
 A c [[]] {};
 
 A d = {}, e = {};
@@ -13,6

[PATCH] D39122: [Sema] Fixes for enum handling for tautological comparison diagnostics

2017-10-20 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added inline comments.



Comment at: lib/Sema/SemaChecking.cpp:8610
 
+  if(!S.getLangOpts().CPlusPlus && OtherT->isEnumeralType()) {
+OtherT = OtherT->getAs()->getDecl()->getIntegerType();

Please drop the braces.



Comment at: lib/Sema/SemaChecking.cpp:8616
 
+  // Special-case for C++ for enum with one enumerator with value of 0
+  if (OtherRange.Width == 0)

You missed a dot at the end.



Comment at: lib/Sema/SemaChecking.cpp:8665
 
+  bool Result;
   bool ConstIsLowerBound = (Op == BO_LT || Op == BO_LE) ^ RhsConstant;

You can define `Result` lower down (and make it `const`).



Comment at: lib/Sema/SemaChecking.cpp:8713
+  QualType WrittenType = OtherT;
+  if(!S.getLangOpts().CPlusPlus && OtherT->isEnumeralType()) {
+OtherT = OtherT->getAs()->getDecl()->getIntegerType();

Same as before. Also, shouldn't this be a function instead of duplicating the 
same code two times?



Comment at: test/Sema/outof-range-enum-constant-compare.c:1
+// RUN: %clang_cc1 -triple=x86_64-pc-linux-gnu -fsyntax-only -DUNSIGNED 
-verify %s
+// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fsyntax-only -DSIGNED -verify %s

I don't know what the convention is, but I would prefer to use platform 
independent tests wherever possible. I couldn't find a flag to change the 
underlying type of an enum, so I'm not sure if my suggestion is even feasible.


Repository:
  rL LLVM

https://reviews.llvm.org/D39122



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


[PATCH] D36101: Fix usage of right shift operator in fold expressions

2017-10-21 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 119767.
Rakete added a comment.

Used the naming convention of LLVM + friendly ping. :)


https://reviews.llvm.org/D36101

Files:
  lib/Parse/ParseExpr.cpp
  test/Parser/cxx1z-fold-expressions.cpp


Index: test/Parser/cxx1z-fold-expressions.cpp
===
--- test/Parser/cxx1z-fold-expressions.cpp
+++ test/Parser/cxx1z-fold-expressions.cpp
@@ -43,3 +43,8 @@
 (int)(undeclared_junk + ...) + // expected-error {{undeclared}}
 (int)(a + ...); // expected-error {{does not contain any unexpanded}}
 }
+
+// fold-operator can be '>' or '>>' too.
+template bool greaterThan() { return (N > ...); }
+template int rightShift() { return (N >> ...); }
+
Index: lib/Parse/ParseExpr.cpp
===
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -270,7 +270,7 @@
   return Level > prec::Unknown && Level != prec::Conditional;
 }
 static bool isFoldOperator(tok::TokenKind Kind) {
-  return isFoldOperator(getBinOpPrecedence(Kind, false, true));
+  return isFoldOperator(getBinOpPrecedence(Kind, true, true));
 }
 
 /// \brief Parse a binary expression that starts with \p LHS and has a


Index: test/Parser/cxx1z-fold-expressions.cpp
===
--- test/Parser/cxx1z-fold-expressions.cpp
+++ test/Parser/cxx1z-fold-expressions.cpp
@@ -43,3 +43,8 @@
 (int)(undeclared_junk + ...) + // expected-error {{undeclared}}
 (int)(a + ...); // expected-error {{does not contain any unexpanded}}
 }
+
+// fold-operator can be '>' or '>>' too.
+template bool greaterThan() { return (N > ...); }
+template int rightShift() { return (N >> ...); }
+
Index: lib/Parse/ParseExpr.cpp
===
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -270,7 +270,7 @@
   return Level > prec::Unknown && Level != prec::Conditional;
 }
 static bool isFoldOperator(tok::TokenKind Kind) {
-  return isFoldOperator(getBinOpPrecedence(Kind, false, true));
+  return isFoldOperator(getBinOpPrecedence(Kind, true, true));
 }
 
 /// \brief Parse a binary expression that starts with \p LHS and has a
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D38954: [Sema] -Wzero-as-null-pointer-constant: don't warn for system macros other than NULL.

2017-10-23 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added inline comments.



Comment at: lib/Sema/Sema.cpp:445
+  // If it is a macro from system header, and if the macro name is not "NULL",
+  // do not warn.
+  SourceLocation MaybeMacroLoc = E->getLocStart();

That comment doesn't really add anything IMO. It just says what the code just 
below says.



Comment at: lib/Sema/Sema.cpp:447
+  SourceLocation MaybeMacroLoc = E->getLocStart();
+  if (SourceMgr.isInSystemMacro(E->getLocStart()) &&
+  !findMacroSpelling(MaybeMacroLoc, "NULL"))

Please use `MaybeMacroLoc` there too.


Repository:
  rL LLVM

https://reviews.llvm.org/D38954



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


[PATCH] D50766: Fix false positive unsequenced access and modification warning in array subscript expression.

2018-08-26 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added a comment.

> What do you think?

Good idea!




Comment at: test/SemaCXX/warn-unsequenced-cxx17.cpp:7
+  // expected-no-diagnostics
+  p[(long long unsigned)(p = 0)] // ok
+}

Oh no, you forgot a semicolon there! :)


https://reviews.llvm.org/D50766



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


[PATCH] D49848: Parse a possible trailing postsfix expression suffix after a fold expression

2018-07-26 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete created this revision.
Rakete added a reviewer: rsmith.

This patch allows the parsing of a postfix expression involving a fold 
expression, which is legal as a fold-expression is a primary-expression.

See also https://llvm.org/pr38282


Repository:
  rC Clang

https://reviews.llvm.org/D49848

Files:
  lib/Parse/ParseExpr.cpp
  test/Parser/cxx1z-fold-expressions.cpp


Index: test/Parser/cxx1z-fold-expressions.cpp
===
--- test/Parser/cxx1z-fold-expressions.cpp
+++ test/Parser/cxx1z-fold-expressions.cpp
@@ -60,3 +60,21 @@
 }
 
 static_assert(nestedFoldOperator<3, 1>() == 1);
+
+// A fold-expression is a primary-expression.
+template 
+constexpr auto castSum(Ts... Args) {
+  return (T)(Args + ...).Value; // expected-error{{member reference base type 
'int' is not a structure or union}}
+}
+
+void prim() {
+  castSum(1, 2);
+  // expected-note@-1{{in instantiation of function template specialization}}
+
+  struct Number {
+int Value;
+constexpr Number operator+(Number Rhs) const { return {Rhs.Value + Value}; 
}
+  };
+
+  static_assert(castSum(Number{1}, Number{2}) == 3);
+}
Index: lib/Parse/ParseExpr.cpp
===
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -2514,7 +2514,10 @@
 }
   } else if (Tok.is(tok::ellipsis) &&
  isFoldOperator(NextToken().getKind())) {
-return ParseFoldExpression(ExprResult(), T);
+Result = ParseFoldExpression(ExprResult(), T);
+if (!Result.isInvalid())
+  Result = ParsePostfixExpressionSuffix(Result.get());
+return Result;
   } else if (isTypeCast) {
 // Parse the expression-list.
 InMessageExpressionRAIIObject InMessage(*this, false);
@@ -2526,8 +2529,12 @@
   // FIXME: If we ever support comma expressions as operands to
   // fold-expressions, we'll need to allow multiple ArgExprs here.
   if (ArgExprs.size() == 1 && isFoldOperator(Tok.getKind()) &&
-  NextToken().is(tok::ellipsis))
-return ParseFoldExpression(ArgExprs[0], T);
+  NextToken().is(tok::ellipsis)) {
+Result = ParseFoldExpression(ArgExprs[0], T);
+if (!Result.isInvalid())
+  Result = ParsePostfixExpressionSuffix(Result.get());
+return Result;
+  }
 
   ExprType = SimpleExpr;
   Result = Actions.ActOnParenListExpr(OpenLoc, Tok.getLocation(),
@@ -2544,8 +2551,12 @@
 }
 ExprType = SimpleExpr;
 
-if (isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis))
-  return ParseFoldExpression(Result, T);
+if (isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis)) {
+  Result = ParseFoldExpression(Result, T);
+  if (!Result.isInvalid())
+Result = ParsePostfixExpressionSuffix(Result.get());
+  return Result;
+}
 
 // Don't build a paren expression unless we actually match a ')'.
 if (!Result.isInvalid() && Tok.is(tok::r_paren))


Index: test/Parser/cxx1z-fold-expressions.cpp
===
--- test/Parser/cxx1z-fold-expressions.cpp
+++ test/Parser/cxx1z-fold-expressions.cpp
@@ -60,3 +60,21 @@
 }
 
 static_assert(nestedFoldOperator<3, 1>() == 1);
+
+// A fold-expression is a primary-expression.
+template 
+constexpr auto castSum(Ts... Args) {
+  return (T)(Args + ...).Value; // expected-error{{member reference base type 'int' is not a structure or union}}
+}
+
+void prim() {
+  castSum(1, 2);
+  // expected-note@-1{{in instantiation of function template specialization}}
+
+  struct Number {
+int Value;
+constexpr Number operator+(Number Rhs) const { return {Rhs.Value + Value}; }
+  };
+
+  static_assert(castSum(Number{1}, Number{2}) == 3);
+}
Index: lib/Parse/ParseExpr.cpp
===
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -2514,7 +2514,10 @@
 }
   } else if (Tok.is(tok::ellipsis) &&
  isFoldOperator(NextToken().getKind())) {
-return ParseFoldExpression(ExprResult(), T);
+Result = ParseFoldExpression(ExprResult(), T);
+if (!Result.isInvalid())
+  Result = ParsePostfixExpressionSuffix(Result.get());
+return Result;
   } else if (isTypeCast) {
 // Parse the expression-list.
 InMessageExpressionRAIIObject InMessage(*this, false);
@@ -2526,8 +2529,12 @@
   // FIXME: If we ever support comma expressions as operands to
   // fold-expressions, we'll need to allow multiple ArgExprs here.
   if (ArgExprs.size() == 1 && isFoldOperator(Tok.getKind()) &&
-  NextToken().is(tok::ellipsis))
-return ParseFoldExpression(ArgExprs[0], T);
+  NextToken().is(tok::ellipsis)) {
+Result = ParseFoldExpression(ArgExprs[0], T);
+if (!Result.isInvalid())
+  Result = ParsePostfixExpressionSuffix(Result.get());
+return Result;
+  }
 
   ExprType = SimpleExpr;
 

[PATCH] D49848: Parse a possible trailing postfix expression suffix after a fold expression

2018-07-26 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 157578.
Rakete added a comment.

@rsmith you're right, it should. But it doesn't, because the the fold 
expression is considered to be a cast expression by ParseParenExpression and 
which parses any postfix pieces immediately after a cast, but it doesn't do so 
for fold expression, because they don't (not surprisingly) involve a cast.

I've added a new type of ParenParseOption for fold-expressions for this, which 
makes the patch way more cleaner :) (I didn't want to reuse SimpleExpr for fold 
expressions - conflicts with the docs for it)


Repository:
  rC Clang

https://reviews.llvm.org/D49848

Files:
  include/clang/Parse/Parser.h
  lib/Parse/ParseExpr.cpp
  test/Parser/cxx1z-fold-expressions.cpp


Index: test/Parser/cxx1z-fold-expressions.cpp
===
--- test/Parser/cxx1z-fold-expressions.cpp
+++ test/Parser/cxx1z-fold-expressions.cpp
@@ -60,3 +60,21 @@
 }
 
 static_assert(nestedFoldOperator<3, 1>() == 1);
+
+// A fold-expression is a primary-expression.
+template 
+constexpr auto castSum(Ts... Args) {
+  return (T)(Args + ...).Value; // expected-error{{member reference base type 
'int' is not a structure or union}}
+}
+
+void prim() {
+  castSum(1, 2);
+  // expected-note@-1{{in instantiation of function template specialization}}
+
+  struct Number {
+int Value;
+constexpr Number operator+(Number Rhs) const { return {Rhs.Value + Value}; 
}
+  };
+
+  static_assert(castSum(Number{1}, Number{2}) == 3);
+}
Index: lib/Parse/ParseExpr.cpp
===
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -779,6 +779,10 @@
   // We have parsed the cast-expression and no postfix-expr pieces are
   // following.
   return Res;
+case FoldExpr:
+  // We parsed fold-expression only. There might be postfix-expr pieces
+  // afterwards; parse them now.
+  break;
 }
 
 break;
@@ -2514,6 +2518,7 @@
 }
   } else if (Tok.is(tok::ellipsis) &&
  isFoldOperator(NextToken().getKind())) {
+ExprType = FoldExpr;
 return ParseFoldExpression(ExprResult(), T);
   } else if (isTypeCast) {
 // Parse the expression-list.
@@ -2526,8 +2531,10 @@
   // FIXME: If we ever support comma expressions as operands to
   // fold-expressions, we'll need to allow multiple ArgExprs here.
   if (ArgExprs.size() == 1 && isFoldOperator(Tok.getKind()) &&
-  NextToken().is(tok::ellipsis))
+  NextToken().is(tok::ellipsis)) {
+ExprType = FoldExpr;
 return ParseFoldExpression(ArgExprs[0], T);
+  }
 
   ExprType = SimpleExpr;
   Result = Actions.ActOnParenListExpr(OpenLoc, Tok.getLocation(),
@@ -2544,8 +2551,10 @@
 }
 ExprType = SimpleExpr;
 
-if (isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis))
+if (isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis)) {
+  ExprType = FoldExpr;
   return ParseFoldExpression(Result, T);
+}
 
 // Don't build a paren expression unless we actually match a ')'.
 if (!Result.isInvalid() && Tok.is(tok::r_paren))
Index: include/clang/Parse/Parser.h
===
--- include/clang/Parse/Parser.h
+++ include/clang/Parse/Parser.h
@@ -1654,7 +1654,8 @@
 SimpleExpr,  // Only parse '(' expression ')'
 CompoundStmt,// Also allow '(' compound-statement ')'
 CompoundLiteral, // Also allow '(' type-name ')' '{' ... '}'
-CastExpr // Also allow '(' type-name ')' 
+CastExpr,// Also allow '(' type-name ')' 
+FoldExpr // Also allow fold-expression 
   };
   ExprResult ParseParenExpression(ParenParseOption &ExprType,
 bool stopIfCastExpr,


Index: test/Parser/cxx1z-fold-expressions.cpp
===
--- test/Parser/cxx1z-fold-expressions.cpp
+++ test/Parser/cxx1z-fold-expressions.cpp
@@ -60,3 +60,21 @@
 }
 
 static_assert(nestedFoldOperator<3, 1>() == 1);
+
+// A fold-expression is a primary-expression.
+template 
+constexpr auto castSum(Ts... Args) {
+  return (T)(Args + ...).Value; // expected-error{{member reference base type 'int' is not a structure or union}}
+}
+
+void prim() {
+  castSum(1, 2);
+  // expected-note@-1{{in instantiation of function template specialization}}
+
+  struct Number {
+int Value;
+constexpr Number operator+(Number Rhs) const { return {Rhs.Value + Value}; }
+  };
+
+  static_assert(castSum(Number{1}, Number{2}) == 3);
+}
Index: lib/Parse/ParseExpr.cpp
===
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -779,6 +779,10 @@
   // We have parsed the cast-expression and no postfix-expr pieces are
   // following.
   return Res;
+case FoldExpr:
+  // We parsed fold-expre

[PATCH] D49848: Parse a possible trailing postfix expression suffix after a fold expression

2018-07-26 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 157580.
Rakete added a comment.

Add a test without any casts.


Repository:
  rC Clang

https://reviews.llvm.org/D49848

Files:
  include/clang/Parse/Parser.h
  lib/Parse/ParseExpr.cpp
  test/Parser/cxx1z-fold-expressions.cpp


Index: test/Parser/cxx1z-fold-expressions.cpp
===
--- test/Parser/cxx1z-fold-expressions.cpp
+++ test/Parser/cxx1z-fold-expressions.cpp
@@ -60,3 +60,29 @@
 }
 
 static_assert(nestedFoldOperator<3, 1>() == 1);
+
+// A fold-expression is a primary-expression.
+template 
+constexpr auto castSum(Ts... Args) {
+  return (T)(Args + ...).Value; // expected-error{{member reference base type 
'int' is not a structure or union}}
+}
+
+template 
+constexpr auto simpleSum(Ts... Args) {
+  return (... + Args).Value; // expected-error{{member reference base type 
'int' is not a structure or union}}
+}
+
+void prim() {
+  castSum(1, 2);
+  // expected-note@-1{{in instantiation of function template specialization}}
+  simpleSum(1, 2);
+  // expected-note@-1{{in instantiation of function template specialization}}
+
+  struct Number {
+int Value;
+constexpr Number operator+(Number Rhs) const { return {Rhs.Value + Value}; 
}
+  };
+
+  static_assert(castSum(Number{1}, Number{2}) == 3);
+  static_assert(simpleSum(Number{1}, Number{2}) == 3);
+}
Index: lib/Parse/ParseExpr.cpp
===
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -779,6 +779,10 @@
   // We have parsed the cast-expression and no postfix-expr pieces are
   // following.
   return Res;
+case FoldExpr:
+  // We parsed fold-expression only. There might be postfix-expr pieces
+  // afterwards; parse them now.
+  break;
 }
 
 break;
@@ -2514,6 +2518,7 @@
 }
   } else if (Tok.is(tok::ellipsis) &&
  isFoldOperator(NextToken().getKind())) {
+ExprType = FoldExpr;
 return ParseFoldExpression(ExprResult(), T);
   } else if (isTypeCast) {
 // Parse the expression-list.
@@ -2526,8 +2531,10 @@
   // FIXME: If we ever support comma expressions as operands to
   // fold-expressions, we'll need to allow multiple ArgExprs here.
   if (ArgExprs.size() == 1 && isFoldOperator(Tok.getKind()) &&
-  NextToken().is(tok::ellipsis))
+  NextToken().is(tok::ellipsis)) {
+ExprType = FoldExpr;
 return ParseFoldExpression(ArgExprs[0], T);
+  }
 
   ExprType = SimpleExpr;
   Result = Actions.ActOnParenListExpr(OpenLoc, Tok.getLocation(),
@@ -2544,8 +2551,10 @@
 }
 ExprType = SimpleExpr;
 
-if (isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis))
+if (isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis)) {
+  ExprType = FoldExpr;
   return ParseFoldExpression(Result, T);
+}
 
 // Don't build a paren expression unless we actually match a ')'.
 if (!Result.isInvalid() && Tok.is(tok::r_paren))
Index: include/clang/Parse/Parser.h
===
--- include/clang/Parse/Parser.h
+++ include/clang/Parse/Parser.h
@@ -1654,7 +1654,8 @@
 SimpleExpr,  // Only parse '(' expression ')'
 CompoundStmt,// Also allow '(' compound-statement ')'
 CompoundLiteral, // Also allow '(' type-name ')' '{' ... '}'
-CastExpr // Also allow '(' type-name ')' 
+CastExpr,// Also allow '(' type-name ')' 
+FoldExpr // Also allow fold-expression 
   };
   ExprResult ParseParenExpression(ParenParseOption &ExprType,
 bool stopIfCastExpr,


Index: test/Parser/cxx1z-fold-expressions.cpp
===
--- test/Parser/cxx1z-fold-expressions.cpp
+++ test/Parser/cxx1z-fold-expressions.cpp
@@ -60,3 +60,29 @@
 }
 
 static_assert(nestedFoldOperator<3, 1>() == 1);
+
+// A fold-expression is a primary-expression.
+template 
+constexpr auto castSum(Ts... Args) {
+  return (T)(Args + ...).Value; // expected-error{{member reference base type 'int' is not a structure or union}}
+}
+
+template 
+constexpr auto simpleSum(Ts... Args) {
+  return (... + Args).Value; // expected-error{{member reference base type 'int' is not a structure or union}}
+}
+
+void prim() {
+  castSum(1, 2);
+  // expected-note@-1{{in instantiation of function template specialization}}
+  simpleSum(1, 2);
+  // expected-note@-1{{in instantiation of function template specialization}}
+
+  struct Number {
+int Value;
+constexpr Number operator+(Number Rhs) const { return {Rhs.Value + Value}; }
+  };
+
+  static_assert(castSum(Number{1}, Number{2}) == 3);
+  static_assert(simpleSum(Number{1}, Number{2}) == 3);
+}
Index: lib/Parse/ParseExpr.cpp
===
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -779,6 +779,10 @@
 

[PATCH] D36357: Added a better diagnostic when using the delete operator with lambdas

2018-07-26 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 157611.
Rakete added a comment.

Rebased + friendly ping


Repository:
  rC Clang

https://reviews.llvm.org/D36357

Files:
  include/clang/Basic/DiagnosticParseKinds.td
  lib/Parse/ParseExprCXX.cpp
  test/Parser/cxx0x-lambda-expressions.cpp
  test/SemaCXX/new-delete-0x.cpp


Index: test/SemaCXX/new-delete-0x.cpp
===
--- test/SemaCXX/new-delete-0x.cpp
+++ test/SemaCXX/new-delete-0x.cpp
@@ -34,6 +34,6 @@
 void bad_deletes()
 {
   // 'delete []' is always array delete, per [expr.delete]p1.
-  // FIXME: Give a better diagnostic.
-  delete []{ return (int*)0; }(); // expected-error {{expected expression}}
+  delete []{ return (int*)0; }(); // expected-error {{'[]' after delete 
interpreted as 'delete[]'}}
 }
+
Index: test/Parser/cxx0x-lambda-expressions.cpp
===
--- test/Parser/cxx0x-lambda-expressions.cpp
+++ test/Parser/cxx0x-lambda-expressions.cpp
@@ -53,7 +53,7 @@
   void delete_lambda(int *p) {
 delete [] p;
 delete [] (int*) { new int }; // ok, compound-literal, not lambda
-delete [] { return new int; } (); // expected-error{{expected expression}}
+delete [] { return new int; } (); // expected-error {{'[]' after delete 
interpreted as 'delete[]'}}
 delete [&] { return new int; } (); // ok, lambda
   }
 
Index: lib/Parse/ParseExprCXX.cpp
===
--- lib/Parse/ParseExprCXX.cpp
+++ lib/Parse/ParseExprCXX.cpp
@@ -2946,15 +2946,44 @@
 //   [Footnote: A lambda expression with a lambda-introducer that consists
 //  of empty square brackets can follow the delete keyword if
 //  the lambda expression is enclosed in parentheses.]
-// FIXME: Produce a better diagnostic if the '[]' is unambiguously a
-//lambda-introducer.
-ArrayDelete = true;
-BalancedDelimiterTracker T(*this, tok::l_square);
 
-T.consumeOpen();
-T.consumeClose();
-if (T.getCloseLocation().isInvalid())
-  return ExprError();
+const Token Next = GetLookAheadToken(2);
+
+// Basic lookahead to check if we have a lambda expression.
+if (Next.isOneOf(tok::l_brace, tok::less) ||
+(Next.is(tok::l_paren) &&
+ GetLookAheadToken(3).isOneOf(tok::r_paren, tok::identifier) &&
+ GetLookAheadToken(4).is(tok::identifier))) {
+  SourceLocation RightBracketLock = NextToken().getLocation();
+  // Warn if the non-capturing lambda isn't surrounded by parenthesis
+  // to disambiguate it from 'delete[]'.
+  ExprResult Lambda = ParseLambdaExpression();
+  if (Lambda.isInvalid())
+return ExprError();
+
+  SourceLocation StartLoc = Lambda.get()->getLocStart();
+  Diag(Start, diag::err_lambda_after_delete)
+  << SourceRange(Start, RightBracketLock)
+  << FixItHint::CreateInsertion(StartLoc, "(")
+  << FixItHint::CreateInsertion(
+ Lexer::getLocForEndOfToken(Lambda.get()->getLocEnd(), 1,
+Actions.getSourceManager(),
+getLangOpts()),
+ ")");
+
+  // Evaluate any postfix expressions used on the lambda.
+  Lambda = ParsePostfixExpressionSuffix(Lambda);
+  return Actions.ActOnCXXDelete(Start, UseGlobal, /*ArrayForm=*/false,
+Lambda.get());
+} else {
+  ArrayDelete = true;
+  BalancedDelimiterTracker T(*this, tok::l_square);
+
+  T.consumeOpen();
+  T.consumeClose();
+  if (T.getCloseLocation().isInvalid())
+return ExprError();
+}
   }
 
   ExprResult Operand(ParseCastExpression(false));
Index: include/clang/Basic/DiagnosticParseKinds.td
===
--- include/clang/Basic/DiagnosticParseKinds.td
+++ include/clang/Basic/DiagnosticParseKinds.td
@@ -99,6 +99,8 @@
   InGroup, DefaultIgnore;
 def ext_alignof_expr : ExtWarn<
   "%0 applied to an expression is a GNU extension">, 
InGroup;
+def err_lambda_after_delete : Error<
+  "'[]' after delete interpreted as 'delete[]'">;
 
 def warn_microsoft_dependent_exists : Warning<
   "dependent %select{__if_not_exists|__if_exists}0 declarations are ignored">, 


Index: test/SemaCXX/new-delete-0x.cpp
===
--- test/SemaCXX/new-delete-0x.cpp
+++ test/SemaCXX/new-delete-0x.cpp
@@ -34,6 +34,6 @@
 void bad_deletes()
 {
   // 'delete []' is always array delete, per [expr.delete]p1.
-  // FIXME: Give a better diagnostic.
-  delete []{ return (int*)0; }(); // expected-error {{expected expression}}
+  delete []{ return (int*)0; }(); // expected-error {{'[]' after delete interpreted as 'delete[]'}}
 }
+
Index: test/Parser/cxx0x-lambda-expressions.cpp
===
--- 

[PATCH] D36357: Added a better diagnostic when using the delete operator with lambdas

2018-07-26 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 157642.
Rakete added a comment.

Addressed review comments.

Note that clang doesn't support the fourth kind of lambda yet ([]<>), because 
https://reviews.llvm.org/D36527 hasn't been merged yet, so I didn't add a test 
case for that one.


Repository:
  rC Clang

https://reviews.llvm.org/D36357

Files:
  include/clang/Basic/DiagnosticParseKinds.td
  lib/Parse/ParseExprCXX.cpp
  test/FixIt/fixit-cxx0x.cpp
  test/Parser/cxx0x-lambda-expressions.cpp
  test/SemaCXX/new-delete-0x.cpp

Index: test/SemaCXX/new-delete-0x.cpp
===
--- test/SemaCXX/new-delete-0x.cpp
+++ test/SemaCXX/new-delete-0x.cpp
@@ -34,6 +34,6 @@
 void bad_deletes()
 {
   // 'delete []' is always array delete, per [expr.delete]p1.
-  // FIXME: Give a better diagnostic.
-  delete []{ return (int*)0; }(); // expected-error {{expected expression}}
+  delete []{ return (int*)0; }(); // expected-error {{'[]' after delete interpreted as 'delete[]'}}
 }
+
Index: test/Parser/cxx0x-lambda-expressions.cpp
===
--- test/Parser/cxx0x-lambda-expressions.cpp
+++ test/Parser/cxx0x-lambda-expressions.cpp
@@ -53,8 +53,11 @@
   void delete_lambda(int *p) {
 delete [] p;
 delete [] (int*) { new int }; // ok, compound-literal, not lambda
-delete [] { return new int; } (); // expected-error{{expected expression}}
+delete [] { return new int; } (); // expected-error {{'[]' after delete interpreted as 'delete[]'}}
 delete [&] { return new int; } (); // ok, lambda
+
+delete []() { return new int; }(); // expected-error{{'[]' after delete interpreted as 'delete[]'}}
+delete [](E Enum) { return new int((int)Enum); }(e); // expected-error{{'[]' after delete interpreted as 'delete[]'}}
   }
 
   // We support init-captures in C++11 as an extension.
Index: test/FixIt/fixit-cxx0x.cpp
===
--- test/FixIt/fixit-cxx0x.cpp
+++ test/FixIt/fixit-cxx0x.cpp
@@ -58,6 +58,9 @@
   (void)[&, i, i]{ }; // expected-error{{'i' can appear only once in a capture list}}
   (void)[] mutable { }; // expected-error{{lambda requires '()' before 'mutable'}}
   (void)[] -> int { }; // expected-error{{lambda requires '()' before return type}}
+
+  delete []() { return new int; }(); // expected-error{{'[]' after delete interpreted as 'delete[]'}}
+  delete [] { return new int; }(); // expected-error{{'[]' after delete interpreted as 'delete[]'}}
 }
 
 #define bar "bar"
Index: lib/Parse/ParseExprCXX.cpp
===
--- lib/Parse/ParseExprCXX.cpp
+++ lib/Parse/ParseExprCXX.cpp
@@ -2946,8 +2946,38 @@
 //   [Footnote: A lambda expression with a lambda-introducer that consists
 //  of empty square brackets can follow the delete keyword if
 //  the lambda expression is enclosed in parentheses.]
-// FIXME: Produce a better diagnostic if the '[]' is unambiguously a
-//lambda-introducer.
+
+const Token Next = GetLookAheadToken(2);
+
+// Basic lookahead to check if we have a lambda expression.
+if (Next.isOneOf(tok::l_brace, tok::less) ||
+(Next.is(tok::l_paren) &&
+ (GetLookAheadToken(3).is(tok::r_paren) ||
+  (GetLookAheadToken(3).is(tok::identifier) &&
+   GetLookAheadToken(4).is(tok::identifier) {
+  SourceLocation RightBracketLock = NextToken().getLocation();
+  // Warn if the non-capturing lambda isn't surrounded by parenthesis
+  // to disambiguate it from 'delete[]'.
+  ExprResult Lambda = ParseLambdaExpression();
+  if (Lambda.isInvalid())
+return ExprError();
+
+  SourceLocation StartLoc = Lambda.get()->getLocStart();
+  Diag(Start, diag::err_lambda_after_delete)
+  << SourceRange(Start, RightBracketLock)
+  << FixItHint::CreateInsertion(StartLoc, "(")
+  << FixItHint::CreateInsertion(
+ Lexer::getLocForEndOfToken(Lambda.get()->getLocEnd(), 0,
+Actions.getSourceManager(),
+getLangOpts()),
+ ")");
+
+  // Evaluate any postfix expressions used on the lambda.
+  Lambda = ParsePostfixExpressionSuffix(Lambda);
+  return Actions.ActOnCXXDelete(Start, UseGlobal, /*ArrayForm=*/false,
+Lambda.get());
+}
+
 ArrayDelete = true;
 BalancedDelimiterTracker T(*this, tok::l_square);
 
Index: include/clang/Basic/DiagnosticParseKinds.td
===
--- include/clang/Basic/DiagnosticParseKinds.td
+++ include/clang/Basic/DiagnosticParseKinds.td
@@ -99,6 +99,8 @@
   InGroup, DefaultIgnore;
 def ext_alignof_expr : ExtWarn<
   "%0 applied to an expression is a GNU extension">, InGroup;
+def err_lambda_after_delete : Erro

[PATCH] D49848: Parse a possible trailing postfix expression suffix after a fold expression

2018-07-27 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 157759.
Rakete added a comment.

Addressed review comments :)


Repository:
  rC Clang

https://reviews.llvm.org/D49848

Files:
  include/clang/Parse/Parser.h
  lib/Parse/ParseExpr.cpp
  test/Parser/cxx1z-fold-expressions.cpp

Index: test/Parser/cxx1z-fold-expressions.cpp
===
--- test/Parser/cxx1z-fold-expressions.cpp
+++ test/Parser/cxx1z-fold-expressions.cpp
@@ -60,3 +60,29 @@
 }
 
 static_assert(nestedFoldOperator<3, 1>() == 1);
+
+// A fold-expression is a primary-expression.
+template 
+constexpr auto castSum(Ts... Args) {
+  return (T)(Args + ...).Value; // expected-error{{member reference base type 'int' is not a structure or union}}
+}
+
+template 
+constexpr auto simpleSum(Ts... Args) {
+  return (... + Args).Value; // expected-error{{member reference base type 'int' is not a structure or union}}
+}
+
+void prim() {
+  castSum(1, 2);
+  // expected-note@-1{{in instantiation of function template specialization}}
+  simpleSum(1, 2);
+  // expected-note@-1{{in instantiation of function template specialization}}
+
+  struct Number {
+int Value;
+constexpr Number operator+(Number Rhs) const { return {Rhs.Value + Value}; }
+  };
+
+  static_assert(castSum(Number{1}, Number{2}) == 3);
+  static_assert(simpleSum(Number{1}, Number{2}) == 3);
+}
Index: lib/Parse/ParseExpr.cpp
===
--- lib/Parse/ParseExpr.cpp
+++ lib/Parse/ParseExpr.cpp
@@ -787,6 +787,10 @@
   // We have parsed the cast-expression and no postfix-expr pieces are
   // following.
   return Res;
+case FoldExpr:
+  // We only parsed a fold-expression. There might be postfix-expr pieces
+  // afterwards; parse them now.
+  break;
 }
 
 break;
@@ -2520,8 +2524,9 @@
   Diag(Tok, diag::err_expected_lbrace_in_compound_literal);
   return ExprError();
 }
-  } else if (Tok.is(tok::ellipsis) &&
+  } else if (ExprType >= FoldExpr && Tok.is(tok::ellipsis) &&
  isFoldOperator(NextToken().getKind())) {
+ExprType = FoldExpr;
 return ParseFoldExpression(ExprResult(), T);
   } else if (isTypeCast) {
 // Parse the expression-list.
@@ -2533,9 +2538,11 @@
 if (!ParseSimpleExpressionList(ArgExprs, CommaLocs)) {
   // FIXME: If we ever support comma expressions as operands to
   // fold-expressions, we'll need to allow multiple ArgExprs here.
-  if (ArgExprs.size() == 1 && isFoldOperator(Tok.getKind()) &&
-  NextToken().is(tok::ellipsis))
+  if (ExprType >= FoldExpr && ArgExprs.size() == 1 &&
+  isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis)) {
+ExprType = FoldExpr;
 return ParseFoldExpression(ArgExprs[0], T);
+  }
 
   ExprType = SimpleExpr;
   Result = Actions.ActOnParenListExpr(OpenLoc, Tok.getLocation(),
@@ -2550,10 +2557,13 @@
   // expressions are parsed correctly.
   Result = Actions.CorrectDelayedTyposInExpr(Result);
 }
-ExprType = SimpleExpr;
 
-if (isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis))
+if (ExprType >= FoldExpr && isFoldOperator(Tok.getKind()) &&
+NextToken().is(tok::ellipsis)) {
+  ExprType = FoldExpr;
   return ParseFoldExpression(Result, T);
+}
+ExprType = SimpleExpr;
 
 // Don't build a paren expression unless we actually match a ')'.
 if (!Result.isInvalid() && Tok.is(tok::r_paren))
Index: include/clang/Parse/Parser.h
===
--- include/clang/Parse/Parser.h
+++ include/clang/Parse/Parser.h
@@ -1653,6 +1653,7 @@
   /// ParenParseOption - Control what ParseParenExpression will parse.
   enum ParenParseOption {
 SimpleExpr,  // Only parse '(' expression ')'
+FoldExpr,// Also allow fold-expression 
 CompoundStmt,// Also allow '(' compound-statement ')'
 CompoundLiteral, // Also allow '(' type-name ')' '{' ... '}'
 CastExpr // Also allow '(' type-name ')' 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D49848: Parse a possible trailing postfix expression suffix after a fold expression

2018-07-27 Thread Nicolas Lesser via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL338170: Parse a possible trailing postfix expression suffix 
after a fold expression (authored by Rakete, committed by ).
Herald added a subscriber: llvm-commits.

Repository:
  rL LLVM

https://reviews.llvm.org/D49848

Files:
  cfe/trunk/include/clang/Parse/Parser.h
  cfe/trunk/lib/Parse/ParseExpr.cpp
  cfe/trunk/test/Parser/cxx1z-fold-expressions.cpp

Index: cfe/trunk/include/clang/Parse/Parser.h
===
--- cfe/trunk/include/clang/Parse/Parser.h
+++ cfe/trunk/include/clang/Parse/Parser.h
@@ -1653,6 +1653,7 @@
   /// ParenParseOption - Control what ParseParenExpression will parse.
   enum ParenParseOption {
 SimpleExpr,  // Only parse '(' expression ')'
+FoldExpr,// Also allow fold-expression 
 CompoundStmt,// Also allow '(' compound-statement ')'
 CompoundLiteral, // Also allow '(' type-name ')' '{' ... '}'
 CastExpr // Also allow '(' type-name ')' 
Index: cfe/trunk/test/Parser/cxx1z-fold-expressions.cpp
===
--- cfe/trunk/test/Parser/cxx1z-fold-expressions.cpp
+++ cfe/trunk/test/Parser/cxx1z-fold-expressions.cpp
@@ -60,3 +60,29 @@
 }
 
 static_assert(nestedFoldOperator<3, 1>() == 1);
+
+// A fold-expression is a primary-expression.
+template 
+constexpr auto castSum(Ts... Args) {
+  return (T)(Args + ...).Value; // expected-error{{member reference base type 'int' is not a structure or union}}
+}
+
+template 
+constexpr auto simpleSum(Ts... Args) {
+  return (... + Args).Value; // expected-error{{member reference base type 'int' is not a structure or union}}
+}
+
+void prim() {
+  castSum(1, 2);
+  // expected-note@-1{{in instantiation of function template specialization}}
+  simpleSum(1, 2);
+  // expected-note@-1{{in instantiation of function template specialization}}
+
+  struct Number {
+int Value;
+constexpr Number operator+(Number Rhs) const { return {Rhs.Value + Value}; }
+  };
+
+  static_assert(castSum(Number{1}, Number{2}) == 3);
+  static_assert(simpleSum(Number{1}, Number{2}) == 3);
+}
Index: cfe/trunk/lib/Parse/ParseExpr.cpp
===
--- cfe/trunk/lib/Parse/ParseExpr.cpp
+++ cfe/trunk/lib/Parse/ParseExpr.cpp
@@ -789,6 +789,10 @@
   // We have parsed the cast-expression and no postfix-expr pieces are
   // following.
   return Res;
+case FoldExpr:
+  // We only parsed a fold-expression. There might be postfix-expr pieces
+  // afterwards; parse them now.
+  break;
 }
 
 break;
@@ -2523,8 +2527,9 @@
   Diag(Tok, diag::err_expected_lbrace_in_compound_literal);
   return ExprError();
 }
-  } else if (Tok.is(tok::ellipsis) &&
+  } else if (ExprType >= FoldExpr && Tok.is(tok::ellipsis) &&
  isFoldOperator(NextToken().getKind())) {
+ExprType = FoldExpr;
 return ParseFoldExpression(ExprResult(), T);
   } else if (isTypeCast) {
 // Parse the expression-list.
@@ -2536,9 +2541,11 @@
 if (!ParseSimpleExpressionList(ArgExprs, CommaLocs)) {
   // FIXME: If we ever support comma expressions as operands to
   // fold-expressions, we'll need to allow multiple ArgExprs here.
-  if (ArgExprs.size() == 1 && isFoldOperator(Tok.getKind()) &&
-  NextToken().is(tok::ellipsis))
+  if (ExprType >= FoldExpr && ArgExprs.size() == 1 &&
+  isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis)) {
+ExprType = FoldExpr;
 return ParseFoldExpression(ArgExprs[0], T);
+  }
 
   ExprType = SimpleExpr;
   Result = Actions.ActOnParenListExpr(OpenLoc, Tok.getLocation(),
@@ -2553,10 +2560,13 @@
   // expressions are parsed correctly.
   Result = Actions.CorrectDelayedTyposInExpr(Result);
 }
-ExprType = SimpleExpr;
 
-if (isFoldOperator(Tok.getKind()) && NextToken().is(tok::ellipsis))
+if (ExprType >= FoldExpr && isFoldOperator(Tok.getKind()) &&
+NextToken().is(tok::ellipsis)) {
+  ExprType = FoldExpr;
   return ParseFoldExpression(Result, T);
+}
+ExprType = SimpleExpr;
 
 // Don't build a paren expression unless we actually match a ')'.
 if (!Result.isInvalid() && Tok.is(tok::r_paren))
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D50119: Compiler support for P1144R0 "__is_trivially_relocatable(T)"

2018-08-01 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added a comment.

- There's a bug in your implementation:

  struct X {
X &operator=(X &&);
  };
  static_assert(__is_trivially_relocatable(X)); // oops, fires!

`X` has a move constructor and a destructor, so it is trivially relocatable.

- Please run your code through clang-format.

- Might be useful to add a note explaining why the type isn't trivially 
relocatable isn't of the general "because it is not destructible".




Comment at: include/clang/Sema/Sema.h:4304
 
+  bool IsTriviallyRelocatableType(QualType QT) const;
+

Any reason why this is a free function? Should be a member function of 
`QualType`.



Comment at: lib/AST/DeclCXX.cpp:283
+if (Base->isVirtual() || !BaseClassDecl->isTriviallyRelocatable()) {
+  //puts("because 283");
+  setIsNotNaturallyTriviallyRelocatable();

Lingering debug message? :) There are many of them.

For a single expression, drop the braces of the if statement.



Comment at: lib/Sema/SemaDeclCXX.cpp:6066
+if (M->hasAttr() || Record->hasAttr()) {
+  // Consider removing this case to simplify the Standard wording.
+} else {

This should be a `// TODO: ...`. Is this comment really appropriate? The 
intended audience isn't compiler writers I think.



Comment at: lib/Sema/SemaDeclCXX.cpp:6157
+
+  if (getLangOpts().CPlusPlus11 &&
+  !Record->hasAttr() &&

This really just checks whether the type has defaulted copy constructor. If 
there was a move constructor, it would have been handled above. If the 
copy/move constructor is implicitly deleted, it would have been handled also 
above. Please simplify this accordingly.



Comment at: lib/Sema/SemaDeclCXX.cpp:6158
+  if (getLangOpts().CPlusPlus11 &&
+  !Record->hasAttr() &&
+  Record->isTriviallyRelocatable()) {

Why do you need to check whether the attribute is present or not? This is 
supposed to be whether the type is naturally trivially relocatable, so the 
presence of the attribute is not important.



Comment at: lib/Sema/SemaDeclCXX.cpp:6656
   SetDeclDeleted(MD, MD->getLocation());
+  if (CSM == CXXMoveConstructor || CSM == CXXDestructor) {
+//puts("because 6646");

You don't actually need those three lines. This is already handled in 
`CheckCompletedCXXClass`.



Comment at: test/SemaCXX/trivially-relocatable.cpp:42
+struct A6;
+struct [[trivially_relocatable]] A6 {};
+// expected-error@-1{{type A6 declared 'trivially_relocatable' after its first 
declaration}}

Why does this restriction exist? None of the existing attributes have it and I 
don't see why it would make sense to disallow this.



Comment at: test/SemaCXX/trivially-relocatable.cpp:471
+struct Incomplete; // expected-note {{forward declaration of 'Incomplete'}}
+struct Regression1 {
+  Incomplete i; // expected-error {{field has incomplete type 'Incomplete'}}

This is the right place for regression tests. Add them to 
test/Parser/cxx-class.cpp.


Repository:
  rC Clang

https://reviews.llvm.org/D50119



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


[PATCH] D50119: Compiler support for P1144R0 "__is_trivially_relocatable(T)"

2018-08-01 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added inline comments.



Comment at: compiler-explorer-llvm-commit.sh:1
+# This is the commit of LLVM that we're currently based on.
+git reset --hard 1fa19f68007cd126a04448093c171f40e556087e

What's this file? A mistake?



Comment at: include/clang/AST/DeclCXX.h:471
 
+/// True when this class's bases and fields are all trivially relocatable,
+/// and the class itself has a defaulted move constructor and a defaulted

That comment misses a "or is a reference".



Comment at: include/clang/Basic/DiagnosticSemaKinds.td:2942
+  "not %select{move-constructible|destructible}2"
+  >;
+

Quuxplusone wrote:
> > Might be useful to add a note explaining why the type isn't trivially 
> > relocatable instead of the general "because it is not destructible".
> 
> You mean, like, a series of notes pointing at "because its base class B is 
> not destructible... because B's destructor is defined as deleted here"?  I 
> agree that might be helpful, but since it only happens when the programmer is 
> messing around with the attribute anyway, I wouldn't want to do anything too 
> innovative or LoC-consuming. I'd cut and paste ~10 lines of code from 
> somewhere else that already does something like that if you point me at it, 
> but otherwise I think it's not worth the number of extra codepaths that would 
> need to be tested.
Fair enough.



Comment at: include/clang/Sema/Sema.h:4304
 
+  bool IsTriviallyRelocatableType(QualType QT) const;
+

Quuxplusone wrote:
> Rakete wrote:
> > Any reason why this is a free function? Should be a member function of 
> > `QualType`.
> `class QualType` is defined in `AST/`, whereas all the C++-specific 
> TriviallyRelocatable stuff is currently confined to `Sema/`. My impression 
> was that I should try to preserve that separation, even if it meant being 
> ugly right here. I agree that this is a stupid hack, and would love to get 
> rid of it, but I think I need some guidance as to how much mixing of `AST` 
> and `Sema` is permitted.
Nah, it's fine. There are lots of C++ specific things in AST/, because the AST 
nodes represent C++-y stuff. Trivially copyable is also part of `QualType`, 
even though it's C++ specific.



Comment at: lib/Sema/SemaDecl.cpp:15823
 CXXRecord->setImplicitDestructorIsDeleted();
+CXXRecord->setIsNotNaturallyTriviallyRelocatable();
 SetDeclDeleted(Dtor, CXXRecord->getLocation());

You don't need this. This is already handled by `CheckCompleteCXXClass`.



Comment at: lib/Sema/SemaDeclAttr.cpp:6481
 break;
+  case ParsedAttr::AT_TriviallyRelocatable:
+handleTriviallyRelocatableAttr(S, D, AL);

Why is this attribute under "Microsoft Attributes"? ;)



Comment at: lib/Sema/SemaDeclCXX.cpp:6166
+if (SMOR.getKind() != SpecialMemberOverloadResult::Success ||
+!SMOR.getMethod()->isDefaulted()) {
+  Record->setIsNotNaturallyTriviallyRelocatable();

Extra braces.



Comment at: lib/Sema/SemaDeclCXX.cpp:6187
+Record->dropAttr();
+  } else if (Record->needsImplicitMoveConstructor() &&
+ Record->defaultedMoveConstructorIsDeleted()) {

This is dead code. `Record` never needs an implicit move constructor at this 
point, because either 1) it never did or 2) it was defined above by 
`LookupSpecialMember`.



Comment at: lib/Sema/SemaDeclCXX.cpp:12631
 ClassDecl->setImplicitMoveConstructorIsDeleted();
+ClassDecl->setIsNotNaturallyTriviallyRelocatable();
 SetDeclDeleted(MoveConstructor, ClassLoc);

Same, already handled by `CheckCompleteCXXClass`.



Comment at: lib/Sema/SemaDeclCXX.cpp:6157
+
+  if (getLangOpts().CPlusPlus11 &&
+  !Record->hasAttr() &&

Quuxplusone wrote:
> Rakete wrote:
> > This really just checks whether the type has defaulted copy constructor. If 
> > there was a move constructor, it would have been handled above. If the 
> > copy/move constructor is implicitly deleted, it would have been handled 
> > also above. Please simplify this accordingly.
> Can you elaborate on this one? I assume you mean that some of lines 6157 
> through 6171 are superfluous, but I can't figure out which ones or how to 
> simplify it.
Actually, nvm. I was thinking of calling a few functions instead of call 
`LookupSpecialMember`, but I forgot that those functions can only work if there 
was previously a call to `LookupSpecialMember` :/.



Comment at: test/SemaCXX/trivially-relocatable.cpp:42
+struct A6;
+struct [[trivially_relocatable]] A6 {};
+// expected-error@-1{{type A6 declared 'trivially_relocatable' after its first 
declaration}}

Quuxplusone wrote:
> Rakete wrote:
> > Why does this restriction exi

[PATCH] D50119: Compiler support for P1144R0 "__is_trivially_relocatable(T)"

2018-08-02 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added inline comments.



Comment at: lib/Sema/SemaDeclCXX.cpp:6187
+Record->dropAttr();
+  } else if (Record->needsImplicitMoveConstructor() &&
+ Record->defaultedMoveConstructorIsDeleted()) {

Quuxplusone wrote:
> Rakete wrote:
> > This is dead code. `Record` never needs an implicit move constructor at 
> > this point, because either 1) it never did or 2) it was defined above by 
> > `LookupSpecialMember`.
> Confirmed that this code is never hit; and removed. Just for my own 
> information: you're saying that the call to `LookupSpecialMember` on line 
> 6179, even though it's looking up the //destructor//, will actually cause all 
> the `needsImplicitFootor` flags to get resolved? And so also I guess I should 
> never have been looking at those flags directly; I should have handled this 
> case by calling `LookupSpecialMember` like I do on line 6196. Is that 
> basically correct?
No, not the 6179 one, but the one before it 6163. Yeah you could have :)


Repository:
  rC Clang

https://reviews.llvm.org/D50119



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


[PATCH] D50119: Compiler support for P1144R0 "__is_trivially_relocatable(T)"

2018-08-02 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added inline comments.



Comment at: lib/Sema/SemaDeclCXX.cpp:6187
+Record->dropAttr();
+  } else if (Record->needsImplicitMoveConstructor() &&
+ Record->defaultedMoveConstructorIsDeleted()) {

Rakete wrote:
> Quuxplusone wrote:
> > Rakete wrote:
> > > This is dead code. `Record` never needs an implicit move constructor at 
> > > this point, because either 1) it never did or 2) it was defined above by 
> > > `LookupSpecialMember`.
> > Confirmed that this code is never hit; and removed. Just for my own 
> > information: you're saying that the call to `LookupSpecialMember` on line 
> > 6179, even though it's looking up the //destructor//, will actually cause 
> > all the `needsImplicitFootor` flags to get resolved? And so also I guess I 
> > should never have been looking at those flags directly; I should have 
> > handled this case by calling `LookupSpecialMember` like I do on line 6196. 
> > Is that basically correct?
> No, not the 6179 one, but the one before it 6163. Yeah you could have :)
Sorry for the noise, that isn't it because of the if statement right before 
6163 :/. I was wrong...

Every implicit constructor is already defined before the call to 
`CheckCompletedCXXClass` (except if it's a template), so `needsImplicitFootor` 
is always `false`. This means that you can drop the if statement right before 
6163, because it's always true.

I'm 99% sure of the previous paragraph. :)



Comment at: lib/Sema/SemaDeclCXX.cpp:6091
 
+  for (auto *F : Record->fields()) {
+if (F->isMutable()) {

Can you move this in `ActOnFields`? That way we avoid two iterations of the 
fields.


Repository:
  rC Clang

https://reviews.llvm.org/D50119



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


[PATCH] D50119: Compiler support for P1144R0 "__is_trivially_relocatable(T)"

2018-08-02 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added inline comments.



Comment at: lib/Sema/SemaDeclCXX.cpp:6174
+  Record->hasAttr() &&
+  !isTemplateInstantiation(Record->getTemplateSpecializationKind())) {
+if (Record->getDefinition() && !Record->isDependentContext() &&

The call to `isTemplateInstantiation` is wrong. Consider:

```
template
struct [[trivially_relocatable]] A {
  T t;
};

struct X {
  X() = default;
  X(X &&) = delete;
};

A d;
static_assert(!__is_trivially_relocatable(decltype(d))); // oops, fires
```

There is also no diagnostic saying that `A` cannot be marked 
`[[trivially_relocatable]]`.



Comment at: lib/Sema/SemaDeclCXX.cpp:6176
+if (Record->getDefinition() && !Record->isDependentContext() &&
+!Record->isBeingDefined()) {
+  // Check that the destructor is non-deleted.

`Record` is never being defined at this point, even for templates. It also 
always has a definition AFAIK.


Repository:
  rC Clang

https://reviews.llvm.org/D50119



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


[PATCH] D50119: Compiler support for P1144R0 "__is_trivially_relocatable(T)"

2018-08-02 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added a reviewer: Rakete.
Rakete added inline comments.



Comment at: lib/Sema/SemaDeclCXX.cpp:6091
 
+  for (auto *F : Record->fields()) {
+if (F->isMutable()) {

Quuxplusone wrote:
> Rakete wrote:
> > Can you move this in `ActOnFields`? That way we avoid two iterations of the 
> > fields.
> Done. Btw, I notice that `ActOnFields` spends a lot of time doing 
> `dyn_cast(Record)` over and over. If I had commit privs, I'd 
> refactor it to compute `CXXRecordDecl *CXXRecord = 
> dyn_cast_or_null(Record);` once at the very top of the 
> function, and then use `CXXRecord` throughout.
Done. :) Thanks



Comment at: lib/Sema/SemaDeclCXX.cpp:6174
+  Record->hasAttr() &&
+  !isTemplateInstantiation(Record->getTemplateSpecializationKind())) {
+if (Record->getDefinition() && !Record->isDependentContext() &&

Quuxplusone wrote:
> Rakete wrote:
> > The call to `isTemplateInstantiation` is wrong. Consider:
> > 
> > ```
> > template
> > struct [[trivially_relocatable]] A {
> >   T t;
> > };
> > 
> > struct X {
> >   X() = default;
> >   X(X &&) = delete;
> > };
> > 
> > A d;
> > static_assert(!__is_trivially_relocatable(decltype(d))); // oops, fires
> > ```
> > 
> > There is also no diagnostic saying that `A` cannot be marked 
> > `[[trivially_relocatable]]`.
> The absence of any diagnostics is intentional. We're saying that `A` is 
> trivially relocatable except-of-course-when-it's-not-relocatable-at-all, 
> similar to how templates currently work with `constexpr`.
> 
> However, the fact that `__is_trivially_relocatable(A)` when 
> `!__is_constructible(A, A&&)` does seem like a bug. I should probably 
> move the `isTemplateInstantiation` check down to control just the diagnostic, 
> eh?
Yes, good idea.


Repository:
  rC Clang

https://reviews.llvm.org/D50119



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


[PATCH] D50291: [C++] Delay checking of constexpr-ness for special members.

2018-08-03 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete created this revision.
Rakete added a reviewer: rsmith.

Specific class layouts meant that the constexpr-ness of a special member could 
only be decided after every special member was seen. However, this was at odds 
with the implementation, which checked the constexpr-ness for each special 
member in the order in which they were declared (hence that the bug only occurs 
when special members are ordered in a specific order).

This patch moves the checking of constexpr-ness after evaluating each special 
member.
This fixes https://llvm.org/pr38143


Repository:
  rC Clang

https://reviews.llvm.org/D50291

Files:
  include/clang/Sema/Sema.h
  lib/Sema/SemaDeclCXX.cpp

Index: lib/Sema/SemaDeclCXX.cpp
===
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -6020,6 +6020,7 @@
 
   bool HasMethodWithOverrideControl = false,
HasOverridingMethodWithoutOverrideControl = false;
+  CXXMethodDecl *CopyAssignment = nullptr, *MoveAssignment = nullptr;
   if (!Record->isDependentType()) {
 for (auto *M : Record->methods()) {
   // See if a method overloads virtual methods in a base
@@ -6049,6 +6050,11 @@
 }
   }
 
+  if (CSM == CXXCopyAssignment)
+CopyAssignment = M;
+  else if (CSM == CXXMoveAssignment)
+MoveAssignment = M;
+
   // Set triviality for the purpose of calls if this is a user-provided
   // copy/move constructor or destructor.
   if ((CSM == CXXCopyConstructor || CSM == CXXMoveConstructor ||
@@ -6071,6 +6077,22 @@
 }
   }
 }
+
+// Now we can decide whether the special members are constexpr.
+auto ActOnSpecialMember = [this, &Record](CXXMethodDecl *MD) {
+  if (!MD->isInvalidDecl() && MD->isExplicitlyDefaulted()) {
+CheckExplicitlyDefaultedSpecialMemberConstexpr(MD);
+Record->finishedDefaultedOrDeletedMember(MD);
+  }
+};
+for (auto *M : Record->ctors())
+  ActOnSpecialMember(M);
+if (CopyAssignment)
+  ActOnSpecialMember(CopyAssignment);
+if (MoveAssignment)
+  ActOnSpecialMember(MoveAssignment);
+if (CXXDestructorDecl *CD = Record->getDestructor())
+  ActOnSpecialMember(CD);
   }
 
   if (HasMethodWithOverrideControl &&
@@ -6532,20 +6554,8 @@
   // C++11 [dcl.fct.def.default]p2:
   //   An explicitly-defaulted function may be declared constexpr only if it
   //   would have been implicitly declared as constexpr,
-  // Do not apply this rule to members of class templates, since core issue 1358
-  // makes such functions always instantiate to constexpr functions. For
-  // functions which cannot be constexpr (for non-constructors in C++11 and for
-  // destructors in C++1y), this is checked elsewhere.
-  bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, RD, CSM,
- HasConstParam);
-  if ((getLangOpts().CPlusPlus14 ? !isa(MD)
- : isa(MD)) &&
-  MD->isConstexpr() && !Constexpr &&
-  MD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) {
-Diag(MD->getLocStart(), diag::err_incorrect_defaulted_constexpr) << CSM;
-// FIXME: Explain why the special member can't be constexpr.
-HadError = true;
-  }
+  // We need to delay this, because at this point we may not have enough
+  // information to determine if MD is really constexpr or not.
 
   //   and may have an explicit exception-specification only if it is compatible
   //   with the exception-specification on the implicit declaration.
@@ -6568,8 +6578,6 @@
   if (First) {
 //  -- it is implicitly considered to be constexpr if the implicit
 // definition would be,
-MD->setConstexpr(Constexpr);
-
 //  -- it is implicitly considered to have the same exception-specification
 // as if it had been implicitly declared,
 FunctionProtoType::ExtProtoInfo EPI = Type->getExtProtoInfo();
@@ -6598,6 +6606,39 @@
 MD->setInvalidDecl();
 }
 
+void Sema::CheckExplicitlyDefaultedSpecialMemberConstexpr(CXXMethodDecl *MD) {
+  CXXSpecialMember CSM = getSpecialMember(MD);
+  assert(MD && MD->isExplicitlyDefaulted() && CSM != CXXInvalid &&
+ "not an explicitly-defaulted special member");
+
+  const FunctionProtoType *Type = MD->getType()->getAs();
+
+  unsigned ExpectedParams =
+  CSM != CXXDefaultConstructor && CSM != CXXDestructor;
+  QualType ArgType = ExpectedParams ? Type->getParamType(0) : QualType();
+
+  bool HasConstParam = ExpectedParams && ArgType->isReferenceType() &&
+   ArgType->getPointeeType().isConstQualified();
+
+  // Do not apply this rule to members of class templates, since core issue 1358
+  // makes such functions always instantiate to constexpr functions. For
+  // functions which cannot be constexpr (for non-constructors in C++11 and for
+  // destructors in C++1y), this is checked elsewhere.
+  bool Constexpr = defaultedSpecialMemberIsConstexpr(*this,

[PATCH] D50291: [C++] Delay checking of constexpr-ness for special members.

2018-08-03 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 159160.
Rakete added a comment.

Add missing test cases. :)


Repository:
  rC Clang

https://reviews.llvm.org/D50291

Files:
  include/clang/Sema/Sema.h
  lib/Sema/SemaDeclCXX.cpp
  test/CXX/special/class.copy/p10.cpp

Index: test/CXX/special/class.copy/p10.cpp
===
--- /dev/null
+++ test/CXX/special/class.copy/p10.cpp
@@ -0,0 +1,25 @@
+// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+// The implicitly-defined copy/move assignment operator is constexpr if
+// - X is a literal type, and
+// - [...]
+//
+// PR38143: Order of defaulted special members matters.
+struct X {
+  constexpr X() = default;
+  constexpr X(const X &) = default;
+  constexpr X &operator=(const X &) = default;
+  ~X() = default;
+  constexpr X(X &&) = default;
+  constexpr X &operator=(X &&) = default;
+};
+
+struct Y {
+  constexpr Y &operator=(const Y &) = default;
+  constexpr Y &operator=(Y &&) = default;
+  constexpr Y() = default;
+  constexpr Y(const Y &) = default;
+  ~Y() = default;
+  constexpr Y(Y &&) = default;
+};
Index: lib/Sema/SemaDeclCXX.cpp
===
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -6020,6 +6020,7 @@
 
   bool HasMethodWithOverrideControl = false,
HasOverridingMethodWithoutOverrideControl = false;
+  CXXMethodDecl *CopyAssignment = nullptr, *MoveAssignment = nullptr;
   if (!Record->isDependentType()) {
 for (auto *M : Record->methods()) {
   // See if a method overloads virtual methods in a base
@@ -6049,6 +6050,11 @@
 }
   }
 
+  if (CSM == CXXCopyAssignment)
+CopyAssignment = M;
+  else if (CSM == CXXMoveAssignment)
+MoveAssignment = M;
+
   // Set triviality for the purpose of calls if this is a user-provided
   // copy/move constructor or destructor.
   if ((CSM == CXXCopyConstructor || CSM == CXXMoveConstructor ||
@@ -6071,6 +6077,22 @@
 }
   }
 }
+
+// Now we can decide whether the special members are constexpr.
+auto ActOnSpecialMember = [this, &Record](CXXMethodDecl *MD) {
+  if (!MD->isInvalidDecl() && MD->isExplicitlyDefaulted()) {
+CheckExplicitlyDefaultedSpecialMemberConstexpr(MD);
+Record->finishedDefaultedOrDeletedMember(MD);
+  }
+};
+for (auto *M : Record->ctors())
+  ActOnSpecialMember(M);
+if (CopyAssignment)
+  ActOnSpecialMember(CopyAssignment);
+if (MoveAssignment)
+  ActOnSpecialMember(MoveAssignment);
+if (CXXDestructorDecl *CD = Record->getDestructor())
+  ActOnSpecialMember(CD);
   }
 
   if (HasMethodWithOverrideControl &&
@@ -6532,20 +6554,8 @@
   // C++11 [dcl.fct.def.default]p2:
   //   An explicitly-defaulted function may be declared constexpr only if it
   //   would have been implicitly declared as constexpr,
-  // Do not apply this rule to members of class templates, since core issue 1358
-  // makes such functions always instantiate to constexpr functions. For
-  // functions which cannot be constexpr (for non-constructors in C++11 and for
-  // destructors in C++1y), this is checked elsewhere.
-  bool Constexpr = defaultedSpecialMemberIsConstexpr(*this, RD, CSM,
- HasConstParam);
-  if ((getLangOpts().CPlusPlus14 ? !isa(MD)
- : isa(MD)) &&
-  MD->isConstexpr() && !Constexpr &&
-  MD->getTemplatedKind() == FunctionDecl::TK_NonTemplate) {
-Diag(MD->getLocStart(), diag::err_incorrect_defaulted_constexpr) << CSM;
-// FIXME: Explain why the special member can't be constexpr.
-HadError = true;
-  }
+  // We need to delay this, because at this point we may not have enough
+  // information to determine if MD is really constexpr or not.
 
   //   and may have an explicit exception-specification only if it is compatible
   //   with the exception-specification on the implicit declaration.
@@ -6568,8 +6578,6 @@
   if (First) {
 //  -- it is implicitly considered to be constexpr if the implicit
 // definition would be,
-MD->setConstexpr(Constexpr);
-
 //  -- it is implicitly considered to have the same exception-specification
 // as if it had been implicitly declared,
 FunctionProtoType::ExtProtoInfo EPI = Type->getExtProtoInfo();
@@ -6598,6 +6606,39 @@
 MD->setInvalidDecl();
 }
 
+void Sema::CheckExplicitlyDefaultedSpecialMemberConstexpr(CXXMethodDecl *MD) {
+  CXXSpecialMember CSM = getSpecialMember(MD);
+  assert(MD && MD->isExplicitlyDefaulted() && CSM != CXXInvalid &&
+ "not an explicitly-defaulted special member");
+
+  const FunctionProtoType *Type = MD->getType()->getAs();
+
+  unsigned ExpectedParams =
+  CSM != CXXDefaultConstructor && CSM != CXXDestructor;
+  QualType ArgType = ExpectedParams ? Type->getParamType(0) : QualType();
+
+  bool HasConstParam = Expec

[PATCH] D40445: [C++17] Allow an empty expression in an if init statement

2018-01-04 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 128659.
Rakete added a comment.

Rebased + friendly 2018 ping :)


https://reviews.llvm.org/D40445

Files:
  lib/Parse/ParseExprCXX.cpp
  test/CXX/stmt.stmt/stmt.select/p3.cpp

Index: test/CXX/stmt.stmt/stmt.select/p3.cpp
===
--- test/CXX/stmt.stmt/stmt.select/p3.cpp
+++ test/CXX/stmt.stmt/stmt.select/p3.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++1z -Wc++14-compat -verify %s -DCPP17
 
 int f();
 
@@ -10,10 +11,67 @@
   }
 }
 
-
 void h() {
   if (int x = f()) // expected-note 2{{previous definition}}
 int x; // expected-error{{redefinition of 'x'}}
   else
 int x; // expected-error{{redefinition of 'x'}}
 }
+
+void ifInitStatement() {
+  int Var = 0;
+
+  if (int I = 0; true) {}
+  if (Var + Var; true) {}
+  if (; true) {}
+#ifdef CPP17
+  // expected-warning@-4 {{if initialization statements are incompatible with C++ standards before C++17}}
+  // expected-warning@-4 {{if initialization statements are incompatible with C++ standards before C++17}}
+  // expected-warning@-4 {{if initialization statements are incompatible with C++ standards before C++17}}
+#else
+  // expected-warning@-8 {{'if' initialization statements are a C++17 extension}}
+  // expected-warning@-8 {{'if' initialization statements are a C++17 extension}}
+  // expected-warning@-8 {{'if' initialization statements are a C++17 extension}}
+#endif
+}
+
+void switchInitStatement() {
+  int Var = 0;
+
+  switch (int I = 0; Var) {}
+  switch (Var + Var; Var) {}
+  switch (; Var) {}
+#ifdef CPP17
+  // expected-warning@-4 {{switch initialization statements are incompatible with C++ standards before C++17}}
+  // expected-warning@-4 {{switch initialization statements are incompatible with C++ standards before C++17}}
+  // expected-warning@-4 {{switch initialization statements are incompatible with C++ standards before C++17}}
+#else
+  // expected-warning@-8 {{'switch' initialization statements are a C++17 extension}}
+  // expected-warning@-8 {{'switch' initialization statements are a C++17 extension}}
+  // expected-warning@-8 {{'switch' initialization statements are a C++17 extension}}
+#endif
+}
+
+// TODO: Better diagnostics for while init statements.
+void whileInitStatement() {
+  while (int I = 10; I--); // expected-error {{expected ')'}}
+  // expected-note@-1 {{to match this '('}}
+  // expected-error@-2 {{use of undeclared identifier 'I'}}
+
+  int Var = 10;
+  while (Var + Var; Var--) {} // expected-error {{expected ')'}}
+  // expected-note@-1 {{to match this '('}}
+  // expected-error@-2 {{expected ';' after expression}}
+  // expected-error@-3 {{expected expression}}
+  // expected-warning@-4 {{while loop has empty body}}
+  // expected-note@-5 {{put the semicolon on a separate line to silence this warning}}
+}
+
+// TODO: This is needed because clang can't seem to diagnose invalid syntax after the
+// last loop above. It would be nice to remove this.
+void whileInitStatement2() {
+  while (; false) {} // expected-error {{expected expression}}
+  // expected-warning@-1 {{expression result unused}}
+  // expected-error@-2 {{expected ';' after expression}}
+  // expected-error@-3 {{expected expression}}
+}
Index: lib/Parse/ParseExprCXX.cpp
===
--- lib/Parse/ParseExprCXX.cpp
+++ lib/Parse/ParseExprCXX.cpp
@@ -1742,17 +1742,32 @@
   ParsedAttributesWithRange attrs(AttrFactory);
   MaybeParseCXX11Attributes(attrs);
 
+  const auto WarnOnInit = [this, &CK] {
+Diag(Tok.getLocation(), getLangOpts().CPlusPlus17
+? diag::warn_cxx14_compat_init_statement
+: diag::ext_init_statement)
+<< (CK == Sema::ConditionKind::Switch);
+  };
+
   // Determine what kind of thing we have.
   switch (isCXXConditionDeclarationOrInitStatement(InitStmt)) {
   case ConditionOrInitStatement::Expression: {
 ProhibitAttributes(attrs);
 
+// We can have an empty expression here.
+//   if (; true);
+if (InitStmt && TryConsumeToken(tok::semi)) {
+  WarnOnInit();
+  return ParseCXXCondition(nullptr, Loc, CK);
+}
+
 // Parse the expression.
 ExprResult Expr = ParseExpression(); // expression
 if (Expr.isInvalid())
   return Sema::ConditionError();
 
 if (InitStmt && Tok.is(tok::semi)) {
+  WarnOnInit();
   *InitStmt = Actions.ActOnExprStmt(Expr.get());
   ConsumeToken();
   return ParseCXXCondition(nullptr, Loc, CK);
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D39679: [C++11] Fix warning when dropping cv-qualifiers when assigning to a reference with a braced initializer list

2018-01-04 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 128661.
Rakete added a comment.

Rebased + friendly 2018 ping :)


https://reviews.llvm.org/D39679

Files:
  lib/Sema/SemaInit.cpp
  test/SemaCXX/references.cpp


Index: test/SemaCXX/references.cpp
===
--- test/SemaCXX/references.cpp
+++ test/SemaCXX/references.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s 
 int g(int);
 
 void f() {
@@ -55,6 +56,13 @@
   //  const double& rcd2 = 2; // rcd2 refers to temporary with value 2.0
   const volatile int cvi = 1;
   const int& r = cvi; // expected-error{{binding value of type 'const volatile 
int' to reference to type 'const int' drops 'volatile' qualifier}}
+
+#if __cplusplus >= 201103L
+  const int& r2{cvi}; // expected-error{{binding value of type 'const volatile 
int' to reference to type 'const int' drops 'volatile' qualifier}}
+
+  const int a = 2;
+  int& r3{a}; // expected-error{{binding value of type 'const int' to 
reference to type 'int' drops 'const'}}
+#endif
 }
 
 // C++ [dcl.init.ref]p3
Index: lib/Sema/SemaInit.cpp
===
--- lib/Sema/SemaInit.cpp
+++ lib/Sema/SemaInit.cpp
@@ -7696,6 +7696,12 @@
 
   case FK_ReferenceInitDropsQualifiers: {
 QualType SourceType = Args[0]->getType();
+
+// For braced initializer lists, we want to get the type
+// of its (only) element, and not the "type" of the list itself.
+if (const auto *List = dyn_cast(Args[0]))
+  SourceType = List->getInit(0)->getType();
+
 QualType NonRefType = DestType.getNonReferenceType();
 Qualifiers DroppedQualifiers =
 SourceType.getQualifiers() - NonRefType.getQualifiers();


Index: test/SemaCXX/references.cpp
===
--- test/SemaCXX/references.cpp
+++ test/SemaCXX/references.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s 
 int g(int);
 
 void f() {
@@ -55,6 +56,13 @@
   //  const double& rcd2 = 2; // rcd2 refers to temporary with value 2.0
   const volatile int cvi = 1;
   const int& r = cvi; // expected-error{{binding value of type 'const volatile int' to reference to type 'const int' drops 'volatile' qualifier}}
+
+#if __cplusplus >= 201103L
+  const int& r2{cvi}; // expected-error{{binding value of type 'const volatile int' to reference to type 'const int' drops 'volatile' qualifier}}
+
+  const int a = 2;
+  int& r3{a}; // expected-error{{binding value of type 'const int' to reference to type 'int' drops 'const'}}
+#endif
 }
 
 // C++ [dcl.init.ref]p3
Index: lib/Sema/SemaInit.cpp
===
--- lib/Sema/SemaInit.cpp
+++ lib/Sema/SemaInit.cpp
@@ -7696,6 +7696,12 @@
 
   case FK_ReferenceInitDropsQualifiers: {
 QualType SourceType = Args[0]->getType();
+
+// For braced initializer lists, we want to get the type
+// of its (only) element, and not the "type" of the list itself.
+if (const auto *List = dyn_cast(Args[0]))
+  SourceType = List->getInit(0)->getType();
+
 QualType NonRefType = DestType.getNonReferenceType();
 Qualifiers DroppedQualifiers =
 SourceType.getQualifiers() - NonRefType.getQualifiers();
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D38216: [C++17] Fix class template argument deduction for default constructors without an initializer

2018-01-04 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 128662.
Rakete marked an inline comment as done.
Rakete added a comment.

Rebased + friendly 2018 ping


https://reviews.llvm.org/D38216

Files:
  lib/Sema/SemaDecl.cpp
  test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
  test/Parser/cxx1z-class-template-argument-deduction.cpp


Index: test/Parser/cxx1z-class-template-argument-deduction.cpp
===
--- test/Parser/cxx1z-class-template-argument-deduction.cpp
+++ test/Parser/cxx1z-class-template-argument-deduction.cpp
@@ -52,7 +52,7 @@
 
   operator A(); // expected-error {{requires template arguments; argument 
deduction not allowed in conversion function type}}
 
-  static A x; // expected-error {{declaration of variable 'x' with deduced 
type 'A' requires an initializer}}
+  static A x;
   static constexpr A y = 0;
 };
 
@@ -114,7 +114,6 @@
 (void)A{n};
 (void)new A(n);
 (void)new A{n};
-// FIXME: We should diagnose the lack of an initializer here.
 (void)new A;
   }
 }
@@ -127,7 +126,7 @@
 
   auto k() -> A; // expected-error{{requires template arguments}}
 
-  A a; // expected-error {{declaration of variable 'a' with deduced type 'A' 
requires an initializer}}
+  A a;
   A b = 0;
   const A c = 0;
   A (parens) = 0; // expected-error {{cannot use parentheses when declaring 
variable with deduced class template specialization type}}
Index: test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
===
--- test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
+++ test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
@@ -5,14 +5,13 @@
 A(int) -> A;
 
 static constexpr inline const volatile A a = {}; // ok, specifiers are 
permitted
-// FIXME: There isn't really a good reason to reject this.
-A b; // expected-error {{requires an initializer}}
+A b;
 A c [[]] {};
 
 A d = {}, e = {};
 A f(0), g{}; // expected-error {{template arguments deduced as 'A' in 
declaration of 'f' and deduced as 'A' in declaration of 'g'}}
 
 struct B {
-  static A a; // expected-error {{requires an initializer}}
+  static A a;
 };
-extern A x; // expected-error {{requires an initializer}}
+extern A x;
Index: lib/Sema/SemaDecl.cpp
===
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -10053,14 +10053,18 @@
   assert(Deduced && "deduceVarTypeFromInitializer for non-deduced type");
 
   // C++11 [dcl.spec.auto]p3
-  if (!Init) {
+  // Except for class argument deduction.
+  if (!Init && !isa(Deduced)) {
 assert(VDecl && "no init for init capture deduction?");
 Diag(VDecl->getLocation(), diag::err_auto_var_requires_init)
   << VDecl->getDeclName() << Type;
 return QualType();
   }
 
-  ArrayRef DeduceInits = Init;
+  ArrayRef DeduceInits;
+  if (Init)
+DeduceInits = Init;
+
   if (DirectInit) {
 if (auto *PL = dyn_cast_or_null(Init))
   DeduceInits = PL->exprs();


Index: test/Parser/cxx1z-class-template-argument-deduction.cpp
===
--- test/Parser/cxx1z-class-template-argument-deduction.cpp
+++ test/Parser/cxx1z-class-template-argument-deduction.cpp
@@ -52,7 +52,7 @@
 
   operator A(); // expected-error {{requires template arguments; argument deduction not allowed in conversion function type}}
 
-  static A x; // expected-error {{declaration of variable 'x' with deduced type 'A' requires an initializer}}
+  static A x;
   static constexpr A y = 0;
 };
 
@@ -114,7 +114,6 @@
 (void)A{n};
 (void)new A(n);
 (void)new A{n};
-// FIXME: We should diagnose the lack of an initializer here.
 (void)new A;
   }
 }
@@ -127,7 +126,7 @@
 
   auto k() -> A; // expected-error{{requires template arguments}}
 
-  A a; // expected-error {{declaration of variable 'a' with deduced type 'A' requires an initializer}}
+  A a;
   A b = 0;
   const A c = 0;
   A (parens) = 0; // expected-error {{cannot use parentheses when declaring variable with deduced class template specialization type}}
Index: test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
===
--- test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
+++ test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
@@ -5,14 +5,13 @@
 A(int) -> A;
 
 static constexpr inline const volatile A a = {}; // ok, specifiers are permitted
-// FIXME: There isn't really a good reason to reject this.
-A b; // expected-error {{requires an initializer}}
+A b;
 A c [[]] {};
 
 A d = {}, e = {};
 A f(0), g{}; // expected-error {{template arguments deduced as 'A' in declaration of 'f' and deduced as 'A' in declaration of 'g'}}
 
 struct B {
-  static A a; // expected-error {{requires an initializer}}
+  static A a;
 };
-extern A x; // expected-error {{requires an initializer}}
+e

[PATCH] D37442: [C++17] Disallow lambdas in template parameters (PR33696).

2018-01-04 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 128667.
Rakete added a comment.

Rebased + friendly 2018 ping


https://reviews.llvm.org/D37442

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/Parse/ParseDecl.cpp
  lib/Parse/ParseDeclCXX.cpp
  lib/Parse/ParseStmt.cpp
  lib/Parse/ParseTemplate.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaExprCXX.cpp
  lib/Sema/TreeTransform.h
  test/CXX/expr/expr.prim/expr.prim.lambda/p2-template-parameter.cpp

Index: test/CXX/expr/expr.prim/expr.prim.lambda/p2-template-parameter.cpp
===
--- test/CXX/expr/expr.prim/expr.prim.lambda/p2-template-parameter.cpp
+++ test/CXX/expr/expr.prim/expr.prim.lambda/p2-template-parameter.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -std=c++17 %s -verify
+
+template struct Nothing {};
+
+void pr33696() {
+Nothing<[]() { return 0; }()> nothing; // expected-error{{a lambda expression cannot appear in this context}}
+}
+
Index: lib/Sema/TreeTransform.h
===
--- lib/Sema/TreeTransform.h
+++ lib/Sema/TreeTransform.h
@@ -5507,7 +5507,7 @@
   // decltype expressions are not potentially evaluated contexts
   EnterExpressionEvaluationContext Unevaluated(
   SemaRef, Sema::ExpressionEvaluationContext::Unevaluated, nullptr,
-  /*IsDecltype=*/true);
+  Sema::ExpressionType::Decltype);
 
   ExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr());
   if (E.isInvalid())
Index: lib/Sema/SemaExprCXX.cpp
===
--- lib/Sema/SemaExprCXX.cpp
+++ lib/Sema/SemaExprCXX.cpp
@@ -6195,7 +6195,7 @@
   if (RD->isInvalidDecl() || RD->isDependentContext())
 return E;
 
-  bool IsDecltype = ExprEvalContexts.back().IsDecltype;
+  bool IsDecltype = ExprEvalContexts.back().Type == ExpressionType::Decltype;
   CXXDestructorDecl *Destructor = IsDecltype ? nullptr : LookupDestructor(RD);
 
   if (Destructor) {
@@ -6277,7 +6277,8 @@
 /// are omitted for the 'topmost' call in the decltype expression. If the
 /// topmost call bound a temporary, strip that temporary off the expression.
 ExprResult Sema::ActOnDecltypeExpression(Expr *E) {
-  assert(ExprEvalContexts.back().IsDecltype && "not in a decltype expression");
+  assert(ExprEvalContexts.back().Type == ExpressionType::Decltype &&
+ "not in a decltype expression");
 
   // C++11 [expr.call]p11:
   //   If a function call is a prvalue of object type,
@@ -6319,7 +6320,7 @@
 TopBind = nullptr;
 
   // Disable the special decltype handling now.
-  ExprEvalContexts.back().IsDecltype = false;
+  ExprEvalContexts.back().Type = ExpressionType::Other;
 
   // In MS mode, don't perform any extra checking of call return types within a
   // decltype expression.
Index: lib/Sema/SemaExpr.cpp
===
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -13703,51 +13703,50 @@
 void
 Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
   Decl *LambdaContextDecl,
-  bool IsDecltype) {
+  ExpressionType Type) {
   ExprEvalContexts.emplace_back(NewContext, ExprCleanupObjects.size(), Cleanup,
-LambdaContextDecl, IsDecltype);
+LambdaContextDecl, Type);
   Cleanup.reset();
   if (!MaybeODRUseExprs.empty())
 std::swap(MaybeODRUseExprs, ExprEvalContexts.back().SavedMaybeODRUseExprs);
 }
 
 void
 Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
   ReuseLambdaContextDecl_t,
-  bool IsDecltype) {
+  ExpressionType Type) {
   Decl *ClosureContextDecl = ExprEvalContexts.back().ManglingContextDecl;
-  PushExpressionEvaluationContext(NewContext, ClosureContextDecl, IsDecltype);
+  PushExpressionEvaluationContext(NewContext, ClosureContextDecl, Type);
 }
 
 void Sema::PopExpressionEvaluationContext() {
   ExpressionEvaluationContextRecord& Rec = ExprEvalContexts.back();
   unsigned NumTypos = Rec.NumTypos;
 
   if (!Rec.Lambdas.empty()) {
-if (Rec.isUnevaluated() || Rec.isConstantEvaluated()) {
+if (Rec.Type == ExpressionType::TemplateParameter || Rec.isUnevaluated() ||
+(Rec.isConstantEvaluated() && !getLangOpts().CPlusPlus17)) {
   unsigned D;
   if (Rec.isUnevaluated()) {
 // C++11 [expr.prim.lambda]p2:
 //   A lambda-expression shall not appear in an unevaluated operand
 //   (Clause 5).
 D = diag::err_lambda_unevaluated_operand;
-  } else {
+  } else if (Rec.isConstantEvaluated() && !getLangOpts().CPlusPlus17) {
 // C++1y [expr.const]p2:
 //   A conditional-expression e is a core constant expression unless 

[PATCH] D36357: Added a better diagnostic when using the delete operator with lambdas

2018-01-04 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 128668.
Rakete added a comment.

Rebased + friendly 2018 ping :)


https://reviews.llvm.org/D36357

Files:
  include/clang/Basic/DiagnosticParseKinds.td
  lib/Parse/ParseExprCXX.cpp
  test/Parser/cxx0x-lambda-expressions.cpp
  test/SemaCXX/new-delete-0x.cpp


Index: test/SemaCXX/new-delete-0x.cpp
===
--- test/SemaCXX/new-delete-0x.cpp
+++ test/SemaCXX/new-delete-0x.cpp
@@ -34,6 +34,6 @@
 void bad_deletes()
 {
   // 'delete []' is always array delete, per [expr.delete]p1.
-  // FIXME: Give a better diagnostic.
-  delete []{ return (int*)0; }(); // expected-error {{expected expression}}
+  delete []{ return (int*)0; }(); // expected-error {{'[]' after delete 
interpreted as 'delete[]'}}
+  // expected-note@-1 {{add parentheses around the lambda}}
 }
Index: test/Parser/cxx0x-lambda-expressions.cpp
===
--- test/Parser/cxx0x-lambda-expressions.cpp
+++ test/Parser/cxx0x-lambda-expressions.cpp
@@ -53,7 +53,8 @@
   void delete_lambda(int *p) {
 delete [] p;
 delete [] (int*) { new int }; // ok, compound-literal, not lambda
-delete [] { return new int; } (); // expected-error{{expected expression}}
+delete [] { return new int; } (); // expected-error {{'[]' after delete 
interpreted as 'delete[]'}}
+// expected-note@-1 {{add parentheses around the lambda}}
 delete [&] { return new int; } (); // ok, lambda
   }
 
Index: lib/Parse/ParseExprCXX.cpp
===
--- lib/Parse/ParseExprCXX.cpp
+++ lib/Parse/ParseExprCXX.cpp
@@ -2901,15 +2901,45 @@
 //   [Footnote: A lambda expression with a lambda-introducer that consists
 //  of empty square brackets can follow the delete keyword if
 //  the lambda expression is enclosed in parentheses.]
-// FIXME: Produce a better diagnostic if the '[]' is unambiguously a
-//lambda-introducer.
-ArrayDelete = true;
-BalancedDelimiterTracker T(*this, tok::l_square);
+TentativeParsingAction TPA(*this);
 
-T.consumeOpen();
-T.consumeClose();
-if (T.getCloseLocation().isInvalid())
-  return ExprError();
+// Basic lookahead to check if we have a lambda expression. If we
+// encounter two braces with a semicolon, we can be pretty sure
+// that this is a lambda, not say a compound literal. 
+if (!SkipUntil(tok::l_brace, SkipUntilFlags::StopAtSemi) ||
+(NextToken().isNot(tok::r_brace) && !SkipUntil(tok::semi)) ||
+!SkipUntil(tok::r_brace, SkipUntilFlags::StopAtSemi)) {
+  TPA.Revert();
+  ArrayDelete = true;
+  BalancedDelimiterTracker T(*this, tok::l_square);
+
+  T.consumeOpen();
+  T.consumeClose();
+  if (T.getCloseLocation().isInvalid())
+return ExprError();
+} else {
+  TPA.Revert();
+
+  // Warn if the non-capturing lambda isn't surrounded by parenthesis
+  // to disambiguate it from 'delete[]'.
+  ExprResult Lambda = TryParseLambdaExpression();
+  if (!Lambda.isInvalid()) {
+SourceLocation StartLoc = Lambda.get()->getLocStart();
+Diag(Start, diag::err_lambda_after_delete)
+<< SourceRange(Start, StartLoc.getLocWithOffset(1));
+
+SourceLocation BeforeBracket = StartLoc.getLocWithOffset(-1);
+Diag(BeforeBracket, diag::note_lambda_after_delete)
+<< FixItHint::CreateInsertion(BeforeBracket, "(")
+<< FixItHint::CreateInsertion(
+   Lambda.get()->getLocEnd().getLocWithOffset(1), ")");
+
+// Evaluate any postfix expressions used on the lambda.
+Lambda = ParsePostfixExpressionSuffix(Lambda);
+return Actions.ActOnCXXDelete(Start, UseGlobal, /*ArrayForm=*/false,
+  Lambda.get());
+  }
+}
   }
 
   ExprResult Operand(ParseCastExpression(false));
Index: include/clang/Basic/DiagnosticParseKinds.td
===
--- include/clang/Basic/DiagnosticParseKinds.td
+++ include/clang/Basic/DiagnosticParseKinds.td
@@ -99,6 +99,10 @@
   InGroup, DefaultIgnore;
 def ext_alignof_expr : ExtWarn<
   "%0 applied to an expression is a GNU extension">, 
InGroup;
+def err_lambda_after_delete : Error<
+  "'[]' after delete interpreted as 'delete[]'">;
+def note_lambda_after_delete : Note<
+  "add parentheses around the lambda">;
 
 def warn_microsoft_dependent_exists : Warning<
   "dependent %select{__if_not_exists|__if_exists}0 declarations are ignored">, 


Index: test/SemaCXX/new-delete-0x.cpp
===
--- test/SemaCXX/new-delete-0x.cpp
+++ test/SemaCXX/new-delete-0x.cpp
@@ -34,6 +34,6 @@
 void bad_deletes()
 {
   // 'delete []' is always array delete, per [expr.delete]p1.
-  // FIXME: Give a better diagnostic.
-  delete []{ return (in

[PATCH] D40445: [C++17] Allow an empty expression in an if init statement

2018-01-05 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 128729.
Rakete added a comment.

Addressed review comments. I'll write up a patch in the next coming days then :)


https://reviews.llvm.org/D40445

Files:
  lib/Parse/ParseExprCXX.cpp
  test/CXX/stmt.stmt/stmt.select/p3.cpp

Index: test/CXX/stmt.stmt/stmt.select/p3.cpp
===
--- test/CXX/stmt.stmt/stmt.select/p3.cpp
+++ test/CXX/stmt.stmt/stmt.select/p3.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++1z -Wc++14-compat -verify %s -DCPP17
 
 int f();
 
@@ -10,10 +11,68 @@
   }
 }
 
-
 void h() {
   if (int x = f()) // expected-note 2{{previous definition}}
 int x; // expected-error{{redefinition of 'x'}}
   else
 int x; // expected-error{{redefinition of 'x'}}
 }
+
+void ifInitStatement() {
+  int Var = 0;
+
+  if (int I = 0; true) {}
+  if (Var + Var; true) {}
+  if (; true) {}
+#ifdef CPP17
+  // expected-warning@-4 {{if initialization statements are incompatible with C++ standards before C++17}}
+  // expected-warning@-4 {{if initialization statements are incompatible with C++ standards before C++17}}
+  // expected-warning@-4 {{if initialization statements are incompatible with C++ standards before C++17}}
+#else
+  // expected-warning@-8 {{'if' initialization statements are a C++17 extension}}
+  // expected-warning@-8 {{'if' initialization statements are a C++17 extension}}
+  // expected-warning@-8 {{'if' initialization statements are a C++17 extension}}
+#endif
+}
+
+void switchInitStatement() {
+  int Var = 0;
+
+  switch (int I = 0; Var) {}
+  switch (Var + Var; Var) {}
+  switch (; Var) {}
+#ifdef CPP17
+  // expected-warning@-4 {{switch initialization statements are incompatible with C++ standards before C++17}}
+  // expected-warning@-4 {{switch initialization statements are incompatible with C++ standards before C++17}}
+  // expected-warning@-4 {{switch initialization statements are incompatible with C++ standards before C++17}}
+#else
+  // expected-warning@-8 {{'switch' initialization statements are a C++17 extension}}
+  // expected-warning@-8 {{'switch' initialization statements are a C++17 extension}}
+  // expected-warning@-8 {{'switch' initialization statements are a C++17 extension}}
+#endif
+}
+
+// TODO: Better diagnostics for while init statements.
+void whileInitStatement() {
+  while (int I = 10; I--); // expected-error {{expected ')'}}
+  // expected-note@-1 {{to match this '('}}
+  // expected-error@-2 {{use of undeclared identifier 'I'}}
+
+  int Var = 10;
+  while (Var + Var; Var--) {} // expected-error {{expected ')'}}
+  // expected-note@-1 {{to match this '('}}
+  // expected-error@-2 {{expected ';' after expression}}
+  // expected-error@-3 {{expected expression}}
+  // expected-warning@-4 {{while loop has empty body}}
+  // expected-note@-5 {{put the semicolon on a separate line to silence this warning}}
+}
+
+// TODO: This is needed because clang can't seem to diagnose invalid syntax after the
+// last loop above. It would be nice to remove this.
+void whileInitStatement2() {
+  while (; false) {} // expected-error {{expected expression}}
+  // expected-warning@-1 {{expression result unused}}
+  // expected-error@-2 {{expected ';' after expression}}
+  // expected-error@-3 {{expected expression}}
+}
+
Index: lib/Parse/ParseExprCXX.cpp
===
--- lib/Parse/ParseExprCXX.cpp
+++ lib/Parse/ParseExprCXX.cpp
@@ -1742,17 +1742,34 @@
   ParsedAttributesWithRange attrs(AttrFactory);
   MaybeParseCXX11Attributes(attrs);
 
+  const auto WarnOnInit = [this, &CK] {
+Diag(Tok.getLocation(), getLangOpts().CPlusPlus17
+? diag::warn_cxx14_compat_init_statement
+: diag::ext_init_statement)
+<< (CK == Sema::ConditionKind::Switch);
+  };
+
   // Determine what kind of thing we have.
   switch (isCXXConditionDeclarationOrInitStatement(InitStmt)) {
   case ConditionOrInitStatement::Expression: {
 ProhibitAttributes(attrs);
 
+// We can have an empty expression here.
+//   if (; true);
+if (InitStmt && Tok.is(tok::semi)) {
+  WarnOnInit();
+  SourceLocation SemiLoc = ConsumeToken();
+  *InitStmt = Actions.ActOnNullStmt(SemiLoc);
+  return ParseCXXCondition(nullptr, Loc, CK);
+}
+
 // Parse the expression.
 ExprResult Expr = ParseExpression(); // expression
 if (Expr.isInvalid())
   return Sema::ConditionError();
 
 if (InitStmt && Tok.is(tok::semi)) {
+  WarnOnInit();
   *InitStmt = Actions.ActOnExprStmt(Expr.get());
   ConsumeToken();
   return ParseCXXCondition(nullptr, Loc, CK);
@@ -1762,10 +1779,7 @@
   }
 
   case ConditionOrInitStatement::InitStmtDecl: {
-Diag(Tok.getLocation(), getLangOpts().CPlusPlus17
-? diag::warn_cxx14_compat_init_statement
- 

[PATCH] D36357: Added a better diagnostic when using the delete operator with lambdas

2018-01-05 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added inline comments.



Comment at: lib/Parse/ParseExprCXX.cpp:2906-2912
+// Basic lookahead to check if we have a lambda expression. If we
+// encounter two braces with a semicolon, we can be pretty sure
+// that this is a lambda, not say a compound literal. 
+if (!SkipUntil(tok::l_brace, SkipUntilFlags::StopAtSemi) ||
+(NextToken().isNot(tok::r_brace) && !SkipUntil(tok::semi)) ||
+!SkipUntil(tok::r_brace, SkipUntilFlags::StopAtSemi)) {
+  TPA.Revert();

rsmith wrote:
> This seems error-prone. Given:
> 
> ```
> for (item *p = first, *oldp = p; p; p = p->next, delete [] oldp, oldp = p) {
>   /*...*/;
> }
> ```
> 
> ... we'll decide the //delete-expression// is followed by a lambda. Likewise 
> for cases like:
> 
> ```
> delete [] f->getPtr([] {
>   return blah;
> });
> ```
> 
> Our goal here should be a fast heuristic (don't use lookahead except when 
> you're already confident you have a lambda) and zero false positives. How 
> about these heuristics instead:
> 
> Assume that the `delete []` is actually `delete` followed by a lambda if 
> either:
> 
>  * The next token is `{` or `<`, or
>  * The next token is `(` and either
> * the following token is `)` or
> * the following tokens are a type specifier followed by an identifier
> 
> This should have no false positives, and only has false negatives if a lambda 
> has an unnamed parameter or a parameter with a non-trivial parameter type. 
> (For the last condition, we could try to tentatively parse an entire 
> parameter and see if it has a name, which would handle all cases except an 
> expression/declaration ambiguity in the parameter declaration, but that seems 
> like overkill to me. This is already performing more lookahead than I'd like, 
> but `delete []` expressions are rare enough that using two lookahead tokens 
> for an improved error message seems OK.)
Ah, I see. I had no idea that lookaheads were that expensive. Thanks for 
finding a better algorithm than me :)



https://reviews.llvm.org/D36357



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


[PATCH] D38216: [C++17] Fix class template argument deduction for default constructors without an initializer

2018-03-13 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 138187.
Rakete added a comment.

Addressed review comments :)

Thanks!


https://reviews.llvm.org/D38216

Files:
  lib/Sema/SemaDecl.cpp
  test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
  test/Parser/cxx1z-class-template-argument-deduction.cpp


Index: test/Parser/cxx1z-class-template-argument-deduction.cpp
===
--- test/Parser/cxx1z-class-template-argument-deduction.cpp
+++ test/Parser/cxx1z-class-template-argument-deduction.cpp
@@ -137,7 +137,6 @@
 (void)A{n};
 (void)new A(n);
 (void)new A{n};
-// FIXME: We should diagnose the lack of an initializer here.
 (void)new A;
   }
 }
@@ -150,7 +149,7 @@
 
   auto k() -> A; // expected-error{{requires template arguments}}
 
-  A a; // expected-error {{declaration of variable 'a' with deduced type 'A' 
requires an initializer}}
+  A a;
   A b = 0;
   const A c = 0;
   A (parens) = 0; // expected-error {{cannot use parentheses when declaring 
variable with deduced class template specialization type}}
Index: test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
===
--- test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
+++ test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
@@ -5,8 +5,7 @@
 A(int) -> A;
 
 static constexpr inline const volatile A a = {}; // ok, specifiers are 
permitted
-// FIXME: There isn't really a good reason to reject this.
-A b; // expected-error {{requires an initializer}}
+A b;
 A c [[]] {};
 
 A d = {}, e = {};
Index: lib/Sema/SemaDecl.cpp
===
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -10395,12 +10395,22 @@
   // C++11 [dcl.spec.auto]p3
   if (!Init) {
 assert(VDecl && "no init for init capture deduction?");
-Diag(VDecl->getLocation(), diag::err_auto_var_requires_init)
-  << VDecl->getDeclName() << Type;
-return QualType();
+
+// Except for class argument deduction, and then for an initializing
+// declaration only, i.e. no static at class scope or extern.
+if (!isa(Deduced) ||
+VDecl->hasExternalStorage() ||
+VDecl->isStaticDataMember()) {
+  Diag(VDecl->getLocation(), diag::err_auto_var_requires_init)
+<< VDecl->getDeclName() << Type;
+  return QualType();
+}
   }
 
-  ArrayRef DeduceInits = Init;
+  ArrayRef DeduceInits;
+  if (Init)
+DeduceInits = Init;
+
   if (DirectInit) {
 if (auto *PL = dyn_cast_or_null(Init))
   DeduceInits = PL->exprs();


Index: test/Parser/cxx1z-class-template-argument-deduction.cpp
===
--- test/Parser/cxx1z-class-template-argument-deduction.cpp
+++ test/Parser/cxx1z-class-template-argument-deduction.cpp
@@ -137,7 +137,6 @@
 (void)A{n};
 (void)new A(n);
 (void)new A{n};
-// FIXME: We should diagnose the lack of an initializer here.
 (void)new A;
   }
 }
@@ -150,7 +149,7 @@
 
   auto k() -> A; // expected-error{{requires template arguments}}
 
-  A a; // expected-error {{declaration of variable 'a' with deduced type 'A' requires an initializer}}
+  A a;
   A b = 0;
   const A c = 0;
   A (parens) = 0; // expected-error {{cannot use parentheses when declaring variable with deduced class template specialization type}}
Index: test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
===
--- test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
+++ test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
@@ -5,8 +5,7 @@
 A(int) -> A;
 
 static constexpr inline const volatile A a = {}; // ok, specifiers are permitted
-// FIXME: There isn't really a good reason to reject this.
-A b; // expected-error {{requires an initializer}}
+A b;
 A c [[]] {};
 
 A d = {}, e = {};
Index: lib/Sema/SemaDecl.cpp
===
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -10395,12 +10395,22 @@
   // C++11 [dcl.spec.auto]p3
   if (!Init) {
 assert(VDecl && "no init for init capture deduction?");
-Diag(VDecl->getLocation(), diag::err_auto_var_requires_init)
-  << VDecl->getDeclName() << Type;
-return QualType();
+
+// Except for class argument deduction, and then for an initializing
+// declaration only, i.e. no static at class scope or extern.
+if (!isa(Deduced) ||
+VDecl->hasExternalStorage() ||
+VDecl->isStaticDataMember()) {
+  Diag(VDecl->getLocation(), diag::err_auto_var_requires_init)
+<< VDecl->getDeclName() << Type;
+  return QualType();
+}
   }
 
-  ArrayRef DeduceInits = Init;
+  ArrayRef DeduceInits;
+  if (Init)
+DeduceInits = Init;
+
   if (DirectInit) {
 if (auto *PL = dyn_cast_or_null(Init))
   DeduceInits = PL->exprs();

[PATCH] D36357: Added a better diagnostic when using the delete operator with lambdas

2018-03-14 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 138335.
Rakete added a comment.

> Did you forget to upload the updated patch? This looks unchanged compared to 
> the prior version.

Whoops, that's true. Sorry...


https://reviews.llvm.org/D36357

Files:
  include/clang/Basic/DiagnosticParseKinds.td
  lib/Parse/ParseExprCXX.cpp
  test/Parser/cxx0x-lambda-expressions.cpp
  test/SemaCXX/new-delete-0x.cpp

Index: test/SemaCXX/new-delete-0x.cpp
===
--- test/SemaCXX/new-delete-0x.cpp
+++ test/SemaCXX/new-delete-0x.cpp
@@ -34,6 +34,7 @@
 void bad_deletes()
 {
   // 'delete []' is always array delete, per [expr.delete]p1.
-  // FIXME: Give a better diagnostic.
-  delete []{ return (int*)0; }(); // expected-error {{expected expression}}
+  delete []{ return (int*)0; }(); // expected-error {{'[]' after delete interpreted as 'delete[]'}}
+  // expected-note@-1 {{add parentheses around the lambda}}
 }
+
Index: test/Parser/cxx0x-lambda-expressions.cpp
===
--- test/Parser/cxx0x-lambda-expressions.cpp
+++ test/Parser/cxx0x-lambda-expressions.cpp
@@ -53,7 +53,8 @@
   void delete_lambda(int *p) {
 delete [] p;
 delete [] (int*) { new int }; // ok, compound-literal, not lambda
-delete [] { return new int; } (); // expected-error{{expected expression}}
+delete [] { return new int; } (); // expected-error {{'[]' after delete interpreted as 'delete[]'}}
+// expected-note@-1 {{add parentheses around the lambda}}
 delete [&] { return new int; } (); // ok, lambda
   }
 
Index: lib/Parse/ParseExprCXX.cpp
===
--- lib/Parse/ParseExprCXX.cpp
+++ lib/Parse/ParseExprCXX.cpp
@@ -2903,15 +2903,47 @@
 //   [Footnote: A lambda expression with a lambda-introducer that consists
 //  of empty square brackets can follow the delete keyword if
 //  the lambda expression is enclosed in parentheses.]
-// FIXME: Produce a better diagnostic if the '[]' is unambiguously a
-//lambda-introducer.
-ArrayDelete = true;
-BalancedDelimiterTracker T(*this, tok::l_square);
 
-T.consumeOpen();
-T.consumeClose();
-if (T.getCloseLocation().isInvalid())
-  return ExprError();
+const Token Next = GetLookAheadToken(2);
+const Token After = GetLookAheadToken(3);
+const Token Last = GetLookAheadToken(4);
+
+// Basic lookahead to check if we have a lambda expression.
+if (Next.isOneOf(tok::l_brace, tok::less) ||
+(Next.is(tok::l_paren) && (
+  After.is(tok::r_paren) || (After.is(tok::identifier) &&
+Last.is(tok::identifier))
+))) {
+  // Warn if the non-capturing lambda isn't surrounded by parenthesis
+  // to disambiguate it from 'delete[]'.
+  ExprResult Lambda = TryParseLambdaExpression();
+  if (!Lambda.isInvalid()) {
+SourceLocation StartLoc = Lambda.get()->getLocStart();
+Diag(Start, diag::err_lambda_after_delete)
+<< SourceRange(Start, StartLoc.getLocWithOffset(1));
+
+SourceLocation BeforeBracket = StartLoc.getLocWithOffset(-1);
+Diag(BeforeBracket, diag::note_lambda_after_delete)
+<< FixItHint::CreateInsertion(BeforeBracket, "(")
+<< FixItHint::CreateInsertion(
+   Lambda.get()->getLocEnd().getLocWithOffset(1), ")");
+
+// Evaluate any postfix expressions used on the lambda.
+Lambda = ParsePostfixExpressionSuffix(Lambda);
+return Actions.ActOnCXXDelete(Start, UseGlobal, /*ArrayForm=*/false,
+  Lambda.get());
+  }
+  else
+return ExprError();
+} else {
+  ArrayDelete = true;
+  BalancedDelimiterTracker T(*this, tok::l_square);
+
+  T.consumeOpen();
+  T.consumeClose();
+  if (T.getCloseLocation().isInvalid())
+return ExprError();
+}
   }
 
   ExprResult Operand(ParseCastExpression(false));
Index: include/clang/Basic/DiagnosticParseKinds.td
===
--- include/clang/Basic/DiagnosticParseKinds.td
+++ include/clang/Basic/DiagnosticParseKinds.td
@@ -99,6 +99,10 @@
   InGroup, DefaultIgnore;
 def ext_alignof_expr : ExtWarn<
   "%0 applied to an expression is a GNU extension">, InGroup;
+def err_lambda_after_delete : Error<
+  "'[]' after delete interpreted as 'delete[]'">;
+def note_lambda_after_delete : Note<
+  "add parentheses around the lambda">;
 
 def warn_microsoft_dependent_exists : Warning<
   "dependent %select{__if_not_exists|__if_exists}0 declarations are ignored">, 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D36357: Added a better diagnostic when using the delete operator with lambdas

2018-03-14 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added a comment.

@rsmith Which type specifiers should I test for? just `T`? Or also `T*`, `T&`, 
...? Now I'm just checking for an identifier, but anything else would make the 
lookahead more complicated I think. Any ideas?


https://reviews.llvm.org/D36357



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


[PATCH] D37442: [C++17] Disallow lambdas in template parameters (PR33696).

2018-03-14 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 138337.
Rakete added a comment.

Rebase and ping :)


https://reviews.llvm.org/D37442

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/Parse/ParseDecl.cpp
  lib/Parse/ParseDeclCXX.cpp
  lib/Parse/ParseStmt.cpp
  lib/Parse/ParseTemplate.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaExprCXX.cpp
  lib/Sema/TreeTransform.h
  test/CXX/expr/expr.prim/expr.prim.lambda/p2-template-parameter.cpp

Index: test/CXX/expr/expr.prim/expr.prim.lambda/p2-template-parameter.cpp
===
--- test/CXX/expr/expr.prim/expr.prim.lambda/p2-template-parameter.cpp
+++ test/CXX/expr/expr.prim/expr.prim.lambda/p2-template-parameter.cpp
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -std=c++17 %s -verify
+
+template struct Nothing {};
+
+void pr33696() {
+Nothing<[]() { return 0; }()> nothing; // expected-error{{a lambda expression cannot appear in this context}}
+}
+
Index: lib/Sema/TreeTransform.h
===
--- lib/Sema/TreeTransform.h
+++ lib/Sema/TreeTransform.h
@@ -5495,7 +5495,7 @@
   // decltype expressions are not potentially evaluated contexts
   EnterExpressionEvaluationContext Unevaluated(
   SemaRef, Sema::ExpressionEvaluationContext::Unevaluated, nullptr,
-  /*IsDecltype=*/true);
+  Sema::ExpressionEvaluationContextRecord::EK_Decltype);
 
   ExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr());
   if (E.isInvalid())
Index: lib/Sema/SemaExprCXX.cpp
===
--- lib/Sema/SemaExprCXX.cpp
+++ lib/Sema/SemaExprCXX.cpp
@@ -6226,7 +6226,8 @@
   if (RD->isInvalidDecl() || RD->isDependentContext())
 return E;
 
-  bool IsDecltype = ExprEvalContexts.back().IsDecltype;
+  bool IsDecltype = ExprEvalContexts.back().ExprContext ==
+ExpressionEvaluationContextRecord::EK_Decltype;
   CXXDestructorDecl *Destructor = IsDecltype ? nullptr : LookupDestructor(RD);
 
   if (Destructor) {
@@ -6308,7 +6309,9 @@
 /// are omitted for the 'topmost' call in the decltype expression. If the
 /// topmost call bound a temporary, strip that temporary off the expression.
 ExprResult Sema::ActOnDecltypeExpression(Expr *E) {
-  assert(ExprEvalContexts.back().IsDecltype && "not in a decltype expression");
+  assert(ExprEvalContexts.back().ExprContext ==
+ ExpressionEvaluationContextRecord::EK_Decltype &&
+ "not in a decltype expression");
 
   // C++11 [expr.call]p11:
   //   If a function call is a prvalue of object type,
@@ -6350,7 +6353,8 @@
 TopBind = nullptr;
 
   // Disable the special decltype handling now.
-  ExprEvalContexts.back().IsDecltype = false;
+  ExprEvalContexts.back().ExprContext =
+  ExpressionEvaluationContextRecord::EK_Other;
 
   // In MS mode, don't perform any extra checking of call return types within a
   // decltype expression.
Index: lib/Sema/SemaExpr.cpp
===
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -13757,53 +13757,53 @@
 }
 
 void
-Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
-  Decl *LambdaContextDecl,
-  bool IsDecltype) {
+Sema::PushExpressionEvaluationContext(
+ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl,
+ExpressionEvaluationContextRecord::ExpressionKind ExprContext) {
   ExprEvalContexts.emplace_back(NewContext, ExprCleanupObjects.size(), Cleanup,
-LambdaContextDecl, IsDecltype);
+LambdaContextDecl, ExprContext);
   Cleanup.reset();
   if (!MaybeODRUseExprs.empty())
 std::swap(MaybeODRUseExprs, ExprEvalContexts.back().SavedMaybeODRUseExprs);
 }
 
 void
-Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
-  ReuseLambdaContextDecl_t,
-  bool IsDecltype) {
+Sema::PushExpressionEvaluationContext(
+ExpressionEvaluationContext NewContext, ReuseLambdaContextDecl_t,
+ExpressionEvaluationContextRecord::ExpressionKind ExprContext) {
   Decl *ClosureContextDecl = ExprEvalContexts.back().ManglingContextDecl;
-  PushExpressionEvaluationContext(NewContext, ClosureContextDecl, IsDecltype);
+  PushExpressionEvaluationContext(NewContext, ClosureContextDecl, ExprContext);
 }
 
 void Sema::PopExpressionEvaluationContext() {
   ExpressionEvaluationContextRecord& Rec = ExprEvalContexts.back();
   unsigned NumTypos = Rec.NumTypos;
 
   if (!Rec.Lambdas.empty()) {
-if (Rec.isUnevaluated() || Rec.isConstantEvaluated()) {
+using ExpressionKind = ExpressionEvaluationContextRecord::ExpressionKind;
+if (Rec.ExprContext == ExpressionKind::EK_TemplateParameter || Rec.isUnevaluated() ||
+(Rec.isConstantEvaluated() 

[PATCH] D40445: [C++17] Allow an empty expression in an if init statement

2018-03-14 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 138339.
Rakete added a comment.

Rebase and ping :)


https://reviews.llvm.org/D40445

Files:
  lib/Parse/ParseExprCXX.cpp
  test/CXX/stmt.stmt/stmt.select/p3.cpp

Index: test/CXX/stmt.stmt/stmt.select/p3.cpp
===
--- test/CXX/stmt.stmt/stmt.select/p3.cpp
+++ test/CXX/stmt.stmt/stmt.select/p3.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++1z -Wc++14-compat -verify %s -DCPP17
 
 int f();
 
@@ -10,10 +11,67 @@
   }
 }
 
-
 void h() {
   if (int x = f()) // expected-note 2{{previous definition}}
 int x; // expected-error{{redefinition of 'x'}}
   else
 int x; // expected-error{{redefinition of 'x'}}
 }
+
+void ifInitStatement() {
+  int Var = 0;
+
+  if (int I = 0; true) {}
+  if (Var + Var; true) {}
+  if (; true) {}
+#ifdef CPP17
+  // expected-warning@-4 {{if initialization statements are incompatible with C++ standards before C++17}}
+  // expected-warning@-4 {{if initialization statements are incompatible with C++ standards before C++17}}
+  // expected-warning@-4 {{if initialization statements are incompatible with C++ standards before C++17}}
+#else
+  // expected-warning@-8 {{'if' initialization statements are a C++17 extension}}
+  // expected-warning@-8 {{'if' initialization statements are a C++17 extension}}
+  // expected-warning@-8 {{'if' initialization statements are a C++17 extension}}
+#endif
+}
+
+void switchInitStatement() {
+  int Var = 0;
+
+  switch (int I = 0; Var) {}
+  switch (Var + Var; Var) {}
+  switch (; Var) {}
+#ifdef CPP17
+  // expected-warning@-4 {{switch initialization statements are incompatible with C++ standards before C++17}}
+  // expected-warning@-4 {{switch initialization statements are incompatible with C++ standards before C++17}}
+  // expected-warning@-4 {{switch initialization statements are incompatible with C++ standards before C++17}}
+#else
+  // expected-warning@-8 {{'switch' initialization statements are a C++17 extension}}
+  // expected-warning@-8 {{'switch' initialization statements are a C++17 extension}}
+  // expected-warning@-8 {{'switch' initialization statements are a C++17 extension}}
+#endif
+}
+
+// TODO: Better diagnostics for while init statements.
+void whileInitStatement() {
+  while (int I = 10; I--); // expected-error {{expected ')'}}
+  // expected-note@-1 {{to match this '('}}
+  // expected-error@-2 {{use of undeclared identifier 'I'}}
+
+  int Var = 10;
+  while (Var + Var; Var--) {} // expected-error {{expected ')'}}
+  // expected-note@-1 {{to match this '('}}
+  // expected-error@-2 {{expected ';' after expression}}
+  // expected-error@-3 {{expected expression}}
+  // expected-warning@-4 {{while loop has empty body}}
+  // expected-note@-5 {{put the semicolon on a separate line to silence this warning}}
+}
+
+// TODO: This is needed because clang can't seem to diagnose invalid syntax after the
+// last loop above. It would be nice to remove this.
+void whileInitStatement2() {
+  while (; false) {} // expected-error {{expected expression}}
+  // expected-warning@-1 {{expression result unused}}
+  // expected-error@-2 {{expected ';' after expression}}
+  // expected-error@-3 {{expected expression}}
+}
Index: lib/Parse/ParseExprCXX.cpp
===
--- lib/Parse/ParseExprCXX.cpp
+++ lib/Parse/ParseExprCXX.cpp
@@ -1744,17 +1744,34 @@
   ParsedAttributesWithRange attrs(AttrFactory);
   MaybeParseCXX11Attributes(attrs);
 
+  const auto WarnOnInit = [this, &CK] {
+Diag(Tok.getLocation(), getLangOpts().CPlusPlus17
+? diag::warn_cxx14_compat_init_statement
+: diag::ext_init_statement)
+<< (CK == Sema::ConditionKind::Switch);
+  };
+
   // Determine what kind of thing we have.
   switch (isCXXConditionDeclarationOrInitStatement(InitStmt)) {
   case ConditionOrInitStatement::Expression: {
 ProhibitAttributes(attrs);
 
+// We can have an empty expression here.
+//   if (; true);
+if (InitStmt && Tok.is(tok::semi)) {
+  WarnOnInit();
+  SourceLocation SemiLoc = ConsumeToken();
+  *InitStmt = Actions.ActOnNullStmt(SemiLoc);
+  return ParseCXXCondition(nullptr, Loc, CK);
+}
+
 // Parse the expression.
 ExprResult Expr = ParseExpression(); // expression
 if (Expr.isInvalid())
   return Sema::ConditionError();
 
 if (InitStmt && Tok.is(tok::semi)) {
+  WarnOnInit();
   *InitStmt = Actions.ActOnExprStmt(Expr.get());
   ConsumeToken();
   return ParseCXXCondition(nullptr, Loc, CK);
@@ -1764,10 +1781,7 @@
   }
 
   case ConditionOrInitStatement::InitStmtDecl: {
-Diag(Tok.getLocation(), getLangOpts().CPlusPlus17
-? diag::warn_cxx14_compat_init_statement
-: diag::ext_init_statement)
-<< (CK == Sema::Conditio

[PATCH] D40445: [C++17] Allow an empty expression in an if init statement

2018-03-14 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added a comment.

@rsmith Can you commit please?


https://reviews.llvm.org/D40445



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


[PATCH] D39679: [C++11] Fix warning when dropping cv-qualifiers when assigning to a reference with a braced initializer list

2018-03-14 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 138423.
Rakete added a comment.

Addressed review comments :)
I added a test case for the crashing code.

Note: I didn't change `Args[0]` to `OnlyArg` in 
`FK_AddressOfUnaddressableFunction`, because I'm pretty sure that C++ doesn't 
have unaddressable functions and thus there is no need to decompose an 
initializer list. Is this correct?


https://reviews.llvm.org/D39679

Files:
  lib/Sema/SemaInit.cpp
  test/SemaCXX/references.cpp

Index: test/SemaCXX/references.cpp
===
--- test/SemaCXX/references.cpp
+++ test/SemaCXX/references.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s 
 int g(int);
 
 void f() {
@@ -55,6 +56,24 @@
   //  const double& rcd2 = 2; // rcd2 refers to temporary with value 2.0
   const volatile int cvi = 1;
   const int& r = cvi; // expected-error{{binding value of type 'const volatile int' to reference to type 'const int' drops 'volatile' qualifier}}
+
+#if __cplusplus >= 201103L
+  const int& r2{cvi}; // expected-error{{binding value of type 'const volatile int' to reference to type 'const int' drops 'volatile' qualifier}}
+
+  const int a = 2;
+  int& r3{a}; // expected-error{{binding value of type 'const int' to reference to type 'int' drops 'const'}}
+
+  const int&& r4{a}; // expected-error{{rvalue reference to type 'const int' cannot bind to lvalue of type 'const int'}}
+
+  void func();
+  void func(int);
+  int &ptr1 = {func}; // expected-error{{address of overloaded function 'func' does not match required type 'int'}}
+  int &&ptr2{func}; // expected-error{{address of overloaded function 'func' does not match required type 'int'}}
+  // expected-note@-4{{candidate function}}
+  // expected-note@-4{{candidate function}}
+  // expected-note@-6{{candidate function}}
+  // expected-note@-6{{candidate function}}
+#endif
 }
 
 // C++ [dcl.init.ref]p3
Index: lib/Sema/SemaInit.cpp
===
--- lib/Sema/SemaInit.cpp
+++ lib/Sema/SemaInit.cpp
@@ -7549,6 +7549,18 @@
   if (!Failed())
 return false;
 
+  // When we want to diagnose only one element of a braced-init-list, we need to factor it out.
+  Expr *OnlyArg;
+  if (Args.size() == 1) {
+auto *List = dyn_cast(Args[0]);
+if (List && List->getNumInits() == 1)
+  OnlyArg = List->getInit(0);
+else
+  OnlyArg = Args[0];
+  }
+  else
+OnlyArg = nullptr;
+
   QualType DestType = Entity.getType();
   switch (Failure) {
   case FK_TooManyInitsForReference:
@@ -7598,7 +7610,7 @@
   ? diag::err_array_init_different_type
   : diag::err_array_init_non_constant_array))
   << DestType.getNonReferenceType()
-  << Args[0]->getType()
+  << OnlyArg->getType()
   << Args[0]->getSourceRange();
 break;
 
@@ -7609,7 +7621,7 @@
 
   case FK_AddressOfOverloadFailed: {
 DeclAccessPair Found;
-S.ResolveAddressOfOverloadedFunction(Args[0],
+S.ResolveAddressOfOverloadedFunction(OnlyArg,
  DestType.getNonReferenceType(),
  true,
  Found);
@@ -7629,11 +7641,11 @@
 case OR_Ambiguous:
   if (Failure == FK_UserConversionOverloadFailed)
 S.Diag(Kind.getLocation(), diag::err_typecheck_ambiguous_condition)
-  << Args[0]->getType() << DestType
+  << OnlyArg->getType() << DestType
   << Args[0]->getSourceRange();
   else
 S.Diag(Kind.getLocation(), diag::err_ref_init_ambiguous)
-  << DestType << Args[0]->getType()
+  << DestType << OnlyArg->getType()
   << Args[0]->getSourceRange();
 
   FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, Args);
@@ -7643,18 +7655,18 @@
   if (!S.RequireCompleteType(Kind.getLocation(),
  DestType.getNonReferenceType(),
   diag::err_typecheck_nonviable_condition_incomplete,
-   Args[0]->getType(), Args[0]->getSourceRange()))
+   OnlyArg->getType(), Args[0]->getSourceRange()))
 S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition)
   << (Entity.getKind() == InitializedEntity::EK_Result)
-  << Args[0]->getType() << Args[0]->getSourceRange()
+  << OnlyArg->getType() << Args[0]->getSourceRange()
   << DestType.getNonReferenceType();
 
   FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args);
   break;
 
 case OR_Deleted: {
   S.Diag(Kind.getLocation(), diag::err_typecheck_deleted_function)
-<< Args[0]->getType() << DestType.getNonReferenceType()
+<< OnlyArg->getType() << DestType.getNonReferenceType()
 << Args[0]->getSourceRange();
   OverloadCandidateSet::iterator Best;
   OverloadingResult Ovl
@@ -76

[PATCH] D44534: Fix codegen for structured binding binding in conditions

2018-03-15 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete created this revision.
Rakete added reviewers: lichray, rsmith.
Rakete added a project: clang.

The codegen for conditions assumes that a normal variable declaration is used 
in a condition, but this is not the case when a structured binding is used.

This fixes PR36747 .


Repository:
  rC Clang

https://reviews.llvm.org/D44534

Files:
  lib/CodeGen/CGStmt.cpp
  test/Parser/decomposed-condition.cpp

Index: test/Parser/decomposed-condition.cpp
===
--- test/Parser/decomposed-condition.cpp
+++ test/Parser/decomposed-condition.cpp
@@ -1,5 +1,20 @@
 // RUN: %clang_cc1 -std=c++1z %s -verify
 
+namespace std {
+  template struct tuple_size;
+  template struct tuple_element;
+}
+
+struct Get {
+  template int get() { return 0; }
+  operator bool() { return true; }
+};
+
+namespace std {
+  template<> struct tuple_size { static constexpr int value = 1; };
+  template<> struct tuple_element<0, Get> { using type = int; };
+}
+
 struct Na {
   bool flag;
   float data;
@@ -17,29 +32,35 @@
 Na g();
 
 namespace CondInIf {
-void h() {
+int h() {
   if (auto [ok, d] = f()) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}}
 ;
   if (auto [ok, d] = g()) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}} expected-error {{value of type 'Na' is not contextually convertible to 'bool'}}
 ;
+  if (auto [value] = Get()) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}}
+return value;
 }
 } // namespace CondInIf
 
 namespace CondInWhile {
-void h() {
+int h() {
   while (auto [ok, d] = f()) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}}
 ;
   while (auto [ok, d] = g()) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}} expected-error {{value of type 'Na' is not contextually convertible to 'bool'}}
 ;
+  while (auto [value] = Get()) // expected-warning{{ISO C++17 does not permit structured binding declaration in a condition}}
+return value;
 }
 } // namespace CondInWhile
 
 namespace CondInFor {
-void h() {
+int h() {
   for (; auto [ok, d] = f();) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}}
 ;
   for (; auto [ok, d] = g();) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}} expected-error {{value of type 'Na' is not contextually convertible to 'bool'}}
 ;
+  for (; auto [value] = Get();) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}}
+return value;
 }
 } // namespace CondInFor
 
@@ -52,10 +73,15 @@
 };
 
 namespace CondInSwitch {
-void h(IntegerLike x) {
+int h(IntegerLike x) {
   switch (auto [ok, d] = x) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}}
 ;
   switch (auto [ok, d] = g()) // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}} expected-error {{statement requires expression of integer type ('Na' invalid)}}
 ;
+  switch (auto [value] = Get()) {// expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}}
+  // expected-warning@-1{{switch condition has boolean value}}
+  case 1:
+return value;
+  }
 }
 } // namespace CondInSwitch
Index: lib/CodeGen/CGStmt.cpp
===
--- lib/CodeGen/CGStmt.cpp
+++ lib/CodeGen/CGStmt.cpp
@@ -608,7 +608,7 @@
 EmitStmt(S.getInit());
 
   if (S.getConditionVariable())
-EmitAutoVarDecl(*S.getConditionVariable());
+EmitDecl(*S.getConditionVariable());
 
   // If the condition constant folds and can be elided, try to avoid emitting
   // the condition and the dead arm of the if/else.
@@ -705,7 +705,7 @@
   RunCleanupsScope ConditionScope(*this);
 
   if (S.getConditionVariable())
-EmitAutoVarDecl(*S.getConditionVariable());
+EmitDecl(*S.getConditionVariable());
 
   // Evaluate the conditional in the while header.  C99 6.8.5.1: The
   // evaluation of the controlling expression takes place before each
@@ -865,7 +865,7 @@
 // If the for statement has a condition scope, emit the local variable
 // declaration.
 if (S.getConditionVariable()) {
-  EmitAutoVarDecl(*S.getConditionVariable());
+  EmitDecl(*S.getConditionVariable());
 }
 
 llvm::BasicBlock *ExitBlock = LoopExit.getBlock();
@@ -1574,7 +1574,7 @@
   // Emit the condition variable if needed inside the entire cleanup scope
   // used by this special case for constant folded switches.
   if (S.getConditionVariable())
-EmitAutoVarDecl(*S.getConditionVariable());
+EmitDecl(*S.getConditionVariable());
 
   // At this point, we are no longer "within" a switch in

[PATCH] D38216: [C++17] Fix class template argument deduction for default constructors without an initializer

2018-03-18 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 138862.
Rakete added a comment.

@lichray Ok done :) Thanks for reviewing


https://reviews.llvm.org/D38216

Files:
  lib/Sema/SemaDecl.cpp
  test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
  test/Parser/cxx1z-class-template-argument-deduction.cpp


Index: test/Parser/cxx1z-class-template-argument-deduction.cpp
===
--- test/Parser/cxx1z-class-template-argument-deduction.cpp
+++ test/Parser/cxx1z-class-template-argument-deduction.cpp
@@ -137,7 +137,6 @@
 (void)A{n};
 (void)new A(n);
 (void)new A{n};
-// FIXME: We should diagnose the lack of an initializer here.
 (void)new A;
   }
 }
@@ -150,7 +149,7 @@
 
   auto k() -> A; // expected-error{{requires template arguments}}
 
-  A a; // expected-error {{declaration of variable 'a' with deduced type 'A' 
requires an initializer}}
+  A a;
   A b = 0;
   const A c = 0;
   A (parens) = 0; // expected-error {{cannot use parentheses when declaring 
variable with deduced class template specialization type}}
Index: test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
===
--- test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
+++ test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
@@ -5,8 +5,7 @@
 A(int) -> A;
 
 static constexpr inline const volatile A a = {}; // ok, specifiers are 
permitted
-// FIXME: There isn't really a good reason to reject this.
-A b; // expected-error {{requires an initializer}}
+A b;
 A c [[]] {};
 
 A d = {}, e = {};
@@ -16,3 +15,5 @@
   static A a; // expected-error {{requires an initializer}}
 };
 extern A x; // expected-error {{requires an initializer}}
+static A y;
+
Index: lib/Sema/SemaDecl.cpp
===
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -10396,12 +10396,22 @@
   // C++11 [dcl.spec.auto]p3
   if (!Init) {
 assert(VDecl && "no init for init capture deduction?");
-Diag(VDecl->getLocation(), diag::err_auto_var_requires_init)
-  << VDecl->getDeclName() << Type;
-return QualType();
+
+// Except for class argument deduction, and then for an initializing
+// declaration only, i.e. no static at class scope or extern.
+if (!isa(Deduced) ||
+VDecl->hasExternalStorage() ||
+VDecl->isStaticDataMember()) {
+  Diag(VDecl->getLocation(), diag::err_auto_var_requires_init)
+<< VDecl->getDeclName() << Type;
+  return QualType();
+}
   }
 
-  ArrayRef DeduceInits = Init;
+  ArrayRef DeduceInits;
+  if (Init)
+DeduceInits = Init;
+
   if (DirectInit) {
 if (auto *PL = dyn_cast_or_null(Init))
   DeduceInits = PL->exprs();


Index: test/Parser/cxx1z-class-template-argument-deduction.cpp
===
--- test/Parser/cxx1z-class-template-argument-deduction.cpp
+++ test/Parser/cxx1z-class-template-argument-deduction.cpp
@@ -137,7 +137,6 @@
 (void)A{n};
 (void)new A(n);
 (void)new A{n};
-// FIXME: We should diagnose the lack of an initializer here.
 (void)new A;
   }
 }
@@ -150,7 +149,7 @@
 
   auto k() -> A; // expected-error{{requires template arguments}}
 
-  A a; // expected-error {{declaration of variable 'a' with deduced type 'A' requires an initializer}}
+  A a;
   A b = 0;
   const A c = 0;
   A (parens) = 0; // expected-error {{cannot use parentheses when declaring variable with deduced class template specialization type}}
Index: test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
===
--- test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
+++ test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.class.deduct/p1.cpp
@@ -5,8 +5,7 @@
 A(int) -> A;
 
 static constexpr inline const volatile A a = {}; // ok, specifiers are permitted
-// FIXME: There isn't really a good reason to reject this.
-A b; // expected-error {{requires an initializer}}
+A b;
 A c [[]] {};
 
 A d = {}, e = {};
@@ -16,3 +15,5 @@
   static A a; // expected-error {{requires an initializer}}
 };
 extern A x; // expected-error {{requires an initializer}}
+static A y;
+
Index: lib/Sema/SemaDecl.cpp
===
--- lib/Sema/SemaDecl.cpp
+++ lib/Sema/SemaDecl.cpp
@@ -10396,12 +10396,22 @@
   // C++11 [dcl.spec.auto]p3
   if (!Init) {
 assert(VDecl && "no init for init capture deduction?");
-Diag(VDecl->getLocation(), diag::err_auto_var_requires_init)
-  << VDecl->getDeclName() << Type;
-return QualType();
+
+// Except for class argument deduction, and then for an initializing
+// declaration only, i.e. no static at class scope or extern.
+if (!isa(Deduced) ||
+VDecl->hasExternalStorage() ||
+VDecl->isStaticDataMember()) {
+  Diag(VDecl->getLocation(),

[PATCH] D36357: Added a better diagnostic when using the delete operator with lambdas

2018-06-21 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added a comment.

@rsmith Should I only check for an identifier, like only "int" and nothing 
else? Because parsing a full type specifier might be a bit expensive, no?


https://reviews.llvm.org/D36357



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


[PATCH] D39679: [C++11] Fix warning when dropping cv-qualifiers when assigning to a reference with a braced initializer list

2018-06-21 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 152370.
Rakete added a comment.

Rebased + friendly ping :)


https://reviews.llvm.org/D39679

Files:
  lib/Sema/SemaInit.cpp
  test/SemaCXX/references.cpp

Index: test/SemaCXX/references.cpp
===
--- test/SemaCXX/references.cpp
+++ test/SemaCXX/references.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s 
 int g(int);
 
 void f() {
@@ -55,6 +56,24 @@
   //  const double& rcd2 = 2; // rcd2 refers to temporary with value 2.0
   const volatile int cvi = 1;
   const int& r = cvi; // expected-error{{binding value of type 'const volatile int' to reference to type 'const int' drops 'volatile' qualifier}}
+
+#if __cplusplus >= 201103L
+  const int& r2{cvi}; // expected-error{{binding value of type 'const volatile int' to reference to type 'const int' drops 'volatile' qualifier}}
+
+  const int a = 2;
+  int& r3{a}; // expected-error{{binding value of type 'const int' to reference to type 'int' drops 'const'}}
+
+  const int&& r4{a}; // expected-error{{rvalue reference to type 'const int' cannot bind to lvalue of type 'const int'}}
+
+  void func();
+  void func(int);
+  int &ptr1 = {func}; // expected-error{{address of overloaded function 'func' does not match required type 'int'}}
+  int &&ptr2{func}; // expected-error{{address of overloaded function 'func' does not match required type 'int'}}
+  // expected-note@-4{{candidate function}}
+  // expected-note@-4{{candidate function}}
+  // expected-note@-6{{candidate function}}
+  // expected-note@-6{{candidate function}}
+#endif
 }
 
 // C++ [dcl.init.ref]p3
Index: lib/Sema/SemaInit.cpp
===
--- lib/Sema/SemaInit.cpp
+++ lib/Sema/SemaInit.cpp
@@ -7565,6 +7565,18 @@
   if (!Failed())
 return false;
 
+  // When we want to diagnose only one element of a braced-init-list, we need to factor it out.
+  Expr *OnlyArg;
+  if (Args.size() == 1) {
+auto *List = dyn_cast(Args[0]);
+if (List && List->getNumInits() == 1)
+  OnlyArg = List->getInit(0);
+else
+  OnlyArg = Args[0];
+  }
+  else
+OnlyArg = nullptr;
+
   QualType DestType = Entity.getType();
   switch (Failure) {
   case FK_TooManyInitsForReference:
@@ -7625,7 +7637,7 @@
   ? diag::err_array_init_different_type
   : diag::err_array_init_non_constant_array))
   << DestType.getNonReferenceType()
-  << Args[0]->getType()
+  << OnlyArg->getType()
   << Args[0]->getSourceRange();
 break;
 
@@ -7636,7 +7648,7 @@
 
   case FK_AddressOfOverloadFailed: {
 DeclAccessPair Found;
-S.ResolveAddressOfOverloadedFunction(Args[0],
+S.ResolveAddressOfOverloadedFunction(OnlyArg,
  DestType.getNonReferenceType(),
  true,
  Found);
@@ -7656,11 +7668,11 @@
 case OR_Ambiguous:
   if (Failure == FK_UserConversionOverloadFailed)
 S.Diag(Kind.getLocation(), diag::err_typecheck_ambiguous_condition)
-  << Args[0]->getType() << DestType
+  << OnlyArg->getType() << DestType
   << Args[0]->getSourceRange();
   else
 S.Diag(Kind.getLocation(), diag::err_ref_init_ambiguous)
-  << DestType << Args[0]->getType()
+  << DestType << OnlyArg->getType()
   << Args[0]->getSourceRange();
 
   FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, Args);
@@ -7670,10 +7682,10 @@
   if (!S.RequireCompleteType(Kind.getLocation(),
  DestType.getNonReferenceType(),
   diag::err_typecheck_nonviable_condition_incomplete,
-   Args[0]->getType(), Args[0]->getSourceRange()))
+   OnlyArg->getType(), Args[0]->getSourceRange()))
 S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition)
   << (Entity.getKind() == InitializedEntity::EK_Result)
-  << Args[0]->getType() << Args[0]->getSourceRange()
+  << OnlyArg->getType() << Args[0]->getSourceRange()
   << DestType.getNonReferenceType();
 
   FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args);
@@ -7681,7 +7693,7 @@
 
 case OR_Deleted: {
   S.Diag(Kind.getLocation(), diag::err_typecheck_deleted_function)
-<< Args[0]->getType() << DestType.getNonReferenceType()
+<< OnlyArg->getType() << DestType.getNonReferenceType()
 << Args[0]->getSourceRange();
   OverloadCandidateSet::iterator Best;
   OverloadingResult Ovl
@@ -7717,7 +7729,7 @@
  : diag::err_lvalue_reference_bind_to_unrelated)
   << DestType.getNonReferenceType().isVolatileQualified()
   << DestType.getNonReferenceType()
-  << Args[0]->getType()
+  << OnlyArg->getType()
   << Args[0]->getSourceRange

[PATCH] D37442: [C++17] Disallow lambdas in template parameters (PR33696).

2018-06-21 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 152374.
Rakete added a comment.

Rebased + friendly ping :)


https://reviews.llvm.org/D37442

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/Parse/ParseDecl.cpp
  lib/Parse/ParseDeclCXX.cpp
  lib/Parse/ParseStmt.cpp
  lib/Parse/ParseTemplate.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaExpr.cpp
  lib/Sema/SemaExprCXX.cpp
  lib/Sema/TreeTransform.h
  test/CXX/expr/expr.prim/expr.prim.lambda/p2-template-parameter.cpp

Index: test/CXX/expr/expr.prim/expr.prim.lambda/p2-template-parameter.cpp
===
--- test/CXX/expr/expr.prim/expr.prim.lambda/p2-template-parameter.cpp
+++ test/CXX/expr/expr.prim/expr.prim.lambda/p2-template-parameter.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -std=c++17 %s -verify
+
+template struct Nothing {};
+
+void pr33696() {
+Nothing<[]() { return 0; }()> nothing; // expected-error{{a lambda expression cannot appear in this context}}
+}
Index: lib/Sema/TreeTransform.h
===
--- lib/Sema/TreeTransform.h
+++ lib/Sema/TreeTransform.h
@@ -5494,7 +5494,7 @@
   // decltype expressions are not potentially evaluated contexts
   EnterExpressionEvaluationContext Unevaluated(
   SemaRef, Sema::ExpressionEvaluationContext::Unevaluated, nullptr,
-  /*IsDecltype=*/true);
+  Sema::ExpressionEvaluationContextRecord::EK_Decltype);
 
   ExprResult E = getDerived().TransformExpr(T->getUnderlyingExpr());
   if (E.isInvalid())
Index: lib/Sema/SemaExprCXX.cpp
===
--- lib/Sema/SemaExprCXX.cpp
+++ lib/Sema/SemaExprCXX.cpp
@@ -6413,7 +6413,8 @@
   if (RD->isInvalidDecl() || RD->isDependentContext())
 return E;
 
-  bool IsDecltype = ExprEvalContexts.back().IsDecltype;
+  bool IsDecltype = ExprEvalContexts.back().ExprContext ==
+ExpressionEvaluationContextRecord::EK_Decltype;
   CXXDestructorDecl *Destructor = IsDecltype ? nullptr : LookupDestructor(RD);
 
   if (Destructor) {
@@ -6495,7 +6496,9 @@
 /// are omitted for the 'topmost' call in the decltype expression. If the
 /// topmost call bound a temporary, strip that temporary off the expression.
 ExprResult Sema::ActOnDecltypeExpression(Expr *E) {
-  assert(ExprEvalContexts.back().IsDecltype && "not in a decltype expression");
+  assert(ExprEvalContexts.back().ExprContext ==
+ ExpressionEvaluationContextRecord::EK_Decltype &&
+ "not in a decltype expression");
 
   // C++11 [expr.call]p11:
   //   If a function call is a prvalue of object type,
@@ -6537,7 +6540,8 @@
 TopBind = nullptr;
 
   // Disable the special decltype handling now.
-  ExprEvalContexts.back().IsDecltype = false;
+  ExprEvalContexts.back().ExprContext =
+  ExpressionEvaluationContextRecord::EK_Other;
 
   // In MS mode, don't perform any extra checking of call return types within a
   // decltype expression.
Index: lib/Sema/SemaExpr.cpp
===
--- lib/Sema/SemaExpr.cpp
+++ lib/Sema/SemaExpr.cpp
@@ -14083,11 +14083,11 @@
 }
 
 void
-Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
-  Decl *LambdaContextDecl,
-  bool IsDecltype) {
+Sema::PushExpressionEvaluationContext(
+ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl,
+ExpressionEvaluationContextRecord::ExpressionKind ExprContext) {
   ExprEvalContexts.emplace_back(NewContext, ExprCleanupObjects.size(), Cleanup,
-LambdaContextDecl, IsDecltype);
+LambdaContextDecl, ExprContext);
   Cleanup.reset();
   if (!MaybeODRUseExprs.empty())
 std::swap(MaybeODRUseExprs, ExprEvalContexts.back().SavedMaybeODRUseExprs);
@@ -14094,11 +14094,11 @@
 }
 
 void
-Sema::PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext,
-  ReuseLambdaContextDecl_t,
-  bool IsDecltype) {
+Sema::PushExpressionEvaluationContext(
+ExpressionEvaluationContext NewContext, ReuseLambdaContextDecl_t,
+ExpressionEvaluationContextRecord::ExpressionKind ExprContext) {
   Decl *ClosureContextDecl = ExprEvalContexts.back().ManglingContextDecl;
-  PushExpressionEvaluationContext(NewContext, ClosureContextDecl, IsDecltype);
+  PushExpressionEvaluationContext(NewContext, ClosureContextDecl, ExprContext);
 }
 
 void Sema::PopExpressionEvaluationContext() {
@@ -14106,7 +14106,9 @@
   unsigned NumTypos = Rec.NumTypos;
 
   if (!Rec.Lambdas.empty()) {
-if (Rec.isUnevaluated() || Rec.isConstantEvaluated()) {
+using ExpressionKind = ExpressionEvaluationContextRecord::ExpressionKind;
+if (Rec.ExprContext == ExpressionKind::EK_TemplateParameter || Rec.isUnevaluated() ||
+(Rec.isConstantEvaluated() && !getLangOp

[PATCH] D39679: [C++11] Fix warning when dropping cv-qualifiers when assigning to a reference with a braced initializer list

2018-06-22 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 152441.
Rakete added a comment.

done :)
Could you commit it please, @rsmith ?


https://reviews.llvm.org/D39679

Files:
  lib/Sema/SemaInit.cpp
  test/SemaCXX/references.cpp

Index: test/SemaCXX/references.cpp
===
--- test/SemaCXX/references.cpp
+++ test/SemaCXX/references.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s 
 int g(int);
 
 void f() {
@@ -55,6 +56,24 @@
   //  const double& rcd2 = 2; // rcd2 refers to temporary with value 2.0
   const volatile int cvi = 1;
   const int& r = cvi; // expected-error{{binding value of type 'const volatile int' to reference to type 'const int' drops 'volatile' qualifier}}
+
+#if __cplusplus >= 201103L
+  const int& r2{cvi}; // expected-error{{binding value of type 'const volatile int' to reference to type 'const int' drops 'volatile' qualifier}}
+
+  const int a = 2;
+  int& r3{a}; // expected-error{{binding value of type 'const int' to reference to type 'int' drops 'const'}}
+
+  const int&& r4{a}; // expected-error{{rvalue reference to type 'const int' cannot bind to lvalue of type 'const int'}}
+
+  void func();
+  void func(int);
+  int &ptr1 = {func}; // expected-error{{address of overloaded function 'func' does not match required type 'int'}}
+  int &&ptr2{func}; // expected-error{{address of overloaded function 'func' does not match required type 'int'}}
+  // expected-note@-4{{candidate function}}
+  // expected-note@-4{{candidate function}}
+  // expected-note@-6{{candidate function}}
+  // expected-note@-6{{candidate function}}
+#endif
 }
 
 // C++ [dcl.init.ref]p3
Index: lib/Sema/SemaInit.cpp
===
--- lib/Sema/SemaInit.cpp
+++ lib/Sema/SemaInit.cpp
@@ -7565,6 +7565,19 @@
   if (!Failed())
 return false;
 
+  // When we want to diagnose only one element of a braced-init-list,
+  // we need to factor it out.
+  Expr *OnlyArg;
+  if (Args.size() == 1) {
+auto *List = dyn_cast(Args[0]);
+if (List && List->getNumInits() == 1)
+  OnlyArg = List->getInit(0);
+else
+  OnlyArg = Args[0];
+  }
+  else
+OnlyArg = nullptr;
+
   QualType DestType = Entity.getType();
   switch (Failure) {
   case FK_TooManyInitsForReference:
@@ -7625,7 +7638,7 @@
   ? diag::err_array_init_different_type
   : diag::err_array_init_non_constant_array))
   << DestType.getNonReferenceType()
-  << Args[0]->getType()
+  << OnlyArg->getType()
   << Args[0]->getSourceRange();
 break;
 
@@ -7636,7 +7649,7 @@
 
   case FK_AddressOfOverloadFailed: {
 DeclAccessPair Found;
-S.ResolveAddressOfOverloadedFunction(Args[0],
+S.ResolveAddressOfOverloadedFunction(OnlyArg,
  DestType.getNonReferenceType(),
  true,
  Found);
@@ -7644,9 +7657,9 @@
   }
 
   case FK_AddressOfUnaddressableFunction: {
-auto *FD = cast(cast(Args[0])->getDecl());
+auto *FD = cast(cast(OnlyArg)->getDecl());
 S.checkAddressOfFunctionIsAvailable(FD, /*Complain=*/true,
-Args[0]->getLocStart());
+OnlyArg->getLocStart());
 break;
   }
 
@@ -7656,11 +7669,11 @@
 case OR_Ambiguous:
   if (Failure == FK_UserConversionOverloadFailed)
 S.Diag(Kind.getLocation(), diag::err_typecheck_ambiguous_condition)
-  << Args[0]->getType() << DestType
+  << OnlyArg->getType() << DestType
   << Args[0]->getSourceRange();
   else
 S.Diag(Kind.getLocation(), diag::err_ref_init_ambiguous)
-  << DestType << Args[0]->getType()
+  << DestType << OnlyArg->getType()
   << Args[0]->getSourceRange();
 
   FailedCandidateSet.NoteCandidates(S, OCD_ViableCandidates, Args);
@@ -7670,10 +7683,10 @@
   if (!S.RequireCompleteType(Kind.getLocation(),
  DestType.getNonReferenceType(),
   diag::err_typecheck_nonviable_condition_incomplete,
-   Args[0]->getType(), Args[0]->getSourceRange()))
+   OnlyArg->getType(), Args[0]->getSourceRange()))
 S.Diag(Kind.getLocation(), diag::err_typecheck_nonviable_condition)
   << (Entity.getKind() == InitializedEntity::EK_Result)
-  << Args[0]->getType() << Args[0]->getSourceRange()
+  << OnlyArg->getType() << Args[0]->getSourceRange()
   << DestType.getNonReferenceType();
 
   FailedCandidateSet.NoteCandidates(S, OCD_AllCandidates, Args);
@@ -7681,7 +7694,7 @@
 
 case OR_Deleted: {
   S.Diag(Kind.getLocation(), diag::err_typecheck_deleted_function)
-<< Args[0]->getType() << DestType.getNonReferenceType()
+<< OnlyArg->getType() << DestType.get

[PATCH] D50766: Fix false positive unsequenced access and modification warning in array subscript expression.

2018-10-10 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added a comment.

Sorry, for some reason I didn't see your updates.

Can you add a test for C++17? Then your patch is good to go! :)


https://reviews.llvm.org/D50766



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


[PATCH] D50766: Fix false positive unsequenced access and modification warning in array subscript expression.

2018-10-10 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete accepted this revision.
Rakete added a comment.
This revision is now accepted and ready to land.

Nevermind my last comment, I was tired. LGTM


https://reviews.llvm.org/D50766



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


[PATCH] D50766: Fix false positive unsequenced access and modification warning in array subscript expression.

2018-10-11 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added inline comments.



Comment at: test/SemaCXX/warn-unsequenced-cxx17.cpp:1
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 -Wno-unused %s
+

lebedev.ri wrote:
> One last-minute thought: this is only a positive test.
> You don't test what happens before C++17.
It is tested. Look at the diff for test/SemaCXX/warn-unsequenced.cpp :)
Or are you suggesting to merge the two files?


https://reviews.llvm.org/D50766



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


[PATCH] D52750: [Diagnostics] Check for integer overflow in array size expressions

2018-10-11 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added a comment.

The array size is still evaluated twice. Try to incorporate the check in 
`Sema::VerifyIntegerConstantExpression`.


https://reviews.llvm.org/D52750



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


[PATCH] D52750: [Diagnostics] Check for integer overflow in array size expressions

2018-10-11 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added a comment.

Nah, you don't even need to call `EvaluateForOverflow` I believe. :) Have a 
look overflow evaluation is done.


https://reviews.llvm.org/D52750



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


[PATCH] D52750: [Diagnostics] Check for integer overflow in array size expressions

2018-10-12 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added a comment.

This doesn't produce a warning in C++11 and up.


https://reviews.llvm.org/D52750



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


[PATCH] D52750: [Diagnostics] Check for integer overflow in array size expressions

2018-10-12 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added a comment.

In https://reviews.llvm.org/D52750#1263466, @xbolva00 wrote:

> In https://reviews.llvm.org/D52750#1263461, @Rakete wrote:
>
> > This doesn't produce a warning in C++11 and up.
>
>
> But see Richard's comment: https://reviews.llvm.org/D52750#125175 so I am not 
> sure :/


I guess I can see why it makes sense to suppress the warning in those cases. 
Sorry.


https://reviews.llvm.org/D52750



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


[PATCH] D53595: [C++17] Reject shadowing of capture by parameter in lambda

2018-10-23 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete created this revision.
Rakete added a reviewer: rsmith.

This change rejects the shadowing of a capture by a parameter in lambdas in 
C++17.

  int main() {
int a;
auto f = [a](int a) { return a; };
  }

results in:

  main.cpp:3:20: error: a lambda parameter cannot shadow an explicitly captured 
entity
auto f = [a](int a) { return a; };
 ^
  main.cpp:3:13: note: variable a is explicitly captured here
auto f = [a](int a) { return a; };
  ^


Repository:
  rC Clang

https://reviews.llvm.org/D53595

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/Sema/SemaLambda.cpp
  test/SemaCXX/warn-shadow-in-lambdas.cpp

Index: test/SemaCXX/warn-shadow-in-lambdas.cpp
===
--- test/SemaCXX/warn-shadow-in-lambdas.cpp
+++ test/SemaCXX/warn-shadow-in-lambdas.cpp
@@ -1,6 +1,7 @@
 // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -D AVOID %s
 // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -Wshadow-uncaptured-local %s
 // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow-all %s
+// RUN: %clang_cc1 -std=c++17 -verify -fsyntax-only -Wshadow-all %s
 
 void foo(int param) { // expected-note 1+ {{previous declaration is here}}
   int var = 0; // expected-note 1+ {{previous declaration is here}}
@@ -78,8 +79,15 @@
 auto f1 = [var] () { // expected-note {{variable 'var' is explicitly captured here}}
   int var = 1; // expected-warning {{declaration shadows a local variable}}
 };
-auto f2 = [param]   // expected-note {{variable 'param' is explicitly captured here}}
- (int param) { ; }; // expected-warning {{declaration shadows a local variable}}
+auto f2 = [param] 
+ (int param) { ; };
+#if __cplusplus < 201703L
+// expected-note@-3{{variable 'param' is explicitly captured here}}
+// expected-warning@-3{{declaration shadows a local variable}}
+#else
+// expected-error@-5{{a lambda parameter cannot shadow an explicitly captured entity}}
+// expected-note@-7{{variable param is explicitly captured here}}
+#endif
   }
 
   // Warn for variables defined in the capture list.
@@ -134,8 +142,16 @@
   auto g1 = [](auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
   auto g2 = [=](auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
 #endif
-  auto g3 = [param] // expected-note {{variable 'param' is explicitly captured here}}
-   (auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
+  auto g3 = [param]
+   (auto param) { ; };
+#if __cplusplus < 201703L
+// expected-note@-3{{variable 'param' is explicitly captured here}}
+// expected-warning@-3{{declaration shadows a local variable}}
+#else
+// expected-error@-5{{a lambda parameter cannot shadow an explicitly captured entity}}
+// expected-note@-7{{variable param is explicitly captured here}}
+#endif
+
 }
 
 void avoidWarningWhenRedefining() {
@@ -145,3 +161,20 @@
 int b = 0; // expected-error {{redefinition of 'b'}}
   };
 }
+
+void parameterShadowCapture() {
+#if __cplusplus >= 201703L
+  int var = 1; // expected-note{{previous declaration is here}}
+  auto f1 = [var](int var) { return var; }; // expected-error{{a lambda parameter cannot shadow an explicitly captured entity}}
+  // expected-note@-1{{variable var is explicitly captured here}}
+
+  auto f2 = [var = 1](int var) { return var; }; // expected-error{{a lambda parameter cannot shadow an explicitly captured entity}}
+  // expected-note@-1{{variable var is explicitly captured here}}
+  // expected-error@-2{{reference to 'var' is ambiguous}}
+  // expected-note@-3{{candidate found by name lookup is 'var'}}
+  // expected-note@-4{{candidate found by name lookup is 'var'}}
+
+  auto f3 = [=](int var) { return var; };
+  // expected-warning@-1{{declaration shadows a local variable}}
+#endif
+}
Index: lib/Sema/SemaLambda.cpp
===
--- lib/Sema/SemaLambda.cpp
+++ lib/Sema/SemaLambda.cpp
@@ -493,15 +493,30 @@
   LSI->finishedExplicitCaptures();
 }
 
-void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope) {
+void Sema::addLambdaParameters(
+const SmallVectorImpl &Captures,
+CXXMethodDecl *CallOperator, Scope *CurScope) {
   // Introduce our parameters into the function scope
   for (unsigned p = 0, NumParams = CallOperator->getNumParams();
p < NumParams; ++p) {
 ParmVarDecl *Param = CallOperator->getParamDecl(p);
 
 // If this has an identifier, add it to the scope stack.
 if (CurScope && Param->getIdentifier()) {
-  CheckShadow(CurScope, Param);
+  bool Error = false;
+  if (getLangOpts().CPlusPlus17) {
+// Resolution of CWG 2211 in C++17 renders shadowing ill-formed.
+for (const auto &Capture: Captures) {
+  if (Capture.Id && Capture.Id->getName() == Param->g

[PATCH] D53595: [C++17] Reject shadowing of capture by parameter in lambda

2018-10-23 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added inline comments.



Comment at: lib/Sema/SemaLambda.cpp:510
+for (const auto &Capture: Captures) {
+  if (Capture.Id && Capture.Id->getName() == Param->getName()) {
+Error = true;

erik.pilkington wrote:
> You should compare `IdentifierInfo`s here, rather than `StringRef`s.
`IdentifierInfo` doesn't have a compare equal or `operator==` function. How do 
you propose I do that? Do I add one?


Repository:
  rC Clang

https://reviews.llvm.org/D53595



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


[PATCH] D53595: [C++17] Reject shadowing of capture by parameter in lambda

2018-10-23 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 170748.
Rakete added a comment.

Addressed review comments! :) Thanks


Repository:
  rC Clang

https://reviews.llvm.org/D53595

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/Sema/SemaLambda.cpp
  test/SemaCXX/warn-shadow-in-lambdas.cpp
  www/cxx_dr_status.html

Index: www/cxx_dr_status.html
===
--- www/cxx_dr_status.html
+++ www/cxx_dr_status.html
@@ -13081,7 +13081,7 @@
 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2211";>2211
 C++17
 Hiding by lambda captures and parameters
-Unknown
+clang 8.0
   
   
 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2212";>2212
Index: test/SemaCXX/warn-shadow-in-lambdas.cpp
===
--- test/SemaCXX/warn-shadow-in-lambdas.cpp
+++ test/SemaCXX/warn-shadow-in-lambdas.cpp
@@ -1,6 +1,7 @@
 // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -D AVOID %s
 // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -Wshadow-uncaptured-local %s
 // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow-all %s
+// RUN: %clang_cc1 -std=c++17 -verify -fsyntax-only -Wshadow-all %s
 
 void foo(int param) { // expected-note 1+ {{previous declaration is here}}
   int var = 0; // expected-note 1+ {{previous declaration is here}}
@@ -78,8 +79,15 @@
 auto f1 = [var] () { // expected-note {{variable 'var' is explicitly captured here}}
   int var = 1; // expected-warning {{declaration shadows a local variable}}
 };
-auto f2 = [param]   // expected-note {{variable 'param' is explicitly captured here}}
- (int param) { ; }; // expected-warning {{declaration shadows a local variable}}
+auto f2 = [param] 
+ (int param) { ; };
+#if __cplusplus < 201703L
+// expected-note@-3{{variable 'param' is explicitly captured here}}
+// expected-warning@-3{{a lambda parameter that shadows a capture is incompatible with C++ standards before C++17}}
+#else
+// expected-error@-5{{a lambda parameter cannot shadow an explicitly captured entity}}
+// expected-note@-7{{variable 'param' is explicitly captured here}}
+#endif
   }
 
   // Warn for variables defined in the capture list.
@@ -134,8 +142,16 @@
   auto g1 = [](auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
   auto g2 = [=](auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
 #endif
-  auto g3 = [param] // expected-note {{variable 'param' is explicitly captured here}}
-   (auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
+  auto g3 = [param]
+   (auto param) { ; };
+#if __cplusplus < 201703L
+// expected-note@-3{{variable 'param' is explicitly captured here}}
+// expected-warning@-3{{a lambda parameter that shadows a capture is incompatible with C++ standards before C++17}}
+#else
+// expected-error@-5{{a lambda parameter cannot shadow an explicitly captured entity}}
+// expected-note@-7{{variable 'param' is explicitly captured here}}
+#endif
+
 }
 
 void avoidWarningWhenRedefining() {
@@ -145,3 +161,20 @@
 int b = 0; // expected-error {{redefinition of 'b'}}
   };
 }
+
+void parameterShadowCapture() {
+#if __cplusplus >= 201703L
+  int var = 1; // expected-note{{previous declaration is here}}
+  auto f1 = [var](int var) { return var; }; // expected-error{{a lambda parameter cannot shadow an explicitly captured entity}}
+  // expected-note@-1{{variable 'var' is explicitly captured here}}
+
+  auto f2 = [var = 1](int var) { return var; }; // expected-error{{a lambda parameter cannot shadow an explicitly captured entity}}
+  // expected-note@-1{{variable 'var' is explicitly captured here}}
+  // expected-error@-2{{reference to 'var' is ambiguous}}
+  // expected-note@-3{{candidate found by name lookup is 'var'}}
+  // expected-note@-4{{candidate found by name lookup is 'var'}}
+
+  auto f3 = [=](int var) { return var; };
+  // expected-warning@-1{{declaration shadows a local variable}}
+#endif
+}
Index: lib/Sema/SemaLambda.cpp
===
--- lib/Sema/SemaLambda.cpp
+++ lib/Sema/SemaLambda.cpp
@@ -493,15 +493,32 @@
   LSI->finishedExplicitCaptures();
 }
 
-void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope) {
+void Sema::addLambdaParameters(
+const SmallVectorImpl &Captures,
+CXXMethodDecl *CallOperator, Scope *CurScope) {
   // Introduce our parameters into the function scope
   for (unsigned p = 0, NumParams = CallOperator->getNumParams();
p < NumParams; ++p) {
 ParmVarDecl *Param = CallOperator->getParamDecl(p);
 
 // If this has an identifier, add it to the scope stack.
 if (CurScope && Param->getIdentifier()) {
-  CheckShadow(CurScope, Param);
+  bool Error = false;
+  // Resolution of CWG 2211 in C++17 renders sh

[PATCH] D53595: [C++17] Reject shadowing of capture by parameter in lambda

2018-10-23 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 170757.
Rakete added a comment.

Use correct clang and version spelling.


Repository:
  rC Clang

https://reviews.llvm.org/D53595

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/Sema/SemaLambda.cpp
  test/SemaCXX/warn-shadow-in-lambdas.cpp
  www/cxx_dr_status.html

Index: www/cxx_dr_status.html
===
--- www/cxx_dr_status.html
+++ www/cxx_dr_status.html
@@ -13081,7 +13081,7 @@
 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2211";>2211
 C++17
 Hiding by lambda captures and parameters
-Unknown
+Clang 8
   
   
 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2212";>2212
Index: test/SemaCXX/warn-shadow-in-lambdas.cpp
===
--- test/SemaCXX/warn-shadow-in-lambdas.cpp
+++ test/SemaCXX/warn-shadow-in-lambdas.cpp
@@ -1,6 +1,7 @@
 // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -D AVOID %s
 // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -Wshadow-uncaptured-local %s
 // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow-all %s
+// RUN: %clang_cc1 -std=c++17 -verify -fsyntax-only -Wshadow-all %s
 
 void foo(int param) { // expected-note 1+ {{previous declaration is here}}
   int var = 0; // expected-note 1+ {{previous declaration is here}}
@@ -78,8 +79,15 @@
 auto f1 = [var] () { // expected-note {{variable 'var' is explicitly captured here}}
   int var = 1; // expected-warning {{declaration shadows a local variable}}
 };
-auto f2 = [param]   // expected-note {{variable 'param' is explicitly captured here}}
- (int param) { ; }; // expected-warning {{declaration shadows a local variable}}
+auto f2 = [param] 
+ (int param) { ; };
+#if __cplusplus < 201703L
+// expected-note@-3{{variable 'param' is explicitly captured here}}
+// expected-warning@-3{{a lambda parameter that shadows a capture is incompatible with C++ standards before C++17}}
+#else
+// expected-error@-5{{a lambda parameter cannot shadow an explicitly captured entity}}
+// expected-note@-7{{variable 'param' is explicitly captured here}}
+#endif
   }
 
   // Warn for variables defined in the capture list.
@@ -134,8 +142,16 @@
   auto g1 = [](auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
   auto g2 = [=](auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
 #endif
-  auto g3 = [param] // expected-note {{variable 'param' is explicitly captured here}}
-   (auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
+  auto g3 = [param]
+   (auto param) { ; };
+#if __cplusplus < 201703L
+// expected-note@-3{{variable 'param' is explicitly captured here}}
+// expected-warning@-3{{a lambda parameter that shadows a capture is incompatible with C++ standards before C++17}}
+#else
+// expected-error@-5{{a lambda parameter cannot shadow an explicitly captured entity}}
+// expected-note@-7{{variable 'param' is explicitly captured here}}
+#endif
+
 }
 
 void avoidWarningWhenRedefining() {
@@ -145,3 +161,20 @@
 int b = 0; // expected-error {{redefinition of 'b'}}
   };
 }
+
+void parameterShadowCapture() {
+#if __cplusplus >= 201703L
+  int var = 1; // expected-note{{previous declaration is here}}
+  auto f1 = [var](int var) { return var; }; // expected-error{{a lambda parameter cannot shadow an explicitly captured entity}}
+  // expected-note@-1{{variable 'var' is explicitly captured here}}
+
+  auto f2 = [var = 1](int var) { return var; }; // expected-error{{a lambda parameter cannot shadow an explicitly captured entity}}
+  // expected-note@-1{{variable 'var' is explicitly captured here}}
+  // expected-error@-2{{reference to 'var' is ambiguous}}
+  // expected-note@-3{{candidate found by name lookup is 'var'}}
+  // expected-note@-4{{candidate found by name lookup is 'var'}}
+
+  auto f3 = [=](int var) { return var; };
+  // expected-warning@-1{{declaration shadows a local variable}}
+#endif
+}
Index: lib/Sema/SemaLambda.cpp
===
--- lib/Sema/SemaLambda.cpp
+++ lib/Sema/SemaLambda.cpp
@@ -493,15 +493,32 @@
   LSI->finishedExplicitCaptures();
 }
 
-void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope) {
+void Sema::addLambdaParameters(
+const SmallVectorImpl &Captures,
+CXXMethodDecl *CallOperator, Scope *CurScope) {
   // Introduce our parameters into the function scope
   for (unsigned p = 0, NumParams = CallOperator->getNumParams();
p < NumParams; ++p) {
 ParmVarDecl *Param = CallOperator->getParamDecl(p);
 
 // If this has an identifier, add it to the scope stack.
 if (CurScope && Param->getIdentifier()) {
-  CheckShadow(CurScope, Param);
+  bool Error = false;
+  // Resolution of CWG 2211 in C++17 renders s

[PATCH] D53595: [C++17] Reject shadowing of capture by parameter in lambda

2018-10-24 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 170828.
Rakete added a comment.

Addresed review comments :)

I updated the dr status file but a lot of unrelated changes made it in. Is this 
okay?


Repository:
  rC Clang

https://reviews.llvm.org/D53595

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/Sema/SemaLambda.cpp
  test/CXX/drs/dr22xx.cpp
  test/SemaCXX/warn-shadow-in-lambdas.cpp
  www/cxx_dr_status.html

Index: www/cxx_dr_status.html
===
--- www/cxx_dr_status.html
+++ www/cxx_dr_status.html
@@ -7437,11 +7437,11 @@
 Brace elision in array temporary initialization
 Unknown
   
-  
-http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1271";>1271
-drafting
+  
+http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1271";>1271
+DR
 Imprecise wording regarding dependent types
-Not resolved
+Unknown
   
   
 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1272";>1272
@@ -11147,7 +11147,7 @@
   
   
 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1889";>1889
-open
+drafting
 Unclear effect of #pragma on conformance
 Not resolved
   
@@ -11170,8 +11170,8 @@
 Unknown
   
   
-http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1893";>1893
-tentatively ready
+http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1893";>1893
+DR
 Function-style cast with braced-init-lists and empty pack expansions
 Unknown
   
@@ -11247,11 +11247,11 @@
 Dependent types and injected-class-names
 Unknown
   
-  
-http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1906";>1906
-review
+  
+http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_closed.html#1906";>1906
+NAD
 Name lookup in member friend declaration
-Not resolved
+Unknown
   
   
 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1907";>1907
@@ -11272,8 +11272,8 @@
 Yes
   
   
-http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1910";>1910
-tentatively ready
+http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1910";>1910
+DR
 “Shall” requirement applied to runtime behavior
 Unknown
   
@@ -11710,8 +11710,8 @@
 Unknown
   
   
-http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1983";>1983
-tentatively ready
+http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1983";>1983
+DR
 Inappropriate use of virt-specifier
 Unknown
   
@@ -12166,8 +12166,8 @@
 Not resolved
   
   
-http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2059";>2059
-tentatively ready
+http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2059";>2059
+DR
 Linkage and deduced return types
 Unknown
   
@@ -12298,8 +12298,8 @@
 Not resolved
   
   
-http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2081";>2081
-tentatively ready
+http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2081";>2081
+DR
 Deduced return type in redeclaration or specialization of function template
 Unknown
   
@@ -12340,8 +12340,8 @@
 Not resolved
   
   
-http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2088";>2088
-tentatively ready
+http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2088";>2088
+DR
 Late tiebreakers in partial ordering
 Unknown
   
@@ -12364,8 +12364,8 @@
 Unknown
   
   
-http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2092";>2092
-tentatively ready
+http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2092";>2092
+DR
 Deduction failure and overload resolution
 Unknown
   
@@ -12796,8 +12796,8 @@
 Unknown
   
   
-http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2164";>2164
-tentatively ready
+http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2164";>2164
+DR
 Name hiding and using-directives
 Unknown
   
@@ -12935,7 +12935,7 @@
   
   
 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2187";>2187
-open
+drafting
 Protected members and access via qualified-id
 Not resolved
   
@@ -13025,7 +13025,7 @@
   
   
 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2202";>2202
-open
+drafting
 When does default argument instantiation occur?
 Not resolved
   
@@ -13081,7 +13081,7 @@
 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2211";>2211
 C++17
 Hiding by lambda captures and parameters
-Unknown
+SVN
   
   
 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2212";>2212
@@ -13127,7 +13127,7 @@
   
   
 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2219";>2219
-open
+drafting
 Dynamically-unreachable handlers
 Not resolved
   
@@ -13168,14 +13168,14 @@
 Un

[PATCH] D53595: [C++17] Reject shadowing of capture by parameter in lambda

2018-10-25 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added a comment.

In https://reviews.llvm.org/D53595#1276330, @rsmith wrote:

> In https://reviews.llvm.org/D53595#1273848, @Rakete wrote:
>
> > Addresed review comments :)
> >
> > I updated the dr status file but a lot of unrelated changes made it in. Is 
> > this okay?
>
>
> Please regenerate the file without your change and check that in as a 
> separate commit prior to this.


Why not afterwards? That way the DR is marked as resolved immediately.


Repository:
  rC Clang

https://reviews.llvm.org/D53595



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


[PATCH] D53595: [C++17] Reject shadowing of capture by parameter in lambda

2018-10-25 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 171174.
Rakete added a comment.

Update DR list.


https://reviews.llvm.org/D53595

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/Sema/SemaLambda.cpp
  test/CXX/drs/dr22xx.cpp
  test/SemaCXX/warn-shadow-in-lambdas.cpp
  www/cxx_dr_status.html

Index: www/cxx_dr_status.html
===
--- www/cxx_dr_status.html
+++ www/cxx_dr_status.html
@@ -13081,7 +13081,7 @@
 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2211";>2211
 C++17
 Hiding by lambda captures and parameters
-Unknown
+SVN
   
   
 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2212";>2212
Index: test/SemaCXX/warn-shadow-in-lambdas.cpp
===
--- test/SemaCXX/warn-shadow-in-lambdas.cpp
+++ test/SemaCXX/warn-shadow-in-lambdas.cpp
@@ -1,6 +1,7 @@
 // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -D AVOID %s
 // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -Wshadow-uncaptured-local %s
 // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow-all %s
+// RUN: %clang_cc1 -std=c++17 -verify -fsyntax-only -Wshadow-all %s
 
 void foo(int param) { // expected-note 1+ {{previous declaration is here}}
   int var = 0; // expected-note 1+ {{previous declaration is here}}
@@ -79,7 +80,7 @@
   int var = 1; // expected-warning {{declaration shadows a local variable}}
 };
 auto f2 = [param]   // expected-note {{variable 'param' is explicitly captured here}}
- (int param) { ; }; // expected-warning {{declaration shadows a local variable}}
+ (int param) { ; }; // expected-error {{a lambda parameter cannot shadow an explicitly captured entity}}
   }
 
   // Warn for variables defined in the capture list.
@@ -135,7 +136,7 @@
   auto g2 = [=](auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
 #endif
   auto g3 = [param] // expected-note {{variable 'param' is explicitly captured here}}
-   (auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
+   (auto param) { ; }; // expected-error {{a lambda parameter cannot shadow an explicitly captured entity}}
 }
 
 void avoidWarningWhenRedefining() {
Index: test/CXX/drs/dr22xx.cpp
===
--- test/CXX/drs/dr22xx.cpp
+++ test/CXX/drs/dr22xx.cpp
@@ -15,3 +15,14 @@
   const volatile unsigned i3 : 1;
 };
 }
+
+#if __cplusplus >= 201103L
+namespace dr2211 { // dr2211: 8
+void f() {
+  int a;
+  auto f = [a](int a) { (void)a; }; // expected-error {{a lambda parameter cannot shadow an explicitly captured entity}}
+  // expected-note@-1{{variable 'a' is explicitly captured here}}
+  auto g = [=](int a) { (void)a; };
+}
+}
+#endif
Index: lib/Sema/SemaLambda.cpp
===
--- lib/Sema/SemaLambda.cpp
+++ lib/Sema/SemaLambda.cpp
@@ -493,7 +493,9 @@
   LSI->finishedExplicitCaptures();
 }
 
-void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope) {
+void Sema::addLambdaParameters(
+ArrayRef Captures,
+CXXMethodDecl *CallOperator, Scope *CurScope) {
   // Introduce our parameters into the function scope
   for (unsigned p = 0, NumParams = CallOperator->getNumParams();
p < NumParams; ++p) {
@@ -501,7 +503,19 @@
 
 // If this has an identifier, add it to the scope stack.
 if (CurScope && Param->getIdentifier()) {
-  CheckShadow(CurScope, Param);
+  bool Error = false;
+  // Resolution of CWG 2211 in C++17 renders shadowing ill-formed, but we
+  // retroactively apply it.
+  for (const auto &Capture : Captures) {
+if (Capture.Id == Param->getIdentifier()) {
+  Error = true;
+  Diag(Param->getLocation(), diag::err_parameter_shadow_capture);
+  Diag(Capture.Loc, diag::note_var_explicitly_captured_here)
+  << Capture.Id << true;
+}
+  }
+  if (!Error)
+CheckShadow(CurScope, Param);
 
   PushOnScopeChains(Param, CurScope);
 }
@@ -1142,7 +1156,7 @@
   LSI->ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
 
   // Add lambda parameters into scope.
-  addLambdaParameters(Method, CurScope);
+  addLambdaParameters(Intro.Captures, Method, CurScope);
 
   // Enter a new evaluation context to insulate the lambda from any
   // cleanups from the enclosing full-expression.
Index: include/clang/Sema/Sema.h
===
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -5580,7 +5580,9 @@
   void finishLambdaExplicitCaptures(sema::LambdaScopeInfo *LSI);
 
   /// Introduce the lambda parameters into scope.
-  void addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope);
+  void addLambdaParameters(
+  ArrayRef Captures,
+  CXXMethodDecl *CallOperator, Scope *

[PATCH] D53595: [C++17] Reject shadowing of capture by parameter in lambda

2018-10-25 Thread Nicolas Lesser via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rC345308: [C++17] Reject shadowing of capture by parameter in 
lambda (authored by Rakete, committed by ).

Repository:
  rC Clang

https://reviews.llvm.org/D53595

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/Sema/SemaLambda.cpp
  test/CXX/drs/dr22xx.cpp
  test/SemaCXX/warn-shadow-in-lambdas.cpp
  www/cxx_dr_status.html

Index: www/cxx_dr_status.html
===
--- www/cxx_dr_status.html
+++ www/cxx_dr_status.html
@@ -13081,7 +13081,7 @@
 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#2211";>2211
 C++17
 Hiding by lambda captures and parameters
-Unknown
+SVN
   
   
 http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#2212";>2212
Index: include/clang/Sema/Sema.h
===
--- include/clang/Sema/Sema.h
+++ include/clang/Sema/Sema.h
@@ -5580,7 +5580,9 @@
   void finishLambdaExplicitCaptures(sema::LambdaScopeInfo *LSI);
 
   /// Introduce the lambda parameters into scope.
-  void addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope);
+  void addLambdaParameters(
+  ArrayRef Captures,
+  CXXMethodDecl *CallOperator, Scope *CurScope);
 
   /// Deduce a block or lambda's return type based on the return
   /// statements present in the body.
Index: include/clang/Basic/DiagnosticSemaKinds.td
===
--- include/clang/Basic/DiagnosticSemaKinds.td
+++ include/clang/Basic/DiagnosticSemaKinds.td
@@ -6630,6 +6630,10 @@
   def ext_star_this_lambda_capture_cxx17 : ExtWarn<
 "capture of '*this' by copy is a C++17 extension">, InGroup;
 
+  // C++17 parameter shadows capture
+  def err_parameter_shadow_capture : Error<
+"a lambda parameter cannot shadow an explicitly captured entity">;
+
   // C++2a [=, this] captures.
   def warn_cxx17_compat_equals_this_lambda_capture : Warning<
 "explicit capture of 'this' with a capture default of '=' is incompatible "
Index: test/SemaCXX/warn-shadow-in-lambdas.cpp
===
--- test/SemaCXX/warn-shadow-in-lambdas.cpp
+++ test/SemaCXX/warn-shadow-in-lambdas.cpp
@@ -1,6 +1,7 @@
 // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -D AVOID %s
 // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow -Wshadow-uncaptured-local %s
 // RUN: %clang_cc1 -std=c++14 -verify -fsyntax-only -Wshadow-all %s
+// RUN: %clang_cc1 -std=c++17 -verify -fsyntax-only -Wshadow-all %s
 
 void foo(int param) { // expected-note 1+ {{previous declaration is here}}
   int var = 0; // expected-note 1+ {{previous declaration is here}}
@@ -79,7 +80,7 @@
   int var = 1; // expected-warning {{declaration shadows a local variable}}
 };
 auto f2 = [param]   // expected-note {{variable 'param' is explicitly captured here}}
- (int param) { ; }; // expected-warning {{declaration shadows a local variable}}
+ (int param) { ; }; // expected-error {{a lambda parameter cannot shadow an explicitly captured entity}}
   }
 
   // Warn for variables defined in the capture list.
@@ -135,7 +136,7 @@
   auto g2 = [=](auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
 #endif
   auto g3 = [param] // expected-note {{variable 'param' is explicitly captured here}}
-   (auto param) { ; }; // expected-warning {{declaration shadows a local variable}}
+   (auto param) { ; }; // expected-error {{a lambda parameter cannot shadow an explicitly captured entity}}
 }
 
 void avoidWarningWhenRedefining() {
Index: test/CXX/drs/dr22xx.cpp
===
--- test/CXX/drs/dr22xx.cpp
+++ test/CXX/drs/dr22xx.cpp
@@ -15,3 +15,14 @@
   const volatile unsigned i3 : 1;
 };
 }
+
+#if __cplusplus >= 201103L
+namespace dr2211 { // dr2211: 8
+void f() {
+  int a;
+  auto f = [a](int a) { (void)a; }; // expected-error {{a lambda parameter cannot shadow an explicitly captured entity}}
+  // expected-note@-1{{variable 'a' is explicitly captured here}}
+  auto g = [=](int a) { (void)a; };
+}
+}
+#endif
Index: lib/Sema/SemaLambda.cpp
===
--- lib/Sema/SemaLambda.cpp
+++ lib/Sema/SemaLambda.cpp
@@ -493,15 +493,29 @@
   LSI->finishedExplicitCaptures();
 }
 
-void Sema::addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope) {
+void Sema::addLambdaParameters(
+ArrayRef Captures,
+CXXMethodDecl *CallOperator, Scope *CurScope) {
   // Introduce our parameters into the function scope
   for (unsigned p = 0, NumParams = CallOperator->getNumParams();
p < NumParams; ++p) {
 ParmVarDecl *Param = CallOperator->getParamDecl(p);
 
 // If this has an identifier, add it to the scope stack.
 if (CurScope && Param->getIdentifier()) {

[PATCH] D36357: Added a better diagnostic when using the delete operator with lambdas

2018-10-28 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 171421.
Rakete added a comment.

Rebase and friendly ping :)


Repository:
  rC Clang

https://reviews.llvm.org/D36357

Files:
  include/clang/Basic/DiagnosticParseKinds.td
  lib/Parse/ParseExprCXX.cpp
  test/FixIt/fixit-cxx0x.cpp
  test/Parser/cxx0x-lambda-expressions.cpp
  test/SemaCXX/new-delete-0x.cpp

Index: test/SemaCXX/new-delete-0x.cpp
===
--- test/SemaCXX/new-delete-0x.cpp
+++ test/SemaCXX/new-delete-0x.cpp
@@ -34,6 +34,6 @@
 void bad_deletes()
 {
   // 'delete []' is always array delete, per [expr.delete]p1.
-  // FIXME: Give a better diagnostic.
-  delete []{ return (int*)0; }(); // expected-error {{expected expression}}
+  delete []{ return (int*)0; }(); // expected-error {{'[]' after delete interpreted as 'delete[]'}}
 }
+
Index: test/Parser/cxx0x-lambda-expressions.cpp
===
--- test/Parser/cxx0x-lambda-expressions.cpp
+++ test/Parser/cxx0x-lambda-expressions.cpp
@@ -53,8 +53,11 @@
   void delete_lambda(int *p) {
 delete [] p;
 delete [] (int*) { new int }; // ok, compound-literal, not lambda
-delete [] { return new int; } (); // expected-error{{expected expression}}
+delete [] { return new int; } (); // expected-error {{'[]' after delete interpreted as 'delete[]'}}
 delete [&] { return new int; } (); // ok, lambda
+
+delete []() { return new int; }(); // expected-error{{'[]' after delete interpreted as 'delete[]'}}
+delete [](E Enum) { return new int((int)Enum); }(e); // expected-error{{'[]' after delete interpreted as 'delete[]'}}
   }
 
   // We support init-captures in C++11 as an extension.
Index: test/FixIt/fixit-cxx0x.cpp
===
--- test/FixIt/fixit-cxx0x.cpp
+++ test/FixIt/fixit-cxx0x.cpp
@@ -58,6 +58,9 @@
   (void)[&, i, i]{ }; // expected-error{{'i' can appear only once in a capture list}}
   (void)[] mutable { }; // expected-error{{lambda requires '()' before 'mutable'}}
   (void)[] -> int { }; // expected-error{{lambda requires '()' before return type}}
+
+  delete []() { return new int; }(); // expected-error{{'[]' after delete interpreted as 'delete[]'}}
+  delete [] { return new int; }(); // expected-error{{'[]' after delete interpreted as 'delete[]'}}
 }
 
 #define bar "bar"
Index: lib/Parse/ParseExprCXX.cpp
===
--- lib/Parse/ParseExprCXX.cpp
+++ lib/Parse/ParseExprCXX.cpp
@@ -2976,8 +2976,38 @@
 //   [Footnote: A lambda expression with a lambda-introducer that consists
 //  of empty square brackets can follow the delete keyword if
 //  the lambda expression is enclosed in parentheses.]
-// FIXME: Produce a better diagnostic if the '[]' is unambiguously a
-//lambda-introducer.
+
+const Token Next = GetLookAheadToken(2);
+
+// Basic lookahead to check if we have a lambda expression.
+if (Next.isOneOf(tok::l_brace, tok::less) ||
+(Next.is(tok::l_paren) &&
+ (GetLookAheadToken(3).is(tok::r_paren) ||
+  (GetLookAheadToken(3).is(tok::identifier) &&
+   GetLookAheadToken(4).is(tok::identifier) {
+  SourceLocation RightBracketLock = NextToken().getLocation();
+  // Warn if the non-capturing lambda isn't surrounded by parenthesis
+  // to disambiguate it from 'delete[]'.
+  ExprResult Lambda = ParseLambdaExpression();
+  if (Lambda.isInvalid())
+return ExprError();
+
+  SourceLocation StartLoc = Lambda.get()->getBeginLoc();
+  Diag(Start, diag::err_lambda_after_delete)
+  << SourceRange(Start, RightBracketLock)
+  << FixItHint::CreateInsertion(StartLoc, "(")
+  << FixItHint::CreateInsertion(
+ Lexer::getLocForEndOfToken(Lambda.get()->getEndLoc(), 0,
+Actions.getSourceManager(),
+getLangOpts()),
+ ")");
+
+  // Evaluate any postfix expressions used on the lambda.
+  Lambda = ParsePostfixExpressionSuffix(Lambda);
+  return Actions.ActOnCXXDelete(Start, UseGlobal, /*ArrayForm=*/false,
+Lambda.get());
+}
+
 ArrayDelete = true;
 BalancedDelimiterTracker T(*this, tok::l_square);
 
Index: include/clang/Basic/DiagnosticParseKinds.td
===
--- include/clang/Basic/DiagnosticParseKinds.td
+++ include/clang/Basic/DiagnosticParseKinds.td
@@ -102,6 +102,8 @@
   InGroup, DefaultIgnore;
 def ext_alignof_expr : ExtWarn<
   "%0 applied to an expression is a GNU extension">, InGroup;
+def err_lambda_after_delete : Error<
+  "'[]' after delete interpreted as 'delete[]'">;
 
 def warn_microsoft_dependent_exists : Warning<
   "dependent %select{__if_not_exists|__if_exists}0 declarations are ign

[PATCH] D53847: [C++2a] P0634r3: Down with typename!

2018-10-29 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete created this revision.
Rakete added a reviewer: rsmith.

This patch implements P0634r3 that removes the need for 'typename' in certain 
contexts.

For example,

  template 
  using foo = T::type; // ok

This is also allowed in previous language versions as an extension, because I 
think it's pretty useful. :)


Repository:
  rC Clang

https://reviews.llvm.org/D53847

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/Parse/ParseDecl.cpp
  lib/Parse/ParseDeclCXX.cpp
  lib/Parse/Parser.cpp
  lib/Sema/SemaDecl.cpp
  test/CXX/drs/dr1xx.cpp
  test/CXX/drs/dr2xx.cpp
  test/CXX/drs/dr4xx.cpp
  test/CXX/drs/dr5xx.cpp
  test/CXX/temp/temp.res/p5.cpp
  test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp
  test/FixIt/fixit.cpp
  test/SemaCXX/MicrosoftCompatibility.cpp
  test/SemaCXX/MicrosoftExtensions.cpp
  test/SemaCXX/MicrosoftSuper.cpp
  test/SemaCXX/PR11358.cpp
  test/SemaCXX/unknown-type-name.cpp

Index: test/SemaCXX/unknown-type-name.cpp
===
--- test/SemaCXX/unknown-type-name.cpp
+++ test/SemaCXX/unknown-type-name.cpp
@@ -1,6 +1,6 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+// RUN: %clang_cc1 -Wc++2a-compat -fsyntax-only -verify %s
+// RUN: %clang_cc1 -Wc++2a-compat -fsyntax-only -verify -std=c++98 %s
+// RUN: %clang_cc1 -Wc++2a-compat -fsyntax-only -verify -std=c++11 %s
 
 // PR3990
 namespace N {
@@ -36,39 +36,39 @@
 
   static int n;
   static type m;
-  static int h(T::type, int); // expected-error{{missing 'typename'}}
-  static int h(T::type x, char); // expected-error{{missing 'typename'}}
+  static int h(T::type, int); // expected-warning {{implicit 'typename' is a C++2a extension}}
+  static int h(T::type x, char); // expected-warning {{implicit 'typename' is a C++2a extension}}
 };
 
 template
-A::type g(T t) { return t; } // expected-error{{missing 'typename'}}
+A::type g(T t) { return t; } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-A::type A::f() { return type(); } // expected-error{{missing 'typename'}}
+A::type A::f() { return type(); } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void f(T::type) { } // expected-error{{missing 'typename'}}
+void f(T::type) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void g(T::type x) { } // expected-error{{missing 'typename'}}
+void g(T::type x) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void f(T::type, int) { } // expected-error{{missing 'typename'}}
+void f(T::type, int) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void f(T::type x, char) { } // expected-error{{missing 'typename'}}
+void f(T::type x, char) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void f(int, T::type) { } // expected-error{{missing 'typename'}}
+void f(int, T::type) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void f(char, T::type x) { } // expected-error{{missing 'typename'}}
+void f(char, T::type x) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void f(int, T::type, int) { } // expected-error{{missing 'typename'}}
+void f(int, T::type, int) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void f(int, T::type x, char) { } // expected-error{{missing 'typename'}}
+void f(int, T::type x, char) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 int *p;
 
@@ -86,26 +86,26 @@
 
 template int A::n(T::value); // ok
 template
-A::type // expected-error{{missing 'typename'}}
+A::type // expected-warning {{implicit 'typename' is a C++2a extension}}
 A::m(T::value, 0); // ok
 
-template int A::h(T::type, int) {} // expected-error{{missing 'typename'}}
-template int A::h(T::type x, char) {} // expected-error{{missing 'typename'}}
+template int A::h(T::type, int) {} // expected-warning {{implicit 'typename' is a C++2a extension}}
+template int A::h(T::type x, char) {} // expected-warning {{implicit 'typename' is a C++2a extension}}
 
-template int h(T::type, int); // expected-error{{missing 'typename'}}
-template int h(T::type x, char); // expected-error{{missing 'typename'}}
+template int h(T::type, int); // expected-warning {{implicit 'typename' is a C++2a extension}}
+template int h(T::type x, char); // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template int junk1(T::junk);
 #if __cplusplus <= 201103L
 // expected-warning@-2 {{variable templates are a C++14 extension}}
 #endif
-template int junk2(T::junk) throw(); // expected-error{{missing 'typename'}}
-template int junk3(T::junk) = delete; // expected-error{{missing 'typename'}}
+template int junk2(T::junk) throw(); // expected-warning {{implicit 'typename' is a

[PATCH] D53847: [C++2a] P0634r3: Down with typename!

2018-10-29 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added inline comments.



Comment at: test/CXX/temp/temp.res/p5.cpp:71
+
+// FIXME: This is ok.
+template 

I think the below is well-formed according to the quote above, but I'm not sure 
I understand it correctly.


Repository:
  rC Clang

https://reviews.llvm.org/D53847



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


[PATCH] D53847: [C++2a] P0634r3: Down with typename!

2018-10-29 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 171609.
Rakete added a comment.

Remove unneeded -Wc++2a-compat flag in tests.


Repository:
  rC Clang

https://reviews.llvm.org/D53847

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/Parse/ParseDecl.cpp
  lib/Parse/ParseDeclCXX.cpp
  lib/Parse/Parser.cpp
  lib/Sema/SemaDecl.cpp
  test/CXX/drs/dr1xx.cpp
  test/CXX/drs/dr2xx.cpp
  test/CXX/drs/dr4xx.cpp
  test/CXX/drs/dr5xx.cpp
  test/CXX/temp/temp.res/p5.cpp
  test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp
  test/FixIt/fixit.cpp
  test/SemaCXX/MicrosoftCompatibility.cpp
  test/SemaCXX/MicrosoftExtensions.cpp
  test/SemaCXX/MicrosoftSuper.cpp
  test/SemaCXX/PR11358.cpp
  test/SemaCXX/unknown-type-name.cpp

Index: test/SemaCXX/unknown-type-name.cpp
===
--- test/SemaCXX/unknown-type-name.cpp
+++ test/SemaCXX/unknown-type-name.cpp
@@ -36,39 +36,39 @@
 
   static int n;
   static type m;
-  static int h(T::type, int); // expected-error{{missing 'typename'}}
-  static int h(T::type x, char); // expected-error{{missing 'typename'}}
+  static int h(T::type, int); // expected-warning {{implicit 'typename' is a C++2a extension}}
+  static int h(T::type x, char); // expected-warning {{implicit 'typename' is a C++2a extension}}
 };
 
 template
-A::type g(T t) { return t; } // expected-error{{missing 'typename'}}
+A::type g(T t) { return t; } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-A::type A::f() { return type(); } // expected-error{{missing 'typename'}}
+A::type A::f() { return type(); } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void f(T::type) { } // expected-error{{missing 'typename'}}
+void f(T::type) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void g(T::type x) { } // expected-error{{missing 'typename'}}
+void g(T::type x) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void f(T::type, int) { } // expected-error{{missing 'typename'}}
+void f(T::type, int) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void f(T::type x, char) { } // expected-error{{missing 'typename'}}
+void f(T::type x, char) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void f(int, T::type) { } // expected-error{{missing 'typename'}}
+void f(int, T::type) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void f(char, T::type x) { } // expected-error{{missing 'typename'}}
+void f(char, T::type x) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void f(int, T::type, int) { } // expected-error{{missing 'typename'}}
+void f(int, T::type, int) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void f(int, T::type x, char) { } // expected-error{{missing 'typename'}}
+void f(int, T::type x, char) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 int *p;
 
@@ -86,26 +86,26 @@
 
 template int A::n(T::value); // ok
 template
-A::type // expected-error{{missing 'typename'}}
+A::type // expected-warning {{implicit 'typename' is a C++2a extension}}
 A::m(T::value, 0); // ok
 
-template int A::h(T::type, int) {} // expected-error{{missing 'typename'}}
-template int A::h(T::type x, char) {} // expected-error{{missing 'typename'}}
+template int A::h(T::type, int) {} // expected-warning {{implicit 'typename' is a C++2a extension}}
+template int A::h(T::type x, char) {} // expected-warning {{implicit 'typename' is a C++2a extension}}
 
-template int h(T::type, int); // expected-error{{missing 'typename'}}
-template int h(T::type x, char); // expected-error{{missing 'typename'}}
+template int h(T::type, int); // expected-warning {{implicit 'typename' is a C++2a extension}}
+template int h(T::type x, char); // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template int junk1(T::junk);
 #if __cplusplus <= 201103L
 // expected-warning@-2 {{variable templates are a C++14 extension}}
 #endif
-template int junk2(T::junk) throw(); // expected-error{{missing 'typename'}}
-template int junk3(T::junk) = delete; // expected-error{{missing 'typename'}}
+template int junk2(T::junk) throw(); // expected-warning {{implicit 'typename' is a C++2a extension}}
+template int junk3(T::junk) = delete; // expected-warning {{implicit 'typename' is a C++2a extension}}
 #if __cplusplus <= 199711L
 //expected-warning@-2 {{deleted function definitions are a C++11 extension}}
 #endif
 
-template int junk4(T::junk j); // expected-error{{missing 'typename'}}
+template int junk4(T::junk j); // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 // FIXME: We can tell this was intended to be a function because it does not
 //have a dependent nested name specifier.
@@ -118,4 +118,5 @@
 // FIXME: We know which type specifier should

[PATCH] D53847: [C++2a] P0634r3: Down with typename!

2018-10-29 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 171612.
Rakete added a comment.

Fix easy errors in tests that I missed by adding explicit template 
instantations.


Repository:
  rC Clang

https://reviews.llvm.org/D53847

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Sema/Sema.h
  lib/Parse/ParseDecl.cpp
  lib/Parse/ParseDeclCXX.cpp
  lib/Parse/Parser.cpp
  lib/Sema/SemaDecl.cpp
  test/CXX/drs/dr1xx.cpp
  test/CXX/drs/dr2xx.cpp
  test/CXX/drs/dr4xx.cpp
  test/CXX/drs/dr5xx.cpp
  test/CXX/temp/temp.res/p5.cpp
  test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp
  test/FixIt/fixit.cpp
  test/SemaCXX/MicrosoftCompatibility.cpp
  test/SemaCXX/MicrosoftExtensions.cpp
  test/SemaCXX/MicrosoftSuper.cpp
  test/SemaCXX/PR11358.cpp
  test/SemaCXX/unknown-type-name.cpp

Index: test/SemaCXX/unknown-type-name.cpp
===
--- test/SemaCXX/unknown-type-name.cpp
+++ test/SemaCXX/unknown-type-name.cpp
@@ -36,39 +36,39 @@
 
   static int n;
   static type m;
-  static int h(T::type, int); // expected-error{{missing 'typename'}}
-  static int h(T::type x, char); // expected-error{{missing 'typename'}}
+  static int h(T::type, int); // expected-warning {{implicit 'typename' is a C++2a extension}}
+  static int h(T::type x, char); // expected-warning {{implicit 'typename' is a C++2a extension}}
 };
 
 template
-A::type g(T t) { return t; } // expected-error{{missing 'typename'}}
+A::type g(T t) { return t; } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-A::type A::f() { return type(); } // expected-error{{missing 'typename'}}
+A::type A::f() { return type(); } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void f(T::type) { } // expected-error{{missing 'typename'}}
+void f(T::type) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void g(T::type x) { } // expected-error{{missing 'typename'}}
+void g(T::type x) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void f(T::type, int) { } // expected-error{{missing 'typename'}}
+void f(T::type, int) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void f(T::type x, char) { } // expected-error{{missing 'typename'}}
+void f(T::type x, char) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void f(int, T::type) { } // expected-error{{missing 'typename'}}
+void f(int, T::type) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void f(char, T::type x) { } // expected-error{{missing 'typename'}}
+void f(char, T::type x) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void f(int, T::type, int) { } // expected-error{{missing 'typename'}}
+void f(int, T::type, int) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void f(int, T::type x, char) { } // expected-error{{missing 'typename'}}
+void f(int, T::type x, char) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 int *p;
 
@@ -86,26 +86,26 @@
 
 template int A::n(T::value); // ok
 template
-A::type // expected-error{{missing 'typename'}}
+A::type // expected-warning {{implicit 'typename' is a C++2a extension}}
 A::m(T::value, 0); // ok
 
-template int A::h(T::type, int) {} // expected-error{{missing 'typename'}}
-template int A::h(T::type x, char) {} // expected-error{{missing 'typename'}}
+template int A::h(T::type, int) {} // expected-warning {{implicit 'typename' is a C++2a extension}}
+template int A::h(T::type x, char) {} // expected-warning {{implicit 'typename' is a C++2a extension}}
 
-template int h(T::type, int); // expected-error{{missing 'typename'}}
-template int h(T::type x, char); // expected-error{{missing 'typename'}}
+template int h(T::type, int); // expected-warning {{implicit 'typename' is a C++2a extension}}
+template int h(T::type x, char); // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template int junk1(T::junk);
 #if __cplusplus <= 201103L
 // expected-warning@-2 {{variable templates are a C++14 extension}}
 #endif
-template int junk2(T::junk) throw(); // expected-error{{missing 'typename'}}
-template int junk3(T::junk) = delete; // expected-error{{missing 'typename'}}
+template int junk2(T::junk) throw(); // expected-warning {{implicit 'typename' is a C++2a extension}}
+template int junk3(T::junk) = delete; // expected-warning {{implicit 'typename' is a C++2a extension}}
 #if __cplusplus <= 199711L
 //expected-warning@-2 {{deleted function definitions are a C++11 extension}}
 #endif
 
-template int junk4(T::junk j); // expected-error{{missing 'typename'}}
+template int junk4(T::junk j); // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 // FIXME: We can tell this was intended to be a function because it does not
 //have a dependent nested name specifier.
@@ -118,4 +118,5 @@
 // FIXME

[PATCH] D56974: [SemaCXX] Fix ICE with structure bindings to members of template

2019-01-20 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added a comment.

Yeah, seems like we don't instantiate `pair` at all in that specific 
case. LGTM but you might want to wait for someone else to confirm.


Repository:
  rC Clang

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

https://reviews.llvm.org/D56974



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


[PATCH] D56974: [SemaCXX] Fix ICE with structure bindings to members of template

2019-01-27 Thread Nicolas Lesser via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rL352323: [SemaCXX] Fix ICE with structure bindings to members 
of template (authored by Rakete, committed by ).
Herald added a subscriber: llvm-commits.

Changed prior to commit:
  https://reviews.llvm.org/D56974?vs=182695&id=183761#toc

Repository:
  rL LLVM

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

https://reviews.llvm.org/D56974

Files:
  cfe/trunk/lib/Sema/SemaDeclCXX.cpp
  cfe/trunk/test/SemaCXX/cxx1z-decomposition.cpp


Index: cfe/trunk/test/SemaCXX/cxx1z-decomposition.cpp
===
--- cfe/trunk/test/SemaCXX/cxx1z-decomposition.cpp
+++ cfe/trunk/test/SemaCXX/cxx1z-decomposition.cpp
@@ -81,4 +81,21 @@
   void f() { static auto [a] = *this; } // expected-error {{cannot be declared 
'static'}}
 };
 
+namespace instantiate_template {
+
+template 
+struct pair {
+  T1 a;
+  T2 b;
+};
+
+const pair &f1();
+
+int f2() {
+  const auto &[a, b] = f1();
+  return a + b;
+}
+
+} // namespace instantiate_template
+
 // FIXME: by-value array copies
Index: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
===
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp
@@ -1300,6 +1300,10 @@
 static bool checkMemberDecomposition(Sema &S, ArrayRef Bindings,
  ValueDecl *Src, QualType DecompType,
  const CXXRecordDecl *OrigRD) {
+  if (S.RequireCompleteType(Src->getLocation(), DecompType,
+diag::err_incomplete_type))
+return true;
+
   CXXCastPath BasePath;
   DeclAccessPair BasePair =
   findDecomposableBaseClass(S, Src->getLocation(), OrigRD, BasePath);


Index: cfe/trunk/test/SemaCXX/cxx1z-decomposition.cpp
===
--- cfe/trunk/test/SemaCXX/cxx1z-decomposition.cpp
+++ cfe/trunk/test/SemaCXX/cxx1z-decomposition.cpp
@@ -81,4 +81,21 @@
   void f() { static auto [a] = *this; } // expected-error {{cannot be declared 'static'}}
 };
 
+namespace instantiate_template {
+
+template 
+struct pair {
+  T1 a;
+  T2 b;
+};
+
+const pair &f1();
+
+int f2() {
+  const auto &[a, b] = f1();
+  return a + b;
+}
+
+} // namespace instantiate_template
+
 // FIXME: by-value array copies
Index: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
===
--- cfe/trunk/lib/Sema/SemaDeclCXX.cpp
+++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp
@@ -1300,6 +1300,10 @@
 static bool checkMemberDecomposition(Sema &S, ArrayRef Bindings,
  ValueDecl *Src, QualType DecompType,
  const CXXRecordDecl *OrigRD) {
+  if (S.RequireCompleteType(Src->getLocation(), DecompType,
+diag::err_incomplete_type))
+return true;
+
   CXXCastPath BasePath;
   DeclAccessPair BasePair =
   findDecomposableBaseClass(S, Src->getLocation(), OrigRD, BasePath);
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D56974: [SemaCXX] Fix ICE with structure bindings to members of template

2019-01-27 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added a comment.

Backporting to 8.0.0 is possibly possible, you'll need to ping Hans. I don't 
know about previous versions though.


Repository:
  rL LLVM

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

https://reviews.llvm.org/D56974



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


[PATCH] D57540: [C++17] Don't crash while diagnosing different access specifier of a deduction guide.

2019-01-31 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete created this revision.
Rakete added a reviewer: rsmith.

This fixes PR40552 by not showing the diagnostic that complains about different 
access specifiers, since the template does not have one.


Repository:
  rC Clang

https://reviews.llvm.org/D57540

Files:
  lib/Sema/SemaDeclCXX.cpp
  test/SemaCXX/cxx1z-class-template-argument-deduction.cpp


Index: test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
===
--- test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
+++ test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
@@ -353,6 +353,13 @@
 template Protected(T) -> Protected; // expected-error 
{{different access}}
 template Private(T) -> Private; // expected-error 
{{different access}}
   };
+
+  // PR40552
+  template  struct Typo {}; // expected-note{{template is declared 
here}}
+  struct Type {
+Typo(); // expected-error{{deduction guide must be declared in the same 
scope}}
+// expected-error@-1{{deduction guide declaration without trailing return 
type}}
+  };
 }
 
 namespace rdar41903969 {
Index: lib/Sema/SemaDeclCXX.cpp
===
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -3175,7 +3175,7 @@
 //   declared] with the same access [as the template].
 if (auto *DG = dyn_cast(NonTemplateMember)) {
   auto *TD = DG->getDeducedTemplate();
-  if (AS != TD->getAccess()) {
+  if (AS != TD->getAccess() && TD->getAccess() != AS_none) {
 Diag(DG->getBeginLoc(), diag::err_deduction_guide_wrong_access);
 Diag(TD->getBeginLoc(), diag::note_deduction_guide_template_access)
 << TD->getAccess();


Index: test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
===
--- test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
+++ test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
@@ -353,6 +353,13 @@
 template Protected(T) -> Protected; // expected-error {{different access}}
 template Private(T) -> Private; // expected-error {{different access}}
   };
+
+  // PR40552
+  template  struct Typo {}; // expected-note{{template is declared here}}
+  struct Type {
+Typo(); // expected-error{{deduction guide must be declared in the same scope}}
+// expected-error@-1{{deduction guide declaration without trailing return type}}
+  };
 }
 
 namespace rdar41903969 {
Index: lib/Sema/SemaDeclCXX.cpp
===
--- lib/Sema/SemaDeclCXX.cpp
+++ lib/Sema/SemaDeclCXX.cpp
@@ -3175,7 +3175,7 @@
 //   declared] with the same access [as the template].
 if (auto *DG = dyn_cast(NonTemplateMember)) {
   auto *TD = DG->getDeducedTemplate();
-  if (AS != TD->getAccess()) {
+  if (AS != TD->getAccess() && TD->getAccess() != AS_none) {
 Diag(DG->getBeginLoc(), diag::err_deduction_guide_wrong_access);
 Diag(TD->getBeginLoc(), diag::note_deduction_guide_template_access)
 << TD->getAccess();
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D53847: [C++2a] P0634r3: Down with typename!

2018-11-01 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 172146.
Rakete marked 6 inline comments as done.
Rakete added a comment.

Addressed review comments! :)


Repository:
  rC Clang

https://reviews.llvm.org/D53847

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Parse/Parser.h
  include/clang/Sema/Scope.h
  include/clang/Sema/Sema.h
  lib/Parse/ParseDecl.cpp
  lib/Parse/ParseDeclCXX.cpp
  lib/Parse/ParseExprCXX.cpp
  lib/Parse/ParseTentative.cpp
  lib/Parse/Parser.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaLookup.cpp
  lib/Sema/SemaTemplate.cpp
  test/CXX/drs/dr1xx.cpp
  test/CXX/drs/dr2xx.cpp
  test/CXX/drs/dr4xx.cpp
  test/CXX/drs/dr5xx.cpp
  test/CXX/temp/temp.res/p5.cpp
  test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp
  test/FixIt/fixit.cpp
  test/SemaCXX/MicrosoftCompatibility.cpp
  test/SemaCXX/MicrosoftExtensions.cpp
  test/SemaCXX/MicrosoftSuper.cpp
  test/SemaCXX/unknown-type-name.cpp

Index: test/SemaCXX/unknown-type-name.cpp
===
--- test/SemaCXX/unknown-type-name.cpp
+++ test/SemaCXX/unknown-type-name.cpp
@@ -36,39 +36,39 @@
 
   static int n;
   static type m;
-  static int h(T::type, int); // expected-error{{missing 'typename'}}
-  static int h(T::type x, char); // expected-error{{missing 'typename'}}
+  static int h(T::type, int); // expected-warning {{implicit 'typename' is a C++2a extension}}
+  static int h(T::type x, char); // expected-warning {{implicit 'typename' is a C++2a extension}}
 };
 
 template
-A::type g(T t) { return t; } // expected-error{{missing 'typename'}}
+A::type g(T t) { return t; } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-A::type A::f() { return type(); } // expected-error{{missing 'typename'}}
+A::type A::f() { return type(); } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void f(T::type) { } // expected-error{{missing 'typename'}}
+void f(T::type) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void g(T::type x) { } // expected-error{{missing 'typename'}}
+void g(T::type x) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void f(T::type, int) { } // expected-error{{missing 'typename'}}
+void f(T::type, int) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void f(T::type x, char) { } // expected-error{{missing 'typename'}}
+void f(T::type x, char) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void f(int, T::type) { } // expected-error{{missing 'typename'}}
+void f(int, T::type) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void f(char, T::type x) { } // expected-error{{missing 'typename'}}
+void f(char, T::type x) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void f(int, T::type, int) { } // expected-error{{missing 'typename'}}
+void f(int, T::type, int) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 template
-void f(int, T::type x, char) { } // expected-error{{missing 'typename'}}
+void f(int, T::type x, char) { } // expected-warning {{implicit 'typename' is a C++2a extension}}
 
 int *p;
 
@@ -86,26 +86,26 @@
 
 template int A::n(T::value); // ok
 template
-A::type // expected-error{{missing 'typename'}}
+A::type // expected-warning {{implicit 'typename' is a C++2a extension}}
 A::m(T::value, 0); // ok
 
-template int A::h(T::type, int) {} // expected-error{{missing 'typename'}}
-template int A::h(T::type x, char) {} // expected-error{{missing 'typename'}}
+template int A::h(T::type, int) {} // expected-warning {{implicit 'typename' is a C++2a extension}}
+template int A::h(T::type x, char) {} // expected-warning {{implicit 'typename' is a C++2a extension}}
 
-template int h(T::type, int); // expected-error{{missing 'typename'}}
-template int h(T::type x, char); // expected-error{{missing 'typename'}}
+template int h(T::type, int); // expected-error {{missing 'typename'}}
+template int h(T::type x, char); // expected-error {{missing 'typename'}}
 
 template int junk1(T::junk);
 #if __cplusplus <= 201103L
 // expected-warning@-2 {{variable templates are a C++14 extension}}
 #endif
-template int junk2(T::junk) throw(); // expected-error{{missing 'typename'}}
-template int junk3(T::junk) = delete; // expected-error{{missing 'typename'}}
+template int junk2(T::junk) throw(); // expected-error {{missing 'typename'}}
+template int junk3(T::junk) = delete; // expected-warning {{implicit 'typename' is a C++2a extension}}
 #if __cplusplus <= 199711L
 //expected-warning@-2 {{deleted function definitions are a C++11 extension}}
 #endif
 
-template int junk4(T::junk j); // expected-error{{missing 'typename'}}
+template int junk4(T::junk j); // expected-error {{missing 'typename'}}
 
 // FIXME: We can tell this was intended to be a function because it does not
 //have a dependent nested na

[PATCH] D53847: [C++2a] P0634r3: Down with typename!

2018-11-01 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete marked 7 inline comments as done.
Rakete added inline comments.



Comment at: lib/Parse/Parser.cpp:1778
+/*IsClassTemplateDeductionContext*/true,
+/*AllowImplicitTypename*/false)) {
   SourceLocation BeginLoc = Tok.getLocation();

rsmith wrote:
> Don't we need to sometimes allow an implicit typename here for correct 
> disambiguation?
This is done elsewhere now. :)



Comment at: test/SemaCXX/unknown-type-name.cpp:50
 template
-void f(T::type) { } // expected-error{{missing 'typename'}}
+void f(T::type) { } // expected-warning {{implicit 'typename' is a C++2a 
extension}}
 

rsmith wrote:
> This is wrong.
> 
> ```
> template
> X f(T::type);
> ```
> 
> declares a variable template. This would be valid if the name `f` were a 
> //qualified-id//, and lookup for `f` found a function template, though.
> 
> (Same for the next 7 cases.)
I agree, but those are definitions, so the next 7 cases and this now are 
correct.



Comment at: test/SemaCXX/unknown-type-name.cpp:102-103
 #endif
-template int junk2(T::junk) throw(); // expected-error{{missing 
'typename'}}
-template int junk3(T::junk) = delete; // expected-error{{missing 
'typename'}}
+template int junk2(T::junk) throw(); // expected-warning 
{{implicit 'typename' is a C++2a extension}}
+template int junk3(T::junk) = delete; // expected-warning 
{{implicit 'typename' is a C++2a extension}}
 #if __cplusplus <= 199711L

rsmith wrote:
> These two are incorrect.
Only the first one is incorrect (i.e. doesn't have implicit typename). The 
second one does, because it's a function definition.


Repository:
  rC Clang

https://reviews.llvm.org/D53847



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


[PATCH] D53847: [C++2a] P0634r3: Down with typename!

2018-11-01 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 172147.
Rakete marked an inline comment as done.
Rakete added a comment.

Remove spaces to be consistent.


Repository:
  rC Clang

https://reviews.llvm.org/D53847

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Parse/Parser.h
  include/clang/Sema/Scope.h
  include/clang/Sema/Sema.h
  lib/Parse/ParseDecl.cpp
  lib/Parse/ParseDeclCXX.cpp
  lib/Parse/ParseExprCXX.cpp
  lib/Parse/ParseTentative.cpp
  lib/Parse/Parser.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaLookup.cpp
  lib/Sema/SemaTemplate.cpp
  test/CXX/drs/dr1xx.cpp
  test/CXX/drs/dr2xx.cpp
  test/CXX/drs/dr4xx.cpp
  test/CXX/drs/dr5xx.cpp
  test/CXX/temp/temp.res/p5.cpp
  test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp
  test/FixIt/fixit.cpp
  test/SemaCXX/MicrosoftCompatibility.cpp
  test/SemaCXX/MicrosoftExtensions.cpp
  test/SemaCXX/MicrosoftSuper.cpp
  test/SemaCXX/unknown-type-name.cpp

Index: test/SemaCXX/unknown-type-name.cpp
===
--- test/SemaCXX/unknown-type-name.cpp
+++ test/SemaCXX/unknown-type-name.cpp
@@ -36,39 +36,39 @@
 
   static int n;
   static type m;
-  static int h(T::type, int); // expected-error{{missing 'typename'}}
-  static int h(T::type x, char); // expected-error{{missing 'typename'}}
+  static int h(T::type, int); // expected-warning{{implicit 'typename' is a C++2a extension}}
+  static int h(T::type x, char); // expected-warning{{implicit 'typename' is a C++2a extension}}
 };
 
 template
-A::type g(T t) { return t; } // expected-error{{missing 'typename'}}
+A::type g(T t) { return t; } // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template
-A::type A::f() { return type(); } // expected-error{{missing 'typename'}}
+A::type A::f() { return type(); } // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template
-void f(T::type) { } // expected-error{{missing 'typename'}}
+void f(T::type) { } // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template
-void g(T::type x) { } // expected-error{{missing 'typename'}}
+void g(T::type x) { } // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template
-void f(T::type, int) { } // expected-error{{missing 'typename'}}
+void f(T::type, int) { } // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template
-void f(T::type x, char) { } // expected-error{{missing 'typename'}}
+void f(T::type x, char) { } // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template
-void f(int, T::type) { } // expected-error{{missing 'typename'}}
+void f(int, T::type) { } // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template
-void f(char, T::type x) { } // expected-error{{missing 'typename'}}
+void f(char, T::type x) { } // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template
-void f(int, T::type, int) { } // expected-error{{missing 'typename'}}
+void f(int, T::type, int) { } // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template
-void f(int, T::type x, char) { } // expected-error{{missing 'typename'}}
+void f(int, T::type x, char) { } // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 int *p;
 
@@ -86,11 +86,11 @@
 
 template int A::n(T::value); // ok
 template
-A::type // expected-error{{missing 'typename'}}
+A::type // expected-warning {{implicit 'typename' is a C++2a extension}}
 A::m(T::value, 0); // ok
 
-template int A::h(T::type, int) {} // expected-error{{missing 'typename'}}
-template int A::h(T::type x, char) {} // expected-error{{missing 'typename'}}
+template int A::h(T::type, int) {} // expected-warning{{implicit 'typename' is a C++2a extension}}
+template int A::h(T::type x, char) {} // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template int h(T::type, int); // expected-error{{missing 'typename'}}
 template int h(T::type x, char); // expected-error{{missing 'typename'}}
@@ -100,7 +100,7 @@
 // expected-warning@-2 {{variable templates are a C++14 extension}}
 #endif
 template int junk2(T::junk) throw(); // expected-error{{missing 'typename'}}
-template int junk3(T::junk) = delete; // expected-error{{missing 'typename'}}
+template int junk3(T::junk) = delete; // expected-warning{{implicit 'typename' is a C++2a extension}}
 #if __cplusplus <= 199711L
 //expected-warning@-2 {{deleted function definitions are a C++11 extension}}
 #endif
@@ -118,4 +118,5 @@
 // FIXME: We know which type specifier should have been specified here. Provide
 //a fix-it to add 'typename A::type'
 template
-A::g() { } // expected-error{{requires a type specifier}}
+A::g() { } // expected-error{{expected unqualified-id}}
+// expected-warning@-1{{implicit 'typename' is a C++2a extension}}
Index: test/SemaCXX/MicrosoftSuper.cpp
===
--- test/SemaCXX/MicrosoftSuper.cpp
+++ test/SemaCXX/MicrosoftSuper.cpp
@@ -108,8 +108,8 @@
   

[PATCH] D53847: [C++2a] P0634r3: Down with typename!

2018-11-01 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added inline comments.



Comment at: test/SemaCXX/unknown-type-name.cpp:50
 template
-void f(T::type) { } // expected-error{{missing 'typename'}}
+void f(T::type) { } // expected-warning {{implicit 'typename' is a C++2a 
extension}}
 

rsmith wrote:
> Rakete wrote:
> > rsmith wrote:
> > > This is wrong.
> > > 
> > > ```
> > > template
> > > X f(T::type);
> > > ```
> > > 
> > > declares a variable template. This would be valid if the name `f` were a 
> > > //qualified-id//, and lookup for `f` found a function template, though.
> > > 
> > > (Same for the next 7 cases.)
> > I agree, but those are definitions, so the next 7 cases and this now are 
> > correct.
> I think you've misunderstood the rule. The rule that I think you're referring 
> to is:
> 
> "A qualified-id is assumed to name a type if it is a decl-specifier of the 
> decl-specifier-seq of a simple-declaration or a function-definition in 
> namespace scope"
> 
> But the decl-specifier-seq is just the type *before* the function name, not 
> the parameter's types. There is no special case for function definitions.
Oh I did! Thanks. Let me update my revision :)


Repository:
  rC Clang

https://reviews.llvm.org/D53847



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


[PATCH] D53847: [C++2a] P0634r3: Down with typename!

2018-11-01 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 172218.
Rakete added a comment.

I'm pretty sure I implemented the rules correctly now :)


Repository:
  rC Clang

https://reviews.llvm.org/D53847

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Parse/Parser.h
  include/clang/Sema/Sema.h
  lib/Parse/ParseDecl.cpp
  lib/Parse/ParseDeclCXX.cpp
  lib/Parse/ParseExprCXX.cpp
  lib/Parse/ParseTentative.cpp
  lib/Parse/Parser.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaTemplate.cpp
  test/CXX/drs/dr1xx.cpp
  test/CXX/drs/dr2xx.cpp
  test/CXX/drs/dr4xx.cpp
  test/CXX/drs/dr5xx.cpp
  test/CXX/temp/temp.res/p5.cpp
  test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp
  test/FixIt/fixit.cpp
  test/SemaCXX/MicrosoftCompatibility.cpp
  test/SemaCXX/MicrosoftExtensions.cpp
  test/SemaCXX/MicrosoftSuper.cpp
  test/SemaCXX/unknown-type-name.cpp

Index: test/SemaCXX/unknown-type-name.cpp
===
--- test/SemaCXX/unknown-type-name.cpp
+++ test/SemaCXX/unknown-type-name.cpp
@@ -36,15 +36,15 @@
 
   static int n;
   static type m;
-  static int h(T::type, int); // expected-error{{missing 'typename'}}
-  static int h(T::type x, char); // expected-error{{missing 'typename'}}
+  static int h(T::type, int); // expected-warning{{implicit 'typename' is a C++2a extension}}
+  static int h(T::type x, char); // expected-warning{{implicit 'typename' is a C++2a extension}}
 };
 
 template
-A::type g(T t) { return t; } // expected-error{{missing 'typename'}}
+A::type g(T t) { return t; } // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template
-A::type A::f() { return type(); } // expected-error{{missing 'typename'}}
+A::type A::f() { return type(); } // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template
 void f(T::type) { } // expected-error{{missing 'typename'}}
@@ -86,11 +86,11 @@
 
 template int A::n(T::value); // ok
 template
-A::type // expected-error{{missing 'typename'}}
+A::type // expected-warning {{implicit 'typename' is a C++2a extension}}
 A::m(T::value, 0); // ok
 
-template int A::h(T::type, int) {} // expected-error{{missing 'typename'}}
-template int A::h(T::type x, char) {} // expected-error{{missing 'typename'}}
+template int A::h(T::type, int) {} // expected-warning{{implicit 'typename' is a C++2a extension}}
+template int A::h(T::type x, char) {} // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template int h(T::type, int); // expected-error{{missing 'typename'}}
 template int h(T::type x, char); // expected-error{{missing 'typename'}}
@@ -118,4 +118,5 @@
 // FIXME: We know which type specifier should have been specified here. Provide
 //a fix-it to add 'typename A::type'
 template
-A::g() { } // expected-error{{requires a type specifier}}
+A::g() { } // expected-error{{expected unqualified-id}}
+// expected-warning@-1{{implicit 'typename' is a C++2a extension}}
Index: test/SemaCXX/MicrosoftSuper.cpp
===
--- test/SemaCXX/MicrosoftSuper.cpp
+++ test/SemaCXX/MicrosoftSuper.cpp
@@ -108,8 +108,8 @@
   typename __super::XXX a;
   typedef typename __super::XXX b;
 
-  __super::XXX c; // expected-error {{missing 'typename'}}
-  typedef __super::XXX d; // expected-error {{missing 'typename'}}
+  __super::XXX c; // expected-warning {{implicit 'typename' is a C++2a extension}}
+  typedef __super::XXX d; // expected-warning {{implicit 'typename' is a C++2a extension}}
 
   void foo() {
 typename __super::XXX e;
@@ -127,8 +127,8 @@
   typename __super::XXX a;
   typedef typename __super::XXX b;
 
-  __super::XXX c; // expected-error {{missing 'typename'}}
-  typedef __super::XXX d; // expected-error {{missing 'typename'}}
+  __super::XXX c; // expected-warning {{implicit 'typename' is a C++2a extension}}
+  typedef __super::XXX d; // expected-warning {{implicit 'typename' is a C++2a extension}}
 
   void foo() {
 typename __super::XXX e;
Index: test/SemaCXX/MicrosoftExtensions.cpp
===
--- test/SemaCXX/MicrosoftExtensions.cpp
+++ test/SemaCXX/MicrosoftExtensions.cpp
@@ -526,7 +526,7 @@
 
 namespace PR32750 {
 template struct A {};
-template struct B : A> { A::C::D d; }; // expected-error {{missing 'typename' prior to dependent type name 'A::C::D'}}
+template struct B : A> { A::C::D d; }; // expected-warning {{implicit 'typename' is a C++2a extension}}
 }
 
 #else
Index: test/SemaCXX/MicrosoftCompatibility.cpp
===
--- test/SemaCXX/MicrosoftCompatibility.cpp
+++ test/SemaCXX/MicrosoftCompatibility.cpp
@@ -199,25 +199,25 @@
typedef B Base2;
typedef A Base3;
 
-   A::TYPE a1; // expected-warning {{missing 'typename' prior to dependent type name}}
-   Base1::TYPE a2; // expected-warning {{missing 'typename' prior to dependent type name}}
+   A::TYPE a1; // ex

[PATCH] D53847: [C++2a] P0634r3: Down with typename!

2018-11-07 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 173056.
Rakete added a comment.

Addressed review comments! :)


Repository:
  rC Clang

https://reviews.llvm.org/D53847

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Parse/Parser.h
  include/clang/Sema/Sema.h
  lib/Parse/ParseDecl.cpp
  lib/Parse/ParseDeclCXX.cpp
  lib/Parse/ParseExprCXX.cpp
  lib/Parse/ParseTentative.cpp
  lib/Parse/Parser.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaTemplate.cpp
  test/CXX/drs/dr1xx.cpp
  test/CXX/drs/dr2xx.cpp
  test/CXX/drs/dr4xx.cpp
  test/CXX/drs/dr5xx.cpp
  test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp
  test/FixIt/fixit.cpp
  test/Parser/editor-placeholder-recovery.cpp
  test/SemaCXX/MicrosoftCompatibility.cpp
  test/SemaCXX/MicrosoftExtensions.cpp
  test/SemaCXX/MicrosoftSuper.cpp
  test/SemaCXX/unknown-type-name.cpp

Index: test/SemaCXX/unknown-type-name.cpp
===
--- test/SemaCXX/unknown-type-name.cpp
+++ test/SemaCXX/unknown-type-name.cpp
@@ -36,15 +36,15 @@
 
   static int n;
   static type m;
-  static int h(T::type, int); // expected-error{{missing 'typename'}}
-  static int h(T::type x, char); // expected-error{{missing 'typename'}}
+  static int h(T::type, int); // expected-warning{{implicit 'typename' is a C++2a extension}}
+  static int h(T::type x, char); // expected-warning{{implicit 'typename' is a C++2a extension}}
 };
 
 template
-A::type g(T t) { return t; } // expected-error{{missing 'typename'}}
+A::type g(T t) { return t; } // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template
-A::type A::f() { return type(); } // expected-error{{missing 'typename'}}
+A::type A::f() { return type(); } // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template
 void f(T::type) { } // expected-error{{missing 'typename'}}
@@ -72,9 +72,7 @@
 
 int *p;
 
-// FIXME: We should assume that 'undeclared' is a type, not a parameter name
-//here, and produce an 'unknown type name' diagnostic instead.
-int f1(undeclared, int); // expected-error{{requires a type specifier}}
+int f1(undeclared, int); // expected-error{{unknown type name 'undeclared'}}
 
 int f2(undeclared, 0); // expected-error{{undeclared identifier}}
 
@@ -86,11 +84,11 @@
 
 template int A::n(T::value); // ok
 template
-A::type // expected-error{{missing 'typename'}}
+A::type // expected-warning {{implicit 'typename' is a C++2a extension}}
 A::m(T::value, 0); // ok
 
-template int A::h(T::type, int) {} // expected-error{{missing 'typename'}}
-template int A::h(T::type x, char) {} // expected-error{{missing 'typename'}}
+template int A::h(T::type, int) {} // expected-warning{{implicit 'typename' is a C++2a extension}}
+template int A::h(T::type x, char) {} // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template int h(T::type, int); // expected-error{{missing 'typename'}}
 template int h(T::type x, char); // expected-error{{missing 'typename'}}
@@ -118,4 +116,5 @@
 // FIXME: We know which type specifier should have been specified here. Provide
 //a fix-it to add 'typename A::type'
 template
-A::g() { } // expected-error{{requires a type specifier}}
+A::g() { } // expected-error{{expected unqualified-id}}
+// expected-warning@-1{{implicit 'typename' is a C++2a extension}}
Index: test/SemaCXX/MicrosoftSuper.cpp
===
--- test/SemaCXX/MicrosoftSuper.cpp
+++ test/SemaCXX/MicrosoftSuper.cpp
@@ -108,8 +108,8 @@
   typename __super::XXX a;
   typedef typename __super::XXX b;
 
-  __super::XXX c; // expected-error {{missing 'typename'}}
-  typedef __super::XXX d; // expected-error {{missing 'typename'}}
+  __super::XXX c; // expected-warning {{implicit 'typename' is a C++2a extension}}
+  typedef __super::XXX d; // expected-warning {{implicit 'typename' is a C++2a extension}}
 
   void foo() {
 typename __super::XXX e;
@@ -127,8 +127,8 @@
   typename __super::XXX a;
   typedef typename __super::XXX b;
 
-  __super::XXX c; // expected-error {{missing 'typename'}}
-  typedef __super::XXX d; // expected-error {{missing 'typename'}}
+  __super::XXX c; // expected-warning {{implicit 'typename' is a C++2a extension}}
+  typedef __super::XXX d; // expected-warning {{implicit 'typename' is a C++2a extension}}
 
   void foo() {
 typename __super::XXX e;
Index: test/SemaCXX/MicrosoftExtensions.cpp
===
--- test/SemaCXX/MicrosoftExtensions.cpp
+++ test/SemaCXX/MicrosoftExtensions.cpp
@@ -526,7 +526,7 @@
 
 namespace PR32750 {
 template struct A {};
-template struct B : A> { A::C::D d; }; // expected-error {{missing 'typename' prior to dependent type name 'A::C::D'}}
+template struct B : A> { A::C::D d; }; // expected-warning {{implicit 'typename' is a C++2a extension}}
 }
 
 #else
Index: test/SemaCXX/MicrosoftCompatibility.cpp
=

[PATCH] D53847: [C++2a] P0634r3: Down with typename!

2018-11-07 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete marked 9 inline comments as done.
Rakete added a comment.

I also found another diagnostic regression:

  template 
  T::type();

The previous error message was something with "nested name specifier does not 
refer to class ...". Now, the T::type part is interpreted as type and so we get 
a "expected unqualified-id" error message.




Comment at: include/clang/Parse/Parser.h:2119
   DeclSpecContext DSC = DeclSpecContext::DSC_normal,
-  LateParsedAttrList *LateAttrs = nullptr);
+  LateParsedAttrList *LateAttrs = nullptr) {
+return ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC, LateAttrs,

This overload is unnecessary; I accidentally included it. I'll change it later 
so that Phab doesn't lose the review comments.



Comment at: include/clang/Parse/Parser.h:2054
+case DeclSpecContext::DSC_template_param:
+case DeclSpecContext::DSC_template_type_arg:
+case DeclSpecContext::DSC_normal:

rsmith wrote:
> This doesn't seem right to me. Doesn't this mean that `X` will change 
> from being a non-type template argument to being a type template argument?
> 
> Maybe that's a bug in the wording paper, though, since that context *is* a 
> /type-id/.
AFAIK no it won't, but I can't really tell if that's the right behavior or not. 
This patch doesn't touch the `X` case.



Comment at: test/SemaCXX/unknown-type-name.cpp:121-122
 template
-A::g() { } // expected-error{{requires a type specifier}}
+A::g() { } // expected-error{{expected unqualified-id}}
+// expected-warning@-1{{implicit 'typename' is a C++2a extension}}

rsmith wrote:
> rsmith wrote:
> > This is a diagnostic quality regression. Perhaps that's an inevitable 
> > consequence of P0634, but we should at least try to do better.
> This is marked "done" but doesn't seem to be done?
Oops, don't know why I did that. I can't figure out a way to fix this. I can 
implement a basic heuristic to detect some very basic cases like this one, but 
I don't think it's worth it.


Repository:
  rC Clang

https://reviews.llvm.org/D53847



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


[PATCH] D54414: [Sema] Make sure we substitute an instantiation-dependent default template parameter

2018-11-12 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete accepted this revision.
Rakete added a comment.
This revision is now accepted and ready to land.

LGTM, thanks :)




Comment at: clang/test/SemaCXX/alias-template.cpp:188
+template >
+int sfinae_me() { return 0; } // expected-note{{candidate template ignored: 
substitution failure}}
+

Very nit: The whole file has a space between the expected string and {{.


Repository:
  rC Clang

https://reviews.llvm.org/D54414



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


[PATCH] D53847: [C++2a] P0634r3: Down with typename!

2018-11-14 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added inline comments.



Comment at: lib/Sema/Sema.cpp:2006-2019
+bool Sema::isDeclaratorFunctionLike(const Declarator &D) {
+  assert(D.getCXXScopeSpec().isSet() &&
+ "can only be called for qualified names");
+  LookupResult LR(*this, D.getIdentifier(), D.getBeginLoc(), 
LookupOrdinaryName,
+  ForVisibleRedeclaration);
+  DeclContext *DC = computeDeclContext(D.getCXXScopeSpec());
+  if (!DC)

rsmith wrote:
> Some thoughts on this:
> 
>  * Can this be unified with the lookup code in `HandleDeclarator`? This is 
> really the same lookup, repeated in two places.
>  * It'd be nice to cache this lookup, rather than performing it three times 
> (once when disambiguating a parenthesized initializer from a function 
> declaration, once when we're about to parse a parameter-declaration-clause, 
> and once in `HandleDeclarator` after parsing completes -- though at least 
> that's reduced to two lookups if you make the change I suggested in 
> `ParseParameterDeclarationClause`)
>  * If we don't do the caching, what happens if lookup fails due to ambiguity? 
> Do we get the same error multiple times (once for each time we perform the 
> lookup)?
I don't think so, because `HandleDeclarator` is called after having already 
parsed the function declaration. I cached it now, but the cleanest solution 
that I could think of is to use `new`. Is this appropriate? Or do you have an 
alternative suggestion?


Repository:
  rC Clang

https://reviews.llvm.org/D53847



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


[PATCH] D53847: [C++2a] P0634r3: Down with typename!

2018-11-14 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 174158.
Rakete marked 11 inline comments as done.
Rakete added a comment.

Addressed review comments :)


Repository:
  rC Clang

https://reviews.llvm.org/D53847

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Parse/Parser.h
  include/clang/Sema/DeclSpec.h
  include/clang/Sema/Sema.h
  lib/Parse/ParseDecl.cpp
  lib/Parse/ParseDeclCXX.cpp
  lib/Parse/ParseExprCXX.cpp
  lib/Parse/ParseTemplate.cpp
  lib/Parse/ParseTentative.cpp
  lib/Parse/Parser.cpp
  lib/Sema/DeclSpec.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaTemplate.cpp
  test/CXX/drs/dr1xx.cpp
  test/CXX/drs/dr2xx.cpp
  test/CXX/drs/dr4xx.cpp
  test/CXX/drs/dr5xx.cpp
  test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp
  test/FixIt/fixit.cpp
  test/Parser/cxx-member-initializers.cpp
  test/Parser/editor-placeholder-recovery.cpp
  test/SemaCXX/MicrosoftCompatibility.cpp
  test/SemaCXX/MicrosoftExtensions.cpp
  test/SemaCXX/MicrosoftSuper.cpp
  test/SemaCXX/unknown-type-name.cpp

Index: test/SemaCXX/unknown-type-name.cpp
===
--- test/SemaCXX/unknown-type-name.cpp
+++ test/SemaCXX/unknown-type-name.cpp
@@ -36,15 +36,15 @@
 
   static int n;
   static type m;
-  static int h(T::type, int); // expected-error{{missing 'typename'}}
-  static int h(T::type x, char); // expected-error{{missing 'typename'}}
+  static int h(T::type, int); // expected-warning{{implicit 'typename' is a C++2a extension}}
+  static int h(T::type x, char); // expected-warning{{implicit 'typename' is a C++2a extension}}
 };
 
 template
-A::type g(T t) { return t; } // expected-error{{missing 'typename'}}
+A::type g(T t) { return t; } // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template
-A::type A::f() { return type(); } // expected-error{{missing 'typename'}}
+A::type A::f() { return type(); } // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template
 void f(T::type) { } // expected-error{{missing 'typename'}}
@@ -72,9 +72,7 @@
 
 int *p;
 
-// FIXME: We should assume that 'undeclared' is a type, not a parameter name
-//here, and produce an 'unknown type name' diagnostic instead.
-int f1(undeclared, int); // expected-error{{requires a type specifier}}
+int f1(undeclared, int); // expected-error{{unknown type name 'undeclared'}}
 
 int f2(undeclared, 0); // expected-error{{undeclared identifier}}
 
@@ -86,11 +84,11 @@
 
 template int A::n(T::value); // ok
 template
-A::type // expected-error{{missing 'typename'}}
+A::type // expected-warning {{implicit 'typename' is a C++2a extension}}
 A::m(T::value, 0); // ok
 
-template int A::h(T::type, int) {} // expected-error{{missing 'typename'}}
-template int A::h(T::type x, char) {} // expected-error{{missing 'typename'}}
+template int A::h(T::type, int) {} // expected-warning{{implicit 'typename' is a C++2a extension}}
+template int A::h(T::type x, char) {} // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template int h(T::type, int); // expected-error{{missing 'typename'}}
 template int h(T::type x, char); // expected-error{{missing 'typename'}}
@@ -118,4 +116,5 @@
 // FIXME: We know which type specifier should have been specified here. Provide
 //a fix-it to add 'typename A::type'
 template
-A::g() { } // expected-error{{requires a type specifier}}
+A::g() { } // expected-error{{expected unqualified-id}}
+// expected-warning@-1{{implicit 'typename' is a C++2a extension}}
Index: test/SemaCXX/MicrosoftSuper.cpp
===
--- test/SemaCXX/MicrosoftSuper.cpp
+++ test/SemaCXX/MicrosoftSuper.cpp
@@ -108,8 +108,8 @@
   typename __super::XXX a;
   typedef typename __super::XXX b;
 
-  __super::XXX c; // expected-error {{missing 'typename'}}
-  typedef __super::XXX d; // expected-error {{missing 'typename'}}
+  __super::XXX c; // expected-warning {{implicit 'typename' is a C++2a extension}}
+  typedef __super::XXX d; // expected-warning {{implicit 'typename' is a C++2a extension}}
 
   void foo() {
 typename __super::XXX e;
@@ -127,8 +127,8 @@
   typename __super::XXX a;
   typedef typename __super::XXX b;
 
-  __super::XXX c; // expected-error {{missing 'typename'}}
-  typedef __super::XXX d; // expected-error {{missing 'typename'}}
+  __super::XXX c; // expected-warning {{implicit 'typename' is a C++2a extension}}
+  typedef __super::XXX d; // expected-warning {{implicit 'typename' is a C++2a extension}}
 
   void foo() {
 typename __super::XXX e;
Index: test/SemaCXX/MicrosoftExtensions.cpp
===
--- test/SemaCXX/MicrosoftExtensions.cpp
+++ test/SemaCXX/MicrosoftExtensions.cpp
@@ -526,7 +526,7 @@
 
 namespace PR32750 {
 template struct A {};
-template struct B : A> { A::C::D d; }; // expected-error {{missing 'typename' prior to dependent type name 'A::C::D'}}
+tem

[PATCH] D53847: [C++2a] P0634r3: Down with typename!

2018-11-14 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added inline comments.



Comment at: include/clang/Parse/Parser.h:2119
   DeclSpecContext DSC = DeclSpecContext::DSC_normal,
-  LateParsedAttrList *LateAttrs = nullptr);
+  LateParsedAttrList *LateAttrs = nullptr) {
+return ParseDeclarationSpecifiers(DS, TemplateInfo, AS, DSC, LateAttrs,

Rakete wrote:
> This overload is unnecessary; I accidentally included it. I'll change it 
> later so that Phab doesn't lose the review comments.
Actually, it's less repetitive if I leave it. So I'll just leave it be.


Repository:
  rC Clang

https://reviews.llvm.org/D53847



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


[PATCH] D53847: [C++2a] P0634r3: Down with typename!

2018-11-27 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 175553.
Rakete added a comment.

Rebase and friendly ping! :)


Repository:
  rC Clang

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

https://reviews.llvm.org/D53847

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Parse/Parser.h
  include/clang/Sema/DeclSpec.h
  include/clang/Sema/Sema.h
  lib/Parse/ParseDecl.cpp
  lib/Parse/ParseDeclCXX.cpp
  lib/Parse/ParseExprCXX.cpp
  lib/Parse/ParseTemplate.cpp
  lib/Parse/ParseTentative.cpp
  lib/Parse/Parser.cpp
  lib/Sema/DeclSpec.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaTemplate.cpp
  test/CXX/drs/dr1xx.cpp
  test/CXX/drs/dr2xx.cpp
  test/CXX/drs/dr4xx.cpp
  test/CXX/drs/dr5xx.cpp
  test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp
  test/FixIt/fixit.cpp
  test/Parser/cxx-member-initializers.cpp
  test/Parser/editor-placeholder-recovery.cpp
  test/SemaCXX/MicrosoftCompatibility.cpp
  test/SemaCXX/MicrosoftExtensions.cpp
  test/SemaCXX/MicrosoftSuper.cpp
  test/SemaCXX/unknown-type-name.cpp

Index: test/SemaCXX/unknown-type-name.cpp
===
--- test/SemaCXX/unknown-type-name.cpp
+++ test/SemaCXX/unknown-type-name.cpp
@@ -36,15 +36,15 @@
 
   static int n;
   static type m;
-  static int h(T::type, int); // expected-error{{missing 'typename'}}
-  static int h(T::type x, char); // expected-error{{missing 'typename'}}
+  static int h(T::type, int); // expected-warning{{implicit 'typename' is a C++2a extension}}
+  static int h(T::type x, char); // expected-warning{{implicit 'typename' is a C++2a extension}}
 };
 
 template
-A::type g(T t) { return t; } // expected-error{{missing 'typename'}}
+A::type g(T t) { return t; } // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template
-A::type A::f() { return type(); } // expected-error{{missing 'typename'}}
+A::type A::f() { return type(); } // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template
 void f(T::type) { } // expected-error{{missing 'typename'}}
@@ -72,9 +72,7 @@
 
 int *p;
 
-// FIXME: We should assume that 'undeclared' is a type, not a parameter name
-//here, and produce an 'unknown type name' diagnostic instead.
-int f1(undeclared, int); // expected-error{{requires a type specifier}}
+int f1(undeclared, int); // expected-error{{unknown type name 'undeclared'}}
 
 int f2(undeclared, 0); // expected-error{{undeclared identifier}}
 
@@ -86,11 +84,11 @@
 
 template int A::n(T::value); // ok
 template
-A::type // expected-error{{missing 'typename'}}
+A::type // expected-warning {{implicit 'typename' is a C++2a extension}}
 A::m(T::value, 0); // ok
 
-template int A::h(T::type, int) {} // expected-error{{missing 'typename'}}
-template int A::h(T::type x, char) {} // expected-error{{missing 'typename'}}
+template int A::h(T::type, int) {} // expected-warning{{implicit 'typename' is a C++2a extension}}
+template int A::h(T::type x, char) {} // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template int h(T::type, int); // expected-error{{missing 'typename'}}
 template int h(T::type x, char); // expected-error{{missing 'typename'}}
@@ -118,4 +116,5 @@
 // FIXME: We know which type specifier should have been specified here. Provide
 //a fix-it to add 'typename A::type'
 template
-A::g() { } // expected-error{{requires a type specifier}}
+A::g() { } // expected-error{{expected unqualified-id}}
+// expected-warning@-1{{implicit 'typename' is a C++2a extension}}
Index: test/SemaCXX/MicrosoftSuper.cpp
===
--- test/SemaCXX/MicrosoftSuper.cpp
+++ test/SemaCXX/MicrosoftSuper.cpp
@@ -108,8 +108,8 @@
   typename __super::XXX a;
   typedef typename __super::XXX b;
 
-  __super::XXX c; // expected-error {{missing 'typename'}}
-  typedef __super::XXX d; // expected-error {{missing 'typename'}}
+  __super::XXX c; // expected-warning {{implicit 'typename' is a C++2a extension}}
+  typedef __super::XXX d; // expected-warning {{implicit 'typename' is a C++2a extension}}
 
   void foo() {
 typename __super::XXX e;
@@ -127,8 +127,8 @@
   typename __super::XXX a;
   typedef typename __super::XXX b;
 
-  __super::XXX c; // expected-error {{missing 'typename'}}
-  typedef __super::XXX d; // expected-error {{missing 'typename'}}
+  __super::XXX c; // expected-warning {{implicit 'typename' is a C++2a extension}}
+  typedef __super::XXX d; // expected-warning {{implicit 'typename' is a C++2a extension}}
 
   void foo() {
 typename __super::XXX e;
Index: test/SemaCXX/MicrosoftExtensions.cpp
===
--- test/SemaCXX/MicrosoftExtensions.cpp
+++ test/SemaCXX/MicrosoftExtensions.cpp
@@ -526,7 +526,7 @@
 
 namespace PR32750 {
 template struct A {};
-template struct B : A> { A::C::D d; }; // expected-error {{missing 'typename' prior to dependent type n

[PATCH] D55039: [sema] Warn of mangling change if function parameters are noexcept.

2018-11-28 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added a comment.

You're missing the case of the function return type of a parameter.

  void f(void (*g())() noexcept); // no warning with trunk nor with your patch


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

https://reviews.llvm.org/D55039



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


[PATCH] D55039: [sema] Warn of mangling change if function parameters are noexcept.

2018-12-03 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added inline comments.



Comment at: lib/Sema/SemaDecl.cpp:9933
+llvm::any_of(FPT->param_types(),
+ [](QualType Q) { return hasNoexcept(Q); }))
+  return true;

You don't need this lambda.



Comment at: lib/Sema/SemaDecl.cpp:10266
   auto *FPT = NewFD->getType()->castAs();
-  bool AnyNoexcept = HasNoexcept(FPT->getReturnType());
-  for (QualType T : FPT->param_types())
-AnyNoexcept |= HasNoexcept(T);
-  if (AnyNoexcept)
+  if (hasNoexcept(FPT->getReturnType()) ||
+  llvm::any_of(FPT->param_types(),

What you're doing here is a subset of what `hasNoexcept` is doing for function 
types. Do you think it would make sense to use `!FPT->isNothrow() && 
hasNoexcept(NewFW->getType())` or something like that?



Comment at: lib/Sema/SemaDecl.cpp:10268
+  llvm::any_of(FPT->param_types(),
+   [](QualType Q) { return hasNoexcept(Q); })) {
 Diag(NewFD->getLocation(),

Same, that lambda is unnecessary.


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

https://reviews.llvm.org/D55039



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


[PATCH] D53847: [C++2a] P0634r3: Down with typename!

2018-12-04 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 176554.
Rakete added a comment.

Rebase + friendly ping :)


Repository:
  rC Clang

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

https://reviews.llvm.org/D53847

Files:
  include/clang/Basic/DiagnosticSemaKinds.td
  include/clang/Parse/Parser.h
  include/clang/Sema/DeclSpec.h
  include/clang/Sema/Sema.h
  lib/Parse/ParseDecl.cpp
  lib/Parse/ParseDeclCXX.cpp
  lib/Parse/ParseExprCXX.cpp
  lib/Parse/ParseTemplate.cpp
  lib/Parse/ParseTentative.cpp
  lib/Parse/Parser.cpp
  lib/Sema/DeclSpec.cpp
  lib/Sema/Sema.cpp
  lib/Sema/SemaDecl.cpp
  lib/Sema/SemaTemplate.cpp
  test/CXX/drs/dr1xx.cpp
  test/CXX/drs/dr2xx.cpp
  test/CXX/drs/dr4xx.cpp
  test/CXX/drs/dr5xx.cpp
  test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp
  test/FixIt/fixit.cpp
  test/Parser/cxx-member-initializers.cpp
  test/Parser/editor-placeholder-recovery.cpp
  test/SemaCXX/MicrosoftCompatibility.cpp
  test/SemaCXX/MicrosoftExtensions.cpp
  test/SemaCXX/MicrosoftSuper.cpp
  test/SemaCXX/unknown-type-name.cpp

Index: test/SemaCXX/unknown-type-name.cpp
===
--- test/SemaCXX/unknown-type-name.cpp
+++ test/SemaCXX/unknown-type-name.cpp
@@ -36,15 +36,15 @@
 
   static int n;
   static type m;
-  static int h(T::type, int); // expected-error{{missing 'typename'}}
-  static int h(T::type x, char); // expected-error{{missing 'typename'}}
+  static int h(T::type, int); // expected-warning{{implicit 'typename' is a C++2a extension}}
+  static int h(T::type x, char); // expected-warning{{implicit 'typename' is a C++2a extension}}
 };
 
 template
-A::type g(T t) { return t; } // expected-error{{missing 'typename'}}
+A::type g(T t) { return t; } // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template
-A::type A::f() { return type(); } // expected-error{{missing 'typename'}}
+A::type A::f() { return type(); } // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template
 void f(T::type) { } // expected-error{{missing 'typename'}}
@@ -72,9 +72,7 @@
 
 int *p;
 
-// FIXME: We should assume that 'undeclared' is a type, not a parameter name
-//here, and produce an 'unknown type name' diagnostic instead.
-int f1(undeclared, int); // expected-error{{requires a type specifier}}
+int f1(undeclared, int); // expected-error{{unknown type name 'undeclared'}}
 
 int f2(undeclared, 0); // expected-error{{undeclared identifier}}
 
@@ -86,11 +84,11 @@
 
 template int A::n(T::value); // ok
 template
-A::type // expected-error{{missing 'typename'}}
+A::type // expected-warning {{implicit 'typename' is a C++2a extension}}
 A::m(T::value, 0); // ok
 
-template int A::h(T::type, int) {} // expected-error{{missing 'typename'}}
-template int A::h(T::type x, char) {} // expected-error{{missing 'typename'}}
+template int A::h(T::type, int) {} // expected-warning{{implicit 'typename' is a C++2a extension}}
+template int A::h(T::type x, char) {} // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template int h(T::type, int); // expected-error{{missing 'typename'}}
 template int h(T::type x, char); // expected-error{{missing 'typename'}}
@@ -118,4 +116,5 @@
 // FIXME: We know which type specifier should have been specified here. Provide
 //a fix-it to add 'typename A::type'
 template
-A::g() { } // expected-error{{requires a type specifier}}
+A::g() { } // expected-error{{expected unqualified-id}}
+// expected-warning@-1{{implicit 'typename' is a C++2a extension}}
Index: test/SemaCXX/MicrosoftSuper.cpp
===
--- test/SemaCXX/MicrosoftSuper.cpp
+++ test/SemaCXX/MicrosoftSuper.cpp
@@ -108,8 +108,8 @@
   typename __super::XXX a;
   typedef typename __super::XXX b;
 
-  __super::XXX c; // expected-error {{missing 'typename'}}
-  typedef __super::XXX d; // expected-error {{missing 'typename'}}
+  __super::XXX c; // expected-warning {{implicit 'typename' is a C++2a extension}}
+  typedef __super::XXX d; // expected-warning {{implicit 'typename' is a C++2a extension}}
 
   void foo() {
 typename __super::XXX e;
@@ -127,8 +127,8 @@
   typename __super::XXX a;
   typedef typename __super::XXX b;
 
-  __super::XXX c; // expected-error {{missing 'typename'}}
-  typedef __super::XXX d; // expected-error {{missing 'typename'}}
+  __super::XXX c; // expected-warning {{implicit 'typename' is a C++2a extension}}
+  typedef __super::XXX d; // expected-warning {{implicit 'typename' is a C++2a extension}}
 
   void foo() {
 typename __super::XXX e;
Index: test/SemaCXX/MicrosoftExtensions.cpp
===
--- test/SemaCXX/MicrosoftExtensions.cpp
+++ test/SemaCXX/MicrosoftExtensions.cpp
@@ -526,7 +526,7 @@
 
 namespace PR32750 {
 template struct A {};
-template struct B : A> { A::C::D d; }; // expected-error {{missing 'typename' prior to dependent type name

[PATCH] D53847: [C++2a] P0634r3: Down with typename!

2019-03-10 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 190012.
Rakete added a comment.
Herald added a subscriber: jdoerfert.
Herald added a project: clang.

Fix a bug where `T::value` inside a functional cast in a template argument 
would be interpreted as a function type.

Also added the missing test file that got lost in a previous revision for some 
reason. :)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D53847

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/DeclSpec.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExprCXX.cpp
  clang/lib/Parse/ParseTemplate.cpp
  clang/lib/Parse/ParseTentative.cpp
  clang/lib/Parse/Parser.cpp
  clang/lib/Sema/DeclSpec.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaTemplate.cpp
  clang/test/CXX/drs/dr1xx.cpp
  clang/test/CXX/drs/dr2xx.cpp
  clang/test/CXX/drs/dr4xx.cpp
  clang/test/CXX/drs/dr5xx.cpp
  clang/test/CXX/temp/temp.res/p5.cpp
  clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp
  clang/test/FixIt/fixit.cpp
  clang/test/Parser/cxx-member-initializers.cpp
  clang/test/Parser/editor-placeholder-recovery.cpp
  clang/test/SemaCXX/MicrosoftCompatibility.cpp
  clang/test/SemaCXX/MicrosoftExtensions.cpp
  clang/test/SemaCXX/MicrosoftSuper.cpp
  clang/test/SemaCXX/unknown-type-name.cpp

Index: clang/test/SemaCXX/unknown-type-name.cpp
===
--- clang/test/SemaCXX/unknown-type-name.cpp
+++ clang/test/SemaCXX/unknown-type-name.cpp
@@ -36,15 +36,15 @@
 
   static int n;
   static type m;
-  static int h(T::type, int); // expected-error{{missing 'typename'}}
-  static int h(T::type x, char); // expected-error{{missing 'typename'}}
+  static int h(T::type, int); // expected-warning{{implicit 'typename' is a C++2a extension}}
+  static int h(T::type x, char); // expected-warning{{implicit 'typename' is a C++2a extension}}
 };
 
 template
-A::type g(T t) { return t; } // expected-error{{missing 'typename'}}
+A::type g(T t) { return t; } // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template
-A::type A::f() { return type(); } // expected-error{{missing 'typename'}}
+A::type A::f() { return type(); } // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template
 void f(T::type) { } // expected-error{{missing 'typename'}}
@@ -72,9 +72,7 @@
 
 int *p;
 
-// FIXME: We should assume that 'undeclared' is a type, not a parameter name
-//here, and produce an 'unknown type name' diagnostic instead.
-int f1(undeclared, int); // expected-error{{requires a type specifier}}
+int f1(undeclared, int); // expected-error{{unknown type name 'undeclared'}}
 
 int f2(undeclared, 0); // expected-error{{undeclared identifier}}
 
@@ -86,11 +84,11 @@
 
 template int A::n(T::value); // ok
 template
-A::type // expected-error{{missing 'typename'}}
+A::type // expected-warning {{implicit 'typename' is a C++2a extension}}
 A::m(T::value, 0); // ok
 
-template int A::h(T::type, int) {} // expected-error{{missing 'typename'}}
-template int A::h(T::type x, char) {} // expected-error{{missing 'typename'}}
+template int A::h(T::type, int) {} // expected-warning{{implicit 'typename' is a C++2a extension}}
+template int A::h(T::type x, char) {} // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template int h(T::type, int); // expected-error{{missing 'typename'}}
 template int h(T::type x, char); // expected-error{{missing 'typename'}}
@@ -118,4 +116,5 @@
 // FIXME: We know which type specifier should have been specified here. Provide
 //a fix-it to add 'typename A::type'
 template
-A::g() { } // expected-error{{requires a type specifier}}
+A::g() { } // expected-error{{expected unqualified-id}}
+// expected-warning@-1{{implicit 'typename' is a C++2a extension}}
Index: clang/test/SemaCXX/MicrosoftSuper.cpp
===
--- clang/test/SemaCXX/MicrosoftSuper.cpp
+++ clang/test/SemaCXX/MicrosoftSuper.cpp
@@ -108,8 +108,8 @@
   typename __super::XXX a;
   typedef typename __super::XXX b;
 
-  __super::XXX c; // expected-error {{missing 'typename'}}
-  typedef __super::XXX d; // expected-error {{missing 'typename'}}
+  __super::XXX c; // expected-warning {{implicit 'typename' is a C++2a extension}}
+  typedef __super::XXX d; // expected-warning {{implicit 'typename' is a C++2a extension}}
 
   void foo() {
 typename __super::XXX e;
@@ -127,8 +127,8 @@
   typename __super::XXX a;
   typedef typename __super::XXX b;
 
-  __super::XXX c; // expected-error {{missing 'typename'}}
-  typedef __super::XXX d; // expected-error {{missing 'typename'}}
+  __super::XXX c; // expected-warning {{implicit 'typename' is a C++2a extension}}
+  typedef

[PATCH] D53847: [C++2a] P0634r3: Down with typename!

2019-03-10 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added a comment.

rsmith:

> Some thoughts on this:
> 
> - Can this be unified with the lookup code in HandleDeclarator? This is 
> really the same lookup, repeated in two places.

What I wrote:

> I don't think so, because HandleDeclarator is called after having already 
> parsed the function declaration. I cached it now, but the cleanest solution 
> that I could think of is to use new. Is this appropriate? Or do you have an 
> alternative suggestion?

Maybe a `llvm::Optional` is more appropriate?

> - It'd be nice to cache this lookup, rather than performing it three times 
> (once when disambiguating a parenthesized initializer from a function 
> declaration, once when we're about to parse a parameter-declaration-clause, 
> and once in HandleDeclarator after parsing completes -- though at least 
> that's reduced to two lookups if you make the change I suggested in 
> ParseParameterDeclarationClause)

Hmm let me see what I can do about that.

> - If we don't do the caching, what happens if lookup fails due to ambiguity? 
> Do we get the same error multiple times (once for each time we perform the 
> lookup)?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D53847



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


[PATCH] D53847: [C++2a] P0634r3: Down with typename!

2019-03-10 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 190013.
Rakete added a comment.

Don't relookup the qualified-id and use the cached one instead if possible.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D53847

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/DeclSpec.h
  clang/include/clang/Sema/Sema.h
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Parse/ParseExprCXX.cpp
  clang/lib/Parse/ParseTemplate.cpp
  clang/lib/Parse/ParseTentative.cpp
  clang/lib/Parse/Parser.cpp
  clang/lib/Sema/DeclSpec.cpp
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaTemplate.cpp
  clang/test/CXX/drs/dr1xx.cpp
  clang/test/CXX/drs/dr2xx.cpp
  clang/test/CXX/drs/dr4xx.cpp
  clang/test/CXX/drs/dr5xx.cpp
  clang/test/CXX/temp/temp.res/p5.cpp
  clang/test/CXX/temp/temp.res/temp.dep/temp.dep.type/p1.cpp
  clang/test/FixIt/fixit.cpp
  clang/test/Parser/cxx-member-initializers.cpp
  clang/test/Parser/editor-placeholder-recovery.cpp
  clang/test/SemaCXX/MicrosoftCompatibility.cpp
  clang/test/SemaCXX/MicrosoftExtensions.cpp
  clang/test/SemaCXX/MicrosoftSuper.cpp
  clang/test/SemaCXX/unknown-type-name.cpp

Index: clang/test/SemaCXX/unknown-type-name.cpp
===
--- clang/test/SemaCXX/unknown-type-name.cpp
+++ clang/test/SemaCXX/unknown-type-name.cpp
@@ -36,15 +36,15 @@
 
   static int n;
   static type m;
-  static int h(T::type, int); // expected-error{{missing 'typename'}}
-  static int h(T::type x, char); // expected-error{{missing 'typename'}}
+  static int h(T::type, int); // expected-warning{{implicit 'typename' is a C++2a extension}}
+  static int h(T::type x, char); // expected-warning{{implicit 'typename' is a C++2a extension}}
 };
 
 template
-A::type g(T t) { return t; } // expected-error{{missing 'typename'}}
+A::type g(T t) { return t; } // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template
-A::type A::f() { return type(); } // expected-error{{missing 'typename'}}
+A::type A::f() { return type(); } // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template
 void f(T::type) { } // expected-error{{missing 'typename'}}
@@ -72,9 +72,7 @@
 
 int *p;
 
-// FIXME: We should assume that 'undeclared' is a type, not a parameter name
-//here, and produce an 'unknown type name' diagnostic instead.
-int f1(undeclared, int); // expected-error{{requires a type specifier}}
+int f1(undeclared, int); // expected-error{{unknown type name 'undeclared'}}
 
 int f2(undeclared, 0); // expected-error{{undeclared identifier}}
 
@@ -86,11 +84,11 @@
 
 template int A::n(T::value); // ok
 template
-A::type // expected-error{{missing 'typename'}}
+A::type // expected-warning {{implicit 'typename' is a C++2a extension}}
 A::m(T::value, 0); // ok
 
-template int A::h(T::type, int) {} // expected-error{{missing 'typename'}}
-template int A::h(T::type x, char) {} // expected-error{{missing 'typename'}}
+template int A::h(T::type, int) {} // expected-warning{{implicit 'typename' is a C++2a extension}}
+template int A::h(T::type x, char) {} // expected-warning{{implicit 'typename' is a C++2a extension}}
 
 template int h(T::type, int); // expected-error{{missing 'typename'}}
 template int h(T::type x, char); // expected-error{{missing 'typename'}}
@@ -118,4 +116,5 @@
 // FIXME: We know which type specifier should have been specified here. Provide
 //a fix-it to add 'typename A::type'
 template
-A::g() { } // expected-error{{requires a type specifier}}
+A::g() { } // expected-error{{expected unqualified-id}}
+// expected-warning@-1{{implicit 'typename' is a C++2a extension}}
Index: clang/test/SemaCXX/MicrosoftSuper.cpp
===
--- clang/test/SemaCXX/MicrosoftSuper.cpp
+++ clang/test/SemaCXX/MicrosoftSuper.cpp
@@ -108,8 +108,8 @@
   typename __super::XXX a;
   typedef typename __super::XXX b;
 
-  __super::XXX c; // expected-error {{missing 'typename'}}
-  typedef __super::XXX d; // expected-error {{missing 'typename'}}
+  __super::XXX c; // expected-warning {{implicit 'typename' is a C++2a extension}}
+  typedef __super::XXX d; // expected-warning {{implicit 'typename' is a C++2a extension}}
 
   void foo() {
 typename __super::XXX e;
@@ -127,8 +127,8 @@
   typename __super::XXX a;
   typedef typename __super::XXX b;
 
-  __super::XXX c; // expected-error {{missing 'typename'}}
-  typedef __super::XXX d; // expected-error {{missing 'typename'}}
+  __super::XXX c; // expected-warning {{implicit 'typename' is a C++2a extension}}
+  typedef __super::XXX d; // expected-warning {{implicit 'typename' is a C++2a extension}}
 
   void foo() {
 typename __super::XXX e;
Index: clang/test/SemaCXX/MicrosoftExtensions.cpp
==

[PATCH] D36357: Added a better diagnostic when using the delete operator with lambdas

2019-03-13 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete updated this revision to Diff 190435.
Rakete added a comment.

Rebase + friendly ping :).


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D36357

Files:
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/lib/Parse/ParseExprCXX.cpp
  clang/test/FixIt/fixit-cxx0x.cpp
  clang/test/Parser/cxx0x-lambda-expressions.cpp
  clang/test/SemaCXX/new-delete-0x.cpp

Index: clang/test/SemaCXX/new-delete-0x.cpp
===
--- clang/test/SemaCXX/new-delete-0x.cpp
+++ clang/test/SemaCXX/new-delete-0x.cpp
@@ -34,6 +34,6 @@
 void bad_deletes()
 {
   // 'delete []' is always array delete, per [expr.delete]p1.
-  // FIXME: Give a better diagnostic.
-  delete []{ return (int*)0; }(); // expected-error {{expected expression}}
+  delete []{ return (int*)0; }(); // expected-error {{'[]' after delete interpreted as 'delete[]'}}
 }
+
Index: clang/test/Parser/cxx0x-lambda-expressions.cpp
===
--- clang/test/Parser/cxx0x-lambda-expressions.cpp
+++ clang/test/Parser/cxx0x-lambda-expressions.cpp
@@ -53,8 +53,11 @@
   void delete_lambda(int *p) {
 delete [] p;
 delete [] (int*) { new int }; // ok, compound-literal, not lambda
-delete [] { return new int; } (); // expected-error{{expected expression}}
+delete [] { return new int; } (); // expected-error {{'[]' after delete interpreted as 'delete[]'}}
 delete [&] { return new int; } (); // ok, lambda
+
+delete []() { return new int; }(); // expected-error{{'[]' after delete interpreted as 'delete[]'}}
+delete [](E Enum) { return new int((int)Enum); }(e); // expected-error{{'[]' after delete interpreted as 'delete[]'}}
   }
 
   // We support init-captures in C++11 as an extension.
Index: clang/test/FixIt/fixit-cxx0x.cpp
===
--- clang/test/FixIt/fixit-cxx0x.cpp
+++ clang/test/FixIt/fixit-cxx0x.cpp
@@ -58,6 +58,9 @@
   (void)[&, i, i]{ }; // expected-error{{'i' can appear only once in a capture list}}
   (void)[] mutable { }; // expected-error{{lambda requires '()' before 'mutable'}}
   (void)[] -> int { }; // expected-error{{lambda requires '()' before return type}}
+
+  delete []() { return new int; }(); // expected-error{{'[]' after delete interpreted as 'delete[]'}}
+  delete [] { return new int; }(); // expected-error{{'[]' after delete interpreted as 'delete[]'}}
 }
 
 #define bar "bar"
Index: clang/lib/Parse/ParseExprCXX.cpp
===
--- clang/lib/Parse/ParseExprCXX.cpp
+++ clang/lib/Parse/ParseExprCXX.cpp
@@ -2984,8 +2984,38 @@
 //   [Footnote: A lambda expression with a lambda-introducer that consists
 //  of empty square brackets can follow the delete keyword if
 //  the lambda expression is enclosed in parentheses.]
-// FIXME: Produce a better diagnostic if the '[]' is unambiguously a
-//lambda-introducer.
+
+const Token Next = GetLookAheadToken(2);
+
+// Basic lookahead to check if we have a lambda expression.
+if (Next.isOneOf(tok::l_brace, tok::less) ||
+(Next.is(tok::l_paren) &&
+ (GetLookAheadToken(3).is(tok::r_paren) ||
+  (GetLookAheadToken(3).is(tok::identifier) &&
+   GetLookAheadToken(4).is(tok::identifier) {
+  SourceLocation RightBracketLock = NextToken().getLocation();
+  // Warn if the non-capturing lambda isn't surrounded by parenthesis
+  // to disambiguate it from 'delete[]'.
+  ExprResult Lambda = ParseLambdaExpression();
+  if (Lambda.isInvalid())
+return ExprError();
+
+  SourceLocation StartLoc = Lambda.get()->getBeginLoc();
+  Diag(Start, diag::err_lambda_after_delete)
+  << SourceRange(Start, RightBracketLock)
+  << FixItHint::CreateInsertion(StartLoc, "(")
+  << FixItHint::CreateInsertion(
+ Lexer::getLocForEndOfToken(Lambda.get()->getEndLoc(), 0,
+Actions.getSourceManager(),
+getLangOpts()),
+ ")");
+
+  // Evaluate any postfix expressions used on the lambda.
+  Lambda = ParsePostfixExpressionSuffix(Lambda);
+  return Actions.ActOnCXXDelete(Start, UseGlobal, /*ArrayForm=*/false,
+Lambda.get());
+}
+
 ArrayDelete = true;
 BalancedDelimiterTracker T(*this, tok::l_square);
 
Index: clang/include/clang/Basic/DiagnosticParseKinds.td
===
--- clang/include/clang/Basic/DiagnosticParseKinds.td
+++ clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -105,6 +105,8 @@
   InGroup, DefaultIgnore;
 def ext_alignof_expr : ExtWarn<
   "%0 applied to an expression is a GNU extension">, InGroup;
+def err_la

[PATCH] D59754: [Sema] Add c++2a designated initializer warnings

2019-03-25 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added inline comments.



Comment at: clang/lib/Sema/SemaInit.cpp:2017
 
+  auto LastIdx = Field != FieldEnd
+ ? Field->getFieldIndex()

Can `Field` ever be `FieldEnd` at this point?



Comment at: clang/lib/Sema/SemaInit.cpp:2044
+ : std::distance(RD->field_begin(), RD->field_end());
+  if (VerifyOnly && (LastIdx >= NextIdx || HasNonDesignatedInit) &&
+  SemaRef.getLangOpts().CPlusPlus2a)

`!VerifyOnly` and braces please.



Comment at: clang/lib/Sema/SemaInit.cpp:2065
+// Warn on mixed designators in C++20
+if (VerifyOnly && HasDesignatedInit && SemaRef.getLangOpts().CPlusPlus2a)
+  SemaRef.Diag(Init->getBeginLoc(), diag::ext_designated_init)

Same here. It should be `!VerifyOnly`. Also braces for the if statement.



Comment at: clang/lib/Sema/SemaInit.cpp:3087
   if (!getLangOpts().C99)
-Diag(DIE->getBeginLoc(), diag::ext_designated_init)
-<< DIE->getSourceRange();
+// Warn on nested and array designators in C++20
+if (!getLangOpts().CPlusPlus2a || Desig.getNumDesignators() > 1 ||

Missing dot.



Comment at: clang/lib/Sema/SemaInit.cpp:3089
+if (!getLangOpts().CPlusPlus2a || Desig.getNumDesignators() > 1 ||
+HasArrayDesignator)
+  Diag(DIE->getBeginLoc(), diag::ext_designated_init)

Braces.



Comment at: clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp:30
+// out of order designators
+A a1 = {.y = 1, .x = 2}; // expected-warning {{designated initializers are a 
C99 feature}}
+

Those warnings are misleading, since C++20 does have designated initializers; 
they just don't support some stuff that C99 does. It would be better  IMO if 
you could separate them. As in, the above should give you: `out-of-order 
designated initializers are a C99 feature` or something like that.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D59754



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


[PATCH] D59754: [Sema] Add c++2a designated initializer warnings

2019-03-25 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added inline comments.



Comment at: clang/test/SemaCXX/cxx2a-initializer-aggregates.cpp:30
+// out of order designators
+A a1 = {.y = 1, .x = 2}; // expected-warning {{designated initializers are a 
C99 feature}}
+

hintonda wrote:
> lebedev.ri wrote:
> > hintonda wrote:
> > > Rakete wrote:
> > > > Those warnings are misleading, since C++20 does have designated 
> > > > initializers; they just don't support some stuff that C99 does. It 
> > > > would be better  IMO if you could separate them. As in, the above 
> > > > should give you: `out-of-order designated initializers are a C99 
> > > > feature` or something like that.
> > > I think that would be a good idea as well, but wanted to get advise first.
> > > As in, the above should give you: out-of-order designated initializers 
> > > are a C99 feature or something like that.
> > 
> > I suppose also the question is, whether to error-out, or support them as an 
> > extension?
> > 
> Although most of them seem fine, the nested ones can be problematic.  Please 
> see https://reviews.llvm.org/D17407 for a proposal on how to fix them.
> I suppose also the question is, whether to error-out, or support them as an 
> extension?

Yes that's true. gcc doesn't support them at all in C++, and it seems like we 
accept it as well, but only for C classes (constructors make clang crash).

But making it an error now breaks backwards compatibility. So I think the best 
solution is to accept it for now, as an extension.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D59754



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


[PATCH] D59754: [Sema] Add c++2a designated initializer warnings

2019-03-26 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added inline comments.



Comment at: clang/lib/Sema/SemaInit.cpp:2044
+ : std::distance(RD->field_begin(), RD->field_end());
+  if (VerifyOnly && (LastIdx >= NextIdx || HasNonDesignatedInit) &&
+  SemaRef.getLangOpts().CPlusPlus2a)

hintonda wrote:
> Rakete wrote:
> > `!VerifyOnly` and braces please.
> Will commit this change as soon as check-clang finishes, but not sure I grok 
> the VerityOnly/!VerifyOnly criteria.  Could you help me out? 
`VerifyOnly` is used if you only want to verify and not actually generate any 
diagnostics or actually do anything that would commit to that change. So only 
generate the warning if `!VerifyOnly`.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D59754



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


[PATCH] D59900: [Sema] Fix a crash when nonnull checking

2019-03-28 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete accepted this revision.
Rakete added a comment.
This revision is now accepted and ready to land.

Otherwise LGTM.




Comment at: clang/test/SemaTemplate/decltype.cpp:1
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+// no crash & no diag

test/SemaCXX/nonnull.cpp would be a better place to put this test.



Comment at: clang/test/SemaTemplate/decltype.cpp:2
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+// no crash & no diag
+

This is redundant :)



Comment at: clang/test/SemaTemplate/decltype.cpp:4
+
+// expected-no-diagnostics
+template 

If you move the test as above you can drop this line.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D59900



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


[PATCH] D60934: [clang] adding explicit(bool) from c++2a

2019-04-25 Thread Nicolas Lesser via Phabricator via cfe-commits
Rakete added a comment.

Thanks for working on this! :)




Comment at: clang/lib/Parse/ParseDecl.cpp:3533
+  if (ExplicitExpr.isInvalid()) {
+Diag(ParenLoc, diag::note_explicit_bool_breaking_change_cxx2a)
+<< FixItHint::CreateReplacement(

This is a useful diagnostic but you'll need to fix (a lot) of false positives:

```
template  struct Foo { explicit(T{} +) Foo(); };
```

gets me:

```
main.cpp:1:50: error: expected expression
template  struct Foo { explicit(T{} +) Foo(); };
 ^
main.cpp:1:44: note: this expression is parsed as explicit(bool) since C++2a
template  struct Foo { explicit(T{} +) Foo(); };
   ^
   explicit(true)
```

Fixit hints should only be used when it is 100% the right fix that works, 
always.



Comment at: clang/lib/Parse/ParseDecl.cpp:3534
+Diag(ParenLoc, diag::note_explicit_bool_breaking_change_cxx2a)
+<< FixItHint::CreateReplacement(
+   SourceRange(ExplicitLoc, ExplicitLoc.getLocWithOffset(

FixIt Hints also need tests :)



Comment at: clang/lib/Sema/DeclSpec.cpp:952
+  assert((ExplicitState != ESF_unresolved || ExplicitExpr) &&
+ "ExplicitExpr can't be null if the state is ESF_resolved_false or "
+ "ESF_unresolved");

The comment seems to explain something else than the code.



Comment at: clang/lib/Sema/DeclSpec.cpp:956
   // intended.
-  if (FS_explicit_specified) {
+  // TODO : it is unclear how to handle multiple explicit(bool) specifiers.
+  if (hasExplicitSpecifier()) {

We accept `explicit explicit`, but we really shouldn't accept 
`explicit(some-expr) explicit(some-other-expr)`. That would just be confusing. 
`explicit explicit(some-expr)` is also borderline.



Comment at: clang/lib/Sema/DeclSpec.cpp:1316
 FixItHint Hint = FixItHint::CreateRemoval(SCLoc);
 S.Diag(SCLoc, diag::err_friend_decl_spec)
   << Keyword << Hint;

Please change this warning so that the whole *explicit-specifier* is underlined 
(or even change the text for conditional explicit):

```
main.cpp:1:36: error: 'explicit' can only be applied to a constructor or 
conversion function
template  struct Foo { explicit(false) void foo(); };
   ^~~~
1 error generated.
```

This will also fix the FixIt Hint.



Comment at: clang/lib/Sema/SemaDeclCXX.cpp:8641
   // C++0x explicit conversion operators.
-  if (DS.isExplicitSpecified())
+  if (DS.hasExplicitSpecifier())
 Diag(DS.getExplicitSpecLoc(),

You should amend the diagnostic, because as of right now `explicit(true)` is 
being diagnosed as C++11 feature.



Comment at: clang/lib/Sema/SemaDeclCXX.cpp:10870
+  ExprResult Converted =
+  CheckBooleanCondition(Loc, ExplicitExpr, /*isConstexpr=*/true);
+  if (Converted.isInvalid())

This assumes that we are in a [constexpr] if, leading to errors like this:

```
int a;
template  struct Foo { explicit(a) Foo(); };
```

```
main.cpp:2:45: error: constexpr if condition is not a constant expression
template  struct Foo { explicit(a) Foo(); };
^
```



Comment at: clang/lib/Sema/SemaDeclCXX.cpp:10876-10881
+return Converted;
+  }
+
+  llvm::APSInt Result;
+  Converted = VerifyIntegerConstantExpression(
+  Converted.get(), &Result, diag::err_noexcept_needs_constant_expression,

Wrong diagnostic.



Comment at: clang/lib/Sema/SemaOverload.cpp:10359
+  default:
+llvm_unreachable("invalide Decl");
+  }

typo.




Comment at: clang/lib/Sema/SemaOverload.cpp:10361
+  }
+  assert(ESI.getPointer() && "null expression should be handled before");
+  S.Diag(Cand->Function->getLocation(),

This fires for an instantiation dependent (but not value dependent) explicit 
specifier that is invalid:

```
template  struct Foo { explicit((T{}, false)) Foo(int); };

int main() { Foo f = 1; }
```



Comment at: clang/test/SemaCXX/cxx2a-compat.cpp:46
+#if __cplusplus <= 201703L
+// expected-warning@-3 {{this expression would be parsed as explicit(bool) in 
C++2a}}
+#if defined(__cpp_conditional_explicit)

would -> will



Comment at: clang/test/SemaCXX/cxx2a-compat.cpp:51
+#else
+// expected-error@-8 {{does not refer to a value}}
+// expected-error@-9 {{expected member name or ';'}}

A fixit hint for this would be great. Also it would be nice if there was a 
nicer error message.


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

https://reviews.llvm.org/D60934



___
cfe-comm

  1   2   >