[PATCH] D114382: [clang] Fix wrong -Wunused-local-typedef warning within a template function

2022-03-07 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: clang/test/SemaCXX/warn-unused-local-typedef.cpp:246
+  typedef int Int; // no-diag
+  typedef char Char; // expected-warning {{unused typedef 'Char'}}
+  Int m;

I haven't tried to understand the main point of this PR, but FWIW, have you 
seen https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61596 ? This looks 
suspiciously like that exact case. (I just filed its dup 
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104792 the other day.)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D114382

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


[PATCH] D119778: [clang] Add a note "deducing return type for 'foo'"

2022-03-04 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone updated this revision to Diff 413089.
Quuxplusone added a comment.
Herald added a project: All.

Rebased after landing D119184 . I'm no longer 
necessarily trying to land this note (it's not directly relevant to my 
interests anymore), but I'd like to show its CI as green before I abandon it. 
@rsmith would you like me to do something other than abandon this?


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

https://reviews.llvm.org/D119778

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Sema/Sema.h
  clang/lib/Frontend/FrontendActions.cpp
  clang/lib/Sema/SemaStmt.cpp
  clang/lib/Sema/SemaTemplateInstantiate.cpp
  clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p2-1z.cpp
  clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7-cxx14.cpp
  clang/test/CXX/dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp
  clang/test/SemaCUDA/autoret-global.cu
  clang/test/SemaCXX/cxx2b-consteval-if.cpp
  clang/test/SemaCXX/deduced-return-type-cxx14.cpp
  clang/test/SemaCXX/deduced-return-void.cpp
  clang/test/SemaCXX/typo-correction-crash.cpp
  clang/test/SemaTemplate/concepts.cpp

Index: clang/test/SemaTemplate/concepts.cpp
===
--- clang/test/SemaTemplate/concepts.cpp
+++ clang/test/SemaTemplate/concepts.cpp
@@ -114,6 +114,7 @@
   }
   template void g5() {
 ([]() -> C auto{ // expected-error-re {{deduced type {{.*}} does not satisfy}}
+// expected-note@-1 {{deducing return type for 'operator()'}}
  return T();
  }(), ...);
   }
@@ -174,26 +175,34 @@
   template concept C = false; // expected-note 6 {{because 'false' evaluated to false}}
 
   C auto f1() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+// expected-note@-1 {{deducing return type for 'f1'}}
 return void();
   }
   C auto f2() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+// expected-note@-1 {{deducing return type for 'f2'}}
 return;
   }
   C auto f3() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+// expected-note@-1 {{deducing return type for 'f3'}}
   }
   C decltype(auto) f4() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  // expected-note@-1 {{deducing return type for 'f4'}}
 return void();
   }
   C decltype(auto) f5() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  // expected-note@-1 {{deducing return type for 'f5'}}
 return;
   }
   C decltype(auto) f6() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  // expected-note@-1 {{deducing return type for 'f6'}}
   }
   C auto& f7() { // expected-error {{cannot form a reference to 'void'}}
+ // expected-note@-1 {{deducing return type for 'f7'}}
 return void();
   }
   C auto& f8() {
 return; // expected-error {{cannot deduce return type 'C auto &' from omitted return expression}}
+// expected-note@-2 {{deducing return type for 'f8'}}
   }
   C auto& f9() { // expected-error {{cannot deduce return type 'C auto &' for function with no return statements}}
   }
Index: clang/test/SemaCXX/typo-correction-crash.cpp
===
--- clang/test/SemaCXX/typo-correction-crash.cpp
+++ clang/test/SemaCXX/typo-correction-crash.cpp
@@ -9,6 +9,7 @@
   return "s";
   return tes; // expected-error {{use of undeclared identifier 'tes'; did you mean 'test'?}}
   // expected-error@-1 {{deduced as 'int' here but deduced as 'const char *' in earlier}}
+  // expected-note@-4 {{deducing return type for 'check2'}}
 }
 
 template  struct is_same { static constexpr bool value = false; };
Index: clang/test/SemaCXX/deduced-return-void.cpp
===
--- clang/test/SemaCXX/deduced-return-void.cpp
+++ clang/test/SemaCXX/deduced-return-void.cpp
@@ -16,10 +16,12 @@
 auto f4() {
   return i;
   return; // expected-error {{'auto' in return type deduced as 'void' here but deduced as 'int' in earlier return statement}}
+  // expected-note@-3 {{deducing return type for 'f4'}}
 }
 auto f5() {
   return i;
   return void(); // expected-error {{'auto' in return type deduced as 'void' here but deduced as 'int' in earlier return statement}}
+ // expected-note@-3 {{deducing return type for 'f5'}}
 }
 
 auto l1 = []() { };
@@ -44,10 +46,12 @@
 decltype(auto) f4() {
   return i;
   return; // expected-error {{'decltype(auto)' in return type deduced as 'void' here but deduced as 'int' in earlier return statement}}
+  // expected-note@-3 {{deducing return type for 'f4'}}
 }
 decltype(auto) f5() {
   return i;
   return void(); // expected-error {{'decltype(auto)' in return type deduced as 'void' here but 

[PATCH] D119184: [clang] [concepts] Check constrained-auto return types for void-returning functions

2022-03-04 Thread Arthur O'Dwyer via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGf0891cd61b2f: [clang] [concepts] Check constrained-auto 
return types for void-returning… (authored by arthur.j.odwyer).

Changed prior to commit:
  https://reviews.llvm.org/D119184?vs=413006=413046#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119184

Files:
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaStmt.cpp
  clang/test/SemaTemplate/concepts.cpp

Index: clang/test/SemaTemplate/concepts.cpp
===
--- clang/test/SemaTemplate/concepts.cpp
+++ clang/test/SemaTemplate/concepts.cpp
@@ -169,3 +169,42 @@
   template void f(T, U) = delete;
   void g() { f(0, 0); }
 }
+
+namespace PR49188 {
+  template concept C = false; // expected-note 6 {{because 'false' evaluated to false}}
+
+  C auto f1() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+return void();
+  }
+  C auto f2() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+return;
+  }
+  C auto f3() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  }
+  C decltype(auto) f4() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+return void();
+  }
+  C decltype(auto) f5() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+return;
+  }
+  C decltype(auto) f6() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  }
+  C auto& f7() { // expected-error {{cannot form a reference to 'void'}}
+return void();
+  }
+  C auto& f8() {
+return; // expected-error {{cannot deduce return type 'C auto &' from omitted return expression}}
+  }
+  C auto& f9() { // expected-error {{cannot deduce return type 'C auto &' for function with no return statements}}
+  }
+}
+namespace PR53911 {
+  template concept C = false;
+
+  C auto *f1() {
+return (void*)nullptr; // FIXME: should error
+  }
+  C auto *f2() {
+return (int*)nullptr; // FIXME: should error
+  }
+}
Index: clang/lib/Sema/SemaStmt.cpp
===
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -3808,19 +3808,26 @@
 LocalTypedefNameReferencer Referencer(*this);
 Referencer.TraverseType(RetExpr->getType());
   } else {
-//  In the case of a return with no operand, the initializer is considered
-//  to be void().
-//
-// Deduction here can only succeed if the return type is exactly 'cv auto'
-// or 'decltype(auto)', so just check for that case directly.
+// For a function with a deduced result type to return void,
+// the result type as written must be 'auto' or 'decltype(auto)',
+// possibly cv-qualified or constrained, but not ref-qualified.
 if (!OrigResultType.getType()->getAs()) {
   Diag(ReturnLoc, diag::err_auto_fn_return_void_but_not_auto)
 << OrigResultType.getType();
   return true;
 }
-// We always deduce U = void in this case.
-Deduced = SubstAutoType(OrigResultType.getType(), Context.VoidTy);
-if (Deduced.isNull())
+// In the case of a return with no operand, the initializer is considered
+// to be 'void()'.
+Expr *Dummy = new (Context) CXXScalarValueInitExpr(
+Context.VoidTy,
+Context.getTrivialTypeSourceInfo(Context.VoidTy, ReturnLoc), ReturnLoc);
+DeduceAutoResult DAR = DeduceAutoType(OrigResultType, Dummy, Deduced);
+
+if (DAR == DAR_Failed && !FD->isInvalidDecl())
+  Diag(ReturnLoc, diag::err_auto_fn_deduction_failure)
+  << OrigResultType.getType() << Dummy->getType();
+
+if (DAR != DAR_Succeeded)
   return true;
   }
 
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -14674,18 +14674,20 @@
   if (getLangOpts().CPlusPlus14) {
 if (!FD->isInvalidDecl() && Body && !FD->isDependentContext() &&
 FD->getReturnType()->isUndeducedType()) {
-  // If the function has a deduced result type but contains no 'return'
-  // statements, the result type as written must be exactly 'auto', and
-  // the deduced result type is 'void'.
+  // For a function with a deduced result type to return void,
+  // the result type as written must be 'auto' or 'decltype(auto)',
+  // possibly cv-qualified or constrained, but not ref-qualified.
   if (!FD->getReturnType()->getAs()) {
 Diag(dcl->getLocation(), diag::err_auto_fn_no_return_but_not_auto)
 << FD->getReturnType();
 FD->setInvalidDecl();
   } else {
-// Substitute 'void' for the 'auto' in the type.
-TypeLoc ResultType = getReturnTypeLoc(FD);
-Context.adjustDeducedFunctionResultType(
-FD, 

[PATCH] D119184: [clang] [concepts] Check constrained-auto return types for void-returning functions

2022-03-04 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone updated this revision to Diff 413006.
Quuxplusone added a comment.
Herald added a project: All.

Rebased, poke CI one last time.
If this is green, imma land it.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119184

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaStmt.cpp
  clang/test/SemaTemplate/concepts.cpp

Index: clang/test/SemaTemplate/concepts.cpp
===
--- clang/test/SemaTemplate/concepts.cpp
+++ clang/test/SemaTemplate/concepts.cpp
@@ -169,3 +169,42 @@
   template void f(T, U) = delete;
   void g() { f(0, 0); }
 }
+
+namespace PR49188 {
+  template concept C = false; // expected-note 6 {{because 'false' evaluated to false}}
+
+  C auto f1() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+return void();
+  }
+  C auto f2() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+return;
+  }
+  C auto f3() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  }
+  C decltype(auto) f4() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+return void();
+  }
+  C decltype(auto) f5() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+return;
+  }
+  C decltype(auto) f6() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  }
+  C auto& f7() { // expected-error {{cannot form a reference to 'void'}}
+return void();
+  }
+  C auto& f8() {
+return; // expected-error {{cannot deduce return type 'C auto &' from omitted return expression}}
+  }
+  C auto& f9() { // expected-error {{cannot deduce return type 'C auto &' for function with no return statements}}
+  }
+}
+namespace PR53911 {
+  template concept C = false;
+
+  C auto *f1() {
+return (void*)nullptr; // FIXME: should error
+  }
+  C auto *f2() {
+return (int*)nullptr; // FIXME: should error
+  }
+}
Index: clang/lib/Sema/SemaStmt.cpp
===
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -3762,8 +3762,8 @@
 bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
 SourceLocation ReturnLoc,
 Expr *,
-AutoType *AT) {
-  // If this is the conversion function for a lambda, we choose to deduce it
+const AutoType *AT) {
+  // If this is the conversion function for a lambda, we choose to deduce its
   // type from the corresponding call operator, not from the synthesized return
   // statement within it. See Sema::DeduceReturnType.
   if (isLambdaConversionOperator(FD))
@@ -3808,19 +3808,26 @@
 LocalTypedefNameReferencer Referencer(*this);
 Referencer.TraverseType(RetExpr->getType());
   } else {
-//  In the case of a return with no operand, the initializer is considered
-//  to be void().
-//
-// Deduction here can only succeed if the return type is exactly 'cv auto'
-// or 'decltype(auto)', so just check for that case directly.
+// For a function with a deduced result type to return void,
+// the result type as written must be 'auto' or 'decltype(auto)',
+// possibly cv-qualified or constrained, but not ref-qualified.
 if (!OrigResultType.getType()->getAs()) {
   Diag(ReturnLoc, diag::err_auto_fn_return_void_but_not_auto)
 << OrigResultType.getType();
   return true;
 }
-// We always deduce U = void in this case.
-Deduced = SubstAutoType(OrigResultType.getType(), Context.VoidTy);
-if (Deduced.isNull())
+// In the case of a return with no operand, the initializer is considered
+// to be 'void()'.
+Expr *Dummy = new (Context) CXXScalarValueInitExpr(
+Context.VoidTy,
+Context.getTrivialTypeSourceInfo(Context.VoidTy, ReturnLoc), ReturnLoc);
+DeduceAutoResult DAR = DeduceAutoType(OrigResultType, Dummy, Deduced);
+
+if (DAR == DAR_Failed && !FD->isInvalidDecl())
+  Diag(ReturnLoc, diag::err_auto_fn_deduction_failure)
+  << OrigResultType.getType() << Dummy->getType();
+
+if (DAR != DAR_Succeeded)
   return true;
   }
 
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -14674,18 +14674,20 @@
   if (getLangOpts().CPlusPlus14) {
 if (!FD->isInvalidDecl() && Body && !FD->isDependentContext() &&
 FD->getReturnType()->isUndeducedType()) {
-  // If the function has a deduced result type but contains no 'return'
-  // statements, the result type as written must be exactly 'auto', and
-  // the deduced result type is 'void'.
+  // For a function with a deduced result type to return void,
+  

[PATCH] D120398: [format] follow up: Use unsigned char as the base of all enums in FormatStyle

2022-03-01 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added a comment.

In D120398#3351998 , @MyDeveloperDay 
wrote:

> Before this lands can we have a discussion about what clarity this gives us?, 
> because I think it makes the code more unreadable, but surely we are saving 
> just 7x(3 bytes) (the difference between and int and a unsigned char for 7 
> enums)
>
> Is saving 21 bytes valuable?

Peanut gallery says: I think giving every enum a concrete underlying type is a 
//good// practice, so I don't think this makes anything less readable. (That 
is, I'd even favor adding `: int` to each of these enums, over the status quo 
where the type is merely implied — we've seen that people can be unsure of the 
exact behavior.)
I can imagine that someone might object that hard-coding one byte for each enum 
might one day cause problems if we want more than 256 possible settings for any 
given enum, but that's not likely, is it?
Re space savings, OP says that they're saving 21 bytes //per object// and that 
they have "lots" of objects in their particular use-case, even if clang-format 
itself doesn't.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D120398

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


[PATCH] D120629: [clang] Remove unused variable AllElementsInt. NFC.

2022-02-28 Thread Arthur O'Dwyer via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGd3db74eadbfc: [clang] Remove unused variable AllElementsInt. 
(authored by arthur.j.odwyer).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D120629

Files:
  clang/lib/Sema/SemaDecl.cpp


Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -18474,9 +18474,6 @@
   unsigned NumNegativeBits = 0;
   unsigned NumPositiveBits = 0;
 
-  // Keep track of whether all elements have type int.
-  bool AllElementsInt = true;
-
   for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
 EnumConstantDecl *ECD =
   cast_or_null(Elements[i]);
@@ -18491,10 +18488,6 @@
 else
   NumNegativeBits = std::max(NumNegativeBits,
  (unsigned)InitVal.getMinSignedBits());
-
-// Keep track of whether every enum element has type int (very common).
-if (AllElementsInt)
-  AllElementsInt = ECD->getType() == Context.IntTy;
   }
 
   // Figure out the type that should be used for this enum.


Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -18474,9 +18474,6 @@
   unsigned NumNegativeBits = 0;
   unsigned NumPositiveBits = 0;
 
-  // Keep track of whether all elements have type int.
-  bool AllElementsInt = true;
-
   for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
 EnumConstantDecl *ECD =
   cast_or_null(Elements[i]);
@@ -18491,10 +18488,6 @@
 else
   NumNegativeBits = std::max(NumNegativeBits,
  (unsigned)InitVal.getMinSignedBits());
-
-// Keep track of whether every enum element has type int (very common).
-if (AllElementsInt)
-  AllElementsInt = ECD->getType() == Context.IntTy;
   }
 
   // Figure out the type that should be used for this enum.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D120629: [clang] Remove unused variable AllElementsInt. NFC.

2022-02-27 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone created this revision.
Quuxplusone added reviewers: rnk, rsmith, sammccall.
Quuxplusone added a project: clang.
Quuxplusone requested review of this revision.
Herald added a subscriber: cfe-commits.

This has been unused ever since it was committed in b8a501ccf1.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D120629

Files:
  clang/lib/Sema/SemaDecl.cpp


Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -18474,9 +18474,6 @@
   unsigned NumNegativeBits = 0;
   unsigned NumPositiveBits = 0;
 
-  // Keep track of whether all elements have type int.
-  bool AllElementsInt = true;
-
   for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
 EnumConstantDecl *ECD =
   cast_or_null(Elements[i]);
@@ -18491,10 +18488,6 @@
 else
   NumNegativeBits = std::max(NumNegativeBits,
  (unsigned)InitVal.getMinSignedBits());
-
-// Keep track of whether every enum element has type int (very common).
-if (AllElementsInt)
-  AllElementsInt = ECD->getType() == Context.IntTy;
   }
 
   // Figure out the type that should be used for this enum.


Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -18474,9 +18474,6 @@
   unsigned NumNegativeBits = 0;
   unsigned NumPositiveBits = 0;
 
-  // Keep track of whether all elements have type int.
-  bool AllElementsInt = true;
-
   for (unsigned i = 0, e = Elements.size(); i != e; ++i) {
 EnumConstantDecl *ECD =
   cast_or_null(Elements[i]);
@@ -18491,10 +18488,6 @@
 else
   NumNegativeBits = std::max(NumNegativeBits,
  (unsigned)InitVal.getMinSignedBits());
-
-// Keep track of whether every enum element has type int (very common).
-if (AllElementsInt)
-  AllElementsInt = ECD->getType() == Context.IntTy;
   }
 
   // Figure out the type that should be used for this enum.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D120398: [format] follow up: Use unsigned char as the base of all enums in FormatStyle

2022-02-27 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added a comment.

> Any runtime penalty? (Usually compilers choose a faster underlying type for 
> enums, not smaller)



> The decision is made in the header (so I think it will always be `int` until 
> this doesn't fit). To decide what is faster the compiler would need to know 
> all the usages. Which it can't.

Yes, Clang chooses `int` by default. In fact, C++11 and later //mandate// that 
a new-style scoped enum `enum class Foo {` means the same thing as `enum class 
Foo : int {` — see https://timsong-cpp.github.io/cppwp/n3337/dcl.enum#5 . For 
unscoped old-style enums, Clang/GCC/MSVC all choose `int` by default, 
//unless// `-fshort-enums` is passed on the command line and/or the enum is 
annotated with `__attribute__((packed))`, in which case it chooses the smallest 
possible type. `-fshort-enums` and `__attribute__((packed))` have no effect on 
new-style scoped enums nor on enums with explicit underlying types.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D120398

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


[PATCH] D113393: [c++2b] Implement P0849R8 auto(x)

2022-02-25 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added a comment.

In D113393#3345275 , @aaron.ballman 
wrote:

>> Also implemented decltype(auto)(x) (https://wg21.link/p0849r2) as a Clang 
>> extension.
>
> I'd like to better understand the use cases for this. WG21 considered this as 
> part of the feature and ultimately rejected it (fairly strongly, according to 
> the EWG polls). From the meeting minutes, it says that the reason EWG 
> disliked the idea is because of its expert-friendly nature and that this 
> facility would present teachability issues. I tend to agree, so I'm wondering 
> why we want to add the feature as an extension when WG21 explicitly rejected 
> it (that doesn't seem in line with our extension policy: 
> https://clang.llvm.org/get_involved.html#criteria).

(I'm not directly answering Aaron's question.)  Personally I think it makes 
sense to support `decltype(auto)(x)` in the same release as `auto(x)`, for the 
same reason we supported `Constrained decltype(auto)` in the same release as 
`Constrained auto`. //But//, rather than have that essentially tangential 
policy discussion in //this// PR, @lichray, would you be willing to split out 
all the changes related to `decltype(auto)(x)` into their own separate PR, (1) 
so that we could land the uncontroversial C++20 `auto(x)` parts sooner rather 
than later, and (2) so that if three years from now someone //does// decide to 
revert `decltype(auto)(x)`, all its changes will be nicely isolated in their 
own commit instead of mixed in with important bits of our C++20 conformance? 
And (3) so that we could have the "Should we do this?" policy discussion in 
//that// PR, instead of here, and (4) the discussion would be more focused 
because we could see //exactly// the set of diffs we're talking about, instead 
of mixed in etc etc.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D113393

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


[PATCH] D120454: clang/www: Add links to tracking issues for C++20 features

2022-02-24 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: clang/www/cxx_status.html:106
+automatically fetch status information from the issue in the tracker. For 
Example:
+a class='autoupdate' 
href='https://github.com/llvm/llvm-project/issues/54006'No/a
+

HTML nit: these attributes should use `"` instead of `'` (ooh, and ditto in the 
actual HTML on lines 961 etc.)



Comment at: clang/www/cxx_status.html:1308-1313

 https://wg21.link/p2082r1;>P2082R1
+  
+No
+  
   

Have you eyeballed the new rendering of this table here? (I haven't.) The 
indentation on these HTML lines is wonky now; looks like lines 1308, 1309, and 
1313 are overindented by 2 spaces?



Comment at: clang/www/cxx_status.html:1652
+ * in the link text field. e.g.
+ * No
+ *

`s/'/"/g`



Comment at: clang/www/cxx_status.html:1660-1664
+Array.from(document.getElementsByClassName("autoupdate")).forEach(element => {
+  if (element.innerHTML != "No")
+return;
+  updateIssueCell(element);
+})

Does this need to be in a `document.onload` or 

[PATCH] D119927: [Clang] [P2025] More exhaustive tests for NRVO

2022-02-19 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: clang/test/CodeGenCXX/nrvo.cpp:1537
+  }
+  return x; // FIXME: NRVO could happen if B == false, but doesn't
+}

Quuxplusone wrote:
> Nit: `s/if/when/`
Serendipitously, I just ran into almost this exact scenario in D120180, where 
C++20's `reverse_iterator` wants to do basically
```
{
  _Iter __tmp = current;
  --__tmp;
  if constexpr (is_pointer_v<_Iter>) {
return __tmp;
  } else {
return std::move(__tmp).operator->();
  }
}
```
and so we want NRVO on `__tmp` in the former case but URVO in the latter case. 
Of course in that specific case, we "want NRVO" only when `__tmp` is a pointer 
and thus NRVO doesn't apply anyway because pointers are returned in registers. 
But it would be nice to have a test case for as-close-as-possible to that 
pattern, if you don't mind adding one.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119927

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


[PATCH] D120086: Explicitly document that `__is_trivially_relocatable(T)` implies that `T` is implicit-lifetime.

2022-02-17 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added a comment.

FWIW, I think this is a good idea. I even think that the parentheses and 
"Note:" are too self-deprecating, and this deserves to be a bigger deal. 
Perhaps `__is_implicit_lifetime(T)` should be an intrinsic in its own right! 
Then you could say very concretely that `__is_trivially_relocatable(T)` implies 
`__is_implicit_lifetime(T)`.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D120086

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


[PATCH] D119184: [clang] [concepts] Check constrained-auto return types for void-returning functions

2022-02-17 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone updated this revision to Diff 409740.
Quuxplusone added a comment.

Rebase and update — this is becoming more and more of a trivial patch, which I 
guess is good!
Add a test case for https://github.com/llvm/llvm-project/issues/53911 (which I 
finally thought to test, and was surprised to find it didn't work either before 
//or// after my patch).


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119184

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaStmt.cpp
  clang/test/SemaTemplate/concepts.cpp

Index: clang/test/SemaTemplate/concepts.cpp
===
--- clang/test/SemaTemplate/concepts.cpp
+++ clang/test/SemaTemplate/concepts.cpp
@@ -169,3 +169,42 @@
   template void f(T, U) = delete;
   void g() { f(0, 0); }
 }
+
+namespace PR49188 {
+  template concept C = false; // expected-note 6 {{because 'false' evaluated to false}}
+
+  C auto f1() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+return void();
+  }
+  C auto f2() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+return;
+  }
+  C auto f3() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  }
+  C decltype(auto) f4() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+return void();
+  }
+  C decltype(auto) f5() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+return;
+  }
+  C decltype(auto) f6() { // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  }
+  C auto& f7() { // expected-error {{cannot form a reference to 'void'}}
+return void();
+  }
+  C auto& f8() {
+return; // expected-error {{cannot deduce return type 'C auto &' from omitted return expression}}
+  }
+  C auto& f9() { // expected-error {{cannot deduce return type 'C auto &' for function with no return statements}}
+  }
+}
+namespace PR53911 {
+  template concept C = false;
+
+  C auto *f1() {
+return (void*)nullptr; // FIXME: should error
+  }
+  C auto *f2() {
+return (int*)nullptr; // FIXME: should error
+  }
+}
Index: clang/lib/Sema/SemaStmt.cpp
===
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -3762,8 +3762,8 @@
 bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
 SourceLocation ReturnLoc,
 Expr *,
-AutoType *AT) {
-  // If this is the conversion function for a lambda, we choose to deduce it
+const AutoType *AT) {
+  // If this is the conversion function for a lambda, we choose to deduce its
   // type from the corresponding call operator, not from the synthesized return
   // statement within it. See Sema::DeduceReturnType.
   if (isLambdaConversionOperator(FD))
@@ -3808,19 +3808,26 @@
 LocalTypedefNameReferencer Referencer(*this);
 Referencer.TraverseType(RetExpr->getType());
   } else {
-//  In the case of a return with no operand, the initializer is considered
-//  to be void().
-//
-// Deduction here can only succeed if the return type is exactly 'cv auto'
-// or 'decltype(auto)', so just check for that case directly.
+// For a function with a deduced result type to return void,
+// the result type as written must be 'auto' or 'decltype(auto)',
+// possibly cv-qualified or constrained, but not ref-qualified.
 if (!OrigResultType.getType()->getAs()) {
   Diag(ReturnLoc, diag::err_auto_fn_return_void_but_not_auto)
 << OrigResultType.getType();
   return true;
 }
-// We always deduce U = void in this case.
-Deduced = SubstAutoType(OrigResultType.getType(), Context.VoidTy);
-if (Deduced.isNull())
+// In the case of a return with no operand, the initializer is considered
+// to be 'void()'.
+Expr *Dummy = new (Context) CXXScalarValueInitExpr(
+Context.VoidTy,
+Context.getTrivialTypeSourceInfo(Context.VoidTy, ReturnLoc), ReturnLoc);
+DeduceAutoResult DAR = DeduceAutoType(OrigResultType, Dummy, Deduced);
+
+if (DAR == DAR_Failed && !FD->isInvalidDecl())
+  Diag(ReturnLoc, diag::err_auto_fn_deduction_failure)
+  << OrigResultType.getType() << Dummy->getType();
+
+if (DAR != DAR_Succeeded)
   return true;
   }
 
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -14660,18 +14660,20 @@
   if (getLangOpts().CPlusPlus14) {
 if (!FD->isInvalidDecl() && Body && !FD->isDependentContext() &&
 FD->getReturnType()->isUndeducedType()) {
-  // If the function has a deduced result type but contains no 'return'
-  // 

[PATCH] D119772: [clang] [NFC] More exhaustive tests for deducing void return types

2022-02-17 Thread Arthur O'Dwyer via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG7adb85884b35: [clang] [NFC] More exhaustive tests for 
deducing void return types (authored by arthur.j.odwyer).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119772

Files:
  clang/test/SemaCXX/deduced-return-void.cpp

Index: clang/test/SemaCXX/deduced-return-void.cpp
===
--- clang/test/SemaCXX/deduced-return-void.cpp
+++ clang/test/SemaCXX/deduced-return-void.cpp
@@ -4,20 +4,137 @@
 // Check that we don't get any extra warning for "return" without an
 // expression, in a function that might have been intended to return
 // void all along.
-auto f1() {
-  return 1;
-  return; // expected-error {{deduced as 'void' here but deduced as 'int' in earlier return statement}}
+decltype(h1) h1() { // expected-error {{use of undeclared identifier 'h1'}}
+  return;
+}
+
+namespace JustAuto {
+int i;
+auto f1() { }
+auto f2() { return; }
+auto f3() { return void(); }
+auto f4() {
+  return i;
+  return; // expected-error {{'auto' in return type deduced as 'void' here but deduced as 'int' in earlier return statement}}
+}
+auto f5() {
+  return i;
+  return void(); // expected-error {{'auto' in return type deduced as 'void' here but deduced as 'int' in earlier return statement}}
 }
 
-decltype(auto) f2() {
-  return 1;
-  return; // expected-error {{deduced as 'void' here but deduced as 'int' in earlier return statement}}
+auto l1 = []() { };
+auto l2 = []() { return; };
+auto l3 = []() { return void(); };
+auto l4 = []() {
+  return i;
+  return; // expected-error {{return type 'void' must match previous return type 'int' when lambda expression has unspecified explicit return type}}
+};
+auto l5 = []() {
+  return i;
+  return void(); // expected-error {{return type 'void' must match previous return type 'int' when lambda expression has unspecified explicit return type}}
+};
+
+} // namespace JustAuto
+
+namespace DecltypeAuto {
+int i;
+decltype(auto) f1() { }
+decltype(auto) f2() { return; }
+decltype(auto) f3() { return void(); }
+decltype(auto) f4() {
+  return i;
+  return; // expected-error {{'decltype(auto)' in return type deduced as 'void' here but deduced as 'int' in earlier return statement}}
+}
+decltype(auto) f5() {
+  return i;
+  return void(); // expected-error {{'decltype(auto)' in return type deduced as 'void' here but deduced as 'int' in earlier return statement}}
 }
 
-auto *g() {
+auto l1 = []() -> decltype(auto) { };
+auto l2 = []() -> decltype(auto) { return; };
+auto l3 = []() -> decltype(auto) { return void(); };
+auto l4 = []() -> decltype(auto) {
+  return i;
+  return; // expected-error {{'decltype(auto)' in return type deduced as 'void' here but deduced as 'int' in earlier return statement}}
+};
+auto l5 = []() -> decltype(auto) {
+  return i;
+  return void(); // expected-error {{'decltype(auto)' in return type deduced as 'void' here but deduced as 'int' in earlier return statement}}
+};
+
+} // namespace DecltypeAuto
+
+namespace AutoPtr {
+int i;
+auto *f1() { } // expected-error {{cannot deduce return type 'auto *' for function with no return statements}}
+auto *f2() {
+  return; // expected-error {{cannot deduce return type 'auto *' from omitted return expression}}
+}
+auto *f3() {
+  return void(); // expected-error {{cannot deduce return type 'auto *' from returned value of type 'void'}}
+}
+auto *f4() {
+  return 
   return; // expected-error {{cannot deduce return type 'auto *' from omitted return expression}}
 }
+auto *f5() {
+  return 
+  return void(); // expected-error {{cannot deduce return type 'auto *' from returned value of type 'void'}}
+}
 
-decltype(h1) h1() { // expected-error {{use of undeclared identifier 'h1'}}
-  return;
+auto l1 = []() -> auto* { }; // expected-error {{cannot deduce return type 'auto *' for function with no return statements}}
+auto l2 = []() -> auto* {
+  return; // expected-error {{cannot deduce return type 'auto *' from omitted return expression}}
+};
+auto l3 = []() -> auto* {
+  return void(); // expected-error {{cannot deduce return type 'auto *' from returned value of type 'void'}}
+};
+auto l4 = []() -> auto* {
+  return 
+  return; // expected-error {{cannot deduce return type 'auto *' from omitted return expression}}
+};
+auto l5 = []() -> auto* {
+  return 
+  return void(); // expected-error {{cannot deduce return type 'auto *' from returned value of type 'void'}}
+};
+} // namespace AutoPtr
+
+namespace AutoRef {
+int i;
+auto& f1() { // expected-error {{cannot deduce return type 'auto &' for function with no return statements}}
+}
+auto& f2() {
+  return; // expected-error {{cannot deduce return type 'auto &' from omitted return expression}}
+}
+auto& f3() {
+  return void(); // expected-error@-1 {{cannot form a reference to 'void'}}
 }
+auto& f4() {
+  return i;
+  return; // expected-error 

[PATCH] D119184: [clang] [concepts] Check constrained-auto return types for void-returning functions

2022-02-17 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: clang/test/SemaCXX/deduced-return-type-cxx14.cpp:116
 
-auto _ret_2() {} // expected-error {{cannot deduce return type 'auto &' 
for function with no return statements}}
+auto _ret_2() {} // expected-error {{cannot form a reference to 'void'}}
 const auto void_ret_3() {} // ok, return type 'const void' is adjusted to 
'void'

sammccall wrote:
> Quuxplusone wrote:
> > sammccall wrote:
> > > This feels like a regression, this diagnostic is just attached to the end 
> > > of the function and there's no longer any explicit indication that the 
> > > return type or deduction is involved.
> > > 
> > > It may be worth keeping the explicit check in `ActOnFinishFunctionBody` 
> > > before the deduction happens to improve the diagnostic in this case.
> > > 
> > > (I don't think it's important to do this in the return-with-no-argument 
> > > case, since the error will point at the return statement which provides 
> > > enough context I think)
> > I agree about the (mild) regression but am not sure what to do about it. I 
> > think it might help if Clang emitted a note `note: during return type 
> > deduction here` (pointer to the offending `return` statement or 
> > end-of-function); do you think I should do that? and if so, how?
> > 
> > > It may be worth keeping the explicit check in `ActOnFinishFunctionBody` 
> > > before the deduction happens to improve the diagnostic in this case.
> > 
> > I can't picture what you mean; can you suggest a specific patch?
> > 
> > In case it matters, I'm a little leery of hard-coding a special case like 
> > we had in the old `DeduceFunctionTypeFromReturnExpr` lines 3814–3816,
> > ```
> > // Deduction here can only succeed if the return type is exactly 'cv 
> > auto'
> > // or 'decltype(auto)', so just check for that case directly.
> > if (!OrigResultType.getType()->getAs()) {
> > ```
> > because special-casing `void` is kind of how we got into this mess in the 
> > first place.
> > I can't picture what you mean; can you suggest a specific patch?
> > In case it matters, I'm a little leery of hard-coding a special case like 
> > we had in the old
> > DeduceFunctionTypeFromReturnExpr
> 
> Yeah, so that was pretty much my suggestion: keep the `getAs()` 
> check in `ActOnFinishFunctionBody` to reject the most common cases with a 
> good diagnostic, and then if it passes do the actual deduction.
> I agree this is ugly, I just didn't really have a better idea.
> 
> > I think it might help if Clang emitted a note note: during return type 
> > deduction here 
> 
> This is a nice idea, maybe better than the existing diagnostic.
> 
> I haven't added notes myself, but I think all you have to do is `add a 
> note_*` entry to DiagnosticSemaKinds.td, and emit it after the primary 
> diagnostic as you'd emit any other diagnostic.
> Here if you see `DAR_Failed` then I think you know the call emitted a 
> diagnostic and you can add the note. I'm not sure about 
> `DAR_FailedAlreadyDiagnosed` - if it means no new diagnostic was emitted then 
> you also don't want to add your note.
> 
> (You'd want to do this in the `if (RetExpr)` case too of course)
> 
> > pointer to the offending return statement or end-of-function
> 
> The main diagnostics is going to point at that location already. So it might 
> be more helpful to point the "during return type deduction" note at the 
> return type written in the function declaration:
> 
> ```
>   return;
>   ^~
> error: cannot form reference to 'void'
> 
> auto& foo() {
>   ^~~~
> note: deducing return type for 'foo'
> ```
@rsmith: This is the discussion that led to D119778 adding the note. I suppose 
that by keeping all the special-case error messages in 
`ActOnFinishFunctionBody`, we've reduced the benefit of the note.
In particular, `void_ret_2` no longer has this "regression," so there's no 
longer any need for the note here — in fact, as you mentioned, the note is a 
bit noisy.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119184

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


[PATCH] D119184: [clang] [concepts] Check constrained-auto return types for void-returning functions

2022-02-17 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: clang/lib/Sema/SemaStmt.cpp:3766
+Expr *, const AutoType *AT,
+bool HasReturnStmt) {
+  // If this is the conversion function for a lambda, we choose to deduce its

rsmith wrote:
> It looks like you ended up not using the new parameter for anything. Did you 
> intend to / do you still need it?
Huh, I guess I don't need it anymore.
Btw, does it make sense that I marked `AT` as `const AutoType *`? Initially I'd 
been worried that something on this codepath might be stashing state inside 
`*AT`, or otherwise updating it to say "This was //written// `auto&`, but now 
//refers// to the type ." This week, I'm not sure why I would have ever 
suspected that.
But still, this codepath //does// update the state of `*FD`, so the fact that 
it doesn't update `*AT` is still somewhat worthy of note...
Anyway, if the `const` is uncontroversial, I could just land that `const` in 
its own commit to shrink this PR a tiny bit.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119184

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


[PATCH] D119927: [Clang] [P2025] More exhaustive tests for NRVO

2022-02-16 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone accepted this revision.
Quuxplusone added a comment.
This revision is now accepted and ready to land.

LGTM FWIW. You might want to wait for someone more authoritative to take a 
look; but it's also only adding test coverage, so it seems pretty 
uncontroversial, I would think.




Comment at: clang/test/CodeGenCXX/nrvo.cpp:165
   if (B)
-return y;
-  return x;
+return y; // NRVO is impossible
+  return x;   // NRVO is impossible

Technically, because `B` is a constant throughout this function, we probably 
//could// do NRVO here by hoisting the condition as if by
```
X x;
if (B) { X y; return y; } // NRVO is possible here
X y; return x; // NRVO is impossible
```
Whether we //should// is another question. :) Also, changing `bool B` to `const 
bool& B` would defeat my idea.



Comment at: clang/test/CodeGenCXX/nrvo.cpp:1149
+//
+void test16() {
+  X x;

It would be helpful to comment these tests also with their p2025 example 
numbers, e.g.
```
void test16() { // http://wg21.link/p2025r2#ex-9
```
It took me a while to realize that the numbers here don't actually match up to 
the examples' numbers in the paper.



Comment at: clang/test/CodeGenCXX/nrvo.cpp:1537
+  }
+  return x; // FIXME: NRVO could happen if B == false, but doesn't
+}

Nit: `s/if/when/`


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119927

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


[PATCH] D119778: [clang] Add a note "deducing return type for 'foo'"

2022-02-16 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone updated this revision to Diff 409359.
Quuxplusone added a comment.

Apply @rsmith's suggested approach.

> I don't see any obvious way that this patch could be responsible for that 
> failure, unless it's something like a pre-existing use of uninitialized 
> memory or a use-after-free and this patch is just changing the happenstance 
> behavior.

Well, it might more likely be the fault of D119184 
 rather than this one per se. D119184 
 is doing things with `Context.VoidTy` that 
weren't there before; could any of that new code be the culprit?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119778

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/include/clang/Sema/Sema.h
  clang/lib/Frontend/FrontendActions.cpp
  clang/lib/Sema/SemaStmt.cpp
  clang/lib/Sema/SemaTemplateInstantiate.cpp
  clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p2-1z.cpp
  clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p7-cxx14.cpp
  clang/test/CXX/dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp
  clang/test/SemaCUDA/autoret-global.cu
  clang/test/SemaCXX/cxx2b-consteval-if.cpp
  clang/test/SemaCXX/deduced-return-type-cxx14.cpp
  clang/test/SemaCXX/deduced-return-void.cpp
  clang/test/SemaCXX/typo-correction-crash.cpp
  clang/test/SemaTemplate/concepts.cpp

Index: clang/test/SemaTemplate/concepts.cpp
===
--- clang/test/SemaTemplate/concepts.cpp
+++ clang/test/SemaTemplate/concepts.cpp
@@ -114,6 +114,7 @@
   }
   template void g5() {
 ([]() -> C auto{ // expected-error-re {{deduced type {{.*}} does not satisfy}}
+// expected-note@-1 {{deducing return type for 'operator()'}}
  return T();
  }(), ...);
   }
@@ -174,11 +175,17 @@
   template concept C = false; // expected-note 6 {{because 'false' evaluated to false}}
 
   C auto f1() { return void(); }   // expected-error {{deduced type 'void' does not satisfy 'C'}}
+   // expected-note@-1 {{deducing return type for 'f1'}}
   C auto f2() { return; }  // expected-error {{deduced type 'void' does not satisfy 'C'}}
+   // expected-note@-1 {{deducing return type for 'f2'}}
   C auto f3() {}   // expected-error {{deduced type 'void' does not satisfy 'C'}}
+   // expected-note@-1 {{deducing return type for 'f3'}}
   C decltype(auto) f4() { return void(); } // expected-error {{deduced type 'void' does not satisfy 'C'}}
+   // expected-note@-1 {{deducing return type for 'f4'}}
   C decltype(auto) f5() { return; }// expected-error {{deduced type 'void' does not satisfy 'C'}}
+   // expected-note@-1 {{deducing return type for 'f5'}}
   C decltype(auto) f6() {} // expected-error {{deduced type 'void' does not satisfy 'C'}}
+   // expected-note@-1 {{deducing return type for 'f6'}}
 
   void g() {
 f1();
Index: clang/test/SemaCXX/typo-correction-crash.cpp
===
--- clang/test/SemaCXX/typo-correction-crash.cpp
+++ clang/test/SemaCXX/typo-correction-crash.cpp
@@ -9,6 +9,7 @@
   return "s";
   return tes; // expected-error {{use of undeclared identifier 'tes'; did you mean 'test'?}}
   // expected-error@-1 {{deduced as 'int' here but deduced as 'const char *' in earlier}}
+  // expected-note@-4 {{deducing return type for 'check2'}}
 }
 
 template  struct is_same { static constexpr bool value = false; };
Index: clang/test/SemaCXX/deduced-return-void.cpp
===
--- clang/test/SemaCXX/deduced-return-void.cpp
+++ clang/test/SemaCXX/deduced-return-void.cpp
@@ -16,10 +16,12 @@
 auto f4() {
   return i;
   return; // expected-error {{'auto' in return type deduced as 'void' here but deduced as 'int' in earlier return statement}}
+  // expected-note@-3 {{deducing return type for 'f4'}}
 }
 auto f5() {
   return i;
   return void(); // expected-error {{'auto' in return type deduced as 'void' here but deduced as 'int' in earlier return statement}}
+ // expected-note@-3 {{deducing return type for 'f5'}}
 }
 
 auto l1 = []() { };
@@ -44,10 +46,12 @@
 decltype(auto) f4() {
   return i;
   return; // expected-error {{'decltype(auto)' in return type deduced as 'void' here but deduced as 'int' in earlier return statement}}
+  // expected-note@-3 {{deducing return type for 'f4'}}
 }
 decltype(auto) f5() {
   return i;
   return void(); // expected-error {{'decltype(auto)' in return type deduced as 'void' here but deduced as 'int' in earlier 

[PATCH] D119927: [Clang] [P2025] More exhaustive tests for NRVO

2022-02-16 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added a comment.

Excellent!




Comment at: clang/test/CodeGenCXX/nrvo.cpp:622
+  if (b)
+return x;
+  else

Similar to what you did in `test5`, I think it'd be helpful to comment //on the 
return line itself// whether NRVO is (done|possible|impossible). E.g.
`return x; // NRVO is impossible`
or
`return x; // FIXME: NRVO could happen, but doesn't`
or
`return x; // NRVO happens`
Your existing comment "No NRVO" is ambiguous — you mean it //doesn't// happen, 
or it //can't possibly// happen? — and makes me think just a little more than I 
ought to, because I have to skim the code and figure out which variable(s) and 
which return statement(s) we're talking about.

(I can see it being arguable whether the comment should go on the `return x;` 
or on the `X x;`. Me personally, I'd put it on the `return`. But I don't care 
enough to argue if someone thinks it should go on the variable definition 
instead.)



Comment at: clang/test/CodeGenCXX/nrvo.cpp:1604
+  X x;
+  return x;
+}

E.g. here, IIUC, I would comment this as
```
return x; // NRVO happens
```


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119927

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


[PATCH] D119778: [clang] Add a note "deducing return type for 'foo'"

2022-02-16 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added a comment.

I'll update with the `CodeSynthesisContext` approach in a little bit. But 
meanwhile there's a problem with both the current patch //and// (I think even 
more) with the new approach. @rsmith any help?:
When I try my latest patch with the libc++ tests, with `bin/llvm-lit -sv 
--param enable_modules=True` (which corresponds to the `-fmodules` compiler 
flag), I get lots of errors like the following. Do you have any idea what's 
going wrong?

I can't minimize the example beyond "all of libc++" because Modules prevents 
`creduce` from doing anything meaningful. And unfortunately whatever's going 
wrong seems to be //specifically// about Modules.

  Assertion failed: (Replacement.isCanonical() && "replacement types must 
always be canonical"), function getSubstTemplateTypeParmType, file 
/Users/aodwyer/llvm-project/clang/lib/AST/ASTContext.cpp, line 4691.
  PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ 
and include the crash backtrace, preprocessed source, and associated run script.
  Stack dump:
  0.Program arguments: /Users/aodwyer/llvm-project/build3/bin/clang-14 -cc1 
-triple x86_64-apple-macosx10.15.0 -Wundef-prefix=TARGET_OS_ 
-Werror=undef-prefix -Wdeprecated-objc-isa-usage 
-Werror=deprecated-objc-isa-usage -emit-obj -mrelax-all --mrelax-relocations 
-disable-free -clear-ast-before-backend -main-file-name rbegin.pass.cpp 
-mrelocation-model pic -pic-level 2 -mframe-pointer=all -ffp-contract=on 
-fno-rounding-math -funwind-tables=2 -target-sdk-version=10.15.6 
-fcompatibility-qualified-id-block-type-checking 
-fvisibility-inlines-hidden-static-local-var -target-cpu penryn -tune-cpu 
generic -mllvm -treat-scalable-fixed-error-as-warning -debugger-tuning=lldb 
-target-linker-version 609.8 -v 
-fcoverage-compilation-dir=/Users/aodwyer/llvm-project/build3/projects/libcxx/test/std/ranges/range.access
 -nostdinc++ -resource-dir /Users/aodwyer/llvm-project/build3/lib/clang/15.0.0 
-isysroot /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk -isystem 
/Users/aodwyer/llvm-project/build3/include/c++/v1 -I 
/Users/aodwyer/llvm-project/build3/projects/libcxx/include/c++build -I 
/Users/aodwyer/llvm-project/libcxx/test/support -D _LIBCPP_DISABLE_AVAILABILITY 
-D _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER -stdlib=libc++ -internal-isystem 
/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/local/include 
-internal-isystem /Users/aodwyer/llvm-project/build3/lib/clang/15.0.0/include 
-internal-externc-isystem 
/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/usr/include -Werror 
-Wall -Wextra -Wshadow -Wundef -Wno-unused-command-line-argument 
-Wno-attributes -Wno-pessimizing-move -Wno-c++11-extensions 
-Wno-user-defined-literals -Wno-noexcept-type -Wno-atomic-alignment 
-Wsign-compare -Wunused-variable -Wunused-parameter -Wunreachable-code 
-Wno-unused-local-typedef -Werror=thread-safety -Wuser-defined-warnings 
-std=c++20 -fdeprecated-macro 
-fdebug-compilation-dir=/Users/aodwyer/llvm-project/build3/projects/libcxx/test/std/ranges/range.access
 -ferror-limit 19 -stack-protector 1 -fblocks -fencode-extended-block-signature 
-fcoroutines-ts -fregister-global-dtors-with-atexit -fgnuc-version=4.2.1 
-fmodules -fimplicit-module-maps 
-fmodules-cache-path=/var/folders/0l/9t0yv2890_g4wgmy53n_mg7wgy/C/clang/ModuleCache
 -fmodules-validate-system-headers -fcxx-exceptions -fexceptions 
-fmax-type-align=16 -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o 
/var/folders/0l/9t0yv2890_g4wgmy53n_mg7wgy/T/lit-tmp-fkh9o_f4/rbegin-d58043.o
 -x c++ 
/Users/aodwyer/llvm-project/libcxx/test/std/ranges/range.access/rbegin.pass.cpp
  1.
/Users/aodwyer/llvm-project/libcxx/test/support/test_iterators.h:524:30: 
current parser token '{'
  Stack dump without symbol names (ensure you have llvm-symbolizer in your PATH 
or set the environment var `LLVM_SYMBOLIZER_PATH` to point to it):
  0  clang-14 0x00010634385d 
llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) + 61
  1  clang-14 0x000106343ddb 
PrintStackTraceSignalHandler(void*) + 27
  2  clang-14 0x000106341cfa llvm::sys::RunSignalHandlers() 
+ 138
  3  clang-14 0x0001063457af SignalHandler(int) + 223
  4  libsystem_platform.dylib 0x7fff677255fd _sigtramp + 29
  5  libsystem_platform.dylib 0x7ffeed912f58 _sigtramp + 
18446744071664753016
  6  libsystem_c.dylib0x7fff675fb808 abort + 120
  7  libsystem_c.dylib0x7fff675faac6 err + 0
  8  clang-14 0x00010b769ce1 
clang::ASTContext::getSubstTemplateTypeParmType(clang::TemplateTypeParmType 
const*, clang::QualType) const + 161
  9  clang-14 0x00010b1feb40 (anonymous 
namespace)::TemplateInstantiator::TransformTemplateTypeParmType(clang::TypeLocBuilder&,
 clang::TemplateTypeParmTypeLoc) + 1456
  10 clang-14 0x00010b1ba74f 
clang::TreeTransform<(anonymous 

[PATCH] D119778: [clang] Add a note "deducing return type for 'foo'"

2022-02-15 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: clang/lib/Sema/SemaStmt.cpp:3805
+if (DAR != DAR_Succeeded) {
+  if (OrigResultType.getBeginLoc().isValid())
+Diag(OrigResultType.getBeginLoc(), diag::note_deducing_return_type_for)

> I am curious about the behavior if we removed the guard `if 
> (OrigResultType.getBeginLoc().isValid())`.

That caused the note to be emitted in some cases without a source location 
(similar to https://github.com/llvm/llvm-project/issues/29054 ). I admit I 
should check to make sure we have a test case for each of these four `if`s, 
though; I suspect we don't.
```
$ cat x.cpp
auto f = []() { return x; };

$ clang++ x.cpp
x.cpp:1:24: error: use of undeclared identifier 'x'
auto f = []() { return x; };
   ^
note: deducing return type for 'operator()'
1 error generated.
```


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119778

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


[PATCH] D119778: [clang] Add a note "deducing return type for 'foo'"

2022-02-15 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone updated this revision to Diff 409095.
Quuxplusone added a comment.

Rebase; adjust more expected output in tests.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119778

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaStmt.cpp
  clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.spec.auto/p2-1z.cpp
  clang/test/CXX/dcl/dcl.spec/dcl.type/dcl.spec.auto/p6.cpp
  clang/test/CXX/temp/temp.constr/temp.constr.constr/non-function-templates.cpp
  clang/test/Sema/invalid-bitwidth-expr.mm
  clang/test/SemaCXX/cxx20-p0388-unbound-ary.cpp
  clang/test/SemaCXX/cxx2b-consteval-if.cpp
  clang/test/SemaCXX/deduced-return-type-cxx14.cpp
  clang/test/SemaCXX/deduced-return-void.cpp
  clang/test/SemaCXX/std-compare-cxx2a.cpp
  clang/test/SemaCXX/typo-correction-crash.cpp
  clang/test/SemaOpenCLCXX/template-astype.cl
  clang/test/SemaTemplate/concepts.cpp

Index: clang/test/SemaTemplate/concepts.cpp
===
--- clang/test/SemaTemplate/concepts.cpp
+++ clang/test/SemaTemplate/concepts.cpp
@@ -114,6 +114,7 @@
   }
   template void g5() {
 ([]() -> C auto{ // expected-error-re {{deduced type {{.*}} does not satisfy}}
+// expected-note@-1 {{deducing return type for 'operator()'}}
  return T();
  }(), ...);
   }
@@ -174,11 +175,17 @@
   template concept C = false; // expected-note 6 {{because 'false' evaluated to false}}
 
   C auto f1() { return void(); }   // expected-error {{deduced type 'void' does not satisfy 'C'}}
+   // expected-note@-1 {{deducing return type for 'f1'}}
   C auto f2() { return; }  // expected-error {{deduced type 'void' does not satisfy 'C'}}
+   // expected-note@-1 {{deducing return type for 'f2'}}
   C auto f3() {}   // expected-error {{deduced type 'void' does not satisfy 'C'}}
+   // expected-note@-1 {{deducing return type for 'f3'}}
   C decltype(auto) f4() { return void(); } // expected-error {{deduced type 'void' does not satisfy 'C'}}
+   // expected-note@-1 {{deducing return type for 'f4'}}
   C decltype(auto) f5() { return; }// expected-error {{deduced type 'void' does not satisfy 'C'}}
+   // expected-note@-1 {{deducing return type for 'f5'}}
   C decltype(auto) f6() {} // expected-error {{deduced type 'void' does not satisfy 'C'}}
+   // expected-note@-1 {{deducing return type for 'f6'}}
 
   void g() {
 f1();
Index: clang/test/SemaOpenCLCXX/template-astype.cl
===
--- clang/test/SemaOpenCLCXX/template-astype.cl
+++ clang/test/SemaOpenCLCXX/template-astype.cl
@@ -11,6 +11,7 @@
 
 auto neg_test_int(int x) { return templated_astype(x); }
 // expected-note@-1{{in instantiation of function template specialization 'templated_astype' requested here}}
+// expected-note@-2{{deducing return type for 'neg_test_int'}}
 
 auto test_short4(short4 x) { return templated_astype(x); }
 
Index: clang/test/SemaCXX/typo-correction-crash.cpp
===
--- clang/test/SemaCXX/typo-correction-crash.cpp
+++ clang/test/SemaCXX/typo-correction-crash.cpp
@@ -2,6 +2,7 @@
 auto check1() {
   return 1;
   return s; // expected-error {{use of undeclared identifier 's'}}
+// expected-note@-3 {{deducing return type for 'check1'}}
 }
 
 int test = 11; // expected-note 2 {{'test' declared here}}
@@ -9,6 +10,7 @@
   return "s";
   return tes; // expected-error {{use of undeclared identifier 'tes'; did you mean 'test'?}}
   // expected-error@-1 {{deduced as 'int' here but deduced as 'const char *' in earlier}}
+  // expected-note@-4 {{deducing return type for 'check2'}}
 }
 
 template  struct is_same { static constexpr bool value = false; };
Index: clang/test/SemaCXX/std-compare-cxx2a.cpp
===
--- clang/test/SemaCXX/std-compare-cxx2a.cpp
+++ clang/test/SemaCXX/std-compare-cxx2a.cpp
@@ -32,6 +32,7 @@
 auto compare_incomplete_test() {
   // expected-error@+1 {{incomplete type 'std::partial_ordering' where a complete type is required}}
   return (-1.2 <=> 123.0);
+  // expected-note@-3 {{deducing return type for 'compare_incomplete_test'}}
 }
 
 namespace std {
@@ -45,6 +46,7 @@
 auto missing_member_test() {
   // expected-error@+1 {{standard library implementation of 'std::partial_ordering' is not supported; member 'equivalent' is missing}}
   return (1.0 <=> 1.0);
+  // expected-note@-3 {{deducing return type for 'missing_member_test'}}
 }
 
 namespace std {
@@ -59,6 +61,7 @@
 auto 

[PATCH] D119184: [clang] [concepts] Check constrained-auto return types for void-returning functions

2022-02-15 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone updated this revision to Diff 409090.
Quuxplusone added a comment.

Rebase; fix the clang-format nit; reinsert a missing `FD->setInvalidDecl()` 
that seemed to be causing crashes in Modules code under libcxx/test/ but 
otherwise doesn't seem to be tested in clang/test/ :(


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119184

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaStmt.cpp
  clang/test/SemaTemplate/concepts.cpp

Index: clang/test/SemaTemplate/concepts.cpp
===
--- clang/test/SemaTemplate/concepts.cpp
+++ clang/test/SemaTemplate/concepts.cpp
@@ -169,3 +169,23 @@
   template void f(T, U) = delete;
   void g() { f(0, 0); }
 }
+
+namespace PR49188 {
+  template concept C = false; // expected-note 6 {{because 'false' evaluated to false}}
+
+  C auto f1() { return void(); }   // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  C auto f2() { return; }  // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  C auto f3() {}   // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  C decltype(auto) f4() { return void(); } // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  C decltype(auto) f5() { return; }// expected-error {{deduced type 'void' does not satisfy 'C'}}
+  C decltype(auto) f6() {} // expected-error {{deduced type 'void' does not satisfy 'C'}}
+
+  void g() {
+f1();
+f2();
+f3();
+f4();
+f5();
+f6();
+  }
+}
Index: clang/lib/Sema/SemaStmt.cpp
===
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -3590,7 +3590,8 @@
 
 AutoType *AT = CurCap->ReturnType->getContainedAutoType();
 assert(AT && "lost auto type from lambda return type");
-if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) {
+if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT,
+ /*HasReturnStmt=*/true)) {
   FD->setInvalidDecl();
   // FIXME: preserve the ill-formed return expression.
   return StmtError();
@@ -3761,9 +3762,9 @@
 /// C++1y [dcl.spec.auto]p6.
 bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
 SourceLocation ReturnLoc,
-Expr *,
-AutoType *AT) {
-  // If this is the conversion function for a lambda, we choose to deduce it
+Expr *, const AutoType *AT,
+bool HasReturnStmt) {
+  // If this is the conversion function for a lambda, we choose to deduce its
   // type from the corresponding call operator, not from the synthesized return
   // statement within it. See Sema::DeduceReturnType.
   if (isLambdaConversionOperator(FD))
@@ -3808,19 +3809,26 @@
 LocalTypedefNameReferencer Referencer(*this);
 Referencer.TraverseType(RetExpr->getType());
   } else {
-//  In the case of a return with no operand, the initializer is considered
-//  to be void().
-//
-// Deduction here can only succeed if the return type is exactly 'cv auto'
-// or 'decltype(auto)', so just check for that case directly.
-if (!OrigResultType.getType()->getAs()) {
+// For a function with a deduced result type to return void,
+// the result type as written must be 'auto' or 'decltype(auto)',
+// possibly cv-qualified or constrained, but not ref-qualified.
+if (!FD->getReturnType()->getAs()) {
   Diag(ReturnLoc, diag::err_auto_fn_return_void_but_not_auto)
-<< OrigResultType.getType();
+  << OrigResultType.getType();
   return true;
 }
-// We always deduce U = void in this case.
-Deduced = SubstAutoType(OrigResultType.getType(), Context.VoidTy);
-if (Deduced.isNull())
+// In the case of a return with no operand, the initializer is considered
+// to be 'void()'.
+Expr *Dummy = new (Context) CXXScalarValueInitExpr(
+Context.VoidTy,
+Context.getTrivialTypeSourceInfo(Context.VoidTy, ReturnLoc), ReturnLoc);
+DeduceAutoResult DAR = DeduceAutoType(OrigResultType, Dummy, Deduced);
+
+if (DAR == DAR_Failed && !FD->isInvalidDecl())
+  Diag(ReturnLoc, diag::err_auto_fn_deduction_failure)
+  << OrigResultType.getType() << Dummy->getType();
+
+if (DAR != DAR_Succeeded)
   return true;
   }
 
@@ -3989,7 +3997,8 @@
   // trying to deduce its return type.
   // (Some return values may be needlessly wrapped in RecoveryExpr).
   if (FD->isInvalidDecl() ||
-  DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) {
+  

[PATCH] D119893: [clang-format] Fixed handling of requires clauses followed by attributes

2022-02-15 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: clang/lib/Format/UnwrappedLineParser.cpp:3018-3019
   do {
+bool LambdaThisTimeAllowed = LambdaNextTimeAllowed;
+LambdaNextTimeAllowed = false;
+

Nit: For this pattern, consider `bool LambdaThisTimeAllowed = 
std::exchange(LambdaNextTimeAllowed, false);`



Comment at: clang/lib/Format/UnwrappedLineParser.cpp:3102
+  LambdaNextTimeAllowed = true;
+  LLVM_FALLTHROUGH;
+case tok::numeric_constant:

This seems like an overuse of fallthrough; how about simply
```
LambdaNextTimeAllowed = true;
nextToken();
break;
```
?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119893

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


[PATCH] D119792: [Clang] [P2025] Analyze only potential scopes for NRVO

2022-02-15 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added a reviewer: mizvekov.
Quuxplusone added a comment.

The code is above my pay grade, but FWIW, I super support the intent of this 
patch! Let's get p2025 support into Clang! :)

> The collection of common cases contains 20 examples: §4.1. Examples. Here is 
> the current status of these examples:
>
> [OK] 13 out of 20 examples are working in Clang as expected.
> [FAIL] 13th example: should be considered separately (as part of fixing 
> consteval code)
> [FAIL] 14th example: should be considered separately (as I haven't looked yet 
> how CXXCatchStmt works).
> [FAIL] 18th example: is unfixable now because of Clang's architecture: my 
> comment on the issue.
> [OK with the patch] 7th, 8th, 11th, 15th example: are working with this patch.

I think it would be an extremely good idea to commit all 20 of these test cases 
to clang/test/CodeGenCXX/, with their current behavior, as a preliminary patch. 
Then, D119792  can more clearly show (1) what 
behavior it's changing, (2) what behavior it's keeping the same, and (3) the 
fact that it's not regressing any behavior.  Also, you'll help 
future-maintainers by giving them some extra test cases that have already been 
identified as interesting, even if you personally aren't changing behavior 
related to those particular test cases.

(I recently took the same tactic with D119772 
 as a preliminary for D119184 
 + D119778 
, and it was very helpful, at least to me. :))


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119792

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


[PATCH] D119778: [clang] Add a note "deducing return type for 'foo'"

2022-02-14 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone created this revision.
Quuxplusone added reviewers: sammccall, rsmith, dblaikie, majnemer, mizvekov, 
ChuanqiXu.
Quuxplusone added a project: clang.
Quuxplusone requested review of this revision.
Herald added a subscriber: cfe-commits.

Emit the note when we fail to deduce a return type, or deduce conflicting 
return types.

It's emitted a //little// too eagerly, e.g. I wish we could avoid it in cases 
like

  $ bin/clang++ x.cpp
  x.cpp:1:19: error: use of undeclared identifier 'x'
  auto f() { return x; }
^
  x.cpp:1:1: note: deducing return type for 'f'
  auto f() { return x; }
  ^~~~
  1 error generated.

But Clang doesn't seem to be able to distinguish "parsing and type-checking the 
return //expression//" from "deducing the function's actual return //type//," 
and I'm not inclined to dig this rabbit hole deeper than I already have. I 
think this is still a reasonably clean place to stop digging.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D119778

Files:
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/Sema/SemaStmt.cpp
  clang/test/Sema/invalid-bitwidth-expr.mm
  clang/test/SemaCXX/cxx20-p0388-unbound-ary.cpp
  clang/test/SemaCXX/cxx2b-consteval-if.cpp
  clang/test/SemaCXX/deduced-return-type-cxx14.cpp
  clang/test/SemaCXX/deduced-return-void.cpp
  clang/test/SemaCXX/std-compare-cxx2a.cpp
  clang/test/SemaCXX/typo-correction-crash.cpp
  clang/test/SemaOpenCLCXX/template-astype.cl
  clang/test/SemaTemplate/concepts.cpp

Index: clang/test/SemaTemplate/concepts.cpp
===
--- clang/test/SemaTemplate/concepts.cpp
+++ clang/test/SemaTemplate/concepts.cpp
@@ -114,6 +114,7 @@
   }
   template void g5() {
 ([]() -> C auto{ // expected-error-re {{deduced type {{.*}} does not satisfy}}
+// expected-note@-1 {{deducing return type for 'operator()'}}
  return T();
  }(), ...);
   }
@@ -174,11 +175,17 @@
   template concept C = false; // expected-note 6 {{because 'false' evaluated to false}}
 
   C auto f1() { return void(); }   // expected-error {{deduced type 'void' does not satisfy 'C'}}
+   // expected-note@-1 {{deducing return type for 'f1'}}
   C auto f2() { return; }  // expected-error {{deduced type 'void' does not satisfy 'C'}}
+   // expected-note@-1 {{deducing return type for 'f2'}}
   C auto f3() {}   // expected-error {{deduced type 'void' does not satisfy 'C'}}
+   // expected-note@-1 {{deducing return type for 'f3'}}
   C decltype(auto) f4() { return void(); } // expected-error {{deduced type 'void' does not satisfy 'C'}}
+   // expected-note@-1 {{deducing return type for 'f4'}}
   C decltype(auto) f5() { return; }// expected-error {{deduced type 'void' does not satisfy 'C'}}
+   // expected-note@-1 {{deducing return type for 'f5'}}
   C decltype(auto) f6() {} // expected-error {{deduced type 'void' does not satisfy 'C'}}
+   // expected-note@-1 {{deducing return type for 'f6'}}
 
   void g() {
 f1();
Index: clang/test/SemaOpenCLCXX/template-astype.cl
===
--- clang/test/SemaOpenCLCXX/template-astype.cl
+++ clang/test/SemaOpenCLCXX/template-astype.cl
@@ -11,6 +11,7 @@
 
 auto neg_test_int(int x) { return templated_astype(x); }
 // expected-note@-1{{in instantiation of function template specialization 'templated_astype' requested here}}
+// expected-note@-2{{deducing return type for 'neg_test_int'}}
 
 auto test_short4(short4 x) { return templated_astype(x); }
 
Index: clang/test/SemaCXX/typo-correction-crash.cpp
===
--- clang/test/SemaCXX/typo-correction-crash.cpp
+++ clang/test/SemaCXX/typo-correction-crash.cpp
@@ -2,6 +2,7 @@
 auto check1() {
   return 1;
   return s; // expected-error {{use of undeclared identifier 's'}}
+// expected-note@-3 {{deducing return type for 'check1'}}
 }
 
 int test = 11; // expected-note 2 {{'test' declared here}}
@@ -9,6 +10,7 @@
   return "s";
   return tes; // expected-error {{use of undeclared identifier 'tes'; did you mean 'test'?}}
   // expected-error@-1 {{deduced as 'int' here but deduced as 'const char *' in earlier}}
+  // expected-note@-4 {{deducing return type for 'check2'}}
 }
 
 template  struct is_same { static constexpr bool value = false; };
Index: clang/test/SemaCXX/std-compare-cxx2a.cpp
===
--- clang/test/SemaCXX/std-compare-cxx2a.cpp
+++ clang/test/SemaCXX/std-compare-cxx2a.cpp
@@ -32,6 +32,7 @@
 auto compare_incomplete_test() {
   // 

[PATCH] D119184: [clang] [concepts] Check constrained-auto return types for void-returning functions

2022-02-14 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone updated this revision to Diff 408594.
Quuxplusone marked an inline comment as done and an inline comment as not done.
Quuxplusone added a comment.

Address review comments; add exhaustive tests as a parent revision.


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

https://reviews.llvm.org/D119184

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaStmt.cpp
  clang/test/SemaTemplate/concepts.cpp

Index: clang/test/SemaTemplate/concepts.cpp
===
--- clang/test/SemaTemplate/concepts.cpp
+++ clang/test/SemaTemplate/concepts.cpp
@@ -169,3 +169,23 @@
   template void f(T, U) = delete;
   void g() { f(0, 0); }
 }
+
+namespace PR49188 {
+  template concept C = false; // expected-note 6 {{because 'false' evaluated to false}}
+
+  C auto f1() { return void(); }   // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  C auto f2() { return; }  // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  C auto f3() {}   // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  C decltype(auto) f4() { return void(); } // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  C decltype(auto) f5() { return; }// expected-error {{deduced type 'void' does not satisfy 'C'}}
+  C decltype(auto) f6() {} // expected-error {{deduced type 'void' does not satisfy 'C'}}
+
+  void g() {
+f1();
+f2();
+f3();
+f4();
+f5();
+f6();
+  }
+}
Index: clang/lib/Sema/SemaStmt.cpp
===
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -3590,7 +3590,8 @@
 
 AutoType *AT = CurCap->ReturnType->getContainedAutoType();
 assert(AT && "lost auto type from lambda return type");
-if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) {
+if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT,
+ /*HasReturnStmt=*/true)) {
   FD->setInvalidDecl();
   // FIXME: preserve the ill-formed return expression.
   return StmtError();
@@ -3761,9 +3762,9 @@
 /// C++1y [dcl.spec.auto]p6.
 bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
 SourceLocation ReturnLoc,
-Expr *,
-AutoType *AT) {
-  // If this is the conversion function for a lambda, we choose to deduce it
+Expr *, const AutoType *AT,
+bool HasReturnStmt) {
+  // If this is the conversion function for a lambda, we choose to deduce its
   // type from the corresponding call operator, not from the synthesized return
   // statement within it. See Sema::DeduceReturnType.
   if (isLambdaConversionOperator(FD))
@@ -3808,19 +3809,26 @@
 LocalTypedefNameReferencer Referencer(*this);
 Referencer.TraverseType(RetExpr->getType());
   } else {
-//  In the case of a return with no operand, the initializer is considered
-//  to be void().
-//
-// Deduction here can only succeed if the return type is exactly 'cv auto'
-// or 'decltype(auto)', so just check for that case directly.
-if (!OrigResultType.getType()->getAs()) {
+// For a function with a deduced result type to return void,
+// the result type as written must be 'auto' or 'decltype(auto)',
+// possibly cv-qualified or constrained, but not ref-qualified.
+if (!FD->getReturnType()->getAs()) {
   Diag(ReturnLoc, diag::err_auto_fn_return_void_but_not_auto)
-<< OrigResultType.getType();
+  << OrigResultType.getType();
   return true;
 }
-// We always deduce U = void in this case.
-Deduced = SubstAutoType(OrigResultType.getType(), Context.VoidTy);
-if (Deduced.isNull())
+// In the case of a return with no operand, the initializer is considered
+// to be 'void()'.
+Expr *Dummy = new (Context) CXXScalarValueInitExpr(
+Context.VoidTy,
+Context.getTrivialTypeSourceInfo(Context.VoidTy, ReturnLoc), ReturnLoc);
+DeduceAutoResult DAR = DeduceAutoType(OrigResultType, Dummy, Deduced);
+
+if (DAR == DAR_Failed && !FD->isInvalidDecl())
+  Diag(ReturnLoc, diag::err_auto_fn_deduction_failure)
+<< OrigResultType.getType() << Dummy->getType();
+
+if (DAR != DAR_Succeeded)
   return true;
   }
 
@@ -3989,7 +3997,8 @@
   // trying to deduce its return type.
   // (Some return values may be needlessly wrapped in RecoveryExpr).
   if (FD->isInvalidDecl() ||
-  DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) {
+  DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT,
+   /*HasReturnStmt=*/true)) 

[PATCH] D119772: [clang] [NFC] More exhaustive tests for deducing void return types

2022-02-14 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone created this revision.
Quuxplusone added reviewers: sammccall, rsmith, dblaikie, mizvekov.
Quuxplusone added a project: clang.
Quuxplusone requested review of this revision.
Herald added a subscriber: cfe-commits.

This is a preliminary ahead of D119184  (I'll 
rebase that one on top of this). This shows what Clang's //current// behavior 
is for various deduced-return-type situations. Then, in D119184 
, I'll be able to demonstrate exactly how the 
diagnostics on each of these situations change.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D119772

Files:
  clang/test/SemaCXX/deduced-return-void.cpp

Index: clang/test/SemaCXX/deduced-return-void.cpp
===
--- clang/test/SemaCXX/deduced-return-void.cpp
+++ clang/test/SemaCXX/deduced-return-void.cpp
@@ -4,20 +4,137 @@
 // Check that we don't get any extra warning for "return" without an
 // expression, in a function that might have been intended to return
 // void all along.
-auto f1() {
-  return 1;
-  return; // expected-error {{deduced as 'void' here but deduced as 'int' in earlier return statement}}
+decltype(h1) h1() { // expected-error {{use of undeclared identifier 'h1'}}
+  return;
+}
+
+namespace JustAuto {
+int i;
+auto f1() { }
+auto f2() { return; }
+auto f3() { return void(); }
+auto f4() {
+  return i;
+  return; // expected-error {{'auto' in return type deduced as 'void' here but deduced as 'int' in earlier return statement}}
+}
+auto f5() {
+  return i;
+  return void(); // expected-error {{'auto' in return type deduced as 'void' here but deduced as 'int' in earlier return statement}}
 }
 
-decltype(auto) f2() {
-  return 1;
-  return; // expected-error {{deduced as 'void' here but deduced as 'int' in earlier return statement}}
+auto l1 = []() { };
+auto l2 = []() { return; };
+auto l3 = []() { return void(); };
+auto l4 = []() {
+  return i;
+  return; // expected-error {{return type 'void' must match previous return type 'int' when lambda expression has unspecified explicit return type}}
+};
+auto l5 = []() {
+  return i;
+  return void(); // expected-error {{return type 'void' must match previous return type 'int' when lambda expression has unspecified explicit return type}}
+};
+
+} // namespace JustAuto
+
+namespace DecltypeAuto {
+int i;
+decltype(auto) f1() { }
+decltype(auto) f2() { return; }
+decltype(auto) f3() { return void(); }
+decltype(auto) f4() {
+  return i;
+  return; // expected-error {{'decltype(auto)' in return type deduced as 'void' here but deduced as 'int' in earlier return statement}}
+}
+decltype(auto) f5() {
+  return i;
+  return void(); // expected-error {{'decltype(auto)' in return type deduced as 'void' here but deduced as 'int' in earlier return statement}}
 }
 
-auto *g() {
+auto l1 = []() -> decltype(auto) { };
+auto l2 = []() -> decltype(auto) { return; };
+auto l3 = []() -> decltype(auto) { return void(); };
+auto l4 = []() -> decltype(auto) {
+  return i;
+  return; // expected-error {{'decltype(auto)' in return type deduced as 'void' here but deduced as 'int' in earlier return statement}}
+};
+auto l5 = []() -> decltype(auto) {
+  return i;
+  return void(); // expected-error {{'decltype(auto)' in return type deduced as 'void' here but deduced as 'int' in earlier return statement}}
+};
+
+} // namespace DecltypeAuto
+
+namespace AutoPtr {
+int i;
+auto *f1() { } // expected-error {{cannot deduce return type 'auto *' for function with no return statements}}
+auto *f2() {
+  return; // expected-error {{cannot deduce return type 'auto *' from omitted return expression}}
+}
+auto *f3() {
+  return void(); // expected-error {{cannot deduce return type 'auto *' from returned value of type 'void'}}
+}
+auto *f4() {
+  return 
   return; // expected-error {{cannot deduce return type 'auto *' from omitted return expression}}
 }
+auto *f5() {
+  return 
+  return void(); // expected-error {{cannot deduce return type 'auto *' from returned value of type 'void'}}
+}
 
-decltype(h1) h1() { // expected-error {{use of undeclared identifier 'h1'}}
-  return;
+auto l1 = []() -> auto* { }; // expected-error {{cannot deduce return type 'auto *' for function with no return statements}}
+auto l2 = []() -> auto* {
+  return; // expected-error {{cannot deduce return type 'auto *' from omitted return expression}}
+};
+auto l3 = []() -> auto* {
+  return void(); // expected-error {{cannot deduce return type 'auto *' from returned value of type 'void'}}
+};
+auto l4 = []() -> auto* {
+  return 
+  return; // expected-error {{cannot deduce return type 'auto *' from omitted return expression}}
+};
+auto l5 = []() -> auto* {
+  return 
+  return void(); // expected-error {{cannot deduce return type 'auto *' from returned value of type 'void'}}
+};
+} // namespace AutoPtr
+
+namespace AutoRef {
+int i;
+auto& f1() { // expected-error {{cannot deduce return type 'auto &' for 

[PATCH] D119094: [clang] Don't emit redundant warnings for 'return;'

2022-02-14 Thread Arthur O'Dwyer via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG3c8d2aa87c17: [clang] Dont emit redundant warnings for 
return; (authored by arthur.j.odwyer).

Changed prior to commit:
  https://reviews.llvm.org/D119094?vs=406838=408434#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119094

Files:
  clang/lib/Sema/SemaStmt.cpp
  clang/test/SemaCXX/deduced-return-void.cpp


Index: clang/test/SemaCXX/deduced-return-void.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/deduced-return-void.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
+
+// Check that we don't get any extra warning for "return" without an
+// expression, in a function that might have been intended to return
+// void all along.
+auto f1() {
+  return 1;
+  return; // expected-error {{deduced as 'void' here but deduced as 'int' in 
earlier return statement}}
+}
+
+decltype(auto) f2() {
+  return 1;
+  return; // expected-error {{deduced as 'void' here but deduced as 'int' in 
earlier return statement}}
+}
+
+auto *g() {
+  return; // expected-error {{cannot deduce return type 'auto *' from omitted 
return expression}}
+}
+
+decltype(h1) h1() { // expected-error {{use of undeclared identifier 'h1'}}
+  return;
+}
Index: clang/lib/Sema/SemaStmt.cpp
===
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -4098,7 +4098,9 @@
   } else if (!RetValExp && !HasDependentReturnType) {
 FunctionDecl *FD = getCurFunctionDecl();
 
-if (getLangOpts().CPlusPlus11 && FD && FD->isConstexpr()) {
+if ((FD && FD->isInvalidDecl()) || FnRetType->containsErrors()) {
+  // The intended return type might have been "void", so don't warn.
+} else if (getLangOpts().CPlusPlus11 && FD && FD->isConstexpr()) {
   // C++11 [stmt.return]p2
   Diag(ReturnLoc, diag::err_constexpr_return_missing_expr)
   << FD << FD->isConsteval();


Index: clang/test/SemaCXX/deduced-return-void.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/deduced-return-void.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
+
+// Check that we don't get any extra warning for "return" without an
+// expression, in a function that might have been intended to return
+// void all along.
+auto f1() {
+  return 1;
+  return; // expected-error {{deduced as 'void' here but deduced as 'int' in earlier return statement}}
+}
+
+decltype(auto) f2() {
+  return 1;
+  return; // expected-error {{deduced as 'void' here but deduced as 'int' in earlier return statement}}
+}
+
+auto *g() {
+  return; // expected-error {{cannot deduce return type 'auto *' from omitted return expression}}
+}
+
+decltype(h1) h1() { // expected-error {{use of undeclared identifier 'h1'}}
+  return;
+}
Index: clang/lib/Sema/SemaStmt.cpp
===
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -4098,7 +4098,9 @@
   } else if (!RetValExp && !HasDependentReturnType) {
 FunctionDecl *FD = getCurFunctionDecl();
 
-if (getLangOpts().CPlusPlus11 && FD && FD->isConstexpr()) {
+if ((FD && FD->isInvalidDecl()) || FnRetType->containsErrors()) {
+  // The intended return type might have been "void", so don't warn.
+} else if (getLangOpts().CPlusPlus11 && FD && FD->isConstexpr()) {
   // C++11 [stmt.return]p2
   Diag(ReturnLoc, diag::err_constexpr_return_missing_expr)
   << FD << FD->isConsteval();
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D119670: [clang] Warn on unqualified calls to std::move and std::forward

2022-02-14 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: clang/lib/Sema/SemaExpr.cpp:6437
+  NamedDecl *D = dyn_cast_or_null(Call->getCalleeDecl());
+  if (!D || !D->isInStdNamespace())
+return;

cor3ntin wrote:
> erichkeane wrote:
> > Quuxplusone wrote:
> > > erichkeane wrote:
> > > > Do we really want this?  I guess I would think doing:
> > > > 
> > > > 
> > > > ```
> > > > void MyFunc(auto whatever) {
> > > >   auto X = move(whatever);
> > > > ```
> > > > 
> > > > when I MEAN std::move, just for it to pick up a non-std::move the 1st 
> > > > time is likely the same problem?  Or should it get a separate warning?
> > > That's a good point (IMHO). Perhaps instead of making this a specific 
> > > case of "warn for unqualified call to things in `std` (namely `move` and 
> > > `forward`)," we should make it a specific case of "warn for any 
> > > unqualified use of //this identifier// (namely `move` and `forward`)." 
> > > That's closer in spirit to Nico Josuttis's comment that `move` is almost 
> > > like a keyword in modern C++, and therefore shouldn't be thrown around 
> > > willy-nilly. Either you mean `std::move` (in which case qualify it), or 
> > > you mean some other `my::move` (in which case qualify it), but using the 
> > > bare word `move` is inappropriate in modern C++ no matter whether it 
> > > //currently// finds something out of `std` or not.
> > > I'm ambivalent between these two ways of looking at the issue. Maybe 
> > > someone can think up a reason to prefer one or the other?
> > > 
> > > libc++'s tests do include several recently-added instances of `move` as a 
> > > //variable name//, e.g. `auto copy(x); auto move(std::move(x));`. This 
> > > confuses grep but would not confuse Clang, for better and worse. I don't 
> > > expect that real code would ever do this, either.
> > > 
> > > @erichkeane's specific example is a //template//, which means it's going 
> > > to be picked up by D72282 `clang-tidy bugprone-unintended-adl` also. 
> > > Using ADL inside templates triggers multiple red flags simultaneously. 
> > > Whereas this D119670 is the only thing that's going to catch unqualified 
> > > `move` in //non-template// code.
> > > That's a good point (IMHO). Perhaps instead of making this a specific 
> > > case of "warn for unqualified call to things in `std` (namely `move` and 
> > > `forward`)," we should make it a specific case of "warn for any 
> > > unqualified use of //this identifier// (namely `move` and `forward`)." 
> > > That's closer in spirit to Nico Josuttis's comment that `move` is almost 
> > > like a keyword in modern C++, and therefore shouldn't be thrown around 
> > > willy-nilly. Either you mean `std::move` (in which case qualify it), or 
> > > you mean some other `my::move` (in which case qualify it), but using the 
> > > bare word `move` is inappropriate in modern C++ no matter whether it 
> > > //currently// finds something out of `std` or not.
> > 
> > Ah! I guess that was just my interpretation of how this patch worked: Point 
> > out troublesome 'keyword-like-library-functions' used unqualified.  I think 
> > the alternative (warn for unqualified call to things in std) is so 
> > incredibly noisy as to be worthless, particularly in light of 'using' 
> > statements.
> > 
> > > @erichkeane's specific example is a //template//, which means it's going 
> > > to be picked up by D72282 `clang-tidy bugprone-unintended-adl` also. 
> > > Using ADL inside templates triggers multiple red flags simultaneously. 
> > > Whereas this D119670 is the only thing that's going to catch unqualified 
> > > `move` in //non-template// code.
> > 
> > This was a template for convenience sake (so y'all couldn't "well actually" 
> > me on the type I chose), but good to know we have a warning like that!
> > 
> > What I was TRYING to point out a case where the person is using `move` or 
> > `forward` intending to have the `std` version, but accidentially ending up 
> > with thier own version.
> It is *likely* the same problem. The problem is the "likely" does a lot of 
> heavy lifting here.
> I think there is general agreement that std::move should be called qualified, 
> not that `move` is somehow a special identifier that users should not use. 
> These are almost contradictory statements - aka if we wanted to discourage 
> people to name their function move, we wouldn't also need or want to force 
> them to qualify their call.
> 
> It is very possible that `std::move` cannot be used at all in the TU because 
> it is simply not declared, in which case the code would be perfectly fine.
> A slightly more involved approach would be to try to detect whether std::move 
> is declared by doing a lookup and warn in that case, but I'm not sure that 
> brings much.
> I certainly disagree that calling a function `move` is cause for warning.
> I certainly disagree that calling a function `move` is cause for warning.

Right, agreed. For example, `boost::move` exists, and that's 

[PATCH] D113369: [clang-format] Extend SpaceBeforeParens for requires

2022-02-14 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: clang/docs/ClangFormatStyleOptions.rst:4007
 
+  * ``bool AfterRequiresKeywordInRequiresClause`` If ``true``, put space 
between requires keyword in a requires clause and
+opening parentheses, if there is one.

curdeius wrote:
> Wouldn't `AfterRequiresInClause`/`AfterRequiresInExpression` be meaningful 
> enough?
+1, I have no problem with `AfterRequiresInClause` and 
`AfterRequiresInExpression`!


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

https://reviews.llvm.org/D113369

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


[PATCH] D119670: [clang] Warn on unqualified calls to std::move and std::forward

2022-02-14 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added a comment.

Tangential data point: I hacked up this check to find //all// unqualified `std` 
functions and ran it on libc++'s tests and also on some of my own codebase 
(including re2, asio, protobuf). I'm fixing the issues it turned up in libc++'s 
tests. In the other codebases, there was a lot of `min` and `max` in multiple 
codebases; several uses of `back_inserter` and `getline` across different 
codebases; scattered probably-accidental use of algorithms in protobuf (`sort`, 
`stable_sort`, `binary_search`); one file contained `using std::setw` etc.; and 
asio makes very heavy use of unqualified `declval`.
This is irrelevant to Corentin's interests with this PR; I'm just dumping the 
finding here in case anyone's ever interested in generalizing this check and 
wants to know what it would find.




Comment at: clang/lib/Sema/SemaExpr.cpp:6437
+  NamedDecl *D = dyn_cast_or_null(Call->getCalleeDecl());
+  if (!D || !D->isInStdNamespace())
+return;

erichkeane wrote:
> Do we really want this?  I guess I would think doing:
> 
> 
> ```
> void MyFunc(auto whatever) {
>   auto X = move(whatever);
> ```
> 
> when I MEAN std::move, just for it to pick up a non-std::move the 1st time is 
> likely the same problem?  Or should it get a separate warning?
That's a good point (IMHO). Perhaps instead of making this a specific case of 
"warn for unqualified call to things in `std` (namely `move` and `forward`)," 
we should make it a specific case of "warn for any unqualified use of //this 
identifier// (namely `move` and `forward`)." That's closer in spirit to Nico 
Josuttis's comment that `move` is almost like a keyword in modern C++, and 
therefore shouldn't be thrown around willy-nilly. Either you mean `std::move` 
(in which case qualify it), or you mean some other `my::move` (in which case 
qualify it), but using the bare word `move` is inappropriate in modern C++ no 
matter whether it //currently// finds something out of `std` or not.
I'm ambivalent between these two ways of looking at the issue. Maybe someone 
can think up a reason to prefer one or the other?

libc++'s tests do include several recently-added instances of `move` as a 
//variable name//, e.g. `auto copy(x); auto move(std::move(x));`. This confuses 
grep but would not confuse Clang, for better and worse. I don't expect that 
real code would ever do this, either.

@erichkeane's specific example is a //template//, which means it's going to be 
picked up by D72282 `clang-tidy bugprone-unintended-adl` also. Using ADL inside 
templates triggers multiple red flags simultaneously. Whereas this D119670 is 
the only thing that's going to catch unqualified `move` in //non-template// 
code.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119670

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


[PATCH] D119670: [clang] Warn on unqualified calls to std::move and std::forward

2022-02-13 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: clang/include/clang/Basic/DiagnosticSemaKinds.td:4812
+def warn_unqualified_call_to_std_function : Warning<
+  "unqualified call to %0">, InGroup>;
+

This should probably be named `-Wunqualified-std-move` resp. 
`-Wunqualified-std-forward`, so that we preserve our ability to add a more 
generalized `-Wunqualified-std-call` diagnostic (probably not enabled by 
default) in the future.

I'd actually like to go ahead and add the generalized diagnostic right now, 
since it would be about 10 extra lines of code, and at least //I// would use it 
as soon as it landed in trunk! But I'm prepared for that to be controversial 
and wouldn't necessarily pick that hill to die on. :)  (Ah, and I'm reminded 
that the generalized diagnostic would need a bigger list of hard-coded 
functions to ignore, such as `swap` and `begin` and `end` and so on.)



Comment at: clang/test/SemaCXX/unqualified-std-call.cpp:34
+  std::move(foo);
+  move(foo); // expected-warning{{unqualified call to std::move}}
+

I'd like to see a test where the template finds `move` via ADL, rather than 
being directly in the scope of a `using namespace std` directive. This is the 
most important case AIUI, because we can train people not to `using namespace` 
but we can't so easily train them not to accidentally forget a `std::`.
I'd like to see a couple of tests where the (function, resp. template) is 
itself located inside `namespace std`. (You mention you deliberately want to 
warn on this, and I think that's good, but I don't see any tests for it.)
I'd like to see a test where the `std::move` that is found by lookup is 
actually `std::__1::move` with an inline namespace, because that's what libc++ 
actually does in practice. (This should still warn.)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119670

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


[PATCH] D119138: [clang-format] Further improve support for requires expressions

2022-02-11 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: clang/lib/Format/UnwrappedLineParser.cpp:2798-2802
+// This one is really tricky, since most tokens doesn't have a type yet.
+// The & or && can be binary operators, then we have a requires
+// expression. But they also can be r-value overload indicators, then
+// we have a trailing requires clause. We try to detect the latter and
+// default to the expressions.

s/doesn't/don't/
IIUC you're talking about, like, `void member() && requires (` — is that right?
It might help the reader to give an example snippet right here. (OTOH, it might 
be "obvious," I don't know. I'm not in the target audience for this code.)
...Ah, I see you give a snippet on line 2837 that's basically what I mean; I 
just first felt the need for that snippet all the way up //here//.



Comment at: clang/lib/Format/UnwrappedLineParser.cpp:2835-2841
+  // FIXME: We need an annotation on the paren to really know if it is a
+  // function call:
+  // ... foo() && requires ...
+  // or a declaration:
+  // void foo() && requires ...
+  // there is no distinction possible right now. We go for the latter,
+  // because it's more likely to appear in code.

I think it's weird that your heuristic parses backward rather than forward. I 
would think that the next token //after// the `requires` keyword tells you what 
it is with pretty high probability:
`requires requires` — it's a clause
`requires identifier` — it's a clause
`requires {` — it's an expression
`requires (` — unclear, apply further heuristics

Or are those heuristics already present in trunk, and this PR is just dealing 
with the "unclear" case?



Comment at: clang/lib/Format/UnwrappedLineParser.cpp:2882
+  if (BeforeLastParenContent->isSimpleTypeSpecifier()) {
+// Definetly function delcaration.
+return false;




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

https://reviews.llvm.org/D119138

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


[PATCH] D119184: [clang] [concepts] Check constrained-auto return types for void-returning functions

2022-02-10 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone marked an inline comment as not done.
Quuxplusone added inline comments.



Comment at: clang/lib/Sema/SemaStmt.cpp:3816
+Context.getTrivialTypeSourceInfo(Context.VoidTy, ReturnLoc), 
ReturnLoc);
+Expr *Dummy = R.get();
+DeduceAutoResult DAR = DeduceAutoType(OrigResultType, Dummy, Deduced);

sammccall wrote:
> why initialize into an ExprResult instead of an Expr* directly?
Because I didn't know the latter was possible. :) Btw, I assume there's no 
worry here about how the Expr will ultimately get garbage-collected, right? All 
the code I looked at seems pretty cavalier about it, so I assume `new 
(Context)` magically takes care of the memory management part.



Comment at: clang/lib/Sema/SemaStmt.cpp:3819
+if (DAR == DAR_Failed && !FD->isInvalidDecl())
+  Diag(ReturnLoc, HasReturnStmt ? 
diag::err_auto_fn_return_void_but_not_auto
+: diag::err_auto_fn_no_return_but_not_auto)

sammccall wrote:
> (BTW, err_auto_fn_return_void_but_not_auto has no testcases, feel free to add 
> one near `deduced-return-type-cxx14.cpp:341`, or not)
Will do.



Comment at: clang/test/SemaCXX/deduced-return-type-cxx14.cpp:116
 
-auto _ret_2() {} // expected-error {{cannot deduce return type 'auto &' 
for function with no return statements}}
+auto _ret_2() {} // expected-error {{cannot form a reference to 'void'}}
 const auto void_ret_3() {} // ok, return type 'const void' is adjusted to 
'void'

sammccall wrote:
> This feels like a regression, this diagnostic is just attached to the end of 
> the function and there's no longer any explicit indication that the return 
> type or deduction is involved.
> 
> It may be worth keeping the explicit check in `ActOnFinishFunctionBody` 
> before the deduction happens to improve the diagnostic in this case.
> 
> (I don't think it's important to do this in the return-with-no-argument case, 
> since the error will point at the return statement which provides enough 
> context I think)
I agree about the (mild) regression but am not sure what to do about it. I 
think it might help if Clang emitted a note `note: during return type deduction 
here` (pointer to the offending `return` statement or end-of-function); do you 
think I should do that? and if so, how?

> It may be worth keeping the explicit check in `ActOnFinishFunctionBody` 
> before the deduction happens to improve the diagnostic in this case.

I can't picture what you mean; can you suggest a specific patch?

In case it matters, I'm a little leery of hard-coding a special case like we 
had in the old `DeduceFunctionTypeFromReturnExpr` lines 3814–3816,
```
// Deduction here can only succeed if the return type is exactly 'cv auto'
// or 'decltype(auto)', so just check for that case directly.
if (!OrigResultType.getType()->getAs()) {
```
because special-casing `void` is kind of how we got into this mess in the first 
place.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119184

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


[PATCH] D119351: Update all LLVM documentation mentioning runtimes in LLVM_ENABLE_PROJECTS

2022-02-10 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: bolt/docs/OptimizingClang.md:228-236
 $ CPATH=${TOPLEV}/stage1/install/bin/
-$ cmake -G Ninja ${TOPLEV}/llvm-project/llvm -DLLVM_TARGETS_TO_BUILD=X86 \
+$ cmake -G Ninja -S ${TOPLEV}/llvm-project/llvm -B ${TOPLEV}/stage2-prof-gen \
+-DLLVM_TARGETS_TO_BUILD=X86 \
 -DCMAKE_BUILD_TYPE=Release \
 -DCMAKE_C_COMPILER=$CPATH/clang -DCMAKE_CXX_COMPILER=$CPATH/clang++ \
 -DLLVM_ENABLE_PROJECTS="clang;lld" \
 -DLLVM_USE_LINKER=lld -DLLVM_BUILD_INSTRUMENTED=ON \

ldionne wrote:
> Quuxplusone wrote:
> > FWIW, I personally prefer to run cmake and ninja //from// the build 
> > directory, i.e.
> > ```
> > $ mkdir ${TOPLEV}/llvm-project/llvm/stage2-prof-gen
> > $ cd ${TOPLEV}/llvm-project/llvm/stage2-prof-gen
> > $ CPATH=${TOPLEV}/stage1/install/bin
> > $ cmake -G Ninja \
> > -DLLVM_TARGETS_TO_BUILD=X86 \
> > ~~~
> > -DCMAKE_INSTALL_PREFIX=${TOPLEV}/stage2-prof-gen/install \
> > ../llvm-project/llvm
> > $ ninja install
> > ```
> > This is the style that was used in `DataFlowSanitizer.rst` below, which you 
> > explicitly moved away from into `-B`/`-S`/`-C` land (where I find it harder 
> > to keep straight all the different extra options that are needed).
> > 
> > Orthogonally, I'm worried that the advice on lines 73–74 of README.md 
> > doesn't mention `CMAKE_INSTALL_PREFIX`. When I'm building libc++ locally as 
> > part of my development workflow, I //absolutely do not// want to blow away 
> > my computer's default standard library installation; but what //do// I want 
> > to do? Should I use something like `-DCMAKE_INSTALL_PREFIX=$(pwd)/install` 
> > as depicted here? Can I really not get away with "running it out of the 
> > buildroot" the way I'm used to?— I //must// install it somewhere on my 
> > system in order to test it at all?
> > Re: `-C` `-B` `-S`
> 
> I really like using those flags because it makes the command relocatable, 
> i.e. it works regardless of where it is being run. As such, it's way more 
> copy-pasteable too. However, since that's orthogonal to this change, I'll 
> revert to the old style just so we have fewer things to argue about. But in 
> general, for libc++/libc++abi/libunwind instructions, you'll find that I want 
> things documented this way for that reason.
> 
> > Re: `CMAKE_INSTALL_PREFIX`
> 
> You don't necessarily need to install it in order to test it -- we test 
> libc++ all the time without running the `install-cxx` target. Furthermore, I 
> would expect that most systems nowadays have some sort of integrity 
> protection that prevents you from doing something bad like that. Apple 
> platforms certainly do -- you simply can't overwrite your `libc++.1.dylib` 
> anymore and render your system unusable. Still, I'll add a word of caution to 
> `CMAKE_INSTALL_PREFIX` above even though it's orthogonal to this patch -- 
> it's easy enough to do.
FWIW, the `CMAKE_INSTALL_PREFIX` change is an improvement but only //slightly// 
more reassuring than before. ;) Part of my paranoia is that I happen to know 
that Homebrew stores things in `/usr/local/...` as well (although probably 
entirely under `/usr/local/Cellar/...`?) and I wouldn't want to blow those away 
//either//.
Apparently on my Apple system I have `/usr/lib/libc++.dylib`, 
`/System/DriverKit/usr/lib/libc++.dylib`, and 
`/usr/local/Cellar/llvm/12.0.1/lib/libc++.dylib`.

> we test libc++ all the time without running the `install-cxx` target

Well, I know I do, but I don't use ENABLE_RUNTIMES yet... and the how-to below 
//does// end with the line `ninja -C build install-cxx`. If there's a 
supported/expected-to-work way to build and test libc++ that doesn't use `ninja 
install-cxx`, it'd be cool to mention it.

Anyway, this is all just me fudding and shouldn't block this PR. :)



Comment at: llvm/docs/GettingStarted.rst:633-634
+| | full monorepo layout). The default list is empty.  
|
+| | Can include: libcxx, libcxxabi, libunwind, 
|
+| | compiler-rt, libc, or openmp.  
|
 
+-++

The other list is a-z order; this one could be too.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119351

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


[PATCH] D119184: [clang] [concepts] Check constrained-auto return types for void-returning functions

2022-02-09 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone updated this revision to Diff 407284.
Quuxplusone added a comment.

Rebase; clang-format.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119184

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaStmt.cpp
  clang/test/SemaCXX/deduced-return-type-cxx14.cpp
  clang/test/SemaTemplate/concepts.cpp

Index: clang/test/SemaTemplate/concepts.cpp
===
--- clang/test/SemaTemplate/concepts.cpp
+++ clang/test/SemaTemplate/concepts.cpp
@@ -169,3 +169,23 @@
   template void f(T, U) = delete;
   void g() { f(0, 0); }
 }
+
+namespace PR49188 {
+  template concept C = false; // expected-note 6 {{because 'false' evaluated to false}}
+
+  C auto f1() { return void(); }   // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  C auto f2() { return; }  // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  C auto f3() {}   // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  C decltype(auto) f4() { return void(); } // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  C decltype(auto) f5() { return; }// expected-error {{deduced type 'void' does not satisfy 'C'}}
+  C decltype(auto) f6() {} // expected-error {{deduced type 'void' does not satisfy 'C'}}
+
+  void g() {
+f1();
+f2();
+f3();
+f4();
+f5();
+f6();
+  }
+}
Index: clang/test/SemaCXX/deduced-return-type-cxx14.cpp
===
--- clang/test/SemaCXX/deduced-return-type-cxx14.cpp
+++ clang/test/SemaCXX/deduced-return-type-cxx14.cpp
@@ -113,7 +113,7 @@
 using Void = void;
 using Void = decltype(void_ret());
 
-auto _ret_2() {} // expected-error {{cannot deduce return type 'auto &' for function with no return statements}}
+auto _ret_2() {} // expected-error {{cannot form a reference to 'void'}}
 const auto void_ret_3() {} // ok, return type 'const void' is adjusted to 'void'
 
 const auto void_ret_4() {
Index: clang/lib/Sema/SemaStmt.cpp
===
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -3590,7 +3590,7 @@
 
 AutoType *AT = CurCap->ReturnType->getContainedAutoType();
 assert(AT && "lost auto type from lambda return type");
-if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) {
+if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT, true)) {
   FD->setInvalidDecl();
   // FIXME: preserve the ill-formed return expression.
   return StmtError();
@@ -3761,9 +3761,9 @@
 /// C++1y [dcl.spec.auto]p6.
 bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
 SourceLocation ReturnLoc,
-Expr *,
-AutoType *AT) {
-  // If this is the conversion function for a lambda, we choose to deduce it
+Expr *, const AutoType *AT,
+bool HasReturnStmt) {
+  // If this is the conversion function for a lambda, we choose to deduce its
   // type from the corresponding call operator, not from the synthesized return
   // statement within it. See Sema::DeduceReturnType.
   if (isLambdaConversionOperator(FD))
@@ -3808,19 +3808,18 @@
 LocalTypedefNameReferencer Referencer(*this);
 Referencer.TraverseType(RetExpr->getType());
   } else {
-//  In the case of a return with no operand, the initializer is considered
-//  to be void().
-//
-// Deduction here can only succeed if the return type is exactly 'cv auto'
-// or 'decltype(auto)', so just check for that case directly.
-if (!OrigResultType.getType()->getAs()) {
-  Diag(ReturnLoc, diag::err_auto_fn_return_void_but_not_auto)
-<< OrigResultType.getType();
-  return true;
-}
-// We always deduce U = void in this case.
-Deduced = SubstAutoType(OrigResultType.getType(), Context.VoidTy);
-if (Deduced.isNull())
+// In the case of a return with no operand, the initializer is considered
+// to be 'void()'.
+ExprResult R = new (Context) CXXScalarValueInitExpr(
+Context.VoidTy,
+Context.getTrivialTypeSourceInfo(Context.VoidTy, ReturnLoc), ReturnLoc);
+Expr *Dummy = R.get();
+DeduceAutoResult DAR = DeduceAutoType(OrigResultType, Dummy, Deduced);
+if (DAR == DAR_Failed && !FD->isInvalidDecl())
+  Diag(ReturnLoc, HasReturnStmt ? diag::err_auto_fn_return_void_but_not_auto
+: diag::err_auto_fn_no_return_but_not_auto)
+  << OrigResultType.getType();
+if (DAR != DAR_Succeeded)
   return true;
   }
 
@@ -3988,8 +3987,8 @@
   // we saw a `return` whose 

[PATCH] D119351: Update all LLVM documentation mentioning runtimes in LLVM_ENABLE_PROJECTS

2022-02-09 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: bolt/docs/OptimizingClang.md:228-236
 $ CPATH=${TOPLEV}/stage1/install/bin/
-$ cmake -G Ninja ${TOPLEV}/llvm-project/llvm -DLLVM_TARGETS_TO_BUILD=X86 \
+$ cmake -G Ninja -S ${TOPLEV}/llvm-project/llvm -B ${TOPLEV}/stage2-prof-gen \
+-DLLVM_TARGETS_TO_BUILD=X86 \
 -DCMAKE_BUILD_TYPE=Release \
 -DCMAKE_C_COMPILER=$CPATH/clang -DCMAKE_CXX_COMPILER=$CPATH/clang++ \
 -DLLVM_ENABLE_PROJECTS="clang;lld" \
 -DLLVM_USE_LINKER=lld -DLLVM_BUILD_INSTRUMENTED=ON \

FWIW, I personally prefer to run cmake and ninja //from// the build directory, 
i.e.
```
$ mkdir ${TOPLEV}/llvm-project/llvm/stage2-prof-gen
$ cd ${TOPLEV}/llvm-project/llvm/stage2-prof-gen
$ CPATH=${TOPLEV}/stage1/install/bin
$ cmake -G Ninja \
-DLLVM_TARGETS_TO_BUILD=X86 \
~~~
-DCMAKE_INSTALL_PREFIX=${TOPLEV}/stage2-prof-gen/install \
../llvm-project/llvm
$ ninja install
```
This is the style that was used in `DataFlowSanitizer.rst` below, which you 
explicitly moved away from into `-B`/`-S`/`-C` land (where I find it harder to 
keep straight all the different extra options that are needed).

Orthogonally, I'm worried that the advice on lines 73–74 of README.md doesn't 
mention `CMAKE_INSTALL_PREFIX`. When I'm building libc++ locally as part of my 
development workflow, I //absolutely do not// want to blow away my computer's 
default standard library installation; but what //do// I want to do? Should I 
use something like `-DCMAKE_INSTALL_PREFIX=$(pwd)/install` as depicted here? 
Can I really not get away with "running it out of the buildroot" the way I'm 
used to?— I //must// install it somewhere on my system in order to test it at 
all?



Comment at: flang/README.md:37
+If you are interested in writing new documentation, follow
 [markdown style guide from 
LLVM](https://github.com/llvm/llvm-project/blob/main/llvm/docs/MarkdownQuickstartTemplate.md).
 




Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119351

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


[PATCH] D119184: [clang] [concepts] Check constrained-auto return types for void-returning functions

2022-02-08 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone updated this revision to Diff 406847.
Quuxplusone added a comment.

Update one additional test where the expected output has changed:

  auto& f() { }

now produces "can't make a reference to void" instead of "can't deduce `auto&` 
from no return statements." I think this is a mild regression in diagnostic 
quality, but I don't immediately see what we should do about it so I'm inclined 
to take the hit. Suggestions welcome.


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

https://reviews.llvm.org/D119184

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaStmt.cpp
  clang/test/SemaCXX/deduced-return-type-cxx14.cpp
  clang/test/SemaTemplate/concepts.cpp

Index: clang/test/SemaTemplate/concepts.cpp
===
--- clang/test/SemaTemplate/concepts.cpp
+++ clang/test/SemaTemplate/concepts.cpp
@@ -169,3 +169,14 @@
   template void f(T, U) = delete;
   void g() { f(0, 0); }
 }
+
+namespace PR49188 {
+  template concept C = false; // expected-note 6 {{because 'false' evaluated to false}}
+  C auto f1() { return void(); } // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  C auto f2() { return; } // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  C auto f3() { } // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  C decltype(auto) f4() { return void(); } // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  C decltype(auto) f5() { return; } // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  C decltype(auto) f6() { } // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  void g() { f1(); f2(); f3(); f4(); f5(); f6(); }
+}
Index: clang/test/SemaCXX/deduced-return-type-cxx14.cpp
===
--- clang/test/SemaCXX/deduced-return-type-cxx14.cpp
+++ clang/test/SemaCXX/deduced-return-type-cxx14.cpp
@@ -113,7 +113,7 @@
 using Void = void;
 using Void = decltype(void_ret());
 
-auto _ret_2() {} // expected-error {{cannot deduce return type 'auto &' for function with no return statements}}
+auto _ret_2() {} // expected-error {{cannot form a reference to 'void'}}
 const auto void_ret_3() {} // ok, return type 'const void' is adjusted to 'void'
 
 const auto void_ret_4() {
Index: clang/lib/Sema/SemaStmt.cpp
===
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -3590,7 +3590,7 @@
 
 AutoType *AT = CurCap->ReturnType->getContainedAutoType();
 assert(AT && "lost auto type from lambda return type");
-if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) {
+if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT, true)) {
   FD->setInvalidDecl();
   // FIXME: preserve the ill-formed return expression.
   return StmtError();
@@ -3762,8 +3762,9 @@
 bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
 SourceLocation ReturnLoc,
 Expr *,
-AutoType *AT) {
-  // If this is the conversion function for a lambda, we choose to deduce it
+const AutoType *AT,
+bool HasReturnStmt) {
+  // If this is the conversion function for a lambda, we choose to deduce its
   // type from the corresponding call operator, not from the synthesized return
   // statement within it. See Sema::DeduceReturnType.
   if (isLambdaConversionOperator(FD))
@@ -3808,19 +3809,18 @@
 LocalTypedefNameReferencer Referencer(*this);
 Referencer.TraverseType(RetExpr->getType());
   } else {
-//  In the case of a return with no operand, the initializer is considered
-//  to be void().
-//
-// Deduction here can only succeed if the return type is exactly 'cv auto'
-// or 'decltype(auto)', so just check for that case directly.
-if (!OrigResultType.getType()->getAs()) {
-  Diag(ReturnLoc, diag::err_auto_fn_return_void_but_not_auto)
-<< OrigResultType.getType();
-  return true;
-}
-// We always deduce U = void in this case.
-Deduced = SubstAutoType(OrigResultType.getType(), Context.VoidTy);
-if (Deduced.isNull())
+// In the case of a return with no operand, the initializer is considered
+// to be 'void()'.
+ExprResult R = new (Context) CXXScalarValueInitExpr(
+  Context.VoidTy, Context.getTrivialTypeSourceInfo(Context.VoidTy, ReturnLoc),
+  ReturnLoc);
+Expr *Dummy = R.get();
+DeduceAutoResult DAR = DeduceAutoType(OrigResultType, Dummy, Deduced);
+if (DAR == DAR_Failed && !FD->isInvalidDecl())
+  Diag(ReturnLoc, HasReturnStmt ? diag::err_auto_fn_return_void_but_not_auto
+: diag::err_auto_fn_no_return_but_not_auto)
+  << 

[PATCH] D119094: [clang] Don't emit redundant warnings for 'return;'

2022-02-08 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone updated this revision to Diff 406838.
Quuxplusone added a comment.

Oops. I'd put `[clang] [test] Fix an apparent typo in 
SemaCXX/consteval-return-void.cpp` in a separate commit for hygiene purposes, 
and forgot to include that commit in this diff. Updated.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119094

Files:
  clang/lib/Sema/SemaStmt.cpp
  clang/test/SemaCXX/consteval-return-void.cpp
  clang/test/SemaCXX/deduced-return-void.cpp


Index: clang/test/SemaCXX/deduced-return-void.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/deduced-return-void.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
+
+// Check that we don't get any extra warning for "return" without an
+// expression, in a function that might have been intended to return
+// void all along.
+auto f1() {
+  return 1;
+  return; // expected-error {{deduced as 'void' here but deduced as 'int' in 
earlier return statement}}
+}
+
+decltype(auto) f2() {
+  return 1;
+  return; // expected-error {{deduced as 'void' here but deduced as 'int' in 
earlier return statement}}
+}
+
+auto *g() {
+  return; // expected-error {{cannot deduce return type 'auto *' from omitted 
return expression}}
+}
+
+decltype(h1) h1() { // expected-error {{use of undeclared identifier 'h1'}}
+  return;
+}
Index: clang/test/SemaCXX/consteval-return-void.cpp
===
--- clang/test/SemaCXX/consteval-return-void.cpp
+++ clang/test/SemaCXX/consteval-return-void.cpp
@@ -10,8 +10,8 @@
 enum E {};
 
 constexpr E operator+(E,E) { return; } // expected-error {{non-void constexpr 
function 'operator+' should return a value}}
-consteval E operator+(E,E) { return; }  // expected-error {{non-void consteval 
function 'operator+' should return a value}}
-template  constexpr E operator-(E,E) { return; } // expected-error 
{{non-void constexpr function 'operator-' should return a value}}
+consteval E operator-(E,E) { return; }  // expected-error {{non-void consteval 
function 'operator-' should return a value}}
+template  constexpr E operator+(E,E) { return; } // expected-error 
{{non-void constexpr function 'operator+' should return a value}}
 template  consteval E operator-(E,E) { return; } // expected-error 
{{non-void consteval function 'operator-' should return a value}}
 
 template  constexpr E operator*(E,E);
Index: clang/lib/Sema/SemaStmt.cpp
===
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -4098,7 +4098,9 @@
   } else if (!RetValExp && !HasDependentReturnType) {
 FunctionDecl *FD = getCurFunctionDecl();
 
-if (getLangOpts().CPlusPlus11 && FD && FD->isConstexpr()) {
+if ((FD && FD->isInvalidDecl()) || FnRetType->containsErrors()) {
+  // The intended return type might have been "void", so don't warn.
+} else if (getLangOpts().CPlusPlus11 && FD && FD->isConstexpr()) {
   // C++11 [stmt.return]p2
   Diag(ReturnLoc, diag::err_constexpr_return_missing_expr)
   << FD << FD->isConsteval();


Index: clang/test/SemaCXX/deduced-return-void.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/deduced-return-void.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
+
+// Check that we don't get any extra warning for "return" without an
+// expression, in a function that might have been intended to return
+// void all along.
+auto f1() {
+  return 1;
+  return; // expected-error {{deduced as 'void' here but deduced as 'int' in earlier return statement}}
+}
+
+decltype(auto) f2() {
+  return 1;
+  return; // expected-error {{deduced as 'void' here but deduced as 'int' in earlier return statement}}
+}
+
+auto *g() {
+  return; // expected-error {{cannot deduce return type 'auto *' from omitted return expression}}
+}
+
+decltype(h1) h1() { // expected-error {{use of undeclared identifier 'h1'}}
+  return;
+}
Index: clang/test/SemaCXX/consteval-return-void.cpp
===
--- clang/test/SemaCXX/consteval-return-void.cpp
+++ clang/test/SemaCXX/consteval-return-void.cpp
@@ -10,8 +10,8 @@
 enum E {};
 
 constexpr E operator+(E,E) { return; }	// expected-error {{non-void constexpr function 'operator+' should return a value}}
-consteval E operator+(E,E) { return; }  // expected-error {{non-void consteval function 'operator+' should return a value}}
-template  constexpr E operator-(E,E) { return; } // expected-error {{non-void constexpr function 'operator-' should return a value}}
+consteval E operator-(E,E) { return; }  // expected-error {{non-void consteval function 'operator-' should return 

[PATCH] D119184: [clang] [concepts] Check constrained-auto return types for void-returning functions

2022-02-07 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone created this revision.
Quuxplusone added reviewers: sammccall, saar.raz, rsmith, mizvekov, majnemer, 
riccibruno.
Quuxplusone added a project: clang.
Quuxplusone requested review of this revision.
Herald added a subscriber: cfe-commits.

Fixes https://github.com/llvm/llvm-project/issues/49188


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D119184

Files:
  clang/include/clang/Sema/Sema.h
  clang/lib/Sema/SemaDecl.cpp
  clang/lib/Sema/SemaStmt.cpp
  clang/test/SemaTemplate/concepts.cpp

Index: clang/test/SemaTemplate/concepts.cpp
===
--- clang/test/SemaTemplate/concepts.cpp
+++ clang/test/SemaTemplate/concepts.cpp
@@ -169,3 +169,14 @@
   template void f(T, U) = delete;
   void g() { f(0, 0); }
 }
+
+namespace PR49188 {
+  template concept C = false; // expected-note 6 {{because 'false' evaluated to false}}
+  C auto f1() { return void(); } // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  C auto f2() { return; } // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  C auto f3() { } // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  C decltype(auto) f4() { return void(); } // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  C decltype(auto) f5() { return; } // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  C decltype(auto) f6() { } // expected-error {{deduced type 'void' does not satisfy 'C'}}
+  void g() { f1(); f2(); f3(); f4(); f5(); f6(); }
+}
Index: clang/lib/Sema/SemaStmt.cpp
===
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -3590,7 +3590,7 @@
 
 AutoType *AT = CurCap->ReturnType->getContainedAutoType();
 assert(AT && "lost auto type from lambda return type");
-if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) {
+if (DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT, true)) {
   FD->setInvalidDecl();
   // FIXME: preserve the ill-formed return expression.
   return StmtError();
@@ -3762,8 +3762,9 @@
 bool Sema::DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD,
 SourceLocation ReturnLoc,
 Expr *,
-AutoType *AT) {
-  // If this is the conversion function for a lambda, we choose to deduce it
+const AutoType *AT,
+bool HasReturnStmt) {
+  // If this is the conversion function for a lambda, we choose to deduce its
   // type from the corresponding call operator, not from the synthesized return
   // statement within it. See Sema::DeduceReturnType.
   if (isLambdaConversionOperator(FD))
@@ -3808,19 +3809,18 @@
 LocalTypedefNameReferencer Referencer(*this);
 Referencer.TraverseType(RetExpr->getType());
   } else {
-//  In the case of a return with no operand, the initializer is considered
-//  to be void().
-//
-// Deduction here can only succeed if the return type is exactly 'cv auto'
-// or 'decltype(auto)', so just check for that case directly.
-if (!OrigResultType.getType()->getAs()) {
-  Diag(ReturnLoc, diag::err_auto_fn_return_void_but_not_auto)
-<< OrigResultType.getType();
-  return true;
-}
-// We always deduce U = void in this case.
-Deduced = SubstAutoType(OrigResultType.getType(), Context.VoidTy);
-if (Deduced.isNull())
+// In the case of a return with no operand, the initializer is considered
+// to be 'void()'.
+ExprResult R = new (Context) CXXScalarValueInitExpr(
+  Context.VoidTy, Context.getTrivialTypeSourceInfo(Context.VoidTy, ReturnLoc),
+  ReturnLoc);
+Expr *Dummy = R.get();
+DeduceAutoResult DAR = DeduceAutoType(OrigResultType, Dummy, Deduced);
+if (DAR == DAR_Failed && !FD->isInvalidDecl())
+  Diag(ReturnLoc, HasReturnStmt ? diag::err_auto_fn_return_void_but_not_auto
+: diag::err_auto_fn_no_return_but_not_auto)
+  << OrigResultType.getType();
+if (DAR != DAR_Succeeded)
   return true;
   }
 
@@ -3989,7 +3989,7 @@
   // trying to deduce its return type.
   // (Some return values may be needlessly wrapped in RecoveryExpr).
   if (FD->isInvalidDecl() ||
-  DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT)) {
+  DeduceFunctionTypeFromReturnExpr(FD, ReturnLoc, RetValExp, AT, true)) {
 FD->setInvalidDecl();
 if (!AllowRecovery)
   return StmtError();
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -14660,18 +14660,12 @@
   if (getLangOpts().CPlusPlus14) {
 if (!FD->isInvalidDecl() && Body && !FD->isDependentContext() &&

[PATCH] D119094: [clang] Don't emit redundant warnings for 'return;'

2022-02-07 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone updated this revision to Diff 406585.
Quuxplusone added a comment.
This revision is now accepted and ready to land.

Fix the two failing test cases (in one case by fixing what seems to have been a 
typo in the test).


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

https://reviews.llvm.org/D119094

Files:
  clang/lib/Sema/SemaStmt.cpp
  clang/test/SemaCXX/deduced-return-void.cpp


Index: clang/test/SemaCXX/deduced-return-void.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/deduced-return-void.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
+
+// Check that we don't get any extra warning for "return" without an
+// expression, in a function that might have been intended to return
+// void all along.
+auto f1() {
+  return 1;
+  return; // expected-error {{deduced as 'void' here but deduced as 'int' in 
earlier return statement}}
+}
+
+decltype(auto) f2() {
+  return 1;
+  return; // expected-error {{deduced as 'void' here but deduced as 'int' in 
earlier return statement}}
+}
+
+auto *g() {
+  return; // expected-error {{cannot deduce return type 'auto *' from omitted 
return expression}}
+}
+
+decltype(h1) h1() { // expected-error {{use of undeclared identifier 'h1'}}
+  return;
+}
Index: clang/lib/Sema/SemaStmt.cpp
===
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -4098,7 +4098,9 @@
   } else if (!RetValExp && !HasDependentReturnType) {
 FunctionDecl *FD = getCurFunctionDecl();
 
-if (getLangOpts().CPlusPlus11 && FD && FD->isConstexpr()) {
+if ((FD && FD->isInvalidDecl()) || FnRetType->containsErrors()) {
+  // The intended return type might have been "void", so don't warn.
+} else if (getLangOpts().CPlusPlus11 && FD && FD->isConstexpr()) {
   // C++11 [stmt.return]p2
   Diag(ReturnLoc, diag::err_constexpr_return_missing_expr)
   << FD << FD->isConsteval();


Index: clang/test/SemaCXX/deduced-return-void.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/deduced-return-void.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
+
+// Check that we don't get any extra warning for "return" without an
+// expression, in a function that might have been intended to return
+// void all along.
+auto f1() {
+  return 1;
+  return; // expected-error {{deduced as 'void' here but deduced as 'int' in earlier return statement}}
+}
+
+decltype(auto) f2() {
+  return 1;
+  return; // expected-error {{deduced as 'void' here but deduced as 'int' in earlier return statement}}
+}
+
+auto *g() {
+  return; // expected-error {{cannot deduce return type 'auto *' from omitted return expression}}
+}
+
+decltype(h1) h1() { // expected-error {{use of undeclared identifier 'h1'}}
+  return;
+}
Index: clang/lib/Sema/SemaStmt.cpp
===
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -4098,7 +4098,9 @@
   } else if (!RetValExp && !HasDependentReturnType) {
 FunctionDecl *FD = getCurFunctionDecl();
 
-if (getLangOpts().CPlusPlus11 && FD && FD->isConstexpr()) {
+if ((FD && FD->isInvalidDecl()) || FnRetType->containsErrors()) {
+  // The intended return type might have been "void", so don't warn.
+} else if (getLangOpts().CPlusPlus11 && FD && FD->isConstexpr()) {
   // C++11 [stmt.return]p2
   Diag(ReturnLoc, diag::err_constexpr_return_missing_expr)
   << FD << FD->isConsteval();
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D119094: [clang] Don't emit redundant warnings for 'return;'

2022-02-07 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added a comment.

In D119094#3301403 , @sammccall wrote:

> In D119094#3301297 , @Quuxplusone 
> wrote:
>
>> Unfortunately some existing tests fail: 
>> https://reviews.llvm.org/harbormaster/unit/view/2282838/
>> I haven't yet figured out why consteval functions are considered to have 
>> `FD->isInvalidDecl()`. There's also an Objective-C failure that I assume 
>> indicates sometimes (when this is a //method// not a //function//) we have 
>> no `FD` at all. I'd need to solve both of these problems (the former being 
>> the difficult one) before I can make progress here.
>
> The example seems to be invalid even apart from the missing return value. (I 
> assume on purpose).

Ohhh, wow, I had missed that. In that case, I'm shocked that Clang isn't giving 
any more serious error message: shouldn't it be considered invalid, and 
diagnosed as an error, to have a `constexpr` definition followed by a 
`consteval` redefinition?
https://godbolt.org/z/vKjGvEor8
However, I think the pattern of operators used (`++--*/*/`) indicates that the 
original author made a typo there, and it should always have been `+-+-*/*/`. 
So I'll feel good about changing that test.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119094

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


[PATCH] D119094: [clang] Don't emit redundant warnings for 'return;'

2022-02-07 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone planned changes to this revision.
Quuxplusone added a comment.

Unfortunately some existing tests fail: 
https://reviews.llvm.org/harbormaster/unit/view/2282838/
I haven't yet figured out why consteval functions are considered to have 
`FD->isInvalidDecl()`. There's also an Objective-C failure that I assume 
indicates sometimes (when this is a //method// not a //function//) we have no 
`FD` at all. I'd need to solve both of these problems (the former being the 
difficult one) before I can make progress here.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D119094

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


[PATCH] D113369: [clang-format] Extend SpaceBeforeParens for requires

2022-02-07 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: clang/include/clang/Format/Format.h:3371
+/// If ``true``, put space between requires keyword in a requires clause 
and
+/// opening parentheses, if there is one.
+/// \code

HazardyKnusperkeks wrote:
> Quuxplusone wrote:
> > Here and line 3380, and possibly elsewhere: `s/parentheses/parenthesis/`
> Non native here, but I think one could argue both were okay. I just copied 
> what the other options state.
It's definitely not grammatical to talk about "opening parentheses, if there is 
one". But if this is just copying pre-existing wording, then OK, no objection 
to someone handling the grammar in a followup PR.


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

https://reviews.llvm.org/D113369

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


[PATCH] D119094: [clang] Don't emit redundant warnings for 'return;'

2022-02-06 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone created this revision.
Quuxplusone added reviewers: rsmith, sammccall, mizvekov, majnemer, riccibruno, 
clang.
Quuxplusone added a project: clang.
Quuxplusone requested review of this revision.
Herald added a subscriber: cfe-commits.

...when the function declaration's return type is already invalid for
some reason. This is relevant to 
https://github.com/llvm/llvm-project/issues/49188
because another way that the declaration's return type could become
invalid is that it might be `C auto` where `C` is false.

(This doesn't actually fix 49188, but it eliminates a surprising redundant 
warning in the fix I tried, and also eliminates redundant warnings in the test 
cases depicted here.)


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D119094

Files:
  clang/lib/Sema/SemaStmt.cpp
  clang/test/SemaCXX/deduced-return-void.cpp


Index: clang/test/SemaCXX/deduced-return-void.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/deduced-return-void.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
+
+// Check that we don't get any extra warning for "return" without an
+// expression, in a function that might have been intended to return
+// void all along.
+auto f1() {
+  return 1;
+  return; // expected-error {{deduced as 'void' here but deduced as 'int' in 
earlier return statement}}
+}
+
+decltype(auto) f2() {
+  return 1;
+  return; // expected-error {{deduced as 'void' here but deduced as 'int' in 
earlier return statement}}
+}
+
+auto *g() {
+  return; // expected-error {{cannot deduce return type 'auto *' from omitted 
return expression}}
+}
+
+decltype(h1) h1() { // expected-error {{use of undeclared identifier 'h1'}}
+  return;
+}
Index: clang/lib/Sema/SemaStmt.cpp
===
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -4098,7 +4098,9 @@
   } else if (!RetValExp && !HasDependentReturnType) {
 FunctionDecl *FD = getCurFunctionDecl();
 
-if (getLangOpts().CPlusPlus11 && FD && FD->isConstexpr()) {
+if (FD->isInvalidDecl()) {
+  // Don't redundantly warn about "return;" if the return type is invalid.
+} else if (getLangOpts().CPlusPlus11 && FD && FD->isConstexpr()) {
   // C++11 [stmt.return]p2
   Diag(ReturnLoc, diag::err_constexpr_return_missing_expr)
   << FD << FD->isConsteval();


Index: clang/test/SemaCXX/deduced-return-void.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/deduced-return-void.cpp
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -std=c++14 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
+
+// Check that we don't get any extra warning for "return" without an
+// expression, in a function that might have been intended to return
+// void all along.
+auto f1() {
+  return 1;
+  return; // expected-error {{deduced as 'void' here but deduced as 'int' in earlier return statement}}
+}
+
+decltype(auto) f2() {
+  return 1;
+  return; // expected-error {{deduced as 'void' here but deduced as 'int' in earlier return statement}}
+}
+
+auto *g() {
+  return; // expected-error {{cannot deduce return type 'auto *' from omitted return expression}}
+}
+
+decltype(h1) h1() { // expected-error {{use of undeclared identifier 'h1'}}
+  return;
+}
Index: clang/lib/Sema/SemaStmt.cpp
===
--- clang/lib/Sema/SemaStmt.cpp
+++ clang/lib/Sema/SemaStmt.cpp
@@ -4098,7 +4098,9 @@
   } else if (!RetValExp && !HasDependentReturnType) {
 FunctionDecl *FD = getCurFunctionDecl();
 
-if (getLangOpts().CPlusPlus11 && FD && FD->isConstexpr()) {
+if (FD->isInvalidDecl()) {
+  // Don't redundantly warn about "return;" if the return type is invalid.
+} else if (getLangOpts().CPlusPlus11 && FD && FD->isConstexpr()) {
   // C++11 [stmt.return]p2
   Diag(ReturnLoc, diag::err_constexpr_return_missing_expr)
   << FD << FD->isConsteval();
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D117603: [clang] Don't typo-fix an expression in a SFINAE context

2022-02-03 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added a comment.

In D117603#3292657 , @var-const wrote:

> @Quuxplusone Now that it's landed, do we still need `__workaround_52970` in 
> libc++? (see 
> https://github.com/llvm/llvm-project/blob/167b623a6af26802af47f455aaa3806faaa9da9e/libcxx/include/__concepts/class_or_enum.h#L28-L30)

It's landed in Clang 14, but libc++14 still needs to support Clang 13 for 
another whole release (six months? a year?), so, no, we can't remove that 
workaround //yet//.
But you're correct that that's the reason I was kinda hurrying to get it fixed 
already before the release/14.x branch — it'll mean libc++ gets to remove the 
workaround 6 (12?) months earlier than otherwise.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D117603

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


[PATCH] D117603: [clang] Don't typo-fix an expression in a SFINAE context

2022-02-01 Thread Arthur O'Dwyer via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGc0185ffaec3c: [clang] Dont typo-fix an expression in a 
SFINAE context. (authored by arthur.j.odwyer).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D117603

Files:
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExprMember.cpp
  clang/test/SemaTemplate/pr52970.cpp

Index: clang/test/SemaTemplate/pr52970.cpp
===
--- /dev/null
+++ clang/test/SemaTemplate/pr52970.cpp
@@ -0,0 +1,63 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify=cxx20 %s
+// expected-no-diagnostics
+
+struct Incomplete;
+template  struct Holder { T t; };
+
+namespace DotFollowingFunctionName {
+struct Good {
+  struct Nested {
+int b;
+  } a;
+};
+
+struct Bad {
+  Holder a();
+};
+
+template 
+constexpr auto f(T t) -> decltype((t.a.b, true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingFunctionName::f(Good{}), "");
+static_assert(!DotFollowingFunctionName::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.a.b; };
+  // cxx20-note@-1 {{because 't.a.b' would be invalid: reference to non-static member function must be called}}
+
+static_assert(C);
+static_assert(!C);
+static_assert(C); // cxx20-error {{static_assert failed}}
+  // cxx20-note@-1 {{because 'DotFollowingFunctionName::Bad' does not satisfy 'C'}}
+#endif
+} // namespace DotFollowingFunctionName
+
+namespace DotFollowingPointer {
+struct Good {
+  int begin();
+};
+using Bad = Holder *;
+
+template 
+constexpr auto f(T t) -> decltype((t.begin(), true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingPointer::f(Good{}), "");
+static_assert(!DotFollowingPointer::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.begin(); };
+  // cxx20-note@-1 {{because 't.begin()' would be invalid: member reference type 'Holder *' is a pointer}}
+
+static_assert(C);
+static_assert(!C);
+static_assert(C); // cxx20-error {{static_assert failed}}
+  // cxx20-note@-1 {{because 'DotFollowingPointer::Bad' (aka 'Holder *') does not satisfy 'C'}}
+#endif
+} // namespace DotFollowingPointer
Index: clang/lib/Sema/SemaExprMember.cpp
===
--- clang/lib/Sema/SemaExprMember.cpp
+++ clang/lib/Sema/SemaExprMember.cpp
@@ -1645,6 +1645,9 @@
   << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
   << FixItHint::CreateReplacement(OpLoc, "->");
 
+  if (S.isSFINAEContext())
+return ExprError();
+
   // Recurse as an -> access.
   IsArrow = true;
   return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -2556,32 +2556,36 @@
 bool (*IsPlausibleResult)(QualType)) {
   SourceLocation Loc = E.get()->getExprLoc();
   SourceRange Range = E.get()->getSourceRange();
-
-  QualType ZeroArgCallTy;
   UnresolvedSet<4> Overloads;
-  if (tryExprAsCall(*E.get(), ZeroArgCallTy, Overloads) &&
-  !ZeroArgCallTy.isNull() &&
-  (!IsPlausibleResult || IsPlausibleResult(ZeroArgCallTy))) {
-// At this point, we know E is potentially callable with 0
-// arguments and that it returns something of a reasonable type,
-// so we can emit a fixit and carry on pretending that E was
-// actually a CallExpr.
-SourceLocation ParenInsertionLoc = getLocForEndOfToken(Range.getEnd());
-bool IsMV = IsCPUDispatchCPUSpecificMultiVersion(E.get());
-Diag(Loc, PD) << /*zero-arg*/ 1 << IsMV << Range
-  << (IsCallableWithAppend(E.get())
-  ? FixItHint::CreateInsertion(ParenInsertionLoc, "()")
-  : FixItHint());
-if (!IsMV)
-  notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult);
-
-// FIXME: Try this before emitting the fixit, and suppress diagnostics
-// while doing so.
-E = BuildCallExpr(nullptr, E.get(), Range.getEnd(), None,
-  Range.getEnd().getLocWithOffset(1));
-return true;
-  }
 
+  // If this is a SFINAE context, don't try anything that might trigger ADL
+  // prematurely.
+  if (!isSFINAEContext()) {
+QualType ZeroArgCallTy;
+if (tryExprAsCall(*E.get(), ZeroArgCallTy, Overloads) &&
+!ZeroArgCallTy.isNull() &&
+(!IsPlausibleResult || IsPlausibleResult(ZeroArgCallTy))) {
+  // At this point, we know E is potentially callable with 0
+  // arguments 

[PATCH] D118552: [clang] [concepts] Correctly(?) handle placeholder types in ExprRequirements.

2022-02-01 Thread Arthur O'Dwyer via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGf6ce45670789: [clang] Correctly(?) handle placeholder types 
in ExprRequirements. (authored by arthur.j.odwyer).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D118552

Files:
  clang/lib/AST/ASTContext.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/SemaTemplateInstantiate.cpp
  clang/lib/Sema/TreeTransform.h
  clang/test/SemaTemplate/constraints.cpp
  clang/test/SemaTemplate/pr52909.cpp

Index: clang/test/SemaTemplate/pr52909.cpp
===
--- /dev/null
+++ clang/test/SemaTemplate/pr52909.cpp
@@ -0,0 +1,71 @@
+// RUN: %clang_cc1 -std=c++20 -verify %s
+// RUN: %clang_cc1 -std=c++2b -verify %s
+
+namespace PR52905 {
+template  concept C = true;
+
+struct A {
+  int begin();
+  int begin() const;
+};
+
+template 
+concept Beginable = requires (T t) {
+  { t.begin } -> C;
+  // expected-note@-1 {{because 't.begin' would be invalid: reference to non-static member function must be called}}
+};
+
+static_assert(Beginable); // expected-error {{static_assert failed}}
+ // expected-note@-1 {{does not satisfy 'Beginable'}}
+} // namespace PR52905
+
+namespace PR52909a {
+
+template constexpr bool B = true;
+template concept True = B;
+
+template 
+int foo(T t) requires requires { // expected-note {{candidate template ignored: constraints not satisfied}}
+{t.begin} -> True; // expected-note {{because 't.begin' would be invalid: reference to non-static member function must be called}}
+}
+{}
+
+struct A { int begin(); };
+auto x = foo(A()); // expected-error {{no matching function for call to 'foo'}}
+
+} // namespace PR52909a
+
+namespace PR52909b {
+
+template concept True = true;
+
+template concept C = requires {
+{ T::begin } -> True; // expected-note {{because 'T::begin' would be invalid: reference to overloaded function could not be resolved}}
+};
+
+struct A {
+static void begin(int);
+static void begin(double);
+};
+
+static_assert(C); // expected-error {{static_assert failed}}
+  // expected-note@-1 {{because 'PR52909b::A' does not satisfy 'C'}}
+
+} // namespace PR52909b
+
+namespace PR53075 {
+template concept True = true;
+
+template concept C = requires {
+{ ::f } -> True; // expected-note {{because '::f' would be invalid: reference to overloaded function could not be resolved}}
+};
+
+struct S {
+int *f();
+int *f() const;
+};
+
+static_assert(C); // expected-error {{static_assert failed}}
+  // expected-note@-1 {{because 'PR53075::S' does not satisfy 'C'}}
+
+} // namespace PR53075
Index: clang/test/SemaTemplate/constraints.cpp
===
--- clang/test/SemaTemplate/constraints.cpp
+++ clang/test/SemaTemplate/constraints.cpp
@@ -24,35 +24,3 @@
   // FIXME: These diagnostics are excessive.
   static_assert(test == 1); // expected-note 2{{while}} expected-note 2{{during}}
 }
-
-namespace PR52905 {
-// A mock for std::convertible_to. Not complete support.
-template 
-concept convertible_to = __is_convertible_to(_From, _To); // expected-note {{evaluated to false}}
-
-template 
-class A {
-public:
-  using iterator = void **;
-
-  iterator begin();
-  const iterator begin() const;
-};
-
-template 
-concept Beginable1 = requires(T t) {
-  { t.begin }
-  ->convertible_to; // expected-note {{not satisfied}}
-};
-
-static_assert(Beginable1>); // expected-error {{static_assert failed}}
-   // expected-note@-1 {{does not satisfy 'Beginable1'}}
-
-template 
-concept Beginable2 = requires(T t) {
-  { t.begin() }
-  ->convertible_to;
-};
-
-static_assert(Beginable2>);
-} // namespace PR52905
Index: clang/lib/Sema/TreeTransform.h
===
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -12494,6 +12494,8 @@
 TransExpr = Req->getExprSubstitutionDiagnostic();
   else {
 ExprResult TransExprRes = getDerived().TransformExpr(Req->getExpr());
+if (TransExprRes.isUsable() && TransExprRes.get()->hasPlaceholderType())
+  TransExprRes = SemaRef.CheckPlaceholderExpr(TransExprRes.get());
 if (TransExprRes.isInvalid())
   return nullptr;
 TransExpr = TransExprRes.get();
Index: clang/lib/Sema/SemaTemplateInstantiate.cpp
===
--- clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1943,6 +1943,9 @@
 if (ExprInst.isInvalid())
   return nullptr;
 ExprResult TransExprRes = TransformExpr(E);
+if (!TransExprRes.isInvalid() && !Trap.hasErrorOccurred() &&
+TransExprRes.get()->hasPlaceholderType())
+  TransExprRes = 

[PATCH] D114903: [clang] Support array placement new in constant expressions

2022-01-31 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added a comment.

I have no special knowledge of this. Seems like "it can't be that easy," but I 
don't know.




Comment at: clang/test/SemaCXX/cxx2a-constexpr-dynalloc.cpp:138
 }
 static_assert(call_std_construct_at());
 

I would think you ought to have the same species of test for the array case, 
also. Could probably be added right in here:
```
  std::construct_at(p + 2, 3);
  bool good = p[0] + p[1] + p[2] == 6;
  std::construct_at(p, 4, 5, 6);
  bool also_good = p[0] + p[1] + p[2] == 15;
```
Also, it would be good to test the behavior of `using T = int[]; new () T{}` 
with an incomplete type, unless that's already tested somewhere.
Also note this test is compile-only (since it expects errors), and so it would 
probably be a good idea to have some tests for the behavior/codegen, not just 
that it seems to be accepted silently by the compiler (and in the presence of 
other errors at that).


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D114903

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


[PATCH] D118552: [clang] [concepts] Correctly(?) handle placeholder types in ExprRequirements.

2022-01-31 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone updated this revision to Diff 404624.
Quuxplusone added a comment.

Update another single-line `if` too.


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

https://reviews.llvm.org/D118552

Files:
  clang/lib/AST/ASTContext.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/SemaTemplateInstantiate.cpp
  clang/lib/Sema/TreeTransform.h
  clang/test/SemaTemplate/constraints.cpp
  clang/test/SemaTemplate/pr52909.cpp

Index: clang/test/SemaTemplate/pr52909.cpp
===
--- /dev/null
+++ clang/test/SemaTemplate/pr52909.cpp
@@ -0,0 +1,71 @@
+// RUN: %clang_cc1 -std=c++20 -verify %s
+// RUN: %clang_cc1 -std=c++2b -verify %s
+
+namespace PR52905 {
+template  concept C = true;
+
+struct A {
+  int begin();
+  int begin() const;
+};
+
+template 
+concept Beginable = requires (T t) {
+  { t.begin } -> C;
+  // expected-note@-1 {{because 't.begin' would be invalid: reference to non-static member function must be called}}
+};
+
+static_assert(Beginable); // expected-error {{static_assert failed}}
+ // expected-note@-1 {{does not satisfy 'Beginable'}}
+} // namespace PR52905
+
+namespace PR52909a {
+
+template constexpr bool B = true;
+template concept True = B;
+
+template 
+int foo(T t) requires requires { // expected-note {{candidate template ignored: constraints not satisfied}}
+{t.begin} -> True; // expected-note {{because 't.begin' would be invalid: reference to non-static member function must be called}}
+}
+{}
+
+struct A { int begin(); };
+auto x = foo(A()); // expected-error {{no matching function for call to 'foo'}}
+
+} // namespace PR52909a
+
+namespace PR52909b {
+
+template concept True = true;
+
+template concept C = requires {
+{ T::begin } -> True; // expected-note {{because 'T::begin' would be invalid: reference to overloaded function could not be resolved}}
+};
+
+struct A {
+static void begin(int);
+static void begin(double);
+};
+
+static_assert(C); // expected-error {{static_assert failed}}
+  // expected-note@-1 {{because 'PR52909b::A' does not satisfy 'C'}}
+
+} // namespace PR52909b
+
+namespace PR53075 {
+template concept True = true;
+
+template concept C = requires {
+{ ::f } -> True; // expected-note {{because '::f' would be invalid: reference to overloaded function could not be resolved}}
+};
+
+struct S {
+int *f();
+int *f() const;
+};
+
+static_assert(C); // expected-error {{static_assert failed}}
+  // expected-note@-1 {{because 'PR53075::S' does not satisfy 'C'}}
+
+} // namespace PR53075
Index: clang/test/SemaTemplate/constraints.cpp
===
--- clang/test/SemaTemplate/constraints.cpp
+++ clang/test/SemaTemplate/constraints.cpp
@@ -24,35 +24,3 @@
   // FIXME: These diagnostics are excessive.
   static_assert(test == 1); // expected-note 2{{while}} expected-note 2{{during}}
 }
-
-namespace PR52905 {
-// A mock for std::convertible_to. Not complete support.
-template 
-concept convertible_to = __is_convertible_to(_From, _To); // expected-note {{evaluated to false}}
-
-template 
-class A {
-public:
-  using iterator = void **;
-
-  iterator begin();
-  const iterator begin() const;
-};
-
-template 
-concept Beginable1 = requires(T t) {
-  { t.begin }
-  ->convertible_to; // expected-note {{not satisfied}}
-};
-
-static_assert(Beginable1>); // expected-error {{static_assert failed}}
-   // expected-note@-1 {{does not satisfy 'Beginable1'}}
-
-template 
-concept Beginable2 = requires(T t) {
-  { t.begin() }
-  ->convertible_to;
-};
-
-static_assert(Beginable2>);
-} // namespace PR52905
Index: clang/lib/Sema/TreeTransform.h
===
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -12494,6 +12494,8 @@
 TransExpr = Req->getExprSubstitutionDiagnostic();
   else {
 ExprResult TransExprRes = getDerived().TransformExpr(Req->getExpr());
+if (TransExprRes.isUsable() && TransExprRes.get()->hasPlaceholderType())
+  TransExprRes = SemaRef.CheckPlaceholderExpr(TransExprRes.get());
 if (TransExprRes.isInvalid())
   return nullptr;
 TransExpr = TransExprRes.get();
Index: clang/lib/Sema/SemaTemplateInstantiate.cpp
===
--- clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1943,6 +1943,9 @@
 if (ExprInst.isInvalid())
   return nullptr;
 ExprResult TransExprRes = TransformExpr(E);
+if (!TransExprRes.isInvalid() && !Trap.hasErrorOccurred() &&
+TransExprRes.get()->hasPlaceholderType())
+  TransExprRes = SemaRef.CheckPlaceholderExpr(TransExprRes.get());
 if (TransExprRes.isInvalid() || Trap.hasErrorOccurred())
   TransExpr = createSubstDiag(SemaRef, Info, [&](llvm::raw_ostream ) {
 E->printPretty(OS, nullptr, 

[PATCH] D118552: [clang] [concepts] Correctly(?) handle placeholder types in ExprRequirements.

2022-01-31 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone updated this revision to Diff 404621.
Quuxplusone added a comment.

Update assert style.


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

https://reviews.llvm.org/D118552

Files:
  clang/lib/AST/ASTContext.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/SemaTemplateInstantiate.cpp
  clang/lib/Sema/TreeTransform.h
  clang/test/SemaTemplate/constraints.cpp
  clang/test/SemaTemplate/pr52909.cpp

Index: clang/test/SemaTemplate/pr52909.cpp
===
--- /dev/null
+++ clang/test/SemaTemplate/pr52909.cpp
@@ -0,0 +1,71 @@
+// RUN: %clang_cc1 -std=c++20 -verify %s
+// RUN: %clang_cc1 -std=c++2b -verify %s
+
+namespace PR52905 {
+template  concept C = true;
+
+struct A {
+  int begin();
+  int begin() const;
+};
+
+template 
+concept Beginable = requires (T t) {
+  { t.begin } -> C;
+  // expected-note@-1 {{because 't.begin' would be invalid: reference to non-static member function must be called}}
+};
+
+static_assert(Beginable); // expected-error {{static_assert failed}}
+ // expected-note@-1 {{does not satisfy 'Beginable'}}
+} // namespace PR52905
+
+namespace PR52909a {
+
+template constexpr bool B = true;
+template concept True = B;
+
+template 
+int foo(T t) requires requires { // expected-note {{candidate template ignored: constraints not satisfied}}
+{t.begin} -> True; // expected-note {{because 't.begin' would be invalid: reference to non-static member function must be called}}
+}
+{}
+
+struct A { int begin(); };
+auto x = foo(A()); // expected-error {{no matching function for call to 'foo'}}
+
+} // namespace PR52909a
+
+namespace PR52909b {
+
+template concept True = true;
+
+template concept C = requires {
+{ T::begin } -> True; // expected-note {{because 'T::begin' would be invalid: reference to overloaded function could not be resolved}}
+};
+
+struct A {
+static void begin(int);
+static void begin(double);
+};
+
+static_assert(C); // expected-error {{static_assert failed}}
+  // expected-note@-1 {{because 'PR52909b::A' does not satisfy 'C'}}
+
+} // namespace PR52909b
+
+namespace PR53075 {
+template concept True = true;
+
+template concept C = requires {
+{ ::f } -> True; // expected-note {{because '::f' would be invalid: reference to overloaded function could not be resolved}}
+};
+
+struct S {
+int *f();
+int *f() const;
+};
+
+static_assert(C); // expected-error {{static_assert failed}}
+  // expected-note@-1 {{because 'PR53075::S' does not satisfy 'C'}}
+
+} // namespace PR53075
Index: clang/test/SemaTemplate/constraints.cpp
===
--- clang/test/SemaTemplate/constraints.cpp
+++ clang/test/SemaTemplate/constraints.cpp
@@ -24,35 +24,3 @@
   // FIXME: These diagnostics are excessive.
   static_assert(test == 1); // expected-note 2{{while}} expected-note 2{{during}}
 }
-
-namespace PR52905 {
-// A mock for std::convertible_to. Not complete support.
-template 
-concept convertible_to = __is_convertible_to(_From, _To); // expected-note {{evaluated to false}}
-
-template 
-class A {
-public:
-  using iterator = void **;
-
-  iterator begin();
-  const iterator begin() const;
-};
-
-template 
-concept Beginable1 = requires(T t) {
-  { t.begin }
-  ->convertible_to; // expected-note {{not satisfied}}
-};
-
-static_assert(Beginable1>); // expected-error {{static_assert failed}}
-   // expected-note@-1 {{does not satisfy 'Beginable1'}}
-
-template 
-concept Beginable2 = requires(T t) {
-  { t.begin() }
-  ->convertible_to;
-};
-
-static_assert(Beginable2>);
-} // namespace PR52905
Index: clang/lib/Sema/TreeTransform.h
===
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -12494,6 +12494,8 @@
 TransExpr = Req->getExprSubstitutionDiagnostic();
   else {
 ExprResult TransExprRes = getDerived().TransformExpr(Req->getExpr());
+if (TransExprRes.isUsable() && TransExprRes.get()->hasPlaceholderType())
+  TransExprRes = SemaRef.CheckPlaceholderExpr(TransExprRes.get());
 if (TransExprRes.isInvalid())
   return nullptr;
 TransExpr = TransExprRes.get();
Index: clang/lib/Sema/SemaTemplateInstantiate.cpp
===
--- clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1943,6 +1943,11 @@
 if (ExprInst.isInvalid())
   return nullptr;
 ExprResult TransExprRes = TransformExpr(E);
+if (TransExprRes.isUsable() && !Trap.hasErrorOccurred()) {
+  if (TransExprRes.get()->hasPlaceholderType()) {
+TransExprRes = SemaRef.CheckPlaceholderExpr(TransExprRes.get());
+  }
+}
 if (TransExprRes.isInvalid() || Trap.hasErrorOccurred())
   TransExpr = createSubstDiag(SemaRef, Info, [&](llvm::raw_ostream ) {
 E->printPretty(OS, nullptr, 

[PATCH] D118552: [clang] [concepts] Correctly(?) handle placeholder types in ExprRequirements.

2022-01-31 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: clang/lib/AST/ASTContext.cpp:3373
 ASTContext::getLValueReferenceType(QualType T, bool SpelledAsLValue) const {
-  assert(getCanonicalType(T) != OverloadTy &&
- "Unresolved overloaded function type");
+  if (T->isPlaceholderType()) {
+assert(T->isSpecificPlaceholderType(BuiltinType::UnknownAny) &&

urnathan wrote:
> sorry to be picky, but
>  (a) why the {...} on the single body stmt? Isn't that against style?
>  (b) are we sure the if's condition is sufficiently const so that it goes 
> away when the assert is inactive?  if's containing a single assert make me 
> nervous.
No problem, I'll move the whole thing into the assert, which will fix both 
points. Ditto line 3414.

(I did it this way originally only for historical reasons, because I had been 
putting extra code (printf/abort) into the `if` to find out what placeholder 
types I needed to grandfather in.)


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

https://reviews.llvm.org/D118552

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


[PATCH] D118552: [clang] [concepts] Correctly(?) handle placeholder types in ExprRequirements.

2022-01-31 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added a comment.

Gentle ping! (@ChuanqiXu @urnathan perhaps?)
I'm hoping to land D118552  followed by a 
re-land of D117603 , this week and 
//ideally// tomorrow. :)


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

https://reviews.llvm.org/D118552

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


[PATCH] D117603: [clang] Don't typo-fix an expression in a SFINAE context

2022-01-30 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone updated this revision to Diff 404381.
Quuxplusone added a comment.

Poke CI (clang-format failed).


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

https://reviews.llvm.org/D117603

Files:
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExprMember.cpp
  clang/test/SemaTemplate/pr52970.cpp

Index: clang/test/SemaTemplate/pr52970.cpp
===
--- /dev/null
+++ clang/test/SemaTemplate/pr52970.cpp
@@ -0,0 +1,63 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify=cxx20 %s
+// expected-no-diagnostics
+
+struct Incomplete;
+template  struct Holder { T t; };
+
+namespace DotFollowingFunctionName {
+struct Good {
+  struct Nested {
+int b;
+  } a;
+};
+
+struct Bad {
+  Holder a();
+};
+
+template 
+constexpr auto f(T t) -> decltype((t.a.b, true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingFunctionName::f(Good{}), "");
+static_assert(!DotFollowingFunctionName::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.a.b; };
+  // cxx20-note@-1 {{because 't.a.b' would be invalid: reference to non-static member function must be called}}
+
+static_assert(C);
+static_assert(!C);
+static_assert(C); // cxx20-error {{static_assert failed}}
+  // cxx20-note@-1 {{because 'DotFollowingFunctionName::Bad' does not satisfy 'C'}}
+#endif
+} // namespace DotFollowingFunctionName
+
+namespace DotFollowingPointer {
+struct Good {
+  int begin();
+};
+using Bad = Holder *;
+
+template 
+constexpr auto f(T t) -> decltype((t.begin(), true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingPointer::f(Good{}), "");
+static_assert(!DotFollowingPointer::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.begin(); };
+  // cxx20-note@-1 {{because 't.begin()' would be invalid: member reference type 'Holder *' is a pointer}}
+
+static_assert(C);
+static_assert(!C);
+static_assert(C); // cxx20-error {{static_assert failed}}
+  // cxx20-note@-1 {{because 'DotFollowingPointer::Bad' (aka 'Holder *') does not satisfy 'C'}}
+#endif
+} // namespace DotFollowingPointer
Index: clang/lib/Sema/SemaExprMember.cpp
===
--- clang/lib/Sema/SemaExprMember.cpp
+++ clang/lib/Sema/SemaExprMember.cpp
@@ -1645,6 +1645,9 @@
   << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
   << FixItHint::CreateReplacement(OpLoc, "->");
 
+  if (S.isSFINAEContext())
+return ExprError();
+
   // Recurse as an -> access.
   IsArrow = true;
   return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -2556,32 +2556,36 @@
 bool (*IsPlausibleResult)(QualType)) {
   SourceLocation Loc = E.get()->getExprLoc();
   SourceRange Range = E.get()->getSourceRange();
-
-  QualType ZeroArgCallTy;
   UnresolvedSet<4> Overloads;
-  if (tryExprAsCall(*E.get(), ZeroArgCallTy, Overloads) &&
-  !ZeroArgCallTy.isNull() &&
-  (!IsPlausibleResult || IsPlausibleResult(ZeroArgCallTy))) {
-// At this point, we know E is potentially callable with 0
-// arguments and that it returns something of a reasonable type,
-// so we can emit a fixit and carry on pretending that E was
-// actually a CallExpr.
-SourceLocation ParenInsertionLoc = getLocForEndOfToken(Range.getEnd());
-bool IsMV = IsCPUDispatchCPUSpecificMultiVersion(E.get());
-Diag(Loc, PD) << /*zero-arg*/ 1 << IsMV << Range
-  << (IsCallableWithAppend(E.get())
-  ? FixItHint::CreateInsertion(ParenInsertionLoc, "()")
-  : FixItHint());
-if (!IsMV)
-  notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult);
-
-// FIXME: Try this before emitting the fixit, and suppress diagnostics
-// while doing so.
-E = BuildCallExpr(nullptr, E.get(), Range.getEnd(), None,
-  Range.getEnd().getLocWithOffset(1));
-return true;
-  }
 
+  // If this is a SFINAE context, don't try anything that might trigger ADL
+  // prematurely.
+  if (!isSFINAEContext()) {
+QualType ZeroArgCallTy;
+if (tryExprAsCall(*E.get(), ZeroArgCallTy, Overloads) &&
+!ZeroArgCallTy.isNull() &&
+(!IsPlausibleResult || IsPlausibleResult(ZeroArgCallTy))) {
+  // At this point, we know E is potentially callable with 0
+  // arguments and that it returns something of a reasonable type,
+  // so we can emit a fixit and carry on pretending that E was
+  // actually a CallExpr.
+  SourceLocation 

[PATCH] D118552: [clang] [concepts] Correctly(?) handle placeholder types in ExprRequirements.

2022-01-30 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone updated this revision to Diff 404380.
Quuxplusone added a comment.

Poke CI (clang-format failed).


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

https://reviews.llvm.org/D118552

Files:
  clang/lib/AST/ASTContext.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/SemaTemplateInstantiate.cpp
  clang/lib/Sema/TreeTransform.h
  clang/test/SemaTemplate/constraints.cpp
  clang/test/SemaTemplate/pr52909.cpp

Index: clang/test/SemaTemplate/pr52909.cpp
===
--- /dev/null
+++ clang/test/SemaTemplate/pr52909.cpp
@@ -0,0 +1,71 @@
+// RUN: %clang_cc1 -std=c++20 -verify %s
+// RUN: %clang_cc1 -std=c++2b -verify %s
+
+namespace PR52905 {
+template  concept C = true;
+
+struct A {
+  int begin();
+  int begin() const;
+};
+
+template 
+concept Beginable = requires (T t) {
+  { t.begin } -> C;
+  // expected-note@-1 {{because 't.begin' would be invalid: reference to non-static member function must be called}}
+};
+
+static_assert(Beginable); // expected-error {{static_assert failed}}
+ // expected-note@-1 {{does not satisfy 'Beginable'}}
+} // namespace PR52905
+
+namespace PR52909a {
+
+template constexpr bool B = true;
+template concept True = B;
+
+template 
+int foo(T t) requires requires { // expected-note {{candidate template ignored: constraints not satisfied}}
+{t.begin} -> True; // expected-note {{because 't.begin' would be invalid: reference to non-static member function must be called}}
+}
+{}
+
+struct A { int begin(); };
+auto x = foo(A()); // expected-error {{no matching function for call to 'foo'}}
+
+} // namespace PR52909a
+
+namespace PR52909b {
+
+template concept True = true;
+
+template concept C = requires {
+{ T::begin } -> True; // expected-note {{because 'T::begin' would be invalid: reference to overloaded function could not be resolved}}
+};
+
+struct A {
+static void begin(int);
+static void begin(double);
+};
+
+static_assert(C); // expected-error {{static_assert failed}}
+  // expected-note@-1 {{because 'PR52909b::A' does not satisfy 'C'}}
+
+} // namespace PR52909b
+
+namespace PR53075 {
+template concept True = true;
+
+template concept C = requires {
+{ ::f } -> True; // expected-note {{because '::f' would be invalid: reference to overloaded function could not be resolved}}
+};
+
+struct S {
+int *f();
+int *f() const;
+};
+
+static_assert(C); // expected-error {{static_assert failed}}
+  // expected-note@-1 {{because 'PR53075::S' does not satisfy 'C'}}
+
+} // namespace PR53075
Index: clang/test/SemaTemplate/constraints.cpp
===
--- clang/test/SemaTemplate/constraints.cpp
+++ clang/test/SemaTemplate/constraints.cpp
@@ -24,35 +24,3 @@
   // FIXME: These diagnostics are excessive.
   static_assert(test == 1); // expected-note 2{{while}} expected-note 2{{during}}
 }
-
-namespace PR52905 {
-// A mock for std::convertible_to. Not complete support.
-template 
-concept convertible_to = __is_convertible_to(_From, _To); // expected-note {{evaluated to false}}
-
-template 
-class A {
-public:
-  using iterator = void **;
-
-  iterator begin();
-  const iterator begin() const;
-};
-
-template 
-concept Beginable1 = requires(T t) {
-  { t.begin }
-  ->convertible_to; // expected-note {{not satisfied}}
-};
-
-static_assert(Beginable1>); // expected-error {{static_assert failed}}
-   // expected-note@-1 {{does not satisfy 'Beginable1'}}
-
-template 
-concept Beginable2 = requires(T t) {
-  { t.begin() }
-  ->convertible_to;
-};
-
-static_assert(Beginable2>);
-} // namespace PR52905
Index: clang/lib/Sema/TreeTransform.h
===
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -12494,6 +12494,8 @@
 TransExpr = Req->getExprSubstitutionDiagnostic();
   else {
 ExprResult TransExprRes = getDerived().TransformExpr(Req->getExpr());
+if (TransExprRes.isUsable() && TransExprRes.get()->hasPlaceholderType())
+  TransExprRes = SemaRef.CheckPlaceholderExpr(TransExprRes.get());
 if (TransExprRes.isInvalid())
   return nullptr;
 TransExpr = TransExprRes.get();
Index: clang/lib/Sema/SemaTemplateInstantiate.cpp
===
--- clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1943,6 +1943,11 @@
 if (ExprInst.isInvalid())
   return nullptr;
 ExprResult TransExprRes = TransformExpr(E);
+if (TransExprRes.isUsable() && !Trap.hasErrorOccurred()) {
+  if (TransExprRes.get()->hasPlaceholderType()) {
+TransExprRes = SemaRef.CheckPlaceholderExpr(TransExprRes.get());
+  }
+}
 if (TransExprRes.isInvalid() || Trap.hasErrorOccurred())
   TransExpr = createSubstDiag(SemaRef, Info, [&](llvm::raw_ostream ) {
 E->printPretty(OS, 

[PATCH] D118552: [clang] [concepts] Correctly(?) handle placeholder types in ExprRequirements.

2022-01-30 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: clang/lib/AST/ASTContext.cpp:3375
+assert(T->isSpecificPlaceholderType(BuiltinType::UnknownAny) && 
"Unresolved placeholder type");
+  }
 

Quuxplusone wrote:
> Btw, I strongly suspect that the presence of placeholder type `UnknownAny` 
> all the way down in here is a bug (@rjmccall, thoughts?). But I found that 
> the test suite didn't pass without this exception, and I'm not terribly 
> interested in tracking down why; I don't have any idea what `UnknownAny` is, 
> myself.
>>! In D118552#3282538, @rjmccall wrote:
> It's a type that the debugger integration uses when it doesn't know the type 
> of a symbol.  If it's a data symbol, you make a `VarDecl` with `UnknownAny` 
> type; if it's a function symbol, you make a `FunctionDecl` with `UnknownAny`. 
>  In either case, if the user fails to cast it, it gets diagnosed as an error.
> 
> I can't think of any reason why we'd want to build a reference to 
> `UnknownAny` type; generally it's bad if the type "escapes" into subordinate 
> positions.  Probably we should be diagnosing something before we try to 
> propagate the `UnknownAny` type.

I've found https://github.com/llvm/llvm-project/issues/32247 on the same topic, 
and updated it with a comment and my own test case.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D118552

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


[PATCH] D117603: [clang] Don't typo-fix an expression in a SFINAE context

2022-01-29 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone updated this revision to Diff 404343.
Quuxplusone added a comment.

Move the regression test to clang/test/SemaTemplate/, alongside the one for 
D118552 . Also, make it test the error 
message wording.


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

https://reviews.llvm.org/D117603

Files:
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExprMember.cpp
  clang/test/SemaTemplate/pr52970.cpp

Index: clang/test/SemaTemplate/pr52970.cpp
===
--- /dev/null
+++ clang/test/SemaTemplate/pr52970.cpp
@@ -0,0 +1,63 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify=cxx20 %s
+// expected-no-diagnostics
+
+struct Incomplete;
+template  struct Holder { T t; };
+
+namespace DotFollowingFunctionName {
+struct Good {
+  struct Nested {
+int b;
+  } a;
+};
+
+struct Bad {
+  Holder a();
+};
+
+template 
+constexpr auto f(T t) -> decltype((t.a.b, true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingFunctionName::f(Good{}), "");
+static_assert(!DotFollowingFunctionName::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.a.b; };
+  // cxx20-note@-1 {{because 't.a.b' would be invalid: reference to non-static member function must be called}}
+
+static_assert(C);
+static_assert(!C);
+static_assert(C); // cxx20-error {{static_assert failed}}
+  // cxx20-note@-1 {{because 'DotFollowingFunctionName::Bad' does not satisfy 'C'}}
+#endif
+} // namespace DotFollowingFunctionName
+
+namespace DotFollowingPointer {
+struct Good {
+  int begin();
+};
+using Bad = Holder *;
+
+template 
+constexpr auto f(T t) -> decltype((t.begin(), true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingPointer::f(Good{}), "");
+static_assert(!DotFollowingPointer::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.begin(); };
+  // cxx20-note@-1 {{because 't.begin()' would be invalid: member reference type 'Holder *' is a pointer}}
+
+static_assert(C);
+static_assert(!C);
+static_assert(C); // cxx20-error {{static_assert failed}}
+  // cxx20-note@-1 {{because 'DotFollowingPointer::Bad' (aka 'Holder *') does not satisfy 'C'}}
+#endif
+} // namespace DotFollowingPointer
Index: clang/lib/Sema/SemaExprMember.cpp
===
--- clang/lib/Sema/SemaExprMember.cpp
+++ clang/lib/Sema/SemaExprMember.cpp
@@ -1645,6 +1645,9 @@
   << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
   << FixItHint::CreateReplacement(OpLoc, "->");
 
+  if (S.isSFINAEContext())
+return ExprError();
+
   // Recurse as an -> access.
   IsArrow = true;
   return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -2556,32 +2556,35 @@
 bool (*IsPlausibleResult)(QualType)) {
   SourceLocation Loc = E.get()->getExprLoc();
   SourceRange Range = E.get()->getSourceRange();
-
-  QualType ZeroArgCallTy;
   UnresolvedSet<4> Overloads;
-  if (tryExprAsCall(*E.get(), ZeroArgCallTy, Overloads) &&
-  !ZeroArgCallTy.isNull() &&
-  (!IsPlausibleResult || IsPlausibleResult(ZeroArgCallTy))) {
-// At this point, we know E is potentially callable with 0
-// arguments and that it returns something of a reasonable type,
-// so we can emit a fixit and carry on pretending that E was
-// actually a CallExpr.
-SourceLocation ParenInsertionLoc = getLocForEndOfToken(Range.getEnd());
-bool IsMV = IsCPUDispatchCPUSpecificMultiVersion(E.get());
-Diag(Loc, PD) << /*zero-arg*/ 1 << IsMV << Range
-  << (IsCallableWithAppend(E.get())
-  ? FixItHint::CreateInsertion(ParenInsertionLoc, "()")
-  : FixItHint());
-if (!IsMV)
-  notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult);
-
-// FIXME: Try this before emitting the fixit, and suppress diagnostics
-// while doing so.
-E = BuildCallExpr(nullptr, E.get(), Range.getEnd(), None,
-  Range.getEnd().getLocWithOffset(1));
-return true;
-  }
 
+  // If this is a SFINAE context, don't try anything that might trigger ADL
+  // prematurely.
+  if (!isSFINAEContext()) {
+QualType ZeroArgCallTy;
+if (tryExprAsCall(*E.get(), ZeroArgCallTy, Overloads) &&
+!ZeroArgCallTy.isNull() &&
+(!IsPlausibleResult || IsPlausibleResult(ZeroArgCallTy))) {
+  // At this point, we know E is potentially callable with 0
+  // arguments and that it returns something of a 

[PATCH] D117603: [clang] Don't typo-fix an expression in a SFINAE context

2022-01-29 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone updated this revision to Diff 404341.
Quuxplusone added a comment.

It seems like we need `tryToRecoverWithCall` to always identify a diagnostic 
explaining the problem, so just short-circuit-returning `ExprError()` with no 
diagnostic is not acceptable. Let's try this version instead.
(This is also now based on top of D118552 .)


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

https://reviews.llvm.org/D117603

Files:
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExprMember.cpp
  clang/test/SemaCXX/PR52970.cpp

Index: clang/test/SemaCXX/PR52970.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/PR52970.cpp
@@ -0,0 +1,57 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+// expected-no-diagnostics
+
+struct Incomplete;
+template  struct Holder { T t; };
+
+namespace DotFollowingFunctionName {
+struct Good {
+  struct Nested {
+int b;
+  } a;
+};
+
+struct Bad {
+  Holder a();
+};
+
+template 
+constexpr auto f(T t) -> decltype((t.a.b, true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingFunctionName::f(Good{}), "");
+static_assert(!DotFollowingFunctionName::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.a.b; };
+
+static_assert(C);
+static_assert(!C);
+#endif
+} // namespace DotFollowingFunctionName
+
+namespace DotFollowingPointer {
+struct Good {
+  int begin();
+};
+using Bad = Holder *;
+
+template 
+constexpr auto f(T t) -> decltype((t.begin(), true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingPointer::f(Good{}), "");
+static_assert(!DotFollowingPointer::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.begin(); };
+
+static_assert(C);
+static_assert(!C);
+#endif
+} // namespace DotFollowingPointer
Index: clang/lib/Sema/SemaExprMember.cpp
===
--- clang/lib/Sema/SemaExprMember.cpp
+++ clang/lib/Sema/SemaExprMember.cpp
@@ -1645,6 +1645,9 @@
   << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
   << FixItHint::CreateReplacement(OpLoc, "->");
 
+  if (S.isSFINAEContext())
+return ExprError();
+
   // Recurse as an -> access.
   IsArrow = true;
   return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -2556,32 +2556,35 @@
 bool (*IsPlausibleResult)(QualType)) {
   SourceLocation Loc = E.get()->getExprLoc();
   SourceRange Range = E.get()->getSourceRange();
-
-  QualType ZeroArgCallTy;
   UnresolvedSet<4> Overloads;
-  if (tryExprAsCall(*E.get(), ZeroArgCallTy, Overloads) &&
-  !ZeroArgCallTy.isNull() &&
-  (!IsPlausibleResult || IsPlausibleResult(ZeroArgCallTy))) {
-// At this point, we know E is potentially callable with 0
-// arguments and that it returns something of a reasonable type,
-// so we can emit a fixit and carry on pretending that E was
-// actually a CallExpr.
-SourceLocation ParenInsertionLoc = getLocForEndOfToken(Range.getEnd());
-bool IsMV = IsCPUDispatchCPUSpecificMultiVersion(E.get());
-Diag(Loc, PD) << /*zero-arg*/ 1 << IsMV << Range
-  << (IsCallableWithAppend(E.get())
-  ? FixItHint::CreateInsertion(ParenInsertionLoc, "()")
-  : FixItHint());
-if (!IsMV)
-  notePlausibleOverloads(*this, Loc, Overloads, IsPlausibleResult);
-
-// FIXME: Try this before emitting the fixit, and suppress diagnostics
-// while doing so.
-E = BuildCallExpr(nullptr, E.get(), Range.getEnd(), None,
-  Range.getEnd().getLocWithOffset(1));
-return true;
-  }
 
+  // If this is a SFINAE context, don't try anything that might trigger ADL
+  // prematurely.
+  if (!isSFINAEContext()) {
+QualType ZeroArgCallTy;
+if (tryExprAsCall(*E.get(), ZeroArgCallTy, Overloads) &&
+!ZeroArgCallTy.isNull() &&
+(!IsPlausibleResult || IsPlausibleResult(ZeroArgCallTy))) {
+  // At this point, we know E is potentially callable with 0
+  // arguments and that it returns something of a reasonable type,
+  // so we can emit a fixit and carry on pretending that E was
+  // actually a CallExpr.
+  SourceLocation ParenInsertionLoc = getLocForEndOfToken(Range.getEnd());
+  bool IsMV = IsCPUDispatchCPUSpecificMultiVersion(E.get());
+  Diag(Loc, PD) << /*zero-arg*/ 1 << IsMV << Range
+<< (IsCallableWithAppend(E.get())
+? 

[PATCH] D118552: [clang] [concepts] Correctly(?) handle placeholder types in ExprRequirements.

2022-01-29 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added a subscriber: rjmccall.
Quuxplusone added inline comments.



Comment at: clang/lib/AST/ASTContext.cpp:3375
+assert(T->isSpecificPlaceholderType(BuiltinType::UnknownAny) && 
"Unresolved placeholder type");
+  }
 

Btw, I strongly suspect that the presence of placeholder type `UnknownAny` all 
the way down in here is a bug (@rjmccall, thoughts?). But I found that the test 
suite didn't pass without this exception, and I'm not terribly interested in 
tracking down why; I don't have any idea what `UnknownAny` is, myself.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D118552

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


[PATCH] D118552: [clang] [concepts] Correctly(?) handle placeholder types in ExprRequirements.

2022-01-29 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone created this revision.
Quuxplusone added reviewers: ChuanqiXu, saar.raz, rsmith.
Quuxplusone added a project: clang.
Quuxplusone requested review of this revision.
Herald added a subscriber: cfe-commits.

PR52905 was originally papered over in a different way, but I believe this is 
the actually proper fix, or at least closer to it. We need to detect 
placeholder types as close to the front-end as possible, and cause them to fail 
constraints, rather than letting them persist into later stages.

  

Fixes https://llvm.org/PR52905
Fixes https://llvm.org/PR52909
Fixes https://llvm.org/PR53075


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D118552

Files:
  clang/lib/AST/ASTContext.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/SemaTemplateInstantiate.cpp
  clang/lib/Sema/TreeTransform.h
  clang/test/SemaTemplate/constraints.cpp
  clang/test/SemaTemplate/pr52909.cpp

Index: clang/test/SemaTemplate/pr52909.cpp
===
--- /dev/null
+++ clang/test/SemaTemplate/pr52909.cpp
@@ -0,0 +1,71 @@
+// RUN: %clang_cc1 -std=c++20 -verify %s
+// RUN: %clang_cc1 -std=c++2b -verify %s
+
+namespace PR52905 {
+template  concept C = true;
+
+struct A {
+  int begin();
+  int begin() const;
+};
+
+template 
+concept Beginable = requires (T t) {
+  { t.begin } -> C;
+  // expected-note@-1 {{because 't.begin' would be invalid: reference to non-static member function must be called}}
+};
+
+static_assert(Beginable); // expected-error {{static_assert failed}}
+ // expected-note@-1 {{does not satisfy 'Beginable'}}
+} // namespace PR52905
+
+namespace PR52909a {
+
+template constexpr bool B = true;
+template concept True = B;
+
+template 
+int foo(T t) requires requires { // expected-note {{candidate template ignored: constraints not satisfied}}
+{t.begin} -> True; // expected-note {{because 't.begin' would be invalid: reference to non-static member function must be called}}
+}
+{}
+
+struct A { int begin(); };
+auto x = foo(A()); // expected-error {{no matching function for call to 'foo'}}
+
+} // namespace PR52909a
+
+namespace PR52909b {
+
+template concept True = true;
+
+template concept C = requires {
+{ T::begin } -> True; // expected-note {{because 'T::begin' would be invalid: reference to overloaded function could not be resolved}}
+};
+
+struct A {
+static void begin(int);
+static void begin(double);
+};
+
+static_assert(C); // expected-error {{static_assert failed}}
+  // expected-note@-1 {{because 'PR52909b::A' does not satisfy 'C'}}
+
+} // namespace PR52909b
+
+namespace PR53075 {
+template concept True = true;
+
+template concept C = requires {
+{ ::f } -> True; // expected-note {{because '::f' would be invalid: reference to overloaded function could not be resolved}}
+};
+
+struct S {
+int *f();
+int *f() const;
+};
+
+static_assert(C); // expected-error {{static_assert failed}}
+  // expected-note@-1 {{because 'PR53075::S' does not satisfy 'C'}}
+
+} // namespace PR53075
Index: clang/test/SemaTemplate/constraints.cpp
===
--- clang/test/SemaTemplate/constraints.cpp
+++ clang/test/SemaTemplate/constraints.cpp
@@ -24,35 +24,3 @@
   // FIXME: These diagnostics are excessive.
   static_assert(test == 1); // expected-note 2{{while}} expected-note 2{{during}}
 }
-
-namespace PR52905 {
-// A mock for std::convertible_to. Not complete support.
-template 
-concept convertible_to = __is_convertible_to(_From, _To); // expected-note {{evaluated to false}}
-
-template 
-class A {
-public:
-  using iterator = void **;
-
-  iterator begin();
-  const iterator begin() const;
-};
-
-template 
-concept Beginable1 = requires(T t) {
-  { t.begin }
-  ->convertible_to; // expected-note {{not satisfied}}
-};
-
-static_assert(Beginable1>); // expected-error {{static_assert failed}}
-   // expected-note@-1 {{does not satisfy 'Beginable1'}}
-
-template 
-concept Beginable2 = requires(T t) {
-  { t.begin() }
-  ->convertible_to;
-};
-
-static_assert(Beginable2>);
-} // namespace PR52905
Index: clang/lib/Sema/TreeTransform.h
===
--- clang/lib/Sema/TreeTransform.h
+++ clang/lib/Sema/TreeTransform.h
@@ -12494,6 +12494,8 @@
 TransExpr = Req->getExprSubstitutionDiagnostic();
   else {
 ExprResult TransExprRes = getDerived().TransformExpr(Req->getExpr());
+if (TransExprRes.isUsable() && TransExprRes.get()->hasPlaceholderType())
+  TransExprRes = SemaRef.CheckPlaceholderExpr(TransExprRes.get());
 if (TransExprRes.isInvalid())
   return nullptr;
 TransExpr = TransExprRes.get();
Index: clang/lib/Sema/SemaTemplateInstantiate.cpp
===
--- clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1943,6 +1943,11 @@
   

[PATCH] D118518: [clang][NFC] Change some ->getType()->isPlaceholderType() to just ->hasPlaceholderType()

2022-01-29 Thread Arthur O'Dwyer via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG424400da2db8: [clang][NFC] Change some 
-getType()-isPlaceholderType() to just… (authored by arthur.j.odwyer).

Changed prior to commit:
  https://reviews.llvm.org/D118518?vs=404198=404265#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D118518

Files:
  clang/lib/Sema/SemaCoroutine.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp

Index: clang/lib/Sema/SemaExprCXX.cpp
===
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -564,7 +564,7 @@
 SourceLocation RParenLoc) {
   bool WasEvaluated = false;
   if (E && !E->isTypeDependent()) {
-if (E->getType()->isPlaceholderType()) {
+if (E->hasPlaceholderType()) {
   ExprResult result = CheckPlaceholderExpr(E);
   if (result.isInvalid()) return ExprError();
   E = result.get();
@@ -5704,7 +5704,7 @@
   SourceLocation RParen) {
   if (Queried->isTypeDependent()) {
 // Delay type-checking for type-dependent expressions.
-  } else if (Queried->getType()->isPlaceholderType()) {
+  } else if (Queried->hasPlaceholderType()) {
 ExprResult PE = CheckPlaceholderExpr(Queried);
 if (PE.isInvalid()) return ExprError();
 return BuildExpressionTrait(ET, KWLoc, PE.get(), RParen);
@@ -5720,8 +5720,7 @@
 ExprValueKind ,
 SourceLocation Loc,
 bool isIndirect) {
-  assert(!LHS.get()->getType()->isPlaceholderType() &&
- !RHS.get()->getType()->isPlaceholderType() &&
+  assert(!LHS.get()->hasPlaceholderType() && !RHS.get()->hasPlaceholderType() &&
  "placeholders should have been weeded out by now");
 
   // The LHS undergoes lvalue conversions if this is ->*, and undergoes the
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -497,7 +497,7 @@
 /// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4).
 ExprResult Sema::DefaultFunctionArrayConversion(Expr *E, bool Diagnose) {
   // Handle any placeholder expressions which made it here.
-  if (E->getType()->isPlaceholderType()) {
+  if (E->hasPlaceholderType()) {
 ExprResult result = CheckPlaceholderExpr(E);
 if (result.isInvalid()) return ExprError();
 E = result.get();
@@ -621,7 +621,7 @@
 
 ExprResult Sema::DefaultLvalueConversion(Expr *E) {
   // Handle any placeholder expressions which made it here.
-  if (E->getType()->isPlaceholderType()) {
+  if (E->hasPlaceholderType()) {
 ExprResult result = CheckPlaceholderExpr(E);
 if (result.isInvalid()) return ExprError();
 E = result.get();
@@ -4685,7 +4685,7 @@
 Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc,
   Expr *idx, SourceLocation rbLoc) {
   if (base && !base->getType().isNull() &&
-  base->getType()->isSpecificPlaceholderType(BuiltinType::OMPArraySection))
+  base->hasPlaceholderType(BuiltinType::OMPArraySection))
 return ActOnOMPArraySectionExpr(base, lbLoc, idx, SourceLocation(),
 SourceLocation(), /*Length*/ nullptr,
 /*Stride=*/nullptr, rbLoc);
@@ -4711,8 +4711,7 @@
   };
   // The matrix subscript operator ([][])is considered a single operator.
   // Separating the index expressions by parenthesis is not allowed.
-  if (base->getType()->isSpecificPlaceholderType(
-  BuiltinType::IncompleteMatrixIdx) &&
+  if (base->hasPlaceholderType(BuiltinType::IncompleteMatrixIdx) &&
   !isa(base)) {
 Diag(base->getExprLoc(), diag::err_matrix_separate_incomplete_index)
 << SourceRange(base->getBeginLoc(), rbLoc);
@@ -4944,9 +4943,8 @@
   SourceLocation ColonLocSecond,
   Expr *Length, Expr *Stride,
   SourceLocation RBLoc) {
-  if (Base->getType()->isPlaceholderType() &&
-  !Base->getType()->isSpecificPlaceholderType(
-  BuiltinType::OMPArraySection)) {
+  if (Base->hasPlaceholderType() &&
+  !Base->hasPlaceholderType(BuiltinType::OMPArraySection)) {
 ExprResult Result = CheckPlaceholderExpr(Base);
 if (Result.isInvalid())
   return ExprError();
@@ -5114,8 +5112,7 @@
 }
   }
 
-  if (!Base->getType()->isSpecificPlaceholderType(
-  BuiltinType::OMPArraySection)) {
+  if (!Base->hasPlaceholderType(BuiltinType::OMPArraySection)) {
 ExprResult Result = DefaultFunctionArrayLvalueConversion(Base);
 if (Result.isInvalid())
   return 

[PATCH] D118518: [clang][NFC] Change some ->getType()->isPlaceholderType() to just ->hasPlaceholderType()

2022-01-28 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone created this revision.
Quuxplusone added reviewers: ChuanqiXu, urnathan, efriedma, kazu.
Quuxplusone added a project: clang.
Quuxplusone requested review of this revision.
Herald added a subscriber: cfe-commits.

While trying to figure out https://github.com/llvm/llvm-project/issues/52909 
(which I still have not), it seemed like we could simplify some of these 
expressions.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D118518

Files:
  clang/lib/Sema/SemaCoroutine.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/lib/Sema/SemaExprCXX.cpp

Index: clang/lib/Sema/SemaExprCXX.cpp
===
--- clang/lib/Sema/SemaExprCXX.cpp
+++ clang/lib/Sema/SemaExprCXX.cpp
@@ -564,7 +564,7 @@
 SourceLocation RParenLoc) {
   bool WasEvaluated = false;
   if (E && !E->isTypeDependent()) {
-if (E->getType()->isPlaceholderType()) {
+if (E->hasPlaceholderType()) {
   ExprResult result = CheckPlaceholderExpr(E);
   if (result.isInvalid()) return ExprError();
   E = result.get();
@@ -5704,7 +5704,7 @@
   SourceLocation RParen) {
   if (Queried->isTypeDependent()) {
 // Delay type-checking for type-dependent expressions.
-  } else if (Queried->getType()->isPlaceholderType()) {
+  } else if (Queried->hasPlaceholderType()) {
 ExprResult PE = CheckPlaceholderExpr(Queried);
 if (PE.isInvalid()) return ExprError();
 return BuildExpressionTrait(ET, KWLoc, PE.get(), RParen);
@@ -5720,8 +5720,8 @@
 ExprValueKind ,
 SourceLocation Loc,
 bool isIndirect) {
-  assert(!LHS.get()->getType()->isPlaceholderType() &&
- !RHS.get()->getType()->isPlaceholderType() &&
+  assert(!LHS.get()->hasPlaceholderType() &&
+ !RHS.get()->hasPlaceholderType() &&
  "placeholders should have been weeded out by now");
 
   // The LHS undergoes lvalue conversions if this is ->*, and undergoes the
Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -497,7 +497,7 @@
 /// DefaultFunctionArrayConversion (C99 6.3.2.1p3, C99 6.3.2.1p4).
 ExprResult Sema::DefaultFunctionArrayConversion(Expr *E, bool Diagnose) {
   // Handle any placeholder expressions which made it here.
-  if (E->getType()->isPlaceholderType()) {
+  if (E->hasPlaceholderType()) {
 ExprResult result = CheckPlaceholderExpr(E);
 if (result.isInvalid()) return ExprError();
 E = result.get();
@@ -621,7 +621,7 @@
 
 ExprResult Sema::DefaultLvalueConversion(Expr *E) {
   // Handle any placeholder expressions which made it here.
-  if (E->getType()->isPlaceholderType()) {
+  if (E->hasPlaceholderType()) {
 ExprResult result = CheckPlaceholderExpr(E);
 if (result.isInvalid()) return ExprError();
 E = result.get();
@@ -4685,7 +4685,7 @@
 Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base, SourceLocation lbLoc,
   Expr *idx, SourceLocation rbLoc) {
   if (base && !base->getType().isNull() &&
-  base->getType()->isSpecificPlaceholderType(BuiltinType::OMPArraySection))
+  base->hasPlaceholderType(BuiltinType::OMPArraySection))
 return ActOnOMPArraySectionExpr(base, lbLoc, idx, SourceLocation(),
 SourceLocation(), /*Length*/ nullptr,
 /*Stride=*/nullptr, rbLoc);
@@ -4711,8 +4711,7 @@
   };
   // The matrix subscript operator ([][])is considered a single operator.
   // Separating the index expressions by parenthesis is not allowed.
-  if (base->getType()->isSpecificPlaceholderType(
-  BuiltinType::IncompleteMatrixIdx) &&
+  if (base->hasPlaceholderType(BuiltinType::IncompleteMatrixIdx) &&
   !isa(base)) {
 Diag(base->getExprLoc(), diag::err_matrix_separate_incomplete_index)
 << SourceRange(base->getBeginLoc(), rbLoc);
@@ -4944,9 +4943,8 @@
   SourceLocation ColonLocSecond,
   Expr *Length, Expr *Stride,
   SourceLocation RBLoc) {
-  if (Base->getType()->isPlaceholderType() &&
-  !Base->getType()->isSpecificPlaceholderType(
-  BuiltinType::OMPArraySection)) {
+  if (Base->hasPlaceholderType() &&
+  !Base->hasPlaceholderType(BuiltinType::OMPArraySection)) {
 ExprResult Result = CheckPlaceholderExpr(Base);
 if (Result.isInvalid())
   return ExprError();
@@ -5114,8 +5112,7 @@
 }
   }
 
-  if (!Base->getType()->isSpecificPlaceholderType(
-  BuiltinType::OMPArraySection)) {
+  if (!Base->hasPlaceholderType(BuiltinType::OMPArraySection)) {
 ExprResult Result = DefaultFunctionArrayLvalueConversion(Base);
 if (Result.isInvalid())
   return 

[PATCH] D117603: [clang] Don't typo-fix an expression in a SFINAE context

2022-01-27 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone reopened this revision.
Quuxplusone added a comment.
This revision is now accepted and ready to land.

I'm not sure if this caused
https://lab.llvm.org/buildbot/#/builders/60/builds/6350
https://lab.llvm.org/buildbot/#/builders/119/builds/7433
but I'm acting as if it did.

Anyone see how this patch might have caused a placeholder type to survive into 
mangling, //on Windows specifically?//

  Assertion failed: !E->hasPlaceholderType() && "unexpected placeholder", file 
C:\buildbot\as-builder-2\x-aarch64\llvm-project\clang\lib\Sema\SemaType.cpp, 
line 9031
  PLEASE submit a bug report to https://github.com/llvm/llvm-project/issues/ 
and include the crash backtrace, preprocessed source, and associated run script.
  Stack dump:
  0.Program arguments: 
c:\\buildbot\\as-builder-2\\x-aarch64\\build\\bin\\clang++.exe -cc1 -triple 
aarch64-unknown-linux-gnu -emit-obj -mrelax-all --mrelax-relocations 
-disable-free -clear-ast-before-backend -main-file-name deduct_F.pass.cpp 
-mrelocation-model static -mframe-pointer=non-leaf -fmath-errno 
-ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 
-target-cpu generic -target-feature +neon -target-feature +v8a -target-abi 
aapcs -fallow-half-arguments-and-returns -mllvm 
-treat-scalable-fixed-error-as-warning -debugger-tuning=gdb -v 
-fcoverage-compilation-dir=C:\\buildbot\\as-builder-2\\x-aarch64\\build\\runtimes\\runtimes-bins\\libcxx\\test\\std\\utilities\\function.objects\\func.wrap\\func.wrap.func\\func.wrap.func.con
 -nostdinc++ -resource-dir 
c:\\buildbot\\as-builder-2\\x-aarch64\\build\\lib\\clang\\14.0.0 -I 
C:/buildbot/as-builder-2/x-aarch64/build/include\\aarch64-unknown-linux-gnu\\c++\\v1
 -I C:/buildbot/as-builder-2/x-aarch64/build/include/c++/v1 -I 
C:/buildbot/as-builder-2/x-aarch64/build/runtimes/runtimes-bins/libcxx\\include\\c++build
 -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -I 
C:/buildbot/as-builder-2/x-aarch64/llvm-project/libcxx\\test/support -D 
_LIBCPP_DISABLE_AVAILABILITY -D _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER -D 
_LIBCPP_HAS_THREAD_API_PTHREAD -D _LIBCPP_ABI_VERSION=1 -isysroot 
C:/buildbot/.aarch64-ubuntu -internal-isystem 
c:\\buildbot\\as-builder-2\\x-aarch64\\build\\lib\\clang\\14.0.0\\include 
-internal-isystem C:/buildbot/.aarch64-ubuntu/usr/local/include 
-internal-isystem 
C:/buildbot/.aarch64-ubuntu/usr/lib/gcc/aarch64-linux-gnu/5.4.0/../../../../aarch64-linux-gnu/include
 -internal-externc-isystem 
C:/buildbot/.aarch64-ubuntu/usr/include/aarch64-linux-gnu 
-internal-externc-isystem C:/buildbot/.aarch64-ubuntu/include 
-internal-externc-isystem C:/buildbot/.aarch64-ubuntu/usr/include -Werror -Wall 
-Wextra -Wshadow -Wundef -Wno-unused-command-line-argument -Wno-attributes 
-Wno-pessimizing-move -Wno-c++11-extensions -Wno-user-defined-literals 
-Wno-noexcept-type -Wno-atomic-alignment -Wsign-compare -Wunused-variable 
-Wunused-parameter -Wunreachable-code -Wno-unused-local-typedef 
-Werror=thread-safety -Wuser-defined-warnings -Wno-macro-redefined 
-Wno-macro-redefined -std=c++2b -fdeprecated-macro 
-fdebug-compilation-dir=C:\\buildbot\\as-builder-2\\x-aarch64\\build\\runtimes\\runtimes-bins\\libcxx\\test\\std\\utilities\\function.objects\\func.wrap\\func.wrap.func\\func.wrap.func.con
 -ferror-limit 19 -fcoroutines-ts -fno-signed-char -fgnuc-version=4.2.1 
-fcxx-exceptions -fexceptions -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o 
C:\\Users\\buildbot\\AppData\\Local\\Temp\\lit-tmp-ex1gsg43\\deduct_F-0ed146.o 
-x c++ 
C:\\buildbot\\as-builder-2\\x-aarch64\\llvm-project\\libcxx\\test\\std\\utilities\\function.objects\\func.wrap\\func.wrap.func\\func.wrap.func.con\\deduct_F.pass.cpp
  1.
C:\buildbot\as-builder-2\x-aarch64\llvm-project\libcxx\test\std\utilities\function.objects\func.wrap\func.wrap.func\func.wrap.func.con\deduct_F.pass.cpp:136:37:
 current parser token ')'
   #0 0x7ff65e92b105 
(c:\buildbot\as-builder-2\x-aarch64\build\bin\clang++.exe+0xfdb105)
   #1 0x7fffb07cd167 (C:\Windows\SYSTEM32\ucrtbase.DLL+0x6d167)
   #2 0x7fffb07cdff1 (C:\Windows\SYSTEM32\ucrtbase.DLL+0x6dff1)
  [...]


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D117603

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


[PATCH] D117603: [clang] Don't typo-fix an expression in a SFINAE context

2022-01-27 Thread Arthur O'Dwyer via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG9be5f4d5afd9: [clang] Dont typo-fix an expression in a 
SFINAE context. (authored by arthur.j.odwyer).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D117603

Files:
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExprMember.cpp
  clang/test/SemaCXX/PR52970.cpp


Index: clang/test/SemaCXX/PR52970.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/PR52970.cpp
@@ -0,0 +1,57 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+// expected-no-diagnostics
+
+struct Incomplete;
+template  struct Holder { T t; };
+
+namespace DotFollowingFunctionName {
+struct Good {
+  struct Nested {
+int b;
+  } a;
+};
+
+struct Bad {
+  Holder a();
+};
+
+template 
+constexpr auto f(T t) -> decltype((t.a.b, true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingFunctionName::f(Good{}), "");
+static_assert(!DotFollowingFunctionName::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.a.b; };
+
+static_assert(C);
+static_assert(!C);
+#endif
+} // namespace DotFollowingFunctionName
+
+namespace DotFollowingPointer {
+struct Good {
+  int begin();
+};
+using Bad = Holder *;
+
+template 
+constexpr auto f(T t) -> decltype((t.begin(), true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingPointer::f(Good{}), "");
+static_assert(!DotFollowingPointer::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.begin(); };
+
+static_assert(C);
+static_assert(!C);
+#endif
+} // namespace DotFollowingPointer
Index: clang/lib/Sema/SemaExprMember.cpp
===
--- clang/lib/Sema/SemaExprMember.cpp
+++ clang/lib/Sema/SemaExprMember.cpp
@@ -1645,6 +1645,9 @@
   << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
   << FixItHint::CreateReplacement(OpLoc, "->");
 
+  if (S.isSFINAEContext())
+return ExprError();
+
   // Recurse as an -> access.
   IsArrow = true;
   return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -2554,6 +2554,11 @@
 bool Sema::tryToRecoverWithCall(ExprResult , const PartialDiagnostic ,
 bool ForceComplain,
 bool (*IsPlausibleResult)(QualType)) {
+  if (isSFINAEContext()) {
+// If this is a SFINAE context, don't try anything that might trigger ADL
+// prematurely.
+return false;
+  }
   SourceLocation Loc = E.get()->getExprLoc();
   SourceRange Range = E.get()->getSourceRange();
 


Index: clang/test/SemaCXX/PR52970.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/PR52970.cpp
@@ -0,0 +1,57 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+// expected-no-diagnostics
+
+struct Incomplete;
+template  struct Holder { T t; };
+
+namespace DotFollowingFunctionName {
+struct Good {
+  struct Nested {
+int b;
+  } a;
+};
+
+struct Bad {
+  Holder a();
+};
+
+template 
+constexpr auto f(T t) -> decltype((t.a.b, true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingFunctionName::f(Good{}), "");
+static_assert(!DotFollowingFunctionName::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.a.b; };
+
+static_assert(C);
+static_assert(!C);
+#endif
+} // namespace DotFollowingFunctionName
+
+namespace DotFollowingPointer {
+struct Good {
+  int begin();
+};
+using Bad = Holder *;
+
+template 
+constexpr auto f(T t) -> decltype((t.begin(), true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingPointer::f(Good{}), "");
+static_assert(!DotFollowingPointer::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.begin(); };
+
+static_assert(C);
+static_assert(!C);
+#endif
+} // namespace DotFollowingPointer
Index: clang/lib/Sema/SemaExprMember.cpp
===
--- clang/lib/Sema/SemaExprMember.cpp
+++ clang/lib/Sema/SemaExprMember.cpp
@@ -1645,6 +1645,9 @@
   << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
   << FixItHint::CreateReplacement(OpLoc, "->");
 
+  if (S.isSFINAEContext())

[PATCH] D115867: [C++20] [Coroutines] Warning for always_inline coroutine

2022-01-25 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone accepted this revision.
Quuxplusone added a comment.
This revision is now accepted and ready to land.

LGTM now, modulo my suggested edits (and the necessary corresponding edits in 
the test case).
I don't think I'm really qualified to accept, but as nobody else is looking, 
and my name is the one with the red next to it, I'll at least change mine to 
green. I //recommend// getting someone else to look at this before landing it.




Comment at: clang/include/clang/Basic/AttrDocs.td:6140-6142
+Note that a coroutine function wouldn't get inlined in O0 if it is marked with 
"always_inline".
+In other optimization levels, only the first part of the coroutine - "ramp 
function"`_
+can be guaranteed to be inlined.

Why is the `-O0` behavior different for coroutines, versus regular functions? 
My understanding from this documentation is that `-O0 + always_inline` //will// 
attempt inlining for regular functions, but will //not// attempt inlining (not 
even of the ramp) for coroutines. That feels asymmetric and weird.
So my default assumption is that maybe this documentation is wrong?
...ah, I see you mention below that this is a known deficiency. So I think this 
documentation is OK after you take my suggested edit. (I don't know if it would 
be appropriate to mention the bug number in this documentation as well, so I'll 
err on the side of not mentioning it.)



Comment at: clang/include/clang/Basic/DiagnosticSemaKinds.td:11109
+def warn_always_inline_coroutine : Warning<
+  "a coroutine may be split into pieces and not every piece of the coroutine 
can be guaranteed to be inlined"
+  >,





Comment at: clang/lib/Sema/SemaCoroutine.cpp:1084-1089
+  // The coroutine marked always inline might not be inlined properly in 
current
+  // compiler support. Since the coroutine would be splitted into pieces. And
+  // the call to resume() and destroy() functions might be indirect call. Also
+  // the ramp function wouldn't get inlined under O0 due to pipeline ordering
+  // problems. It might be different to what users expects to. Emit a warning 
to
+  // tell it.

Update the bug number, filing a new bug if needed. That way at least we have a 
place the reader can go to learn more about what you're talking about.


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

https://reviews.llvm.org/D115867

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


[PATCH] D117603: [clang] Don't typo-fix an expression in a SFINAE context

2022-01-25 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added reviewers: ChuanqiXu, urnathan, hokein, dblaikie.
Quuxplusone added a comment.

Add some more reviewers who've touched SemaCXX recently. Ping! If no objections 
are forthcoming, I'd like to land this on Friday morning.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D117603

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


[PATCH] D92956: Fix range-loop-analysis checks for trivial copyability

2022-01-20 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added a comment.

What ever happened to this patch? @fanfuqiang, are you still around to rebase 
this? Do you need someone to commit it for you?
(Not that I'm saying I think it's perfect as is — I haven't looked and don't 
know the code that well — but just wondering what kept this from being landed a 
year ago.)

The bug it fixes is now https://github.com/llvm/llvm-project/issues/47355


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D92956

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


[PATCH] D117603: [clang] Don't typo-fix an expression in a SFINAE context

2022-01-20 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone updated this revision to Diff 401652.
Quuxplusone added a comment.

Clang-formatted.

@mizvekov or @rsmith: ping?
I'd like to get this in before Feb 1, which is the release/14.x branch date 
AFAIK; because it affects workarounds in libc++ and thus makes a difference 
whether we will be able to remove the workarounds in version 16 or version 17.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D117603

Files:
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExprMember.cpp
  clang/test/SemaCXX/PR52970.cpp


Index: clang/test/SemaCXX/PR52970.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/PR52970.cpp
@@ -0,0 +1,57 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+// expected-no-diagnostics
+
+struct Incomplete;
+template  struct Holder { T t; };
+
+namespace DotFollowingFunctionName {
+struct Good {
+  struct Nested {
+int b;
+  } a;
+};
+
+struct Bad {
+  Holder a();
+};
+
+template 
+constexpr auto f(T t) -> decltype((t.a.b, true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingFunctionName::f(Good{}), "");
+static_assert(!DotFollowingFunctionName::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.a.b; };
+
+static_assert(C);
+static_assert(!C);
+#endif
+} // namespace DotFollowingFunctionName
+
+namespace DotFollowingPointer {
+struct Good {
+  int begin();
+};
+using Bad = Holder *;
+
+template 
+constexpr auto f(T t) -> decltype((t.begin(), true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingPointer::f(Good{}), "");
+static_assert(!DotFollowingPointer::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.begin(); };
+
+static_assert(C);
+static_assert(!C);
+#endif
+} // namespace DotFollowingPointer
Index: clang/lib/Sema/SemaExprMember.cpp
===
--- clang/lib/Sema/SemaExprMember.cpp
+++ clang/lib/Sema/SemaExprMember.cpp
@@ -1645,6 +1645,9 @@
   << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
   << FixItHint::CreateReplacement(OpLoc, "->");
 
+  if (S.isSFINAEContext())
+return ExprError();
+
   // Recurse as an -> access.
   IsArrow = true;
   return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -2552,6 +2552,11 @@
 bool Sema::tryToRecoverWithCall(ExprResult , const PartialDiagnostic ,
 bool ForceComplain,
 bool (*IsPlausibleResult)(QualType)) {
+  if (isSFINAEContext()) {
+// If this is a SFINAE context, don't try anything that might trigger ADL
+// prematurely.
+return false;
+  }
   SourceLocation Loc = E.get()->getExprLoc();
   SourceRange Range = E.get()->getSourceRange();
 


Index: clang/test/SemaCXX/PR52970.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/PR52970.cpp
@@ -0,0 +1,57 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+// expected-no-diagnostics
+
+struct Incomplete;
+template  struct Holder { T t; };
+
+namespace DotFollowingFunctionName {
+struct Good {
+  struct Nested {
+int b;
+  } a;
+};
+
+struct Bad {
+  Holder a();
+};
+
+template 
+constexpr auto f(T t) -> decltype((t.a.b, true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingFunctionName::f(Good{}), "");
+static_assert(!DotFollowingFunctionName::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.a.b; };
+
+static_assert(C);
+static_assert(!C);
+#endif
+} // namespace DotFollowingFunctionName
+
+namespace DotFollowingPointer {
+struct Good {
+  int begin();
+};
+using Bad = Holder *;
+
+template 
+constexpr auto f(T t) -> decltype((t.begin(), true)) { return true; }
+constexpr bool f(...) { return false; }
+
+static_assert(DotFollowingPointer::f(Good{}), "");
+static_assert(!DotFollowingPointer::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+template 
+concept C = requires(T t) { t.begin(); };
+
+static_assert(C);
+static_assert(!C);
+#endif
+} // namespace DotFollowingPointer
Index: clang/lib/Sema/SemaExprMember.cpp
===
--- clang/lib/Sema/SemaExprMember.cpp
+++ clang/lib/Sema/SemaExprMember.cpp
@@ -1645,6 +1645,9 @@
  

[PATCH] D114732: [clang] Mark `trivial_abi` types as "trivially relocatable".

2022-01-19 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: clang/test/SemaCXX/attr-trivial-abi.cpp:9-11
+// On Windows, trivial relocatability depends only on a trivial copy 
constructor existing.
+// In this case, it is implicitly deleted. Similar concerns apply to later 
tests.
+static_assert(!__is_trivially_relocatable(a), "");

devin.jeanpierre wrote:
> Quuxplusone wrote:
> > (1) Why should Windows be different from everyone else here?
> > (2) AFAIK, a user-defined move ctor means the copy ctor is //not implicitly 
> > declared//, but it's not //deleted//; so I think this comment is slightly 
> > wrong.
> > (2) AFAIK, a user-defined move ctor means the copy ctor is not implicitly 
> > declared, but it's not deleted; so I think this comment is slightly wrong.
> Sorry, I get that confused a lot. :)
> 
> > (1) Why should Windows be different from everyone else here?
> In this change so far, an object is only considered trivially relocatable if 
> it's trivial for calls, and Windows is non-conforming wrt what it considers 
> trivial for calls: it won't consider something trivial for calls if it isn't 
> trivially copyable.
> 
> Code: https://clang.llvm.org/doxygen/SemaDeclCXX_8cpp_source.html#l06558
> 
> It surprised me too. This is a good motivator IMO to support something like 
> your proposal, and have types be trivially relocatable that aren't trivial 
> for calls. This allows, as you mention elsewhere, for optimizations that 
> aren't ABI-breaking, and for e.g. non-conforming platforms like this to still 
> take advantage of trivial relocatability.
> In this change so far, an object is only considered trivially relocatable if 
> it's trivial for calls, and Windows [has a calling convention that's 
> different from the Itanium C++ ABI's calling convention]: it won't consider 
> something trivial for calls if it isn't trivially copyable.

Ah, I see, and I agree with your logic here. It's unintuitive but only for the 
same reasons we've already hashed over: we're introducing an 
`__is_trivially_relocatable(T)` that gives zero false-positives, but (for now) 
frequent false-negatives, and this just happens to be one //additional// source 
of false negatives on Win32 specifically. (And I keep tripping over it because 
this frequent-false-negative `__is_trivially_relocatable(T)` is named the same 
as D50119's "perfect" discriminator.)

Everyone's on board with the idea that we're promising to preserve the true 
positives forever, but at the same time we're expecting that we might 
//someday// fix the false negatives, right? I.e., nobody's expecting 
`!__is_trivially_relocatable(a)` to remain true on Win32 forever? (I'm 
pretty sure we're all on board with this.)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D114732

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


[PATCH] D114732: [clang] Mark `trivial_abi` types as "trivially relocatable".

2022-01-18 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added a comment.

In D114732#3253142 , 
@devin.jeanpierre wrote:

> OK, while I'm struggling to set up a new Windows machine so I can make sure 
> this works on Windows...  @Quuxplusone, after this is merged, do you want to 
> rebase D67524  on top of this, or should I? 
> I can review it -- I think when I looked at it, I only had two ideas for 
> changes:
>
> 1. May need to guard all of these optimizations on the allocator being the 
> standard allocator, since otherwise the change in the number of 
> constructor/destructor calls would be observable to more than just the 
> annotated type.

My intent is that the type-traits `__has_trivial_construct` and 
`__has_trivial_destroy` already handle that. The standard `std::allocator` has 
a trivial `construct` and `destroy`, but so do lots of user-defined allocators.

> 2. changing `std::swap` to correctly handle potentially-overlapping-objects. 
> My thought is we could test that there's no reusable tail padding.
>
> First draft: `has_unique_object_representations` is conservative -- on the 
> Itanium ABI, "POD for the purposes of layout" types can have padding which 
> isn't reused when it's a potentially overlapping subobject.

I'd //like// something that triggers successfully even when there are internal 
padding bytes, e.g. `struct TR { int x; std::string y; }`. (But anything is 
better than nothing. I'm going to keep maintaining my branch for the 
foreseeable future, so I can keep doing my thing no matter what half-measure 
makes it into trunk.)

> Second draft: check by hand:
>
>   
>   struct TestStruct {
> [[no_unique_address]] T x;
> // not sure if this needs to be a bitfield or anything like that, but the 
> idea is this.
> char extra_byte;
>   };
>   bool has_padding = sizeof(TestStruct) == sizeof(T);

If this works, then either my mental model of `[[no_unique_address]]` is wrong 
or my mental model of tail padding is wrong. I would expect more like

  template struct DerivedFrom : public T { char extra_byte; };
  template requires is_final_v struct DerivedFrom { char 
x[sizeof(T)+1]; }; // definitely no objects in the tail padding if it's final
  bool has_padding = sizeof(DerivedFrom) == sizeof(T);

If `T` is final, then it can't have stuff in its tail padding, I think: 
https://godbolt.org/z/69sjf15MY

Anyway, that seems like a reasonable path in the name of getting something 
merged. My //personal// druthers is that the Standard should just admit that 
`std::swap` was never meant to work on polymorphic objects, so therefore it can 
assume it's never swapping `Derived` objects via `Base&`, so therefore it can 
assume tail padding is not an issue, so therefore no metaprogramming is needed 
and it can just always do the efficient thing (which is therefore what I've 
implemented in D67524 ). But I know that's 
unlikely to ever happen.

> (D63620  could in some form also be ported 
> over, but it needs to be guarded behind ABI stability, since 
> `[[clang::trivial_abi]]` is an ABI breaking change. For example, the same way 
> it was done for unique_ptr 
> , with the same 
> benefits.)

The point of `[[trivially_relocatable]]` is that it doesn't change the ABI (and 
therefore also doesn't cause the lifetime-related pitfalls described on that 
web page). So I won't attempt to merge it with `[[trivial_abi]]`, and I'm also 
//personally// uninterested in pursuing a `[[trivial_abi]] std::string` etc., 
because that gives no benefits to people stuck on libc++ ABIv1 (which is 
everyone, AFAICT). But if someone //wants// to implement 
`_LIBCPP_ABI_ENABLE_STRING_TRIVIAL_ABI`, 
`_LIBCPP_ABI_ENABLE_VECTOR_TRIVIAL_ABI`, etc. etc., for the benefit of ABIv2 
users... hey, go for it.




Comment at: clang/test/SemaCXX/attr-trivial-abi.cpp:9-11
+// On Windows, trivial relocatability depends only on a trivial copy 
constructor existing.
+// In this case, it is implicitly deleted. Similar concerns apply to later 
tests.
+static_assert(!__is_trivially_relocatable(a), "");

(1) Why should Windows be different from everyone else here?
(2) AFAIK, a user-defined move ctor means the copy ctor is //not implicitly 
declared//, but it's not //deleted//; so I think this comment is slightly wrong.



Comment at: clang/test/SemaCXX/attr-trivial-abi.cpp:123-127
+#ifdef _WIN32
+static_assert(!__is_trivially_relocatable(CopyDeleted), "");
+#else
+static_assert(__is_trivially_relocatable(CopyDeleted), "");
+#endif

Again, I don't see why Windows should be any different. `CopyDeleted` is 
trivial to move and trivial to destroy; that means (by definition) it's trivial 
to relocate.



Comment at: clang/test/SemaCXX/attr-trivial-abi.cpp:146
+#ifdef _WIN32

[PATCH] D117603: [clang] Don't typo-fix an expression in a SFINAE context

2022-01-18 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone created this revision.
Quuxplusone added reviewers: ldionne, rsmith, leonardchan, mizvekov.
Quuxplusone added a project: clang.
Quuxplusone requested review of this revision.
Herald added a subscriber: cfe-commits.

If this is a SFINAE context, then continuing to look up names (in particular, 
to treat a non-function as a function, and then do ADL) might too-eagerly 
complete a type that it's not safe to complete right now. We should just say 
"okay, that's a substitution failure" and not do any more work than absolutely 
required.

Fixes https://github.com/llvm/llvm-project/issues/52970

  


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D117603

Files:
  clang/lib/Sema/Sema.cpp
  clang/lib/Sema/SemaExprMember.cpp
  clang/test/SemaCXX/PR52970.cpp


Index: clang/test/SemaCXX/PR52970.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/PR52970.cpp
@@ -0,0 +1,59 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+// expected-no-diagnostics
+
+struct Incomplete;
+template struct Holder { T t; };
+
+namespace DotFollowingFunctionName {
+  struct Good {
+struct Nested {
+  int b;
+} a;
+  };
+
+  struct Bad {
+Holder a();
+  };
+
+  template
+  constexpr auto f(T t) -> decltype((t.a.b, true))
+{ return true; }
+  constexpr bool f(...) { return false; }
+
+  static_assert(DotFollowingFunctionName::f(Good{}), "");
+  static_assert(!DotFollowingFunctionName::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+  template
+  concept C = requires (T t) { t.a.b; };
+
+  static_assert(C);
+  static_assert(!C);
+#endif
+}
+
+namespace DotFollowingPointer {
+  struct Good {
+int begin();
+  };
+  using Bad = Holder*;
+
+  template
+  constexpr auto f(T t) -> decltype((t.begin(), true))
+{ return true; }
+  constexpr bool f(...) { return false; }
+
+  static_assert(DotFollowingPointer::f(Good{}), "");
+  static_assert(!DotFollowingPointer::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+  template
+  concept C = requires (T t) { t.begin(); };
+
+  static_assert(C);
+  static_assert(!C);
+#endif
+}
Index: clang/lib/Sema/SemaExprMember.cpp
===
--- clang/lib/Sema/SemaExprMember.cpp
+++ clang/lib/Sema/SemaExprMember.cpp
@@ -1645,6 +1645,9 @@
   << BaseType << int(IsArrow) << BaseExpr.get()->getSourceRange()
   << FixItHint::CreateReplacement(OpLoc, "->");
 
+  if (S.isSFINAEContext())
+return ExprError();
+
   // Recurse as an -> access.
   IsArrow = true;
   return LookupMemberExpr(S, R, BaseExpr, IsArrow, OpLoc, SS,
Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -2552,6 +2552,10 @@
 bool Sema::tryToRecoverWithCall(ExprResult , const PartialDiagnostic ,
 bool ForceComplain,
 bool (*IsPlausibleResult)(QualType)) {
+  if (isSFINAEContext()) {
+// If this is a SFINAE context, don't try anything that might trigger ADL 
prematurely.
+return false;
+  }
   SourceLocation Loc = E.get()->getExprLoc();
   SourceRange Range = E.get()->getSourceRange();
 


Index: clang/test/SemaCXX/PR52970.cpp
===
--- /dev/null
+++ clang/test/SemaCXX/PR52970.cpp
@@ -0,0 +1,59 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++14 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++17 -verify %s
+// RUN: %clang_cc1 -fsyntax-only -std=c++20 -verify %s
+// expected-no-diagnostics
+
+struct Incomplete;
+template struct Holder { T t; };
+
+namespace DotFollowingFunctionName {
+  struct Good {
+struct Nested {
+  int b;
+} a;
+  };
+
+  struct Bad {
+Holder a();
+  };
+
+  template
+  constexpr auto f(T t) -> decltype((t.a.b, true))
+{ return true; }
+  constexpr bool f(...) { return false; }
+
+  static_assert(DotFollowingFunctionName::f(Good{}), "");
+  static_assert(!DotFollowingFunctionName::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+  template
+  concept C = requires (T t) { t.a.b; };
+
+  static_assert(C);
+  static_assert(!C);
+#endif
+}
+
+namespace DotFollowingPointer {
+  struct Good {
+int begin();
+  };
+  using Bad = Holder*;
+
+  template
+  constexpr auto f(T t) -> decltype((t.begin(), true))
+{ return true; }
+  constexpr bool f(...) { return false; }
+
+  static_assert(DotFollowingPointer::f(Good{}), "");
+  static_assert(!DotFollowingPointer::f(Bad{}), "");
+
+#if __cplusplus >= 202002L
+  template
+  concept C = requires (T t) { t.begin(); };
+
+  static_assert(C);
+  static_assert(!C);
+#endif
+}
Index: 

[PATCH] D117535: [clang-tidy] Force LF newlines when writing files

2022-01-18 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone accepted this revision.
Quuxplusone added a comment.
This revision is now accepted and ready to land.

LGTM FWIW.
I might even wonder why this code is using `io.open` instead of just plain 
`open`. (I didn't know `io.open` was a thing; StackOverflow tells me that it 
was something in Python2 but that in Python3 it's a synonym for `open`.)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D117535

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


[PATCH] D116778: [clang-tidy][clang] Don't trigger unused-parameter warnings on naked functions

2022-01-14 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/misc-unused-parameters.cpp:290-292
+// Do not warn on naked functions.
+[[gnu::naked]] int nakedFunction(int a, float b, const char *c) { ; }
+__attribute__((naked)) void nakedFunction(int a, int b) { ; }

In C++, I would expect the programmer to fix the (correct) warning simply by 
eliminating the unused parameter names:
```
[[gnu::naked]] int nakedFunction(int, float, const char *) { ; }
__attribute__((naked)) void nakedFunction(int, int) { ; }
```


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D116778

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


[PATCH] D107450: [clang-tidy] Fix wrong FixIt in performance-move-const-arg

2022-01-14 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone accepted this revision.
Quuxplusone added a comment.
This revision is now accepted and ready to land.

@Sockke: Throughout, `trivially-copyable` should be `trivially copyable` (two 
words).
Other than that, sure, I have no particular opinions at this point.




Comment at: clang-tools-extra/clang-tidy/performance/MoveConstArgCheck.cpp:179
+  QualType NoRefType = (*InvocationParmType)->getPointeeType();
+  PrintingPolicy PolicyWithSupressedTag(getLangOpts());
+  PolicyWithSupressedTag.SuppressTagKeyword = true;

Throughout, `Supress` should be `Suppress`.



Comment at: clang-tools-extra/docs/ReleaseNotes.rst:118
+
+  Removed a wrong FixIt for trivially-copyable objects wrapped by 
``std::move()`` and passed to an rvalue reference parameter. Removal of 
``std::move()`` would break the code.
+




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

https://reviews.llvm.org/D107450

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


[PATCH] D116775: [clang][#47272] Avoid suggesting deprecated version of a declaration over another in typo correction

2022-01-11 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone accepted this revision.
Quuxplusone added a comment.
This revision is now accepted and ready to land.

LGTM!


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

https://reviews.llvm.org/D116775

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


[PATCH] D112221: Mark ATOMIC_VAR_INIT and ATOMIC_FLAG_INIT as deprecated

2022-01-11 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone accepted this revision.
Quuxplusone added a comment.

LGTM FWIW.
I'm not the right person to approve for libc, but I'm not sure any of the 
currently listed reviewers are any more appropriate either. So you should find 
and ping a new reviewer, or just ship it, at your discretion. :)




Comment at: clang/docs/ReleaseNotes.rst:179
+  in C++ code; the STL  header also controls the behavior of these
+  macros and is not impacted by these changes. The  diagnostic
+  can be disabled by defining the ``_CLANG_DISABLE_CRT_DEPRECATION_WARNINGS``




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

https://reviews.llvm.org/D112221

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


[PATCH] D116775: [clang][#47272] Avoid suggesting deprecated version of a declaration over another in typo correction

2022-01-11 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added a comment.

LGTM % comments, but I'll take one more look.




Comment at: clang/test/SemaCXX/typo-correction.cpp:772-782
+namespace B {
+int pr47272();  // expected-note{{'B::pr47272' declared here}}
+}
+
+namespace [[deprecated]] A {
+using B::pr47272;
+}

I'd like `B` to be declared second.
```
namespace [[deprecated]] A { int pr47272; }
namespace B { using A::pr47272; } // expected-note{{'B::pr47272' declared here}}
namespace [[deprecated]] C { using A::pr47272; }

~~~
  int y = ::pr47272; // expected-error{{no member named 'pr47272' in the global 
namespace; did you mean 'B::pr47272'?}}
```
I also changed it from a function to a variable, just to get a little more 
coverage (since `Take()` was already covering functions).


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

https://reviews.llvm.org/D116775

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


[PATCH] D116775: [clang][#47272] Avoid suggesting deprecated version of a declaration over another in typo correction

2022-01-06 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone requested changes to this revision.
Quuxplusone added inline comments.
This revision now requires changes to proceed.



Comment at: clang/lib/Sema/SemaLookup.cpp:4345
+  return;
 }
   }

It seems like this code is overdue for a "compare these two corrections" 
//predicate//. The simple version would be
```
auto IsBetter = [&](const TypoCorrection& TC1, const TypoCorrection& TC2) {
std::pair Key1 = { IsDeprecated(TC1.getFoundDecl()), 
TC1.getAsString(SemaRef.getLangOpts()) };
std::pair Key2 = { IsDeprecated(TC2.getFoundDecl()), 
TC2.getAsString(SemaRef.getLangOpts()) };
return Key1 < Key2;  // prefer non-deprecated, alphabetically earlier 
declarations
};
for (TypoCorrection& TC : CList) {
if (IsBetter(Correction, TC))
TC = Correction;
}
```
Actually, you could even replicate the hoisting of the loop-invariant stuff, 
the way the old code did:
```
std::pair CorrectionKey = { 
IsDeprecated(Correction.getFoundDecl()), 
Correction.getAsString(SemaRef.getLangOpts()) };
auto CorrectionIsBetterThan = [&](const TypoCorrection& TC) {
std::pair Key = { IsDeprecated(TC.getFoundDecl()), 
TC.getAsString(SemaRef.getLangOpts()) };
return CorrectionKey < Key;  // prefer non-deprecated, alphabetically 
earlier declarations
};
for (TypoCorrection& TC : CList) {
if (CorrectionIsBetterThan(TC))
TC = Correction;
}
```



Comment at: clang/test/SemaCXX/typo-correction.cpp:764-769
+namespace Views {
+int Take(); // expected-note{{'Views::Take' declared here}}
+}
+namespace [[deprecated("use Views instead")]] View {
+using Views::Take;
+}

I suggest //three// namespaces, named `[[deprecated]] A`, `B`, and 
`[[deprecated]] C`, and declared in that lexical order too, so that no matter 
how the preference predicate is expressed, we're still testing that the 
non-deprecated (middle) declaration gets chosen.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D116775

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


[PATCH] D115867: [C++20] [Coroutines] Warning for always_inline coroutine

2022-01-04 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone requested changes to this revision.
Quuxplusone added a comment.
This revision now requires changes to proceed.






Comment at: clang/include/clang/Basic/DiagnosticSemaKinds.td:0-3
+def warn_always_inline_coroutine : Warning<
+  "A coroutine marked always_inline might not be inlined properly."
+  >,
+  InGroup;

ChuanqiXu wrote:
> Quuxplusone wrote:
> > ChuanqiXu wrote:
> > > Quuxplusone wrote:
> > > > FWIW, this message isn't particularly helpful to the reader. My code 
> > > > "might" not be optimized "properly"? Does that mean it might be 
> > > > mis-optimized, improperly, and thus break in some way at runtime? Or is 
> > > > the compiler just saying that the attribute will be ignored? Or that it 
> > > > //might// be ignored, but it might not? How do I (the programmer) know 
> > > > whether the bad thing will happen?
> > > > 
> > > > I think as a programmer what I'd //like// to see here is just `"the 
> > > > '%0' attribute has no effect on coroutines"`. That's very clear, and 
> > > > easy to understand. Does that wording reflect what the compiler 
> > > > actually //does//, though?
> > > Thanks for suggestion. The actual behavior isn't easy to describe and 
> > > understand. Since a coroutine would be splitted into pieces. And the 
> > > original function would be reduced and we would call it 'ramp function' 
> > > in compiler. And the call to other new functions would be indirect call. 
> > > The compiler couldn't inline indirect call. But the compiler **might** 
> > > convert the indirect call into direct call so that they could be inlined.
> > > 
> > > In summary, the actual behavior might be described as: "Only the ramp 
> > > function are guaranteed to be inlined and the other new functions may or 
> > > may not get inlined". But the term "ramp funciton" is used in compiler 
> > > only (Some guys in LWG/LEWG know it too). And I believe the term 
> > > shouldn't leak to other users. So I chose the current description. 
> > > 
> > > BTW, I thought the fact that coroutine would be splitted should be 
> > > transparent to users too. This is the reason why I wrote previous 
> > > message. But your words make sense. And I couldn't find methods to make 
> > > it more clear and don't tell the user about coroutine splitting.
> > IIUC, `"this coroutine will be split into pieces; only the first piece will 
> > be inlined"` or simply `"the '%0' attribute applies to only the initial 
> > piece of this coroutine"`. Possible synonyms for "piece" include "section", 
> > "segment", "chunk". Is there any standardese for "the run of stuff in 
> > between two suspension points"?
> > 
> > However, I stand by my initial comment that this message is not helpful to 
> > the programmer. It's warning me that something bad will happen, right? 
> > Instead of having that bad thing happen, why don't you just make the 
> > compiler //ignore the attribute// in this situation?
> > 
> > If your answer is "Because always-inlining the initial piece isn't always 
> > bad; maybe the programmer thinks it's //good//, and //wants// it to 
> > happen," then this shouldn't be a `warning` at all; it should just be 
> > documented in the attribute's documentation. Warnings should be for 
> > bad/unintentional things, not for things someone might do on purpose.
> >  Is there any standardese for "the run of stuff in between two suspension 
> > points"?
> 
> AFAIK, there is no standard terms for it.
> 
> ---
> 
> Very Sorry, I made a mistake in previous comment. The behavior for 
> always-inline ramp function should be: "The ramp function is guaranteed to 
> get inlined with optimization turned on." It implies that ramp function 
> wouldn't get inlined in O0. This is what I am trying to do in: 
> https://reviews.llvm.org/D115790. The current behavior for always-inline 
> coroutine in O0 would be a crash. Here is an example: 
> https://godbolt.org/z/zssKxTPM5.
> 
> And GCC would warn and ban for the always-inline coroutine too: 
> https://godbolt.org/z/7eajb1Gf8. (I understand that it isn't a good argument 
> to say GCC did so. Just a information sharing)
> 
> --- 
> 
> > Warnings should be for bad/unintentional things, not for things someone 
> > might do on purpose.
> 
> My point is that the behavior and semantic is inconsistent. The programmer 
> might think the whole coroutine would be inlined. However, it is not the 
> case. I think it is worth a warning.
>>! In D115867#3218653, @ChuanqiXu wrote:
> @Quuxplusone do you feel good with the current message?

No, it's definitely still ungrammatical English, so it shouldn't ship in this 
state.
Also, I think my entire previous comment stands — both the suggestions for 
improving the English (without much changing the meaning), and my higher-level 
suggestion that you should just change the compiler's behavior to //just 
quietly do the thing the user is asking for//.

If you think the user is really asking to inline 

[PATCH] D114425: [clang] Add __builtin_bswap128

2022-01-03 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added a comment.

In D114425#3216802 , @majnemer wrote:

> OOC, how hard would it be to generalize this builtin a little? It is nice 
> that we have builtins like `__builtin_add_overflow` which do the right thing 
> regardless of their input.
>
> It seems like it would be nice if we started to expose more intrinsics which 
> did the right thing regardless of operand width; another bonus is that it 
> composes well with language features like `_BitInt`.

IMHO such builtins are nice iff the programmer can be 100% sure that the 
compiler will interpret them the same way as a human reader. 
`__builtin_add_overflow` is easy because its first two arguments are 
"mathematical integers" (where integer promotion doesn't matter) and its third 
argument is a pointer (where integer promotion can't happen). So you can really 
throw any combination of types at it, and it'll do "the right thing" 
https://godbolt.org/z/sa7b894oa (although I admit I was surprised that this 
worked).
For a hypothetical `__builtin_bswap`, you would probably need a similar 
pointer-based interface like

  short s16 = 0xFEDC;
  __builtin_bswap();  // hypothetically
  assert(s16 == 0xDCFE);
  
  assert(__builtin_bswap16(s16) == 0xDCFE);
  assert(__builtin_bswap32(s16) == 0xDCFE);  // the problem to solve: s16 
eagerly promotes to int, which changes the result

The downside is that the pointer-based interface is less ergonomic than today's 
value-based signatures, and probably worse codegen at `-O0` (because the 
programmer has to materialize the operand into a named variable, and then the 
compiler won't remove that variable because you might want to debug it). The 
upside (as you said) is that a generic builtin could work with `_ExtInt` types 
and so on.




Comment at: clang/lib/CodeGen/CGBuiltin.cpp:2930
+  }
+  [[fallthrough]];
   case Builtin::BI__builtin_bswap16:

Re clang-format's complaint: I would either move `[[fallthrough]];` inside the 
curly braces, or (probably better) just eliminate the fallthrough by either 
duplicating line 2934 or else doing
```
  case Builtin::BI__builtin_bswap64:
  case Builtin::BI__builtin_bswap128: {
if (BuiltinIDIfNoAsmLabel == Builtin::BI__builtin_bswap128 && 
!Target.hasInt128Type())
  CGM.ErrorUnsupported(E, "__builtin_bswap128");
return RValue::get(emitUnaryBuiltin(*this, E, Intrinsic::bswap));
  }
```


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D114425

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


[PATCH] D112221: Mark ATOMIC_VAR_INIT and ATOMIC_FLAG_INIT as deprecated

2022-01-03 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added a comment.

TLDR on `_CLANG_DISABLE_CRT_DEPRECATION_WARNINGS`: I'm neutral. :)




Comment at: clang/docs/ReleaseNotes.rst:159-164
+ - The ``ATOMIC_VAR_INIT`` macro from  is now diagnosed as
+   deprecated in both C (C17 and later) and C++ (C++20 and later), and
+   ``ATOMIC_FLAG_INIT`` is now diagnosed as deprecated in C++ (C++20 and 
later).
+   The diagnostic can be disabled by defining the
+   ``_CLANG_DISABLE_CRT_DEPRECATION_WARNINGS`` macro prior to including the
+   header.

IIUC, `` is not relevant to C++20; libc++'s `` even 
`#error`s if you include both `` and `` in the same TU.
Defining `_CLANG_DISABLE_CRT_DEPRECATION_WARNINGS` won't affect the warnings in 
C++20; for those you need `_LIBCPP_DISABLE_DEPRECATION_WARNINGS`.
C++20 isn't relevant to this section on "C Language Changes in Clang"; arguably 
it could be listed under "C++ Language Changes in Clang," except that D115995 
didn't change anything about //Clang//. So I think it's fine not to mention 
D115995 anywhere in this file.



Comment at: clang/docs/UsersManual.rst:1128-1130
+  #include  // May include Clang CRT deprecation warnings
+  #define _CLANG_DISABLE_CRT_DEPRECATION_WARNINGS
+  #include  // Clang CRT deprecation warnings are disabled

It is //probably// sketchy to advise people to change the setting of 
`_CLANG_DISABLE_CRT_DEPRECATION_WARNINGS` over the lifetime of a single TU. If 
`` transitively includes ``, this won't work. (Of course 
that's unlikely in this //specific// case, but in general, IMHO we shouldn't 
train people to think that this will always work.)
(In fact, `` transitively includes ``!)
We should train the programmer to think of 
`_CLANG_DISABLE_CRT_DEPRECATION_WARNINGS` as all-or-nothing: set it in your 
build system, or set it at the very top of the TU.



Comment at: clang/lib/Headers/stdatomic.h:42-47
 #define ATOMIC_VAR_INIT(value) (value)
+#if __STDC_VERSION__ >= 201710L || __cplusplus >= 202002L
+/* ATOMIC_VAR_INIT was deprecated in C17 and C++20. */
+#pragma clang deprecated(ATOMIC_VAR_INIT)
+#endif
 #define atomic_init __c11_atomic_init

aaron.ballman wrote:
> Quuxplusone wrote:
> > Hmm, I do think there ought to be some way for the C++20 programmer to 
> > suppress the deprecation warning for these macros (specifically, not just 
> > via `-Wno-deprecated` in their whole project). For deprecations in the C++ 
> > standard library, libc++ offers an all-or-nothing flag: basically you'd do
> > ```
> > #if (__STDC_VERSION__ >= 201710L || __cplusplus >= 202002L) && 
> > !defined(_LIBCPP_DISABLE_DEPRECATION_WARNINGS)
> > /* ATOMIC_VAR_INIT was deprecated in C17 and C++20. */
> > #pragma clang deprecated(ATOMIC_VAR_INIT)
> > #endif
> > ```
> > (This also makes it easy for libcxx/test/ to suppress the deprecation 
> > warning for the purposes of testing.)
> > 
> > However, I'm not sure if it's appropriate to mention 
> > `_LIBCPP_DISABLE_DEPRECATION_WARNINGS` in this header located in 
> > clang/lib/Headers/ instead of libcxx/include/. Someone else will have to 
> > make that call.
> > 
> > It might be that the only way for the programmer (or libcxx/test/) to work 
> > around the warning will be for them to pass `-Wno-deprecated` globally; IMO 
> > that is suboptimal but quite far from disastrous.
> I think this is a reasonable idea. Microsoft has macros for a similar purpose 
> with `_CRT_SECURE_NO_WARNINGS` (IIRC). I would not want to use `_LIBCPP_`  
> for this purpose, but I could imagine it's useful to add something like 
> `_CLANG_DISABLE_DEPRECATION_WARNINGS`. (I'm guessing we don't want 
> per-deprecation granularity on the macro, but if we needed something like 
> that, I think we could add it.)
> 
> I went ahead and added `_CLANG_DISABLE_CRT_DEPRECATION_WARNINGS` to the next 
> version of the patch, and documented it in the release notes and user's 
> manual. We can quibble over the name if you have better suggestions.
Re `_CLANG_DISABLE_CRT_DEPRECATION_WARNINGS`: This naming scheme looks novel — 
I don't see any other `_CLANG_{DIS,EN}ABLE.*` macros in `clang/lib/Headers/` — 
but that might just be because its purpose is also novel. I'm not saying it's a 
good idea, but I don't object to it nor have any particularly better idea.

Btw, where above I said `-Wno-deprecated`, it turns out that 
`-Wno-deprecated-pragma` is slightly finer-grained. Also, I'm like 95% sure 
that C++ is totally covered by D115995, which means whatever you do here is 
relevant only to C17, which means I have no personal stake in its ergonomics. :)


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

https://reviews.llvm.org/D112221

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


[PATCH] D114425: [clang] Add __builtin_bswap128

2022-01-02 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added a comment.

In D114425#3216490 , @craig.topper 
wrote:

> In D114425#3216231 , @philnik wrote:
>
>> In D114425#3209794 , @craig.topper 
>> wrote:
>>
>>> What does the builtin due if __int128 isn't supported? Even though the type 
>>> isn't legal the builtin can still be called with a narrower type that would 
>>> be implicitly converted. Does that work correctly?
>>
>> Would the correct behavior be to throw an error in that case? Or what 
>> exactly do you expect?
>
> gcc only defines the builtin if __int128 is a supported type. It doesn't look 
> like it generates an error, it just leaves it as call to an unknown function. 
> I don't know how easy it is to do the same in clang.

The existing code has some lines like `CGM.ErrorUnsupported(E, 
"__builtin_dwarf_sp_column");` — I would try doing the same kind of thing in 
the case where `__int128` isn't supported. (But I don't know how to make 
`__int128` unsupported! Every place I can see `int128` mentioned in the code, 
it's not conspicuously guarded by any condition.)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D114425

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


[PATCH] D116351: Update Bug report URL to Github Issues

2021-12-31 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: libcxx/docs/index.rst:220
 * `libc++abi Homepage `_
-* `LLVM Bugzilla `_
+* `LLVM Issues `_
 * `libcxx-commits Mailing List`_

ksyx wrote:
> MaskRay wrote:
> > Quuxplusone wrote:
> > > 
> > Would https://github.com/llvm/llvm-project/labels/libc++ be better?
> > 
> > Unfortunately "New issue" on that page does not apply the label 
> > automatically.
> Adding parameter like in 
>  could be the 
> most direct way of doing this, given the label exists, so do assignee 
> (untested)? Besides, the new 
> [[ 
> https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/syntax-for-issue-forms
>  | Issue Forms ]] feature of GitHub is also a good idea that also unifys what 
> to fill out in a request and what to automatically do with the issue.
Given that you are using the "search for label" URLs in the other places now, I 
think (for consistency) it //does// make sense to change this one to 
`https://github.com/llvm/llvm-project/labels/libc++/`. (With or without the 
trailing slash, but be consistent.)

Please do //not// hard-code any links to 
`https://github.com/llvm/llvm-project/issues/new`-anything; IMHO that makes it 
far too likely that people (or robots) who click there will end up creating a 
new spam issue by accident. Someone who's found a bug to report should be taken 
to the //search page// (to search and see if it's already been filed). Taking 
them straight to "create a (probably spam) issue" is completely 
counterproductive.


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

https://reviews.llvm.org/D116351

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


[PATCH] D116351: Update Bug report URL to Github Issues

2021-12-29 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone accepted this revision.
Quuxplusone added a comment.

Tweaked English wording throughout. LGTM with all these modifications made.

Orthogonally, it does occur to me that one might save a //lot// of this churn 
(and also the next time the bug tracker moves, e.g. if we go from GitHub to 
something else) by simply HTTP-redirecting the front page of 
https://bugs.llvm.org/ to https://github.com/llvm/llvm-project/issues/ . Then 
we'd have a stable URL https://bugs.llvm.org/ for "reporting LLVM bugs, 
forever," and we could just use that stable URL everywhere. But OTOH, that's a 
devops task, whereas updating a bunch of documentation in the repo is easy. :)




Comment at: clang-tools-extra/docs/clang-doc.rst:15
 crashes. Submitting reports with information about how to reproduce the issue
-to `the LLVM bugtracker `_ will definitely help the
+to `the LLVM Issues `_ will 
definitely help the
 project. If you have any ideas or suggestions, please to put a feature request

Please leave the English wording as "the LLVM bugtracker" (or "the LLVM bug 
tracker" — really it should be two words). There is no such noun in English as 
"an Issues," which means that the reader won't have any idea what you're 
talking about here unless they click on the link to see where it goes.



Comment at: clang/www/c_status.html:75-76
 
-The https://bugs.llvm.org/;>LLVM bug tracker contains a
-Clang C component that tracks known bugs with Clang's language
+The https://github.com/llvm/llvm-project/issues/;>LLVM Issues 
contains
+issuses labeled with c/c11/c18/c2x that tracks known bugs with Clang's language
 conformance.





Comment at: clang/www/cxx_status.html:79-81
+The https://github.com/llvm/llvm-project/issues/;>LLVM Issues 
contains
+issues labelled with c++/c++11/c++14/c++17/c++20 that track known bugs with 
Clang's
+language conformance labelled in each language mode.

(I think `, "C++17", "C++20", "C++23"` would just be redundant/noise here, and 
would imply a thankless task for someone to go update this list every 3 years. 
Better to just cap it at one or two labels. The reader can be trusted to figure 
out that C++20 issues should be labeled with `C++20`.)



Comment at: clang/www/get_involved.html:68
 href="OpenProjects.html">Open Projects page or look through the https://bugs.llvm.org/;>Bugzilla bug database.
+href="https://github.com/llvm/llvm-project/issues/;>LLVM Issues.
 





Comment at: clang/www/get_started.html:22
 involved with the Clang community.  If you run into problems, please file
-bugs in https://bugs.llvm.org/;>LLVM Bugzilla.
+bugs in https://github.com/llvm/llvm-project/issues;>LLVM 
Issues.
 





Comment at: libcxx/docs/index.rst:220
 * `libc++abi Homepage `_
-* `LLVM Bugzilla `_
+* `LLVM Issues `_
 * `libcxx-commits Mailing List`_





Comment at: libunwind/docs/index.rst:101
 * `LLVM Homepage `_
-* `LLVM Bugzilla `_
+* `LLVM Issues `_
 * `cfe-commits Mailing List`_





Comment at: lld/docs/_templates/indexsidebar.html:3-4
 
 lld bugs should be reported at the
-  LLVM https://bugs.llvm.org/;>Bugzilla.
+  LLVM https://github.com/llvm/llvm-project/issues/;>Issues.




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

https://reviews.llvm.org/D116351

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


[PATCH] D116290: [clang-format] Add enforcement of consistent `class`/typename` keyword for template arguments

2021-12-28 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: clang/lib/Format/TemplateArgumentKeywordFixer.cpp:55
+// For `auto` language version, be conservative and assume we are < C++17
+KeepTemplateTemplateKW = (Style.Standard == FormatStyle::LS_Auto) ||
+ (Style.Standard < FormatStyle::LS_Cpp17);

curdeius wrote:
> avogelsgesang wrote:
> > curdeius wrote:
> > > Isn't it a better name?
> > This flag is actually about the usage of the `class` keyword instead of the 
> > `typename` keyword for template-template arguments.
> > `true` means: "Keep using the `class` instead of the `typename` keyword for 
> > template-template arguments."
> > 
> > I think the name `KeepTemplateTypenameKW` is wrong. "[...]TypenameKW = 
> > true" would mean "use `typename` instead of `class`" to me, and that's 
> > exactly the opposite way around.
> > 
> > As such, I think `KeepTemplateTemplateKW` is in fact the better name. If we 
> > want to make it even more explicit, we could also use 
> > `KeepTemplateTemplateClassKW`. What do you think?
> I did understand it correctly that it is about class keyword in template 
> template parameters, but my brain somehow melted down the road:). You can 
> keep the name as is.
IIUC, it feels like the boolean should be named 
`UseClassKWInTemplateTemplates`, and it shouldn't have anything to do with 
`Keep`ing the human's choice. If the human feeds you some C++17 code using 
`template typename T>` and asks you to format it as C++14 with 
`TAS_Typename`, I think it would be quite appropriate to output 
`template class T>`. (Change `class` to `typename` because 
the human asked for `TAS_Typename`; change `typename` to `class` because C++14 
implies `UseClassKWInTemplateTemplates`.)
Anyway, this should have a unit test too.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D116290

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


[PATCH] D116290: [clang-format] Add enforcement of consistent `class`/typename` keyword for template arguments

2021-12-28 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: clang/unittests/Format/TemplateArgumentKeywordFixerTest.cpp:119
+   Style);
+}
+

My personal recommended style is that the programmer uses `template` 
consistently and therefore anytime you see the (more arcane) `typename` keyword 
it's probably necessary for (more arcane) reasons. You cover some arcane uses 
of `typename` above, but I think this one is conspicuously missing:
https://godbolt.org/z/fa9TM4nrr
```
template
void f();
```
You can handle this by looking for `::` after the identifier, and if you find 
it, then `typename` should be kept as-is. In fact, if you find //any// token 
other than `,` `=` `>` after the identifier, something arcane might be 
happening and it'd be best to keep `typename` as-is.

Vice versa, `template` can't be rewritten as `template`; 
again, I think the right approach is to leave the human's choice alone if you 
see anything other than `,` `=` `>` after the identifier.

In general, the problems of "Can this `typename` be rewritten as `class`" and 
vice versa are probably undecidable, so don't get too carried away with trying 
to be perfect as long as you hit all the most common cases anyone can think of. 
https://quuxplusone.github.io/blog/2019/12/27/template-typename-fun/


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D116290

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


[PATCH] D116204: [C++20] [Coroutines] Allow promise_type to not define return_void or return_value

2021-12-23 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: clang/test/SemaCXX/coroutines.cpp:987
+//
+// So it isn't ill-formed if the promise doesn't define return_value and 
return_void. It is just a UB.
+coro no_return_value_or_return_void() {

It's not UB; it's //potential// UB.
My understanding is that such a coroutine could still be used:
- if it exits by throwing an exception instead of `co_return`'ing
- if it suspends and then its caller `destroy`s it instead of `resume`ing it

I believe it would be useful to have some actual tests for these scenarios, 
that would actually run and check that the runtime behavior is correct, or at 
least check the IR that was generated. Is that possible?


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

https://reviews.llvm.org/D116204

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


[PATCH] D115867: [C++20] [Coroutines] Warning for always_inline coroutine

2021-12-22 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: clang/include/clang/Basic/DiagnosticSemaKinds.td:0-3
+def warn_always_inline_coroutine : Warning<
+  "A coroutine marked always_inline might not be inlined properly."
+  >,
+  InGroup;

ChuanqiXu wrote:
> Quuxplusone wrote:
> > FWIW, this message isn't particularly helpful to the reader. My code 
> > "might" not be optimized "properly"? Does that mean it might be 
> > mis-optimized, improperly, and thus break in some way at runtime? Or is the 
> > compiler just saying that the attribute will be ignored? Or that it 
> > //might// be ignored, but it might not? How do I (the programmer) know 
> > whether the bad thing will happen?
> > 
> > I think as a programmer what I'd //like// to see here is just `"the '%0' 
> > attribute has no effect on coroutines"`. That's very clear, and easy to 
> > understand. Does that wording reflect what the compiler actually //does//, 
> > though?
> Thanks for suggestion. The actual behavior isn't easy to describe and 
> understand. Since a coroutine would be splitted into pieces. And the original 
> function would be reduced and we would call it 'ramp function' in compiler. 
> And the call to other new functions would be indirect call. The compiler 
> couldn't inline indirect call. But the compiler **might** convert the 
> indirect call into direct call so that they could be inlined.
> 
> In summary, the actual behavior might be described as: "Only the ramp 
> function are guaranteed to be inlined and the other new functions may or may 
> not get inlined". But the term "ramp funciton" is used in compiler only (Some 
> guys in LWG/LEWG know it too). And I believe the term shouldn't leak to other 
> users. So I chose the current description. 
> 
> BTW, I thought the fact that coroutine would be splitted should be 
> transparent to users too. This is the reason why I wrote previous message. 
> But your words make sense. And I couldn't find methods to make it more clear 
> and don't tell the user about coroutine splitting.
IIUC, `"this coroutine will be split into pieces; only the first piece will be 
inlined"` or simply `"the '%0' attribute applies to only the initial piece of 
this coroutine"`. Possible synonyms for "piece" include "section", "segment", 
"chunk". Is there any standardese for "the run of stuff in between two 
suspension points"?

However, I stand by my initial comment that this message is not helpful to the 
programmer. It's warning me that something bad will happen, right? Instead of 
having that bad thing happen, why don't you just make the compiler //ignore the 
attribute// in this situation?

If your answer is "Because always-inlining the initial piece isn't always bad; 
maybe the programmer thinks it's //good//, and //wants// it to happen," then 
this shouldn't be a `warning` at all; it should just be documented in the 
attribute's documentation. Warnings should be for bad/unintentional things, not 
for things someone might do on purpose.


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

https://reviews.llvm.org/D115867

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


[PATCH] D115867: [C++20] [Coroutines] Warning for always_inline coroutine

2021-12-22 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone requested changes to this revision.
Quuxplusone added inline comments.
This revision now requires changes to proceed.



Comment at: clang/include/clang/Basic/DiagnosticSemaKinds.td:0-3
+def warn_always_inline_coroutine : Warning<
+  "A coroutine marked always_inline might not be inlined properly."
+  >,
+  InGroup;

FWIW, this message isn't particularly helpful to the reader. My code "might" 
not be optimized "properly"? Does that mean it might be mis-optimized, 
improperly, and thus break in some way at runtime? Or is the compiler just 
saying that the attribute will be ignored? Or that it //might// be ignored, but 
it might not? How do I (the programmer) know whether the bad thing will happen?

I think as a programmer what I'd //like// to see here is just `"the '%0' 
attribute has no effect on coroutines"`. That's very clear, and easy to 
understand. Does that wording reflect what the compiler actually //does//, 
though?


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

https://reviews.llvm.org/D115867

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


[PATCH] D113393: [c++2b] Implement P0849R8 auto(x)

2021-12-13 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added a comment.

Am I seeing correctly that there's no feature-test macro for `auto(x)`?

I'm proposing to introduce `#define _LIBCPP_AUTO_CAST(expr)` into libc++, so 
that we can use it for Ranges things that specify in terms of `auto(x)`... but 
if I want to make it conditionally expand into `auto(x)` on compilers that 
support the feature, I basically have to check the compiler vendor and version 
number? No feature-test macro?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D113393

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


[PATCH] D115374: [NFC][clang] Return std::strings built from raw_string_ostreams more efficiently

2021-12-08 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: clang/include/clang/StaticAnalyzer/Checkers/SValExplainer.h:36
+OS.flush();
+return Str;
   }

FWIW, it appears to me that in most (all?) of these cases, what's really wanted 
is not "a string //and// a stream" but rather "a stream that owns a string" 
(`std::ostringstream` or the LLVM-codebase equivalent thereof). Then the return 
can be `return std::move(OS).str();` — for `std::ostringstream`, this Does The 
Right Thing since C++20, and if LLVM had its own stringstream it could make it 
Do The Right Thing today.
https://en.cppreference.com/w/cpp/io/basic_ostringstream/str



Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D115374

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


[PATCH] D114732: [clang] Mark `trivial_abi` types as "trivially relocatable".

2021-12-07 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: clang/include/clang/Basic/AttrDocs.td:3211-3215
+The compiler will pass and return a trivially relocatable type using the C ABI
+for the underlying type, even when the type would otherwise be considered
+non-trivially-relocatable. If a type is trivially relocatable, has a
+non-trivial destructor, and is passed as an argument by value, the convention
+is that the callee will destroy the object before returning.

rsmith wrote:
> Quuxplusone wrote:
> > devin.jeanpierre wrote:
> > > rsmith wrote:
> > > > I think this documentation change has mixed together two different 
> > > > things. The revised wording says that `[[trivial_abi]]` implies 
> > > > trivially-relocatable and that trivially-relocatable implies passing 
> > > > using the C ABI, which is wrong: the second implication does not hold. 
> > > > What we should say is that `[[trivial_abi]]` (if we're not in the "has 
> > > > no effect" case described below) implies both that the type is 
> > > > trivially-relocatable, and that it is passed using the C ABI (that is, 
> > > > that we trivially relocate in argument passing).
> > > > 
> > > > Instead of the wording changes you have here, perhaps we could leave 
> > > > the old wording alone and add a paragraph that says that a type with 
> > > > the attribute is assumed to be trivially-relocatable for the purpose of 
> > > > `__is_trivially_relocatable`, but that Clang doesn't yet take advantage 
> > > > of this fact anywhere other than argument passing.
> > > Yeah, this was too aggressive a wording change, and might easily change 
> > > later when `[[trivially_relocatable]]` is added.
> > > 
> > > I did drop the "Clang doesn't yet take advantage of this fact anywhere 
> > > other than argument passing.", because I feel like -- does that sort of 
> > > sentiment belong instead in the docs for `__is_trivially_relocatable`? 
> > > Maybe I should change `__is_trivially_relocatable` to note that this is 
> > > never taken advantage of anywhere except in by-value argument passing 
> > > (when the type is trivial for the purpose of calls) and library code.
> > Richard's comment jogged my brain and made we worry about this again. IIUC, 
> > you're saying:
> > 
> > 1. All trivial-abi types //are in fact// trivially relocated, specifically 
> > when they are passed to functions.
> > 2. Therefore, all trivial-abi types are "trivially relocatable" //in 
> > general//.
> > 3. Therefore, all trivial-abi types are safe to optimize in all the ways 
> > depicted in D67524.
> > 
> > I agree with 1 for sure, but I'm skeptical of the logical soundness of 2 
> > and 3. Are we willing to set it in stone?
> > 
> > If we're //not// willing to set that whole syllogism in stone, then I would 
> > object to this patch. Because of //this// syllogism:
> > 
> > 4. This patch makes Clang's `__is_trivially_relocatable(T)` return `true` 
> > for all trivial-abi types.
> > 5. D67524 (rightly) applies its optimizations to all types for which 
> > `__is_trivially_relocatable(T)` is `true`.
> > 6. Therefore, if we adopt this patch, we'd better be dang sure that all 
> > trivial-abi types are safe to optimize in all the ways depicted in D67524.
> > 
> > That is, we must set in stone the idea that all trivial-abi types can 
> > safely:
> > - be swapped trivially, in terms of bytewise swap, inside e.g. std::sort
> > - use trivial (bytewise) relocation inside vector reallocation
> > - use trivial (bytewise) relocation when shifting inside vector::insert or 
> > vector::erase
> > 
> > If @devin.jeanpierre and @rsmith and @rjmccall and @ahatanak are all 
> > nodding along to this and saying "yeah, totally, every premise above is 
> > true and the syllogisms are all valid and those optimizations are all 
> > valid, for every trivial-abi type, forever," then I'm happy.
> What use cases would we be giving up on if we go this way? What would a type 
> look like for which trivial relocation when passing to functions is correct, 
> but for which trivial relocation in general is either incorrect or 
> undesirable?
>! @rsmith wrote:
> What would a type look like for which trivial relocation when passing to 
> functions is correct, but for which trivial relocation in general is either 
> incorrect or undesirable?

I have no examples in mind myself, but that (and my skepticism) are largely due 
to my lack of practical experience with `[[trivial_abi]]`. If I can't come up 
with any //and// you can't come up with any //and//... etc..., then that's good 
news for this PR.

>! @rjmccall wrote:
>
> I am perfectly happy accepting that syllogism. [...] If there is a reason 
> your type [ever] shouldn't be trivially relocated, you should not make it 
> trivial_abi.

Okay, that's good news for this PR also. :)

> Trivial relocation doesn't imply that types have to be safe against being 
> suddenly relocated during the middle of operations while they're not in a 
> safe internal 

[PATCH] D114732: [clang] Mark `trivial_abi` types as "trivially relocatable".

2021-12-07 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: clang/include/clang/Basic/AttrDocs.td:3211-3215
+The compiler will pass and return a trivially relocatable type using the C ABI
+for the underlying type, even when the type would otherwise be considered
+non-trivially-relocatable. If a type is trivially relocatable, has a
+non-trivial destructor, and is passed as an argument by value, the convention
+is that the callee will destroy the object before returning.

devin.jeanpierre wrote:
> rsmith wrote:
> > I think this documentation change has mixed together two different things. 
> > The revised wording says that `[[trivial_abi]]` implies 
> > trivially-relocatable and that trivially-relocatable implies passing using 
> > the C ABI, which is wrong: the second implication does not hold. What we 
> > should say is that `[[trivial_abi]]` (if we're not in the "has no effect" 
> > case described below) implies both that the type is trivially-relocatable, 
> > and that it is passed using the C ABI (that is, that we trivially relocate 
> > in argument passing).
> > 
> > Instead of the wording changes you have here, perhaps we could leave the 
> > old wording alone and add a paragraph that says that a type with the 
> > attribute is assumed to be trivially-relocatable for the purpose of 
> > `__is_trivially_relocatable`, but that Clang doesn't yet take advantage of 
> > this fact anywhere other than argument passing.
> Yeah, this was too aggressive a wording change, and might easily change later 
> when `[[trivially_relocatable]]` is added.
> 
> I did drop the "Clang doesn't yet take advantage of this fact anywhere other 
> than argument passing.", because I feel like -- does that sort of sentiment 
> belong instead in the docs for `__is_trivially_relocatable`? Maybe I should 
> change `__is_trivially_relocatable` to note that this is never taken 
> advantage of anywhere except in by-value argument passing (when the type is 
> trivial for the purpose of calls) and library code.
Richard's comment jogged my brain and made we worry about this again. IIUC, 
you're saying:

1. All trivial-abi types //are in fact// trivially relocated, specifically when 
they are passed to functions.
2. Therefore, all trivial-abi types are "trivially relocatable" //in general//.
3. Therefore, all trivial-abi types are safe to optimize in all the ways 
depicted in D67524.

I agree with 1 for sure, but I'm skeptical of the logical soundness of 2 and 3. 
Are we willing to set it in stone?

If we're //not// willing to set that whole syllogism in stone, then I would 
object to this patch. Because of //this// syllogism:

4. This patch makes Clang's `__is_trivially_relocatable(T)` return `true` for 
all trivial-abi types.
5. D67524 (rightly) applies its optimizations to all types for which 
`__is_trivially_relocatable(T)` is `true`.
6. Therefore, if we adopt this patch, we'd better be dang sure that all 
trivial-abi types are safe to optimize in all the ways depicted in D67524.

That is, we must set in stone the idea that all trivial-abi types can safely:
- be swapped trivially, in terms of bytewise swap, inside e.g. std::sort
- use trivial (bytewise) relocation inside vector reallocation
- use trivial (bytewise) relocation when shifting inside vector::insert or 
vector::erase

If @devin.jeanpierre and @rsmith and @rjmccall and @ahatanak are all nodding 
along to this and saying "yeah, totally, every premise above is true and the 
syllogisms are all valid and those optimizations are all valid, for every 
trivial-abi type, forever," then I'm happy.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D114732

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


[PATCH] D114197: [clang-tidy] Fix false positives involving type aliases in `misc-unconventional-assign-operator` check

2021-12-04 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/misc-unconventional-assign-operator.cpp:151
+  using Alias3 = TemplateTypeAlias;
+  Alias3 =(int) { return *this; }
+};

fwolff wrote:
> whisperity wrote:
> > This is a no-warn due to the parameter being a completely unrelated type, 
> > right? Might worth a comment. I don't see at first glance why a warning 
> > should not happen here.
> Exactly. I've added a comment in the `TypeAlias` struct above, because that 
> one comes first. I've also updated the documentation for this check to make 
> this clearer.
> This is a no-warn due to the parameter being a completely unrelated type, 
> right?

No. If that were the case, this would be a terrible test case, full of 
irrelevant cruft. :)

Once you look past all the levels of type aliases, this is equivalent to
```
template
struct TTA {
TTA& operator=(int) { return *this; }
};
```
and so no warning is given because it's correct code.


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

https://reviews.llvm.org/D114197

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


[PATCH] D113369: [clang-format] Extend SpaceBeforeParens for requires

2021-12-04 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: clang/docs/ClangFormatStyleOptions.rst:3756
+  * ``bool AfterRequiresClause`` If ``true``, put space between requires 
keyword in a requires clause and
+opening parentheses, if is are one.
+

HazardyKnusperkeks wrote:
> Quuxplusone wrote:
> > HazardyKnusperkeks wrote:
> > > curdeius wrote:
> > > > You meant "if there is one", right?
> > > Yeah
> > IMO these options should be named `InRequiresClause` and 
> > `InRequiresExpression`: that's where the space is going. The space doesn't 
> > go //after// the requires-clause. The space doesn't go //after// the 
> > requires-expression.
> > It occurs to me that the name of this option could be analogous to the name 
> > of the option that controls `[]() {}` versus `[] () {}`... except that it 
> > looks like there is no such option (and I'm happy about that). :) Also, the 
> > name of that option would probably just be `AfterCaptureList`, which 
> > doesn't help us in this case.
> I get your point, but the space does not go anywhere in the 
> clause/expression, so `AfterRequiresForClauses`?
(I'd avoid the word `For`, because of keyword `for`.)
A //requires-expression// is the whole expression, `requires + param-list + 
body`: https://eel.is/c++draft/expr.prim.req#nt:requires-expression
A //requires-clause// is the whole clause, `requires + logical-or-expr`: 
https://eel.is/c++draft/temp.pre#nt:requires-clause
Does that resolve your concern about the word `In`?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D113369

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


[PATCH] D113319: [clang-format] Improve require and concept handling

2021-12-04 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: clang/docs/ClangFormatStyleOptions.rst:3464-3483
+  * ``RCPS_TwoLines`` (in configuration: ``TwoLines``)
+The clause always gets its own line, and the content of the clause go
+into the next line with some indentation.
+
+.. code-block:: c++
+
+  template

HazardyKnusperkeks wrote:
> Quuxplusone wrote:
> > This option strikes me as actively harmful; I think you should remove it 
> > from the PR completely. Nobody does this today and nobody should do it in 
> > the future either.
> I will never use it, so I have no strong opinion in that, because it was 
> really easy to add. I will let others decide if we want to offer it.
> it was really easy to add

Even easier not to add. ;)



Comment at: clang/include/clang/Format/Format.h:3130-3136
+  /// \brief The position of the ``requires`` clause for class templates.
+  /// \version 14
+  RequiresClausePositionStyle RequiresClausePositionForClasses;
+
+  /// \brief The position of the ``requires`` clause for function templates.
+  /// \version 14
+  RequiresClausePositionStyle RequiresClausePositionForFunctions;

HazardyKnusperkeks wrote:
> Quuxplusone wrote:
> > What about for variable templates? What about for alias templates? What 
> > about for deduction guides?
> > It makes sense to me to have //one// option for this. It doesn't make sense 
> > to have 2, 3, or 4. Having 5 feels insane. So, I think you should just have 
> > one option that applies consistently to all `requires`-clauses everywhere 
> > in the code.
> That makes sense, in my defense I thought about it and came to the conclusion 
> there would be no need for requires on variable templates, and the others I 
> did not think of.
> 
> Why I have chosen to options is maybe someone wants
> ```template 
> requires ...
> class ...```
> 
> But also
> ```template 
> void foo(T) requires ... {
> ```
> 
> What's your opinion on that?
Well, I see that there is a machine-readable distinction between "`requires` 
after `template`" versus "`requires` after function parameter list," i.e. 
between
```
template requires X
void f(T);

template
void f(T) requires X;
```
The latter position is not (currently) valid for non-functions (e.g. 
`template int v requires X;` is a syntax error).
However, as usual, I don't think that the user should //want// to format these 
differently.
If you're using clang-format to format your code, then you should definitely 
want function-parameter-list-requires-clauses on their own line for sure, to 
avoid confusing strings of tokens such as
```
void f() const noexcept requires foobar;  // bad

void f() const noexcept  // better
  requires foobar;
```
If you do that, then (in my proposed world) you would also automatically get
```
template
  requires foobar  // automatically
void f();

template requires foobar  // can't get this
void f();

template  // could also get this, via manual intervention
void f();
```
And personally I see nothing wrong with that state of affairs.



Comment at: clang/unittests/Format/FormatTest.cpp:22288-22291
+  verifyFormat("template \n"
+   "concept C = ((false || foo()) && C2) || "
+   "(std::trait::value && Baz) ||\n "
+   "   sizeof(T) >= 6;");

HazardyKnusperkeks wrote:
> Quuxplusone wrote:
> > Nit: I was initially very confused by the formatting here, until I realized 
> > that lines 22289 and 22290 are two lines //physically// but represent one 
> > single line in the //test case//. Strongly recommend eliminating the 
> > gratuitous line break.
> I'm not really happy wit the two solutions which come to my mind:
> Using a Style with a lower column limit, or using // clang format off.
I guess the higher-level question (which I didn't think of until seeing many 
other tests) is, redesign this test case to be more targeted and thus shorter. 
E.g. could you `s/std::trait::value/Bar/` or would that destroy the point of 
the test? (I'm not sure because I'm not sure what the point of the test is.)



Comment at: clang/unittests/Format/FormatTest.cpp:22374-22378
+  "template \n"
+  "concept C = decltype([]() { return std::true_type{}; }())::value &&\n"
+  "requires(T t) {\n"
+  "  t.bar();\n"
+  "} && sizeof(T) <= 8;");

HazardyKnusperkeks wrote:
> Quuxplusone wrote:
> > This looks wrong. Current:
> > ```
> > template \n"
> > concept C = decltype([]() { return std::true_type{}; }())::value &&
> > requires(T t) {
> >   t.bar();
> > } && sizeof(T) <= 8;
> > ```
> > but should be:
> > ```
> > template \n"
> > concept C = decltype([]() { return std::true_type{}; }())::value &&
> >   requires(T t) {
> > t.bar();
> >   } && sizeof(T) <= 8;
> > ```
> > (assuming that all the relevant indent-widths are set to `2`).
> For me personally it should look
> ```template \n"
> concept C = 

[PATCH] D113369: [clang-format] Extend SpaceBeforeParens for requires

2021-12-04 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: clang/docs/ClangFormatStyleOptions.rst:3756
+  * ``bool AfterRequiresClause`` If ``true``, put space between requires 
keyword in a requires clause and
+opening parentheses, if is are one.
+

HazardyKnusperkeks wrote:
> curdeius wrote:
> > You meant "if there is one", right?
> Yeah
IMO these options should be named `InRequiresClause` and 
`InRequiresExpression`: that's where the space is going. The space doesn't go 
//after// the requires-clause. The space doesn't go //after// the 
requires-expression.
It occurs to me that the name of this option could be analogous to the name of 
the option that controls `[]() {}` versus `[] () {}`... except that it looks 
like there is no such option (and I'm happy about that). :) Also, the name of 
that option would probably just be `AfterCaptureList`, which doesn't help us in 
this case.



Comment at: clang/include/clang/Format/Format.h:3371
+/// If ``true``, put space between requires keyword in a requires clause 
and
+/// opening parentheses, if there is one.
+/// \code

Here and line 3380, and possibly elsewhere: `s/parentheses/parenthesis/`



Comment at: clang/unittests/Format/FormatTest.cpp:14369
+  "{}",
+  SpaceAfterRequires);
 }

Throughout, I'd like to see simpler test cases and more of them. E.g. I think 
this would suffice, in lieu of lines 14305–14369:
```
SpaceAfterRequires.SpaceBeforeParensOptions.InRequiresClause = true;
SpaceAfterRequires.SpaceBeforeParensOptions.InRequiresExpression = true;
verifyFormat("void f(auto x) requires (requires (int i) { x+i; }) { }", 
SpaceAfterRequires);
verifyFormat("if (requires (int i) { x+i; }) return;", SpaceAfterRequires);
verifyFormat("bool b = requires (int i) { x+i; };", SpaceAfterRequires);

SpaceAfterRequires.SpaceBeforeParensOptions.InRequiresClause = true;
SpaceAfterRequires.SpaceBeforeParensOptions.InRequiresExpression = false;
verifyFormat("void f(auto x) requires (requires(int i) { x+i; }) { }", 
SpaceAfterRequires);
verifyFormat("if (requires(int i) { x+i; }) return;", SpaceAfterRequires);
verifyFormat("bool b = requires(int i) { x+i; };", SpaceAfterRequires);

SpaceAfterRequires.SpaceBeforeParensOptions.InRequiresClause = false;
SpaceAfterRequires.SpaceBeforeParensOptions.InRequiresExpression = true;
verifyFormat("void f(auto x) requires(requires (int i) { x+i; }) { }", 
SpaceAfterRequires);
verifyFormat("if (requires (int i) { x+i; }) return;", SpaceAfterRequires);
verifyFormat("bool b = requires (int i) { x+i; };", SpaceAfterRequires);

SpaceAfterRequires.SpaceBeforeParensOptions.InRequiresClause = false;
SpaceAfterRequires.SpaceBeforeParensOptions.InRequiresExpression = false;
verifyFormat("void f(auto x) requires(requires(int i) { x+i; }) { }", 
SpaceAfterRequires);
verifyFormat("if (requires(int i) { x+i; }) return;", SpaceAfterRequires);
verifyFormat("bool b = requires(int i) { x+i; };", SpaceAfterRequires);
```


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D113369

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


[PATCH] D113319: [clang-format] Improve require and concept handling

2021-12-03 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added inline comments.



Comment at: clang/docs/ClangFormatStyleOptions.rst:3424
+templates or between template and function delcarations. In case of
+after the function delcaration it tries to stick to this.
+

`s/delca/decla/g`
`s/Preceeding/Preceding/g`



Comment at: clang/docs/ClangFormatStyleOptions.rst:3464-3483
+  * ``RCPS_TwoLines`` (in configuration: ``TwoLines``)
+The clause always gets its own line, and the content of the clause go
+into the next line with some indentation.
+
+.. code-block:: c++
+
+  template

This option strikes me as actively harmful; I think you should remove it from 
the PR completely. Nobody does this today and nobody should do it in the future 
either.



Comment at: clang/include/clang/Format/Format.h:2504-2505
 
-  /// Indent the requires clause in a template
+  /// Indent the requires clause in a template, this only applies if the
+  /// ``requires`` is at the beginning of a line.
   /// \code

Comma-splice. But I don't think you need to change this comment at all. It's 
obvious that "indent" applies only to constructs at the left side of the 
(logical) source line.



Comment at: clang/include/clang/Format/Format.h:3130-3136
+  /// \brief The position of the ``requires`` clause for class templates.
+  /// \version 14
+  RequiresClausePositionStyle RequiresClausePositionForClasses;
+
+  /// \brief The position of the ``requires`` clause for function templates.
+  /// \version 14
+  RequiresClausePositionStyle RequiresClausePositionForFunctions;

What about for variable templates? What about for alias templates? What about 
for deduction guides?
It makes sense to me to have //one// option for this. It doesn't make sense to 
have 2, 3, or 4. Having 5 feels insane. So, I think you should just have one 
option that applies consistently to all `requires`-clauses everywhere in the 
code.



Comment at: clang/lib/Format/Format.cpp:1213
+  // This is open for discussions! When will LLVM adapt C++20?
+  LLVMStyle.RequiresClausePositionForClasses = FormatStyle::RCPS_OwnLine;
+  LLVMStyle.RequiresClausePositionForFunctions = FormatStyle::RCPS_OwnLine;

HazardyKnusperkeks wrote:
> What are your opinions on that?
+1 `RequiresClausePosition=OwnLine`, but also `IndentRequires=true`.



Comment at: clang/unittests/Format/FormatTest.cpp:22288-22291
+  verifyFormat("template \n"
+   "concept C = ((false || foo()) && C2) || "
+   "(std::trait::value && Baz) ||\n "
+   "   sizeof(T) >= 6;");

Nit: I was initially very confused by the formatting here, until I realized 
that lines 22289 and 22290 are two lines //physically// but represent one 
single line in the //test case//. Strongly recommend eliminating the gratuitous 
line break.



Comment at: clang/unittests/Format/FormatTest.cpp:22374-22378
+  "template \n"
+  "concept C = decltype([]() { return std::true_type{}; }())::value &&\n"
+  "requires(T t) {\n"
+  "  t.bar();\n"
+  "} && sizeof(T) <= 8;");

This looks wrong. Current:
```
template \n"
concept C = decltype([]() { return std::true_type{}; }())::value &&
requires(T t) {
  t.bar();
} && sizeof(T) <= 8;
```
but should be:
```
template \n"
concept C = decltype([]() { return std::true_type{}; }())::value &&
  requires(T t) {
t.bar();
  } && sizeof(T) <= 8;
```
(assuming that all the relevant indent-widths are set to `2`).



Comment at: clang/unittests/Format/FormatTest.cpp:22597
+  verifyFormat("template \n"
+ "requires(std::invocable...>)\n"
+ "struct constant;",

Currently:
```
template 
requires(std::invocable...>)
struct constant;
```
Should be:
```
template 
requires (std::invocable...>)
struct constant;
```
(notice the extra single space). Add a TODO comment and ship it anyway?



Comment at: clang/unittests/Format/FormatTest.cpp:22643
   verifyFormat("template \n"
-   "concept Context = Traits or\n"
-   "Interface or\n"
-   "Request or\n"
-   "Response or\n"
-   "ContextExtension or\n"
-   "::std::is_copy_constructable or "
-   "::std::is_move_constructable or\n"
-   "requires (T c) {\n"
-   "  { c.response; } -> Response;\n"
-   "} or requires (T c) {\n"
-   "  { c.request; } -> Request;\n"
-   "}\n",
+   "requires requires(T t) {\n"
+   "  typename T::Bar;\n"

Data point: libc++ has a mix of `requires (T t) { }` and `requires(T t) { }`. 
Am I correct that clang-format is not yet smart enough to have a meaningful 
opinion about this 

[PATCH] D115061: [clang-format][NFC] Prefer pass by reference

2021-12-03 Thread Arthur O'Dwyer via Phabricator via cfe-commits
Quuxplusone added a comment.

FWLIW, I'm strongly in favor of "Pass out-parameters by pointer," for the 
reason Marek said (and the reason Google, Bloomberg, Facebook, Mongo, etc, do 
it) — it makes life easier for the reader of the calling code. Especially for 
e.g. `addNextStateToQueue(Penalty, Node, /*NewLine=*/false, Count, Queue)`, I 
don't think it's at all obvious that this is going to modify the value of 
`Count`!
But this isn't my code and I don't know what LLVM's house style is.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D115061

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


  1   2   3   4   5   6   7   >