[PATCH] D152713: [clang-tidy] Correct sizeof/alignas handling in misc-redundant-expression

2023-07-01 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron accepted this revision.
Izaron added a comment.
This revision is now accepted and ready to land.

LGTM! Thank you for the fix!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D152713

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


[PATCH] D146393: [Clang] Support free positioning of labels inside compound statements in C

2023-03-19 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added a comment.

A big TODO: rename `ext_c_label_end_of_compound_statement` to something like 
`ext_c_label_free_positioning`. Since we found out it is more complete than 
just the end of statements.




Comment at: clang/lib/Parse/ParseStmt.cpp:695-697
-  // The substatement is always a 'statement', not a 'declaration', but is
-  // otherwise in the same context as the labeled-statement.
-  StmtCtx &= ~ParsedStmtContext::AllowDeclarationsInC;

Place in code where it matters: 
https://github.com/llvm/llvm-project/blob/84870c4abbacfb97ca025c9219b724f381611380/clang/lib/Parse/ParseStmt.cpp#L237



Comment at: clang/test/OpenMP/threadprivate_messages.cpp:141
 label:
-#pragma omp threadprivate(d4) // expected-error {{'#pragma omp threadprivate' 
cannot be an immediate substatement}}
+#pragma omp threadprivate(d4)
 

TODO: find out if this is okay? (I've got no idea what it does)



Comment at: clang/test/Parser/c2x-label.c:5-6
 void test_label_in_func() {
-int x;
 label1:
+int x;
+label2:

TODO: make sure a warning is printed. I couldn't find correct conditions for 
the warning, I tried and it produced false positive warnings in some other 
tests =(

P.S. Its C++'s counterpart: 
https://github.com/llvm/llvm-project/blob/main/clang/test/Parser/cxx2b-label.cpp


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146393

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


[PATCH] D146393: [Clang] Support free positioning of labels inside compound statements in C

2023-03-19 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron created this revision.
Izaron added reviewers: aaron.ballman, cor3ntin.
Herald added a project: All.
Izaron requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Implements part of paper P2324R2
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2508.pdf
Fixes https://github.com/llvm/llvm-project/issues/61507


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D146393

Files:
  clang/lib/Parse/ParseStmt.cpp
  clang/test/OpenMP/allocate_messages.cpp
  clang/test/OpenMP/threadprivate_messages.cpp
  clang/test/Parser/c2x-label.c


Index: clang/test/Parser/c2x-label.c
===
--- clang/test/Parser/c2x-label.c
+++ clang/test/Parser/c2x-label.c
@@ -2,10 +2,11 @@
 // RUN: %clang_cc1 -fsyntax-only -std=c2x -Wpre-c2x-compat -verify=c2x %s
 
 void test_label_in_func() {
-int x;
 label1:
+int x;
+label2:
 x = 1;
-label2: label3: label4:
+label3: label4: label5:
 } // c17-warning {{label at end of compound statement is a C2x extension}} \
  c2x-warning {{label at end of compound statement is incompatible with C 
standards before C2x}}
 
Index: clang/test/OpenMP/threadprivate_messages.cpp
===
--- clang/test/OpenMP/threadprivate_messages.cpp
+++ clang/test/OpenMP/threadprivate_messages.cpp
@@ -138,7 +138,7 @@
   }
 #pragma omp threadprivate(d3)
 label:
-#pragma omp threadprivate(d4) // expected-error {{'#pragma omp threadprivate' 
cannot be an immediate substatement}}
+#pragma omp threadprivate(d4)
 
 #pragma omp threadprivate(a) // expected-error {{'#pragma omp threadprivate' 
must appear in the scope of the 'a' variable declaration}}
   return (y);
Index: clang/test/OpenMP/allocate_messages.cpp
===
--- clang/test/OpenMP/allocate_messages.cpp
+++ clang/test/OpenMP/allocate_messages.cpp
@@ -141,7 +141,7 @@
   }
 #pragma omp allocate(d3)
 label:
-#pragma omp allocate(d4) // expected-error {{'#pragma omp allocate' cannot be 
an immediate substatement}}
+#pragma omp allocate(d4)
 
 #pragma omp allocate(a) // expected-error {{'#pragma omp allocate' must appear 
in the scope of the 'a' variable declaration}}
   return (y);
Index: clang/lib/Parse/ParseStmt.cpp
===
--- clang/lib/Parse/ParseStmt.cpp
+++ clang/lib/Parse/ParseStmt.cpp
@@ -692,10 +692,6 @@
   assert(Tok.is(tok::identifier) && Tok.getIdentifierInfo() &&
  "Not an identifier!");
 
-  // The substatement is always a 'statement', not a 'declaration', but is
-  // otherwise in the same context as the labeled-statement.
-  StmtCtx &= ~ParsedStmtContext::AllowDeclarationsInC;
-
   Token IdentTok = Tok;  // Save the whole token.
   ConsumeToken();  // eat the identifier.
 


Index: clang/test/Parser/c2x-label.c
===
--- clang/test/Parser/c2x-label.c
+++ clang/test/Parser/c2x-label.c
@@ -2,10 +2,11 @@
 // RUN: %clang_cc1 -fsyntax-only -std=c2x -Wpre-c2x-compat -verify=c2x %s
 
 void test_label_in_func() {
-int x;
 label1:
+int x;
+label2:
 x = 1;
-label2: label3: label4:
+label3: label4: label5:
 } // c17-warning {{label at end of compound statement is a C2x extension}} \
  c2x-warning {{label at end of compound statement is incompatible with C standards before C2x}}
 
Index: clang/test/OpenMP/threadprivate_messages.cpp
===
--- clang/test/OpenMP/threadprivate_messages.cpp
+++ clang/test/OpenMP/threadprivate_messages.cpp
@@ -138,7 +138,7 @@
   }
 #pragma omp threadprivate(d3)
 label:
-#pragma omp threadprivate(d4) // expected-error {{'#pragma omp threadprivate' cannot be an immediate substatement}}
+#pragma omp threadprivate(d4)
 
 #pragma omp threadprivate(a) // expected-error {{'#pragma omp threadprivate' must appear in the scope of the 'a' variable declaration}}
   return (y);
Index: clang/test/OpenMP/allocate_messages.cpp
===
--- clang/test/OpenMP/allocate_messages.cpp
+++ clang/test/OpenMP/allocate_messages.cpp
@@ -141,7 +141,7 @@
   }
 #pragma omp allocate(d3)
 label:
-#pragma omp allocate(d4) // expected-error {{'#pragma omp allocate' cannot be an immediate substatement}}
+#pragma omp allocate(d4)
 
 #pragma omp allocate(a) // expected-error {{'#pragma omp allocate' must appear in the scope of the 'a' variable declaration}}
   return (y);
Index: clang/lib/Parse/ParseStmt.cpp
===
--- clang/lib/Parse/ParseStmt.cpp
+++ clang/lib/Parse/ParseStmt.cpp
@@ -692,10 +692,6 @@
   assert(Tok.is(tok::identifier) && Tok.getIdentifierInfo() &&
  "Not an identifier!");
 
-  // The substatement is always a 'statement', not a 'declaration', but is
-  // otherwise in th

[PATCH] D144334: [Clang] Add C++2b attribute [[assume(expression)]]

2023-02-21 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron marked an inline comment as done.
Izaron added a comment.

In D144334#4142490 , @erichkeane 
wrote:

> Just deliberately not support a part of C++2b.  Implementers have veto'ed 
> features in the past exactly that way.

That's sad. Let's at least write some warning on the `cxx_status.html` like "we 
aren't gonna implement it".




Comment at: clang/lib/CodeGen/CGStmt.cpp:723-727
+case attr::Assume: {
+  llvm::Value *ArgValue = EmitScalarExpr(cast(A)->getCond());
+  llvm::Function *FnAssume = CGM.getIntrinsic(llvm::Intrinsic::assume);
+  Builder.CreateCall(FnAssume, ArgValue);
+  break;

cor3ntin wrote:
> I'm not familiar with codegen. what makes the expression non-evaluated here?
The LLVM docs says it: https://llvm.org/docs/LangRef.html#llvm-assume-intrinsic
> No code is generated for this intrinsic, and instructions that contribute 
> only to the provided condition are not used for code generation
The `ArgValue` and `FnAssume` are the instructions to be discarded according to 
this sentence.

I guess they do it via dead code elimination (at any optimization level).


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D144334

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


[PATCH] D144334: [Clang] Add C++2b attribute [[assume(expression)]]

2023-02-21 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added a comment.

In D144334#4141646 , @erichkeane 
wrote:

> I'm on the fence as to whether we want to implement this feature at all.  As 
> was discussed extensively during the EWG meetings on this: multiple 
> implementers are against this attribute for a variety of reasons, and at 
> least 1 other implementer has stated they might 'implementer veto' this.

I don't quite understand how it works. The feature has been approved for C++2b, 
but it should have not been approved if there were concerns from implementers.

A friend of mine got his proposal rejected because MSVC said they are unable to 
support the new feature.

But it seems like not the case with the `assume` attribute. Could you please 
elaborate: if you decide to not implement this feature, you will kind of revoke 
the proposal or just deliberately do not support a part of C++2b in Clang?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D144334

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


[PATCH] D118743: [clang-tidy] Add `modernize-use-inline-const-variables-in-headers` check

2023-02-18 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron marked 2 inline comments as done.
Izaron added inline comments.



Comment at: 
clang-tools-extra/test/clang-tidy/checkers/modernize/use-inline-const-variables-in-headers.hpp:1
+// RUN: %check_clang_tidy %s -std=c++17 
modernize-use-inline-const-variables-in-headers %t
+

carlosgalvezp wrote:
> Should tests be added for the `CheckNonInline` and `CheckExtern` options?
I decided to split the test into two files as it is done for other checkers 
that have multiple options.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D118743

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


[PATCH] D118743: [clang-tidy] Add `modernize-use-inline-const-variables-in-headers` check

2023-02-18 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 498637.
Izaron added a comment.

Use the common `isInAnonymousNamespace` matcher.

Split the test into two files.

Thanks to @carlosgalvezp for advices!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D118743

Files:
  clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
  clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
  
clang-tools-extra/clang-tidy/modernize/UseInlineConstVariablesInHeadersCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseInlineConstVariablesInHeadersCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/docs/clang-tidy/checks/modernize/use-inline-const-variables-in-headers.rst
  
clang-tools-extra/test/clang-tidy/checkers/modernize/use-inline-const-variables-in-headers-extern.hpp
  
clang-tools-extra/test/clang-tidy/checkers/modernize/use-inline-const-variables-in-headers-non-inline.hpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-inline-const-variables-in-headers-non-inline.hpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-inline-const-variables-in-headers-non-inline.hpp
@@ -0,0 +1,42 @@
+// RUN: %check_clang_tidy %s -std=c++17 modernize-use-inline-const-variables-in-headers %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN: [{key: modernize-use-inline-const-variables-in-headers.CheckNonInline, value: true}, \
+// RUN:  {key: modernize-use-inline-const-variables-in-headers.CheckExtern, value: false}]}"
+
+const int ConstFoo = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: global constant 'ConstFoo' should be marked as 'inline' [modernize-use-inline-const-variables-in-headers]
+// CHECK-FIXES: {{^}}inline const int ConstFoo = 1;{{$}}
+
+namespace N {
+constexpr int NamespaceFoo = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: global constant 'NamespaceFoo' should be marked as 'inline' [modernize-use-inline-const-variables-in-headers]
+// CHECK-FIXES: {{^}}inline constexpr int NamespaceFoo = 1;{{$}}
+} // namespace N
+
+struct S {
+  // no warning: the variable is not at file scope
+  static const int StructFoo = 1;
+};
+
+// no warning: non-const global variables have external linkage
+int NonConstFoo = 1;
+
+// no warning: volatile global variables have external linkage
+const volatile int VolatileFoo = 1;
+
+// no warning: templates and their instantiations have external linkage
+template 
+const auto TemplateFoo = sizeof(T);
+
+// no warning: already fixed
+inline const int InlineFoo = 1;
+
+// no warning: C has no 'inline variables'
+extern "C" {
+const int CFoo0 = 1;
+}
+
+// no warning: 'inline' is invisible when within an unnamed namespace
+namespace {
+const int AnonNamespaceFoo = 1;
+} // namespace
Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-inline-const-variables-in-headers-extern.hpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-inline-const-variables-in-headers-extern.hpp
@@ -0,0 +1,10 @@
+// RUN: %check_clang_tidy %s -std=c++17 modernize-use-inline-const-variables-in-headers %t -- \
+// RUN:   -config="{CheckOptions: \
+// RUN: [{key: modernize-use-inline-const-variables-in-headers.CheckNonInline, value: false}, \
+// RUN:  {key: modernize-use-inline-const-variables-in-headers.CheckExtern, value: true}]}"
+
+extern const int ExternFoo;
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: global constant 'ExternFoo' should be converted to C++17 'inline variable' [modernize-use-inline-const-variables-in-headers]
+
+// no warning: C has no 'inline variables'
+extern "C" const int CFoo1 = 1;
Index: clang-tools-extra/docs/clang-tidy/checks/modernize/use-inline-const-variables-in-headers.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/modernize/use-inline-const-variables-in-headers.rst
@@ -0,0 +1,68 @@
+.. title:: clang-tidy - modernize-use-inline-const-variables-in-headers
+
+modernize-use-inline-const-variables-in-headers
+===
+
+Suggests switching to C++17 ``inline variables`` for non-inline const
+variable definitions and extern const variable declarations in header files.
+Non-inline const variables make a separate instance of the variable for each
+translation unit that includes the header, which can lead to subtle violation
+of the ODR. Extern const variables are a deprecated way to define a constant
+since C++17.
+
+.. code-block:: c++
+
+   // Foo.h
+   const int ConstFoo = 1; // Warning: should be marked as 'inline'
+
+   namespace N {
+ constexpr int NamespaceFoo = 1; // Warning: should be marked as 'inline'
+   }
+
+   extern const int ExternFoo; // Warnin

[PATCH] D144334: [Clang] Add C++2b attribute [[assume(expression)]]

2023-02-18 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added a comment.

If you are not familiar with the `[[assume(expr]]` concept and want to know 
more, I wrote a small article about it recently, with a lot of additional links 
(including to the author of the proposal) - 
https://izaron.github.io/posts/assume/


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D144334

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


[PATCH] D144334: [Clang] Add C++2b attribute [[assume(expression)]]

2023-02-18 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 498625.
Izaron added a comment.

More thorough AST test.

Set the right macros number - thanks to @philnik!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D144334

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/CodeGen/CGStmt.cpp
  clang/lib/Sema/SemaStmtAttr.cpp
  clang/test/AST/ast-dump-attr.cpp
  clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.assume/p1.cpp
  clang/test/CodeGenCXX/cxx2b-assume.cpp
  clang/www/cxx_status.html

Index: clang/www/cxx_status.html
===
--- clang/www/cxx_status.html
+++ clang/www/cxx_status.html
@@ -1501,7 +1501,7 @@
 
   Portable assumptions
   https://wg21.link/P1774R8";>P1774R8
-  No
+  Clang 17
 
 
   Support for UTF-8 as a portable source file encoding
Index: clang/test/CodeGenCXX/cxx2b-assume.cpp
===
--- /dev/null
+++ clang/test/CodeGenCXX/cxx2b-assume.cpp
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -std=c++2b %s -emit-llvm -o - -triple x86_64-linux-gnu -disable-llvm-passes -DUSE_ASSUME | FileCheck %s
+// RUN: %clang_cc1 -std=c++2b %s -emit-llvm -o - -triple x86_64-linux-gnu -O3 | FileCheck --check-prefixes=CHECK-OPT-NOASSUME %s
+// RUN: %clang_cc1 -std=c++2b %s -emit-llvm -o - -triple x86_64-linux-gnu -O3 -DUSE_ASSUME | FileCheck --check-prefixes=CHECK-OPT %s
+
+// CHECK-LABEL: @_Z12divide_by_32i
+// CHECK-NEXT: entry:
+// CHECK-NEXT:   %[[VAR:.*]] = alloca i32, align 4
+// CHECK-NEXT:   store i32 %x, ptr %[[VAR]], align 4
+// CHECK-NEXT:   %0 = load i32, ptr %[[VAR]], align 4
+// CHECK-NEXT:   %[[CMP:.*]] = icmp sge i32 %0, 0
+// CHECK-NEXT:   call void @llvm.assume(i1 %[[CMP]])
+// CHECK-NEXT:   %1 = load i32, ptr %[[VAR]], align 4
+// CHECK-NEXT:   %[[DIV:.*]] = sdiv i32 %1, 32
+// CHECK-NEXT:   ret i32 %[[DIV]]
+//
+// CHECK-OPT-NOASSUME-LABEL: @_Z12divide_by_32i
+// CHECK-OPT-NOASSUME-NEXT: entry:
+// CHECK-OPT-NOASSUME-NEXT:   %[[DIV:.*]] = sdiv i32 %x, 32
+// CHECK-OPT-NOASSUME-NEXT:   ret i32 %[[DIV]]
+//
+// CHECK-OPT-LABEL: @_Z12divide_by_32i
+// CHECK-OPT-NEXT: entry:
+// CHECK-OPT-NEXT:   %[[CMP:.*]] = icmp sgt i32 %x, -1
+// CHECK-OPT-NEXT:   tail call void @llvm.assume(i1 %[[CMP]])
+// CHECK-OPT-NEXT:   %[[DIV:.*]] = lshr i32 %x, 5
+// CHECK-OPT-NEXT:   ret i32 %[[DIV]]
+//
+int divide_by_32(int x) {
+#ifdef USE_ASSUME
+[[assume(x >= 0)]];
+#endif
+return x/32;
+}
+
+// CHECK-LABEL: @_Z9incrementi
+// CHECK-NEXT: entry:
+// CHECK-NEXT:   %[[VAR:.*]] = alloca i32, align 4
+// CHECK-NEXT:   store i32 %y, ptr %[[VAR]], align 4
+// CHECK-NEXT:   %0 = load i32, ptr %[[VAR]], align 4
+// CHECK-NEXT:   %[[VARP1:.*]] = add nsw i32 %0, 1
+// CHECK-NEXT:   store i32 %[[VARP1]], ptr %[[VAR]], align 4
+// CHECK-NEXT:   %[[CMP:.*]] = icmp eq i32 %[[VARP1]], 43
+// CHECK-NEXT:   call void @llvm.assume(i1 %[[CMP]])
+// CHECK-NEXT:   %1 = load i32, ptr %[[VAR]], align 4
+// CHECK-NEXT:   ret i32 %1
+//
+// CHECK-OPT-NOASSUME-LABEL: @_Z9incrementi
+// CHECK-OPT-NOASSUME-NEXT: entry:
+// CHECK-OPT-NOASSUME-NEXT:   ret i32 %y
+//
+// CHECK-OPT-LABEL: @_Z9incrementi
+// CHECK-OPT-NEXT: entry:
+// CHECK-OPT-NEXT:   %[[CMP:.*]] = icmp eq i32 %y, 42
+// CHECK-OPT-NEXT:   tail call void @llvm.assume(i1 %[[CMP]])
+// CHECK-OPT-NEXT:   ret i32 43
+//
+int increment(int y) {
+#ifdef USE_ASSUME
+[[assume(++y == 43)]];
+#endif
+return y;
+}
Index: clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.assume/p1.cpp
===
--- /dev/null
+++ clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.assume/p1.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -fsyntax-only -Wunused -std=c++2b -verify %s
+
+int divide_by_32(int x) {
+[[assume(x >= 0)]];
+return x/32;
+}
+
+int increment(int y) {
+[[assume(++y == 43)]];
+return y;
+}
+
+[[assume(true)]] int incorrects(int y) { // expected-error {{'assume' attribute cannot be applied to a declaration}}
+[[assume(++y == 43)]] int x = 0; // expected-error {{'assume' attribute cannot be applied to a declaration}}
+[[assume(++y == 43)]] x = 0; // expected-error {{'assume' attribute only applies to empty statements}}
+[[assume(++y == 43 && ++y == 44)]];
+[[assume(++y == 43, ++y == 43)]]; // expected-error {{'assume' attribute takes one argument}}
+[[assume]]; // expected-error {{'assume' attribute takes one argument}}
+return y;
+}
Index: clang/test/AST/ast-dump-attr.cpp
===
--- clang/test/AST/ast-dump-attr.cpp
+++ clang/test/AST/ast-dump-attr.cpp
@@ -259,3 +259,18 @@
 // CHECK-NEXT: AnnotateAttr{{.*}} Inherited
 // CHECK-NEXT: UnusedAttr
 // CHECK-NEXT: NoThreadSafetyAna

[PATCH] D144334: [Clang] Add C++2b attribute [[assume(expression)]]

2023-02-18 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added inline comments.



Comment at: clang/include/clang/Basic/Attr.td:1448
+def Assume : StmtAttr {
+  let Spellings = [CXX11<"", "assume", 202302>];
+  let Documentation = [AssumeDocs];

Honestly I don't have a clue what these numbers `202302` (apparently the 
`mm` format) would mean :( I'd be grateful if you could help me with the 
right value for this.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D144334

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


[PATCH] D144334: [Clang] Add C++2b attribute [[assume(expression)]]

2023-02-18 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 498622.
Izaron added a comment.

A small fix for `def FutureAttrs`


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D144334

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/CodeGen/CGStmt.cpp
  clang/lib/Sema/SemaStmtAttr.cpp
  clang/test/AST/ast-dump-attr.cpp
  clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.assume/p1.cpp
  clang/test/CodeGenCXX/cxx2b-assume.cpp
  clang/www/cxx_status.html

Index: clang/www/cxx_status.html
===
--- clang/www/cxx_status.html
+++ clang/www/cxx_status.html
@@ -1501,7 +1501,7 @@
 
   Portable assumptions
   https://wg21.link/P1774R8";>P1774R8
-  No
+  Clang 17
 
 
   Support for UTF-8 as a portable source file encoding
Index: clang/test/CodeGenCXX/cxx2b-assume.cpp
===
--- /dev/null
+++ clang/test/CodeGenCXX/cxx2b-assume.cpp
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -std=c++2b %s -emit-llvm -o - -triple x86_64-linux-gnu -disable-llvm-passes -DUSE_ASSUME | FileCheck %s
+// RUN: %clang_cc1 -std=c++2b %s -emit-llvm -o - -triple x86_64-linux-gnu -O3 | FileCheck --check-prefixes=CHECK-OPT-NOASSUME %s
+// RUN: %clang_cc1 -std=c++2b %s -emit-llvm -o - -triple x86_64-linux-gnu -O3 -DUSE_ASSUME | FileCheck --check-prefixes=CHECK-OPT %s
+
+// CHECK-LABEL: @_Z12divide_by_32i
+// CHECK-NEXT: entry:
+// CHECK-NEXT:   %[[VAR:.*]] = alloca i32, align 4
+// CHECK-NEXT:   store i32 %x, ptr %[[VAR]], align 4
+// CHECK-NEXT:   %0 = load i32, ptr %[[VAR]], align 4
+// CHECK-NEXT:   %[[CMP:.*]] = icmp sge i32 %0, 0
+// CHECK-NEXT:   call void @llvm.assume(i1 %[[CMP]])
+// CHECK-NEXT:   %1 = load i32, ptr %[[VAR]], align 4
+// CHECK-NEXT:   %[[DIV:.*]] = sdiv i32 %1, 32
+// CHECK-NEXT:   ret i32 %[[DIV]]
+//
+// CHECK-OPT-NOASSUME-LABEL: @_Z12divide_by_32i
+// CHECK-OPT-NOASSUME-NEXT: entry:
+// CHECK-OPT-NOASSUME-NEXT:   %[[DIV:.*]] = sdiv i32 %x, 32
+// CHECK-OPT-NOASSUME-NEXT:   ret i32 %[[DIV]]
+//
+// CHECK-OPT-LABEL: @_Z12divide_by_32i
+// CHECK-OPT-NEXT: entry:
+// CHECK-OPT-NEXT:   %[[CMP:.*]] = icmp sgt i32 %x, -1
+// CHECK-OPT-NEXT:   tail call void @llvm.assume(i1 %[[CMP]])
+// CHECK-OPT-NEXT:   %[[DIV:.*]] = lshr i32 %x, 5
+// CHECK-OPT-NEXT:   ret i32 %[[DIV]]
+//
+int divide_by_32(int x) {
+#ifdef USE_ASSUME
+[[assume(x >= 0)]];
+#endif
+return x/32;
+}
+
+// CHECK-LABEL: @_Z9incrementi
+// CHECK-NEXT: entry:
+// CHECK-NEXT:   %[[VAR:.*]] = alloca i32, align 4
+// CHECK-NEXT:   store i32 %y, ptr %[[VAR]], align 4
+// CHECK-NEXT:   %0 = load i32, ptr %[[VAR]], align 4
+// CHECK-NEXT:   %[[VARP1:.*]] = add nsw i32 %0, 1
+// CHECK-NEXT:   store i32 %[[VARP1]], ptr %[[VAR]], align 4
+// CHECK-NEXT:   %[[CMP:.*]] = icmp eq i32 %[[VARP1]], 43
+// CHECK-NEXT:   call void @llvm.assume(i1 %[[CMP]])
+// CHECK-NEXT:   %1 = load i32, ptr %[[VAR]], align 4
+// CHECK-NEXT:   ret i32 %1
+//
+// CHECK-OPT-NOASSUME-LABEL: @_Z9incrementi
+// CHECK-OPT-NOASSUME-NEXT: entry:
+// CHECK-OPT-NOASSUME-NEXT:   ret i32 %y
+//
+// CHECK-OPT-LABEL: @_Z9incrementi
+// CHECK-OPT-NEXT: entry:
+// CHECK-OPT-NEXT:   %[[CMP:.*]] = icmp eq i32 %y, 42
+// CHECK-OPT-NEXT:   tail call void @llvm.assume(i1 %[[CMP]])
+// CHECK-OPT-NEXT:   ret i32 43
+//
+int increment(int y) {
+#ifdef USE_ASSUME
+[[assume(++y == 43)]];
+#endif
+return y;
+}
Index: clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.assume/p1.cpp
===
--- /dev/null
+++ clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.assume/p1.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -fsyntax-only -Wunused -std=c++2b -verify %s
+
+int divide_by_32(int x) {
+[[assume(x >= 0)]];
+return x/32;
+}
+
+int increment(int y) {
+[[assume(++y == 43)]];
+return y;
+}
+
+[[assume(true)]] int incorrects(int y) { // expected-error {{'assume' attribute cannot be applied to a declaration}}
+[[assume(++y == 43)]] int x = 0; // expected-error {{'assume' attribute cannot be applied to a declaration}}
+[[assume(++y == 43)]] x = 0; // expected-error {{'assume' attribute only applies to empty statements}}
+[[assume(++y == 43 && ++y == 44)]];
+[[assume(++y == 43, ++y == 43)]]; // expected-error {{'assume' attribute takes one argument}}
+[[assume]]; // expected-error {{'assume' attribute takes one argument}}
+return y;
+}
Index: clang/test/AST/ast-dump-attr.cpp
===
--- clang/test/AST/ast-dump-attr.cpp
+++ clang/test/AST/ast-dump-attr.cpp
@@ -259,3 +259,14 @@
 // CHECK-NEXT: AnnotateAttr{{.*}} Inherited
 // CHECK-NEXT: UnusedAttr
 // CHECK-NEXT: NoThreadSafetyAnalysisAttr
+
+namespace TestAssume {
+  in

[PATCH] D144334: [Clang] Add C++2b attribute [[assume(expression)]]

2023-02-18 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron created this revision.
Izaron added reviewers: clang-language-wg, aaron.ballman, rsmith, nikic.
Herald added a subscriber: StephenFan.
Herald added a project: All.
Izaron requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Clang already supports assumes for optimizing. Now it is standardized
in C++2b via a new attribute - https://wg21.link/p1774r8.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D144334

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/include/clang/Basic/DiagnosticSemaKinds.td
  clang/lib/CodeGen/CGStmt.cpp
  clang/lib/Sema/SemaStmtAttr.cpp
  clang/test/AST/ast-dump-attr.cpp
  clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.assume/p1.cpp
  clang/test/CodeGenCXX/cxx2b-assume.cpp
  clang/www/cxx_status.html

Index: clang/www/cxx_status.html
===
--- clang/www/cxx_status.html
+++ clang/www/cxx_status.html
@@ -1501,7 +1501,7 @@
 
   Portable assumptions
   https://wg21.link/P1774R8";>P1774R8
-  No
+  Clang 17
 
 
   Support for UTF-8 as a portable source file encoding
Index: clang/test/CodeGenCXX/cxx2b-assume.cpp
===
--- /dev/null
+++ clang/test/CodeGenCXX/cxx2b-assume.cpp
@@ -0,0 +1,62 @@
+// RUN: %clang_cc1 -std=c++2b %s -emit-llvm -o - -triple x86_64-linux-gnu -disable-llvm-passes -DUSE_ASSUME | FileCheck %s
+// RUN: %clang_cc1 -std=c++2b %s -emit-llvm -o - -triple x86_64-linux-gnu -O3 | FileCheck --check-prefixes=CHECK-OPT-NOASSUME %s
+// RUN: %clang_cc1 -std=c++2b %s -emit-llvm -o - -triple x86_64-linux-gnu -O3 -DUSE_ASSUME | FileCheck --check-prefixes=CHECK-OPT %s
+
+// CHECK-LABEL: @_Z12divide_by_32i
+// CHECK-NEXT: entry:
+// CHECK-NEXT:   %[[VAR:.*]] = alloca i32, align 4
+// CHECK-NEXT:   store i32 %x, ptr %[[VAR]], align 4
+// CHECK-NEXT:   %0 = load i32, ptr %[[VAR]], align 4
+// CHECK-NEXT:   %[[CMP:.*]] = icmp sge i32 %0, 0
+// CHECK-NEXT:   call void @llvm.assume(i1 %[[CMP]])
+// CHECK-NEXT:   %1 = load i32, ptr %[[VAR]], align 4
+// CHECK-NEXT:   %[[DIV:.*]] = sdiv i32 %1, 32
+// CHECK-NEXT:   ret i32 %[[DIV]]
+//
+// CHECK-OPT-NOASSUME-LABEL: @_Z12divide_by_32i
+// CHECK-OPT-NOASSUME-NEXT: entry:
+// CHECK-OPT-NOASSUME-NEXT:   %[[DIV:.*]] = sdiv i32 %x, 32
+// CHECK-OPT-NOASSUME-NEXT:   ret i32 %[[DIV]]
+//
+// CHECK-OPT-LABEL: @_Z12divide_by_32i
+// CHECK-OPT-NEXT: entry:
+// CHECK-OPT-NEXT:   %[[CMP:.*]] = icmp sgt i32 %x, -1
+// CHECK-OPT-NEXT:   tail call void @llvm.assume(i1 %[[CMP]])
+// CHECK-OPT-NEXT:   %[[DIV:.*]] = lshr i32 %x, 5
+// CHECK-OPT-NEXT:   ret i32 %[[DIV]]
+//
+int divide_by_32(int x) {
+#ifdef USE_ASSUME
+[[assume(x >= 0)]];
+#endif
+return x/32;
+}
+
+// CHECK-LABEL: @_Z9incrementi
+// CHECK-NEXT: entry:
+// CHECK-NEXT:   %[[VAR:.*]] = alloca i32, align 4
+// CHECK-NEXT:   store i32 %y, ptr %[[VAR]], align 4
+// CHECK-NEXT:   %0 = load i32, ptr %[[VAR]], align 4
+// CHECK-NEXT:   %[[VARP1:.*]] = add nsw i32 %0, 1
+// CHECK-NEXT:   store i32 %[[VARP1]], ptr %[[VAR]], align 4
+// CHECK-NEXT:   %[[CMP:.*]] = icmp eq i32 %[[VARP1]], 43
+// CHECK-NEXT:   call void @llvm.assume(i1 %[[CMP]])
+// CHECK-NEXT:   %1 = load i32, ptr %[[VAR]], align 4
+// CHECK-NEXT:   ret i32 %1
+//
+// CHECK-OPT-NOASSUME-LABEL: @_Z9incrementi
+// CHECK-OPT-NOASSUME-NEXT: entry:
+// CHECK-OPT-NOASSUME-NEXT:   ret i32 %y
+//
+// CHECK-OPT-LABEL: @_Z9incrementi
+// CHECK-OPT-NEXT: entry:
+// CHECK-OPT-NEXT:   %[[CMP:.*]] = icmp eq i32 %y, 42
+// CHECK-OPT-NEXT:   tail call void @llvm.assume(i1 %[[CMP]])
+// CHECK-OPT-NEXT:   ret i32 43
+//
+int increment(int y) {
+#ifdef USE_ASSUME
+[[assume(++y == 43)]];
+#endif
+return y;
+}
Index: clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.assume/p1.cpp
===
--- /dev/null
+++ clang/test/CXX/dcl.dcl/dcl.attr/dcl.attr.assume/p1.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -fsyntax-only -Wunused -std=c++2b -verify %s
+
+int divide_by_32(int x) {
+[[assume(x >= 0)]];
+return x/32;
+}
+
+int increment(int y) {
+[[assume(++y == 43)]];
+return y;
+}
+
+[[assume(true)]] int incorrects(int y) { // expected-error {{'assume' attribute cannot be applied to a declaration}}
+[[assume(++y == 43)]] int x = 0; // expected-error {{'assume' attribute cannot be applied to a declaration}}
+[[assume(++y == 43)]] x = 0; // expected-error {{'assume' attribute only applies to empty statements}}
+[[assume(++y == 43 && ++y == 44)]];
+[[assume(++y == 43, ++y == 43)]]; // expected-error {{'assume' attribute takes one argument}}
+[[assume]]; // expected-error {{'assume' attribute takes one argument}}
+return y;
+}
Index: clang/test/AST/ast-dump-attr.cpp
===

[PATCH] D118743: [clang-tidy] Add `modernize-use-inline-const-variables-in-headers` check

2023-01-01 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added a comment.

In D118743#3965423 , @Lounarok wrote:

> I tried this patch and it's really helpful!

You're welcome!

> According to this ,  "A 
> `constexpr` specifier used in a function or `static` data member (since 
> C++17) declaration implies `inline`."

That's correct, for //functions// and //static data members//.

> However I found that it warns when it comes to `constexpr static` variable.
>
> Snippet: `constexpr static int UNDEFINED_ERROR{0};`
> Warning msg: `warning: global constant 'UNDEFINED_ERROR' should be marked as 
> 'inline' [modernize-use-inline-const-variables-in-headers]`
> According to this ,  "A 
> `constexpr` specifier used in a function or `static` data member (since 
> C++17) declaration implies `inline`." 
> It seems it should not warn on `constexpr static` variable.

`UNDEFINED_ERROR` is neither a //function// nor a //static data member//. 
Therefore a warning is meaningful. There is no `inline` implication in your 
case.

(//data member// is a variable inside a struct/class, but not a "freestanding" 
one)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D118743

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


[PATCH] D136568: [Clang] Support constexpr builtin ilogb

2022-10-27 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added inline comments.



Comment at: clang/lib/AST/ExprConstant.cpp:12452
+int Ilogb;
+if (APFloat::opStatus St = ilogb(F, Ilogb); !isConstantOpStatus(St))
+  return false;

hubert.reinterpretcast wrote:
> hubert.reinterpretcast wrote:
> > hubert.reinterpretcast wrote:
> > > Izaron wrote:
> > > > majnemer wrote:
> > > > > Izaron wrote:
> > > > > > jcranmer-intel wrote:
> > > > > > > Izaron wrote:
> > > > > > > > aaron.ballman wrote:
> > > > > > > > > jcranmer-intel wrote:
> > > > > > > > > > `long double` is `ppc_fp128` on at least some PPC targets, 
> > > > > > > > > > and while I'm not entirely certain of what `ilogb` properly 
> > > > > > > > > > returns in the corner cases of the `ppc_fp128`, I'm not 
> > > > > > > > > > entirely confident that the implementation of `APFloat` is 
> > > > > > > > > > correct in those cases. I'd like someone with PPC 
> > > > > > > > > > background to comment in here.
> > > > > > > > > Paging @hubert.reinterpretcast for help finding a good person 
> > > > > > > > > to comment on the PPC questions.
> > > > > > > > @jcranmer-intel constexpr evaluation is quite 
> > > > > > > > machine-/target-independent. Clang evaluates it based on its 
> > > > > > > > **internal** representation of float variables.
> > > > > > > > 
> > > > > > > > [[ 
> > > > > > > > https://github.com/llvm/llvm-project/blob/2e5bf4da99a2f8d3d4bb4f1a4d1ed968a01e8f02/llvm/include/llvm/ADT/APFloat.h#L1256
> > > > > > > >  | int ilogb ]] uses `Arg.getIEEE()`, that [[ 
> > > > > > > > https://github.com/llvm/llvm-project/blob/2e5bf4da99a2f8d3d4bb4f1a4d1ed968a01e8f02/llvm/include/llvm/ADT/APFloat.h#L819-L825
> > > > > > > >  | returns Clang's internal float representation ]].
> > > > > > > > 
> > > > > > > > Whichever float semantics is being used, [[ 
> > > > > > > > https://github.com/llvm/llvm-project/blob/2e5bf4da99a2f8d3d4bb4f1a4d1ed968a01e8f02/llvm/lib/Support/APFloat.cpp#L54-L61
> > > > > > > >  | minExponent and maxExponent are representable as 
> > > > > > > > APFloatBase::ExponentType ]], which is `int32_t`:
> > > > > > > > ```
> > > > > > > > /// A signed type to represent a floating point numbers 
> > > > > > > > unbiased exponent.
> > > > > > > > typedef int32_t ExponentType;
> > > > > > > > ```
> > > > > > > > 
> > > > > > > > We already use `int ilogb` in some constexpr evaluation code: 
> > > > > > > > [[ 
> > > > > > > > https://github.com/llvm/llvm-project/blob/2e5bf4da99a2f8d3d4bb4f1a4d1ed968a01e8f02/clang/lib/AST/ExprConstant.cpp#L14592
> > > > > > > >  | link ]], it is working correct because it is working on 
> > > > > > > > Clang's float representations.
> > > > > > > > We already use `int ilogb` in some constexpr evaluation code: 
> > > > > > > > [[ 
> > > > > > > > https://github.com/llvm/llvm-project/blob/2e5bf4da99a2f8d3d4bb4f1a4d1ed968a01e8f02/clang/lib/AST/ExprConstant.cpp#L14592
> > > > > > > >  | link ]], it is working correct because it is working on 
> > > > > > > > Clang's float representations.
> > > > > > > 
> > > > > > > `APFloat::getIEEE()`, if I'm following it correctly, only returns 
> > > > > > > the details of the high double in `ppc_fp128` floats, and I'm not 
> > > > > > > sufficiently well-versed in the `ppc_fp128` format to establish 
> > > > > > > whether or not the low double comes into play here. glibc seems 
> > > > > > > to think that the low double comes into play in at least one 
> > > > > > > case: 
> > > > > > > https://github.com/bminor/glibc/blob/30891f35fa7da832b66d80d0807610df361851f3/sysdeps/ieee754/ldbl-128ibm/e_ilogbl.c
> > > > > > Thanks for the link to the glibc code! It helped me to understand 
> > > > > > the IEEE754 standard better.
> > > > > > 
> > > > > > I did some research and it seems like AST supports a fixed set of 
> > > > > > float types, each working good with `ilogb`:
> > > > > > ```
> > > > > > half (__fp16, only for OpenCL), float16, float, double, long 
> > > > > > double, float128
> > > > > > ```
> > > > > > [[ 
> > > > > > https://github.com/llvm/llvm-project/blob/7846d590033e8d661198f4c00f56f46a4993c526/clang/lib/Sema/SemaExpr.cpp#L3911-L3931
> > > > > >  | link to SemaExpr.cpp ]]
> > > > > > 
> > > > > > It means that the constant evaluator doesn't deal with other float 
> > > > > > types including `ppc_fp128`.
> > > > > > If `ppc_fp128` was supported on the AST level, it would anyway come 
> > > > > > through type casting, and `__builtin_ilog` would deal with 
> > > > > > a value of a known type.
> > > > > > 
> > > > > > I checked the list of builtins - each builtin argument of float 
> > > > > > type also supports only common float types:
> > > > > > [[ 
> > > > > > https://github.com/llvm/llvm-project/blob/7846d590033e8d661198f4c00f56f46a4993c526/clang/include/clang/Basic/Builtins.def#L27-L31
> > > > > >  | link to Builtins.def 1 ]]
> > > > > > [[ 
> > > > > > https://github.com/llvm/llvm-project/blob/7846d590033e8d661198f4c00f56f46a4993c526/clang/include/clang/Basic/Built

[PATCH] D136568: [Clang] Support constexpr builtin ilogb

2022-10-27 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added inline comments.



Comment at: clang/lib/AST/ExprConstant.cpp:12452
+int Ilogb;
+if (APFloat::opStatus St = ilogb(F, Ilogb); !isConstantOpStatus(St))
+  return false;

majnemer wrote:
> Izaron wrote:
> > jcranmer-intel wrote:
> > > Izaron wrote:
> > > > aaron.ballman wrote:
> > > > > jcranmer-intel wrote:
> > > > > > `long double` is `ppc_fp128` on at least some PPC targets, and 
> > > > > > while I'm not entirely certain of what `ilogb` properly returns in 
> > > > > > the corner cases of the `ppc_fp128`, I'm not entirely confident 
> > > > > > that the implementation of `APFloat` is correct in those cases. I'd 
> > > > > > like someone with PPC background to comment in here.
> > > > > Paging @hubert.reinterpretcast for help finding a good person to 
> > > > > comment on the PPC questions.
> > > > @jcranmer-intel constexpr evaluation is quite 
> > > > machine-/target-independent. Clang evaluates it based on its 
> > > > **internal** representation of float variables.
> > > > 
> > > > [[ 
> > > > https://github.com/llvm/llvm-project/blob/2e5bf4da99a2f8d3d4bb4f1a4d1ed968a01e8f02/llvm/include/llvm/ADT/APFloat.h#L1256
> > > >  | int ilogb ]] uses `Arg.getIEEE()`, that [[ 
> > > > https://github.com/llvm/llvm-project/blob/2e5bf4da99a2f8d3d4bb4f1a4d1ed968a01e8f02/llvm/include/llvm/ADT/APFloat.h#L819-L825
> > > >  | returns Clang's internal float representation ]].
> > > > 
> > > > Whichever float semantics is being used, [[ 
> > > > https://github.com/llvm/llvm-project/blob/2e5bf4da99a2f8d3d4bb4f1a4d1ed968a01e8f02/llvm/lib/Support/APFloat.cpp#L54-L61
> > > >  | minExponent and maxExponent are representable as 
> > > > APFloatBase::ExponentType ]], which is `int32_t`:
> > > > ```
> > > > /// A signed type to represent a floating point numbers unbiased 
> > > > exponent.
> > > > typedef int32_t ExponentType;
> > > > ```
> > > > 
> > > > We already use `int ilogb` in some constexpr evaluation code: [[ 
> > > > https://github.com/llvm/llvm-project/blob/2e5bf4da99a2f8d3d4bb4f1a4d1ed968a01e8f02/clang/lib/AST/ExprConstant.cpp#L14592
> > > >  | link ]], it is working correct because it is working on Clang's 
> > > > float representations.
> > > > We already use `int ilogb` in some constexpr evaluation code: [[ 
> > > > https://github.com/llvm/llvm-project/blob/2e5bf4da99a2f8d3d4bb4f1a4d1ed968a01e8f02/clang/lib/AST/ExprConstant.cpp#L14592
> > > >  | link ]], it is working correct because it is working on Clang's 
> > > > float representations.
> > > 
> > > `APFloat::getIEEE()`, if I'm following it correctly, only returns the 
> > > details of the high double in `ppc_fp128` floats, and I'm not 
> > > sufficiently well-versed in the `ppc_fp128` format to establish whether 
> > > or not the low double comes into play here. glibc seems to think that the 
> > > low double comes into play in at least one case: 
> > > https://github.com/bminor/glibc/blob/30891f35fa7da832b66d80d0807610df361851f3/sysdeps/ieee754/ldbl-128ibm/e_ilogbl.c
> > Thanks for the link to the glibc code! It helped me to understand the 
> > IEEE754 standard better.
> > 
> > I did some research and it seems like AST supports a fixed set of float 
> > types, each working good with `ilogb`:
> > ```
> > half (__fp16, only for OpenCL), float16, float, double, long double, 
> > float128
> > ```
> > [[ 
> > https://github.com/llvm/llvm-project/blob/7846d590033e8d661198f4c00f56f46a4993c526/clang/lib/Sema/SemaExpr.cpp#L3911-L3931
> >  | link to SemaExpr.cpp ]]
> > 
> > It means that the constant evaluator doesn't deal with other float types 
> > including `ppc_fp128`.
> > If `ppc_fp128` was supported on the AST level, it would anyway come through 
> > type casting, and `__builtin_ilog` would deal with a value of a 
> > known type.
> > 
> > I checked the list of builtins - each builtin argument of float type also 
> > supports only common float types:
> > [[ 
> > https://github.com/llvm/llvm-project/blob/7846d590033e8d661198f4c00f56f46a4993c526/clang/include/clang/Basic/Builtins.def#L27-L31
> >  | link to Builtins.def 1 ]]
> > [[ 
> > https://github.com/llvm/llvm-project/blob/7846d590033e8d661198f4c00f56f46a4993c526/clang/include/clang/Basic/Builtins.def#L53-L54
> >  | link to Builtins.def 2 ]]
> Won't long double map to ppc_fp128 for some targets?
Hi! It will map, but only **after** all the constant (constexpr) calculations 
are done (that is, after the AST parsing stage) - in the Codegen stage.

The Clang's constant evaluator itself never deals with ppc_fp128 and doesn't 
care about the target.
While parsing the AST, the constant evaluator works on the same level with it, 
providing calculated values to the AST being built on-the-fly. At the moment 
AST is built, constant evaluation is over.
The evaluator is target-independent and uses the internal representation for 
`long double`, in the form of emulated **80-bit (x86) format**.

The Codegen can map the AST's `long double` to `ppc_fp128` on some targets.
I

[PATCH] D136568: [Clang] Support constexpr builtin ilogb

2022-10-27 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 471101.
Izaron added a comment.

Deal with MSVC where sizeof(long double) == sizeof(double)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136568

Files:
  clang/docs/LanguageExtensions.rst
  clang/include/clang/Basic/Builtins.def
  clang/lib/AST/ExprConstant.cpp
  clang/test/Sema/constant-builtins-ilogb.cpp
  llvm/include/llvm/ADT/APFloat.h
  llvm/lib/Support/APFloat.cpp
  llvm/unittests/ADT/APFloatTest.cpp

Index: llvm/unittests/ADT/APFloatTest.cpp
===
--- llvm/unittests/ADT/APFloatTest.cpp
+++ llvm/unittests/ADT/APFloatTest.cpp
@@ -3250,46 +3250,99 @@
 }
 
 TEST(APFloatTest, ilogb) {
-  EXPECT_EQ(-1074, ilogb(APFloat::getSmallest(APFloat::IEEEdouble(), false)));
-  EXPECT_EQ(-1074, ilogb(APFloat::getSmallest(APFloat::IEEEdouble(), true)));
-  EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble(), "0x1.ep-1024")));
-  EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble(), "0x1.ep-1023")));
-  EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble(), "-0x1.ep-1023")));
-  EXPECT_EQ(-51, ilogb(APFloat(APFloat::IEEEdouble(), "0x1p-51")));
-  EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble(), "0x1.c60f120d9f87cp-1023")));
-  EXPECT_EQ(-2, ilogb(APFloat(APFloat::IEEEdouble(), "0x0.p-1")));
-  EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble(), "0x1.fffep-1023")));
-  EXPECT_EQ(1023, ilogb(APFloat::getLargest(APFloat::IEEEdouble(), false)));
-  EXPECT_EQ(1023, ilogb(APFloat::getLargest(APFloat::IEEEdouble(), true)));
-
-
-  EXPECT_EQ(0, ilogb(APFloat(APFloat::IEEEsingle(), "0x1p+0")));
-  EXPECT_EQ(0, ilogb(APFloat(APFloat::IEEEsingle(), "-0x1p+0")));
-  EXPECT_EQ(42, ilogb(APFloat(APFloat::IEEEsingle(), "0x1p+42")));
-  EXPECT_EQ(-42, ilogb(APFloat(APFloat::IEEEsingle(), "0x1p-42")));
-
-  EXPECT_EQ(APFloat::IEK_Inf,
-ilogb(APFloat::getInf(APFloat::IEEEsingle(), false)));
-  EXPECT_EQ(APFloat::IEK_Inf,
-ilogb(APFloat::getInf(APFloat::IEEEsingle(), true)));
-  EXPECT_EQ(APFloat::IEK_Zero,
-ilogb(APFloat::getZero(APFloat::IEEEsingle(), false)));
-  EXPECT_EQ(APFloat::IEK_Zero,
-ilogb(APFloat::getZero(APFloat::IEEEsingle(), true)));
-  EXPECT_EQ(APFloat::IEK_NaN,
-ilogb(APFloat::getNaN(APFloat::IEEEsingle(), false)));
-  EXPECT_EQ(APFloat::IEK_NaN,
-ilogb(APFloat::getSNaN(APFloat::IEEEsingle(), false)));
-
-  EXPECT_EQ(127, ilogb(APFloat::getLargest(APFloat::IEEEsingle(), false)));
-  EXPECT_EQ(127, ilogb(APFloat::getLargest(APFloat::IEEEsingle(), true)));
-
-  EXPECT_EQ(-149, ilogb(APFloat::getSmallest(APFloat::IEEEsingle(), false)));
-  EXPECT_EQ(-149, ilogb(APFloat::getSmallest(APFloat::IEEEsingle(), true)));
-  EXPECT_EQ(-126,
-ilogb(APFloat::getSmallestNormalized(APFloat::IEEEsingle(), false)));
-  EXPECT_EQ(-126,
-ilogb(APFloat::getSmallestNormalized(APFloat::IEEEsingle(), true)));
+  int Result;
+
+  EXPECT_EQ(ilogb(APFloat::getSmallest(APFloat::IEEEdouble(), false), Result),
+APFloat::opOK);
+  EXPECT_EQ(-1074, Result);
+  EXPECT_EQ(ilogb(APFloat::getSmallest(APFloat::IEEEdouble(), true), Result),
+APFloat::opOK);
+  EXPECT_EQ(-1074, Result);
+  EXPECT_EQ(
+  ilogb(APFloat(APFloat::IEEEdouble(), "0x1.ep-1024"), Result),
+  APFloat::opOK);
+  EXPECT_EQ(-1023, Result);
+  EXPECT_EQ(
+  ilogb(APFloat(APFloat::IEEEdouble(), "0x1.ep-1023"), Result),
+  APFloat::opOK);
+  EXPECT_EQ(-1023, Result);
+  EXPECT_EQ(
+  ilogb(APFloat(APFloat::IEEEdouble(), "-0x1.ep-1023"), Result),
+  APFloat::opOK);
+  EXPECT_EQ(-1023, Result);
+  EXPECT_EQ(ilogb(APFloat(APFloat::IEEEdouble(), "0x1p-51"), Result),
+APFloat::opOK);
+  EXPECT_EQ(-51, Result);
+  EXPECT_EQ(
+  ilogb(APFloat(APFloat::IEEEdouble(), "0x1.c60f120d9f87cp-1023"), Result),
+  APFloat::opOK);
+  EXPECT_EQ(-1023, Result);
+  EXPECT_EQ(ilogb(APFloat(APFloat::IEEEdouble(), "0x0.p-1"), Result),
+APFloat::opOK);
+  EXPECT_EQ(-2, Result);
+  EXPECT_EQ(ilogb(APFloat(APFloat::IEEEdouble(), "0x1.fffep-1023"), Result),
+APFloat::opOK);
+  EXPECT_EQ(-1023, Result);
+  EXPECT_EQ(ilogb(APFloat::getLargest(APFloat::IEEEdouble(), false), Result),
+APFloat::opOK);
+  EXPECT_EQ(1023, Result);
+  EXPECT_EQ(ilogb(APFloat::getLargest(APFloat::IEEEdouble(), true), Result),
+APFloat::opOK);
+  EXPECT_EQ(1023, Result);
+
+  EXPECT_EQ(ilogb(APFloat(APFloat::IEEEsingle(), "0x1p+0"), Result),
+APFloat::opOK);
+  EXPECT_EQ(0, Result);
+  EXPECT_EQ(ilogb(APFloat(APFloat::IEEEsingle(), "-0x1p+0"), Result),
+APFloat::opOK);
+  EXPECT_EQ(0, Result);
+  EXPECT_EQ(ilogb(APFloat(APFloat::IEEEsingle(), "0x1p+42"), Result),
+APFloat::opOK);
+  EXPECT_EQ(42, Result);
+  EXPECT_EQ(ilogb(APFl

[PATCH] D136568: [Clang] Support constexpr builtin ilogb

2022-10-26 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron marked 2 inline comments as done.
Izaron added inline comments.



Comment at: clang/lib/AST/ExprConstant.cpp:12452
+int Ilogb;
+if (APFloat::opStatus St = ilogb(F, Ilogb); !isConstantOpStatus(St))
+  return false;

jcranmer-intel wrote:
> Izaron wrote:
> > aaron.ballman wrote:
> > > jcranmer-intel wrote:
> > > > `long double` is `ppc_fp128` on at least some PPC targets, and while 
> > > > I'm not entirely certain of what `ilogb` properly returns in the corner 
> > > > cases of the `ppc_fp128`, I'm not entirely confident that the 
> > > > implementation of `APFloat` is correct in those cases. I'd like someone 
> > > > with PPC background to comment in here.
> > > Paging @hubert.reinterpretcast for help finding a good person to comment 
> > > on the PPC questions.
> > @jcranmer-intel constexpr evaluation is quite machine-/target-independent. 
> > Clang evaluates it based on its **internal** representation of float 
> > variables.
> > 
> > [[ 
> > https://github.com/llvm/llvm-project/blob/2e5bf4da99a2f8d3d4bb4f1a4d1ed968a01e8f02/llvm/include/llvm/ADT/APFloat.h#L1256
> >  | int ilogb ]] uses `Arg.getIEEE()`, that [[ 
> > https://github.com/llvm/llvm-project/blob/2e5bf4da99a2f8d3d4bb4f1a4d1ed968a01e8f02/llvm/include/llvm/ADT/APFloat.h#L819-L825
> >  | returns Clang's internal float representation ]].
> > 
> > Whichever float semantics is being used, [[ 
> > https://github.com/llvm/llvm-project/blob/2e5bf4da99a2f8d3d4bb4f1a4d1ed968a01e8f02/llvm/lib/Support/APFloat.cpp#L54-L61
> >  | minExponent and maxExponent are representable as 
> > APFloatBase::ExponentType ]], which is `int32_t`:
> > ```
> > /// A signed type to represent a floating point numbers unbiased exponent.
> > typedef int32_t ExponentType;
> > ```
> > 
> > We already use `int ilogb` in some constexpr evaluation code: [[ 
> > https://github.com/llvm/llvm-project/blob/2e5bf4da99a2f8d3d4bb4f1a4d1ed968a01e8f02/clang/lib/AST/ExprConstant.cpp#L14592
> >  | link ]], it is working correct because it is working on Clang's float 
> > representations.
> > We already use `int ilogb` in some constexpr evaluation code: [[ 
> > https://github.com/llvm/llvm-project/blob/2e5bf4da99a2f8d3d4bb4f1a4d1ed968a01e8f02/clang/lib/AST/ExprConstant.cpp#L14592
> >  | link ]], it is working correct because it is working on Clang's float 
> > representations.
> 
> `APFloat::getIEEE()`, if I'm following it correctly, only returns the details 
> of the high double in `ppc_fp128` floats, and I'm not sufficiently 
> well-versed in the `ppc_fp128` format to establish whether or not the low 
> double comes into play here. glibc seems to think that the low double comes 
> into play in at least one case: 
> https://github.com/bminor/glibc/blob/30891f35fa7da832b66d80d0807610df361851f3/sysdeps/ieee754/ldbl-128ibm/e_ilogbl.c
Thanks for the link to the glibc code! It helped me to understand the IEEE754 
standard better.

I did some research and it seems like AST supports a fixed set of float types, 
each working good with `ilogb`:
```
half (__fp16, only for OpenCL), float16, float, double, long double, float128
```
[[ 
https://github.com/llvm/llvm-project/blob/7846d590033e8d661198f4c00f56f46a4993c526/clang/lib/Sema/SemaExpr.cpp#L3911-L3931
 | link to SemaExpr.cpp ]]

It means that the constant evaluator doesn't deal with other float types 
including `ppc_fp128`.
If `ppc_fp128` was supported on the AST level, it would anyway come through 
type casting, and `__builtin_ilog` would deal with a value of a known 
type.

I checked the list of builtins - each builtin argument of float type also 
supports only common float types:
[[ 
https://github.com/llvm/llvm-project/blob/7846d590033e8d661198f4c00f56f46a4993c526/clang/include/clang/Basic/Builtins.def#L27-L31
 | link to Builtins.def 1 ]]
[[ 
https://github.com/llvm/llvm-project/blob/7846d590033e8d661198f4c00f56f46a4993c526/clang/include/clang/Basic/Builtins.def#L53-L54
 | link to Builtins.def 2 ]]


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136568

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


[PATCH] D136568: [Clang] Support constexpr builtin ilogb

2022-10-26 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 470962.
Izaron added a comment.

Add test for min/max value. Fix comment for ilog.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136568

Files:
  clang/docs/LanguageExtensions.rst
  clang/include/clang/Basic/Builtins.def
  clang/lib/AST/ExprConstant.cpp
  clang/test/Sema/constant-builtins-ilogb.cpp
  llvm/include/llvm/ADT/APFloat.h
  llvm/lib/Support/APFloat.cpp
  llvm/unittests/ADT/APFloatTest.cpp

Index: llvm/unittests/ADT/APFloatTest.cpp
===
--- llvm/unittests/ADT/APFloatTest.cpp
+++ llvm/unittests/ADT/APFloatTest.cpp
@@ -3250,46 +3250,99 @@
 }
 
 TEST(APFloatTest, ilogb) {
-  EXPECT_EQ(-1074, ilogb(APFloat::getSmallest(APFloat::IEEEdouble(), false)));
-  EXPECT_EQ(-1074, ilogb(APFloat::getSmallest(APFloat::IEEEdouble(), true)));
-  EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble(), "0x1.ep-1024")));
-  EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble(), "0x1.ep-1023")));
-  EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble(), "-0x1.ep-1023")));
-  EXPECT_EQ(-51, ilogb(APFloat(APFloat::IEEEdouble(), "0x1p-51")));
-  EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble(), "0x1.c60f120d9f87cp-1023")));
-  EXPECT_EQ(-2, ilogb(APFloat(APFloat::IEEEdouble(), "0x0.p-1")));
-  EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble(), "0x1.fffep-1023")));
-  EXPECT_EQ(1023, ilogb(APFloat::getLargest(APFloat::IEEEdouble(), false)));
-  EXPECT_EQ(1023, ilogb(APFloat::getLargest(APFloat::IEEEdouble(), true)));
-
-
-  EXPECT_EQ(0, ilogb(APFloat(APFloat::IEEEsingle(), "0x1p+0")));
-  EXPECT_EQ(0, ilogb(APFloat(APFloat::IEEEsingle(), "-0x1p+0")));
-  EXPECT_EQ(42, ilogb(APFloat(APFloat::IEEEsingle(), "0x1p+42")));
-  EXPECT_EQ(-42, ilogb(APFloat(APFloat::IEEEsingle(), "0x1p-42")));
-
-  EXPECT_EQ(APFloat::IEK_Inf,
-ilogb(APFloat::getInf(APFloat::IEEEsingle(), false)));
-  EXPECT_EQ(APFloat::IEK_Inf,
-ilogb(APFloat::getInf(APFloat::IEEEsingle(), true)));
-  EXPECT_EQ(APFloat::IEK_Zero,
-ilogb(APFloat::getZero(APFloat::IEEEsingle(), false)));
-  EXPECT_EQ(APFloat::IEK_Zero,
-ilogb(APFloat::getZero(APFloat::IEEEsingle(), true)));
-  EXPECT_EQ(APFloat::IEK_NaN,
-ilogb(APFloat::getNaN(APFloat::IEEEsingle(), false)));
-  EXPECT_EQ(APFloat::IEK_NaN,
-ilogb(APFloat::getSNaN(APFloat::IEEEsingle(), false)));
-
-  EXPECT_EQ(127, ilogb(APFloat::getLargest(APFloat::IEEEsingle(), false)));
-  EXPECT_EQ(127, ilogb(APFloat::getLargest(APFloat::IEEEsingle(), true)));
-
-  EXPECT_EQ(-149, ilogb(APFloat::getSmallest(APFloat::IEEEsingle(), false)));
-  EXPECT_EQ(-149, ilogb(APFloat::getSmallest(APFloat::IEEEsingle(), true)));
-  EXPECT_EQ(-126,
-ilogb(APFloat::getSmallestNormalized(APFloat::IEEEsingle(), false)));
-  EXPECT_EQ(-126,
-ilogb(APFloat::getSmallestNormalized(APFloat::IEEEsingle(), true)));
+  int Result;
+
+  EXPECT_EQ(ilogb(APFloat::getSmallest(APFloat::IEEEdouble(), false), Result),
+APFloat::opOK);
+  EXPECT_EQ(-1074, Result);
+  EXPECT_EQ(ilogb(APFloat::getSmallest(APFloat::IEEEdouble(), true), Result),
+APFloat::opOK);
+  EXPECT_EQ(-1074, Result);
+  EXPECT_EQ(
+  ilogb(APFloat(APFloat::IEEEdouble(), "0x1.ep-1024"), Result),
+  APFloat::opOK);
+  EXPECT_EQ(-1023, Result);
+  EXPECT_EQ(
+  ilogb(APFloat(APFloat::IEEEdouble(), "0x1.ep-1023"), Result),
+  APFloat::opOK);
+  EXPECT_EQ(-1023, Result);
+  EXPECT_EQ(
+  ilogb(APFloat(APFloat::IEEEdouble(), "-0x1.ep-1023"), Result),
+  APFloat::opOK);
+  EXPECT_EQ(-1023, Result);
+  EXPECT_EQ(ilogb(APFloat(APFloat::IEEEdouble(), "0x1p-51"), Result),
+APFloat::opOK);
+  EXPECT_EQ(-51, Result);
+  EXPECT_EQ(
+  ilogb(APFloat(APFloat::IEEEdouble(), "0x1.c60f120d9f87cp-1023"), Result),
+  APFloat::opOK);
+  EXPECT_EQ(-1023, Result);
+  EXPECT_EQ(ilogb(APFloat(APFloat::IEEEdouble(), "0x0.p-1"), Result),
+APFloat::opOK);
+  EXPECT_EQ(-2, Result);
+  EXPECT_EQ(ilogb(APFloat(APFloat::IEEEdouble(), "0x1.fffep-1023"), Result),
+APFloat::opOK);
+  EXPECT_EQ(-1023, Result);
+  EXPECT_EQ(ilogb(APFloat::getLargest(APFloat::IEEEdouble(), false), Result),
+APFloat::opOK);
+  EXPECT_EQ(1023, Result);
+  EXPECT_EQ(ilogb(APFloat::getLargest(APFloat::IEEEdouble(), true), Result),
+APFloat::opOK);
+  EXPECT_EQ(1023, Result);
+
+  EXPECT_EQ(ilogb(APFloat(APFloat::IEEEsingle(), "0x1p+0"), Result),
+APFloat::opOK);
+  EXPECT_EQ(0, Result);
+  EXPECT_EQ(ilogb(APFloat(APFloat::IEEEsingle(), "-0x1p+0"), Result),
+APFloat::opOK);
+  EXPECT_EQ(0, Result);
+  EXPECT_EQ(ilogb(APFloat(APFloat::IEEEsingle(), "0x1p+42"), Result),
+APFloat::opOK);
+  EXPECT_EQ(42, Result);
+  EXPECT_EQ(ilogb(APFloat(APFlo

[PATCH] D136568: [Clang] Support constexpr builtin ilogb

2022-10-26 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added inline comments.



Comment at: clang/lib/AST/ExprConstant.cpp:12452
+int Ilogb;
+if (APFloat::opStatus St = ilogb(F, Ilogb); !isConstantOpStatus(St))
+  return false;

aaron.ballman wrote:
> jcranmer-intel wrote:
> > `long double` is `ppc_fp128` on at least some PPC targets, and while I'm 
> > not entirely certain of what `ilogb` properly returns in the corner cases 
> > of the `ppc_fp128`, I'm not entirely confident that the implementation of 
> > `APFloat` is correct in those cases. I'd like someone with PPC background 
> > to comment in here.
> Paging @hubert.reinterpretcast for help finding a good person to comment on 
> the PPC questions.
@jcranmer-intel constexpr evaluation is quite machine-/target-independent. 
Clang evaluates it based on its **internal** representation of float variables.

[[ 
https://github.com/llvm/llvm-project/blob/2e5bf4da99a2f8d3d4bb4f1a4d1ed968a01e8f02/llvm/include/llvm/ADT/APFloat.h#L1256
 | int ilogb ]] uses `Arg.getIEEE()`, that [[ 
https://github.com/llvm/llvm-project/blob/2e5bf4da99a2f8d3d4bb4f1a4d1ed968a01e8f02/llvm/include/llvm/ADT/APFloat.h#L819-L825
 | returns Clang's internal float representation ]].

Whichever float semantics is being used, [[ 
https://github.com/llvm/llvm-project/blob/2e5bf4da99a2f8d3d4bb4f1a4d1ed968a01e8f02/llvm/lib/Support/APFloat.cpp#L54-L61
 | minExponent and maxExponent are representable as APFloatBase::ExponentType 
]], which is `int32_t`:
```
/// A signed type to represent a floating point numbers unbiased exponent.
typedef int32_t ExponentType;
```

We already use `int ilogb` in some constexpr evaluation code: [[ 
https://github.com/llvm/llvm-project/blob/2e5bf4da99a2f8d3d4bb4f1a4d1ed968a01e8f02/clang/lib/AST/ExprConstant.cpp#L14592
 | link ]], it is working correct because it is working on Clang's float 
representations.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136568

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


[PATCH] D118743: [clang-tidy] Add `modernize-use-inline-const-variables-in-headers` check

2022-10-24 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added a comment.

A friendly ping 🙂


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D118743

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


[PATCH] D136549: [clang] Fix time profile in "isIntegerConstantExpr"

2022-10-23 Thread Evgeny Shulgin via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG2bb50a55b0f5: [clang] Fix time profile in 
"isIntegerConstantExpr" (authored by Izaron).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136549

Files:
  clang/lib/AST/ExprConstant.cpp
  clang/unittests/Support/TimeProfilerTest.cpp


Index: clang/unittests/Support/TimeProfilerTest.cpp
===
--- clang/unittests/Support/TimeProfilerTest.cpp
+++ clang/unittests/Support/TimeProfilerTest.cpp
@@ -37,14 +37,14 @@
 
 // Returns true if code compiles successfully.
 // We only parse AST here. This is enough for constexpr evaluation.
-bool compileFromString(StringRef Code) {
+bool compileFromString(StringRef Code, StringRef Standard, StringRef FileName) 
{
   CompilerInstance Compiler;
   Compiler.createDiagnostics();
 
   auto Invocation = std::make_shared();
   Invocation->getPreprocessorOpts().addRemappedFile(
-  "test.cc", MemoryBuffer::getMemBuffer(Code).release());
-  const char *Args[] = {"-std=c++20", "test.cc"};
+  FileName, MemoryBuffer::getMemBuffer(Code).release());
+  const char *Args[] = {Standard.data(), FileName.data()};
   CompilerInvocation::CreateFromArgs(*Invocation, Args,
  Compiler.getDiagnostics());
   Compiler.setInvocation(std::move(Invocation));
@@ -143,7 +143,7 @@
 
 } // namespace
 
-TEST(TimeProfilerTest, ConstantEvaluation) {
+TEST(TimeProfilerTest, ConstantEvaluationCxx20) {
   constexpr StringRef Code = R"(
 void print(double value);
 
@@ -172,7 +172,7 @@
 )";
 
   setupProfiler();
-  ASSERT_TRUE(compileFromString(Code));
+  ASSERT_TRUE(compileFromString(Code, "-std=c++20", "test.cc"));
   std::string Json = teardownProfiler();
   std::string TraceGraph = buildTraceGraph(Json);
   ASSERT_TRUE(TraceGraph == R"(
@@ -197,3 +197,25 @@
   // NOTE: If this test is failing, run this test with
   // `llvm::errs() << TraceGraph;` and change the assert above.
 }
+
+TEST(TimeProfilerTest, ConstantEvaluationC99) {
+  constexpr StringRef Code = R"(
+struct {
+  short quantval[4]; // 3rd line
+} value;
+)";
+
+  setupProfiler();
+  ASSERT_TRUE(compileFromString(Code, "-std=c99", "test.c"));
+  std::string Json = teardownProfiler();
+  std::string TraceGraph = buildTraceGraph(Json);
+  ASSERT_TRUE(TraceGraph == R"(
+Frontend
+| isIntegerConstantExpr ()
+| EvaluateKnownConstIntCheckOverflow ()
+| PerformPendingInstantiations
+)");
+
+  // NOTE: If this test is failing, run this test with
+  // `llvm::errs() << TraceGraph;` and change the assert above.
+}
Index: clang/lib/AST/ExprConstant.cpp
===
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -15905,9 +15905,7 @@
   assert(!isValueDependent() &&
  "Expression evaluator can't be called on a dependent expression.");
 
-  llvm::TimeTraceScope TimeScope("isIntegerConstantExpr", [&] {
-return Loc->printToString(Ctx.getSourceManager());
-  });
+  ExprTimeTraceScope TimeScope(this, Ctx, "isIntegerConstantExpr");
 
   if (Ctx.getLangOpts().CPlusPlus11)
 return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, nullptr, Loc);


Index: clang/unittests/Support/TimeProfilerTest.cpp
===
--- clang/unittests/Support/TimeProfilerTest.cpp
+++ clang/unittests/Support/TimeProfilerTest.cpp
@@ -37,14 +37,14 @@
 
 // Returns true if code compiles successfully.
 // We only parse AST here. This is enough for constexpr evaluation.
-bool compileFromString(StringRef Code) {
+bool compileFromString(StringRef Code, StringRef Standard, StringRef FileName) {
   CompilerInstance Compiler;
   Compiler.createDiagnostics();
 
   auto Invocation = std::make_shared();
   Invocation->getPreprocessorOpts().addRemappedFile(
-  "test.cc", MemoryBuffer::getMemBuffer(Code).release());
-  const char *Args[] = {"-std=c++20", "test.cc"};
+  FileName, MemoryBuffer::getMemBuffer(Code).release());
+  const char *Args[] = {Standard.data(), FileName.data()};
   CompilerInvocation::CreateFromArgs(*Invocation, Args,
  Compiler.getDiagnostics());
   Compiler.setInvocation(std::move(Invocation));
@@ -143,7 +143,7 @@
 
 } // namespace
 
-TEST(TimeProfilerTest, ConstantEvaluation) {
+TEST(TimeProfilerTest, ConstantEvaluationCxx20) {
   constexpr StringRef Code = R"(
 void print(double value);
 
@@ -172,7 +172,7 @@
 )";
 
   setupProfiler();
-  ASSERT_TRUE(compileFromString(Code));
+  ASSERT_TRUE(compileFromString(Code, "-std=c++20", "test.cc"));
   std::string Json = teardownProfiler();
   std::string TraceGraph = buildTraceGraph(Json);
   ASSERT_TRUE(TraceGraph == R"(
@@ -197,3 +197,25 @@
   // NOTE: If this test is failing, run this test with
   // `llvm::errs() << TraceGraph;` and change the assert above.

[PATCH] D136549: [clang] Fix time profile in "isIntegerConstantExpr"

2022-10-23 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron marked 2 inline comments as done.
Izaron added inline comments.



Comment at: clang/lib/AST/ExprConstant.cpp:15908
 
-  llvm::TimeTraceScope TimeScope("isIntegerConstantExpr", [&] {
-return Loc->printToString(Ctx.getSourceManager());
-  });
+  ExprTimeTraceScope TimeScope(this, Ctx, "isIntegerConstantExpr");
 

jloser wrote:
> **Question** This looks like the right fix for this call site.  Are the other 
> two uses of `llvm::TimeTraceScope` as a local variable subject to similar 
> problems? I don't think so since we don't try to get the location explicitly, 
> but want to confirm.
That's a good question! We use custom `llvm::TimeTraceScope` in three places:

```
isPotentialConstantExpr
EvaluateAsInitializer
EvaluateWithSubstitution
```

The problem with `isIntegerConstantExpr` (which I fixed in this patch) was that 
the `Loc` was `nullptr` (and there were no tests that would catch it).

The three functions with custom time traces use either `const VarDecl *VD` or 
`const FunctionDecl *FD`. These variables are surely not `nullptr` because the 
methods bravely use them (`VD->doSmth()`/`FD->doSmth()`).

Also our unit test covers `isPotentialConstantExpr` and `EvaluateAsInitializer` 
(you can see them in `ASSERT_TRUE`).
So I think there is no obvious problems that I can think of =)



Comment at: clang/unittests/Support/TimeProfilerTest.cpp:209
+  setupProfiler();
+  ASSERT_TRUE(compileFromString(Code, "-std=c99", "test.c"));
+  std::string Json = teardownProfiler();

jloser wrote:
> **Question** Is adding the ability to plumb the standards mode just useful 
> for this bug fix in the sense of reducing the trace graph output of the AST?
This is useful for bug fix, because some `ExprConstant.cpp` methods are called 
only for C code (not for C++ code). C and C++ have a somewhat different 
constant evaluations.

The segfault in `Expr::isIntegerConstantExpr` was only discoverable when 
compiling C code, because there is a explicit condition for calling this method 
only for C code:
https://github.com/llvm/llvm-project/blob/08d1c43c7023a2e955c43fbf4c3f1635f91521e0/clang/lib/Sema/SemaExpr.cpp#L17318


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136549

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


[PATCH] D136568: [Clang] Support constexpr builtin ilogb

2022-10-23 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added a comment.

This patch is similar to `__bultin_fmax`: https://reviews.llvm.org/D134369

The constexpr version of ilogb matches the libc realization, this is verified 
with the same tests:
https://github.com/llvm/llvm-project/blob/main/libc/test/src/math/ILogbTest.h

  test_special_numbers -> ILOGB_TEST_SPECIAL_NUMBERS
  test_powers_of_two -> ILOGB_TEST_POWERS_OF_TWO
  test_some_integers -> ILOGB_TEST_SOME_INTEGERS

https://eel.is/c++draft/library.c#3 says that a floating-point exception other 
than `FE_INEXACT` causes it to not be a constant expression.
I check it with small `ilog` function refactoring and the new function 
`isConstantOpStatus`.

The online documentation (https://en.cppreference.com/w/cpp/numeric/math/ilogb) 
says:

  1. If the correct result is greater than INT_MAX or smaller than INT_MIN, 
FE_INVALID is raised.
  2. If arg is ±0, ±∞, or NaN, FE_INVALID is raised.
  3. In all other cases, the result is exact (FE_INEXACT is never raised) and 
the current rounding mode is ignored

The first point seemingly never occur, because llvm's `ilogb` return type is 
`int`.
The second point is handled as expected (`APFloatTest.cpp` checks it)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136568

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


[PATCH] D136568: [Clang] Support constexpr builtin ilogb

2022-10-23 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron created this revision.
Izaron added reviewers: jcranmer-intel, aaron.ballman, cor3ntin, efriedma.
Herald added a subscriber: hiraditya.
Herald added a project: All.
Izaron requested review of this revision.
Herald added projects: clang, LLVM.
Herald added subscribers: llvm-commits, cfe-commits.

Support constexpr version of __builtin_ilogb and its variations.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D136568

Files:
  clang/docs/LanguageExtensions.rst
  clang/include/clang/Basic/Builtins.def
  clang/lib/AST/ExprConstant.cpp
  clang/test/Sema/constant-builtins-ilogb.cpp
  llvm/include/llvm/ADT/APFloat.h
  llvm/lib/Support/APFloat.cpp
  llvm/unittests/ADT/APFloatTest.cpp

Index: llvm/unittests/ADT/APFloatTest.cpp
===
--- llvm/unittests/ADT/APFloatTest.cpp
+++ llvm/unittests/ADT/APFloatTest.cpp
@@ -3250,46 +3250,99 @@
 }
 
 TEST(APFloatTest, ilogb) {
-  EXPECT_EQ(-1074, ilogb(APFloat::getSmallest(APFloat::IEEEdouble(), false)));
-  EXPECT_EQ(-1074, ilogb(APFloat::getSmallest(APFloat::IEEEdouble(), true)));
-  EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble(), "0x1.ep-1024")));
-  EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble(), "0x1.ep-1023")));
-  EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble(), "-0x1.ep-1023")));
-  EXPECT_EQ(-51, ilogb(APFloat(APFloat::IEEEdouble(), "0x1p-51")));
-  EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble(), "0x1.c60f120d9f87cp-1023")));
-  EXPECT_EQ(-2, ilogb(APFloat(APFloat::IEEEdouble(), "0x0.p-1")));
-  EXPECT_EQ(-1023, ilogb(APFloat(APFloat::IEEEdouble(), "0x1.fffep-1023")));
-  EXPECT_EQ(1023, ilogb(APFloat::getLargest(APFloat::IEEEdouble(), false)));
-  EXPECT_EQ(1023, ilogb(APFloat::getLargest(APFloat::IEEEdouble(), true)));
-
-
-  EXPECT_EQ(0, ilogb(APFloat(APFloat::IEEEsingle(), "0x1p+0")));
-  EXPECT_EQ(0, ilogb(APFloat(APFloat::IEEEsingle(), "-0x1p+0")));
-  EXPECT_EQ(42, ilogb(APFloat(APFloat::IEEEsingle(), "0x1p+42")));
-  EXPECT_EQ(-42, ilogb(APFloat(APFloat::IEEEsingle(), "0x1p-42")));
-
-  EXPECT_EQ(APFloat::IEK_Inf,
-ilogb(APFloat::getInf(APFloat::IEEEsingle(), false)));
-  EXPECT_EQ(APFloat::IEK_Inf,
-ilogb(APFloat::getInf(APFloat::IEEEsingle(), true)));
-  EXPECT_EQ(APFloat::IEK_Zero,
-ilogb(APFloat::getZero(APFloat::IEEEsingle(), false)));
-  EXPECT_EQ(APFloat::IEK_Zero,
-ilogb(APFloat::getZero(APFloat::IEEEsingle(), true)));
-  EXPECT_EQ(APFloat::IEK_NaN,
-ilogb(APFloat::getNaN(APFloat::IEEEsingle(), false)));
-  EXPECT_EQ(APFloat::IEK_NaN,
-ilogb(APFloat::getSNaN(APFloat::IEEEsingle(), false)));
-
-  EXPECT_EQ(127, ilogb(APFloat::getLargest(APFloat::IEEEsingle(), false)));
-  EXPECT_EQ(127, ilogb(APFloat::getLargest(APFloat::IEEEsingle(), true)));
-
-  EXPECT_EQ(-149, ilogb(APFloat::getSmallest(APFloat::IEEEsingle(), false)));
-  EXPECT_EQ(-149, ilogb(APFloat::getSmallest(APFloat::IEEEsingle(), true)));
-  EXPECT_EQ(-126,
-ilogb(APFloat::getSmallestNormalized(APFloat::IEEEsingle(), false)));
-  EXPECT_EQ(-126,
-ilogb(APFloat::getSmallestNormalized(APFloat::IEEEsingle(), true)));
+  int Result;
+
+  EXPECT_EQ(ilogb(APFloat::getSmallest(APFloat::IEEEdouble(), false), Result),
+APFloat::opOK);
+  EXPECT_EQ(-1074, Result);
+  EXPECT_EQ(ilogb(APFloat::getSmallest(APFloat::IEEEdouble(), true), Result),
+APFloat::opOK);
+  EXPECT_EQ(-1074, Result);
+  EXPECT_EQ(
+  ilogb(APFloat(APFloat::IEEEdouble(), "0x1.ep-1024"), Result),
+  APFloat::opOK);
+  EXPECT_EQ(-1023, Result);
+  EXPECT_EQ(
+  ilogb(APFloat(APFloat::IEEEdouble(), "0x1.ep-1023"), Result),
+  APFloat::opOK);
+  EXPECT_EQ(-1023, Result);
+  EXPECT_EQ(
+  ilogb(APFloat(APFloat::IEEEdouble(), "-0x1.ep-1023"), Result),
+  APFloat::opOK);
+  EXPECT_EQ(-1023, Result);
+  EXPECT_EQ(ilogb(APFloat(APFloat::IEEEdouble(), "0x1p-51"), Result),
+APFloat::opOK);
+  EXPECT_EQ(-51, Result);
+  EXPECT_EQ(
+  ilogb(APFloat(APFloat::IEEEdouble(), "0x1.c60f120d9f87cp-1023"), Result),
+  APFloat::opOK);
+  EXPECT_EQ(-1023, Result);
+  EXPECT_EQ(ilogb(APFloat(APFloat::IEEEdouble(), "0x0.p-1"), Result),
+APFloat::opOK);
+  EXPECT_EQ(-2, Result);
+  EXPECT_EQ(ilogb(APFloat(APFloat::IEEEdouble(), "0x1.fffep-1023"), Result),
+APFloat::opOK);
+  EXPECT_EQ(-1023, Result);
+  EXPECT_EQ(ilogb(APFloat::getLargest(APFloat::IEEEdouble(), false), Result),
+APFloat::opOK);
+  EXPECT_EQ(1023, Result);
+  EXPECT_EQ(ilogb(APFloat::getLargest(APFloat::IEEEdouble(), true), Result),
+APFloat::opOK);
+  EXPECT_EQ(1023, Result);
+
+  EXPECT_EQ(ilogb(APFloat(APFloat::IEEEsingle(), "0x1p+0"), Result),
+APFloat::opOK);
+  EXPECT_EQ(0, Result);
+  EXPECT_EQ(ilogb(APFloat(APFloat::IEEEsingle(), "-0x1p+0"), Result),
+APFloat::opOK);
+

[PATCH] D136549: [clang] Fix time profile in "isIntegerConstantExpr"

2022-10-23 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron created this revision.
Izaron added reviewers: dyung, aaron.ballman, jloser.
Herald added a project: All.
Izaron requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

The time profiler in `Expr::isIntegerConstantExpr` used to
call `Loc->printToString`, it was inconsistent with other time
profiles in the file and caused segfaults if `Loc` was `nullptr`.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D136549

Files:
  clang/lib/AST/ExprConstant.cpp
  clang/unittests/Support/TimeProfilerTest.cpp


Index: clang/unittests/Support/TimeProfilerTest.cpp
===
--- clang/unittests/Support/TimeProfilerTest.cpp
+++ clang/unittests/Support/TimeProfilerTest.cpp
@@ -37,14 +37,14 @@
 
 // Returns true if code compiles successfully.
 // We only parse AST here. This is enough for constexpr evaluation.
-bool compileFromString(StringRef Code) {
+bool compileFromString(StringRef Code, StringRef Standard, StringRef FileName) 
{
   CompilerInstance Compiler;
   Compiler.createDiagnostics();
 
   auto Invocation = std::make_shared();
   Invocation->getPreprocessorOpts().addRemappedFile(
-  "test.cc", MemoryBuffer::getMemBuffer(Code).release());
-  const char *Args[] = {"-std=c++20", "test.cc"};
+  FileName, MemoryBuffer::getMemBuffer(Code).release());
+  const char *Args[] = {Standard.data(), FileName.data()};
   CompilerInvocation::CreateFromArgs(*Invocation, Args,
  Compiler.getDiagnostics());
   Compiler.setInvocation(std::move(Invocation));
@@ -143,7 +143,7 @@
 
 } // namespace
 
-TEST(TimeProfilerTest, ConstantEvaluation) {
+TEST(TimeProfilerTest, ConstantEvaluationCxx20) {
   constexpr StringRef Code = R"(
 void print(double value);
 
@@ -172,7 +172,7 @@
 )";
 
   setupProfiler();
-  ASSERT_TRUE(compileFromString(Code));
+  ASSERT_TRUE(compileFromString(Code, "-std=c++20", "test.cc"));
   std::string Json = teardownProfiler();
   std::string TraceGraph = buildTraceGraph(Json);
   ASSERT_TRUE(TraceGraph == R"(
@@ -197,3 +197,25 @@
   // NOTE: If this test is failing, run this test with
   // `llvm::errs() << TraceGraph;` and change the assert above.
 }
+
+TEST(TimeProfilerTest, ConstantEvaluationC99) {
+  constexpr StringRef Code = R"(
+struct {
+  short quantval[4]; // 3rd line
+} value;
+)";
+
+  setupProfiler();
+  ASSERT_TRUE(compileFromString(Code, "-std=c99", "test.c"));
+  std::string Json = teardownProfiler();
+  std::string TraceGraph = buildTraceGraph(Json);
+  ASSERT_TRUE(TraceGraph == R"(
+Frontend
+| isIntegerConstantExpr ()
+| EvaluateKnownConstIntCheckOverflow ()
+| PerformPendingInstantiations
+)");
+
+  // NOTE: If this test is failing, run this test with
+  // `llvm::errs() << TraceGraph;` and change the assert above.
+}
Index: clang/lib/AST/ExprConstant.cpp
===
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -15905,9 +15905,7 @@
   assert(!isValueDependent() &&
  "Expression evaluator can't be called on a dependent expression.");
 
-  llvm::TimeTraceScope TimeScope("isIntegerConstantExpr", [&] {
-return Loc->printToString(Ctx.getSourceManager());
-  });
+  ExprTimeTraceScope TimeScope(this, Ctx, "isIntegerConstantExpr");
 
   if (Ctx.getLangOpts().CPlusPlus11)
 return EvaluateCPlusPlus11IntegralConstantExpr(Ctx, this, nullptr, Loc);


Index: clang/unittests/Support/TimeProfilerTest.cpp
===
--- clang/unittests/Support/TimeProfilerTest.cpp
+++ clang/unittests/Support/TimeProfilerTest.cpp
@@ -37,14 +37,14 @@
 
 // Returns true if code compiles successfully.
 // We only parse AST here. This is enough for constexpr evaluation.
-bool compileFromString(StringRef Code) {
+bool compileFromString(StringRef Code, StringRef Standard, StringRef FileName) {
   CompilerInstance Compiler;
   Compiler.createDiagnostics();
 
   auto Invocation = std::make_shared();
   Invocation->getPreprocessorOpts().addRemappedFile(
-  "test.cc", MemoryBuffer::getMemBuffer(Code).release());
-  const char *Args[] = {"-std=c++20", "test.cc"};
+  FileName, MemoryBuffer::getMemBuffer(Code).release());
+  const char *Args[] = {Standard.data(), FileName.data()};
   CompilerInvocation::CreateFromArgs(*Invocation, Args,
  Compiler.getDiagnostics());
   Compiler.setInvocation(std::move(Invocation));
@@ -143,7 +143,7 @@
 
 } // namespace
 
-TEST(TimeProfilerTest, ConstantEvaluation) {
+TEST(TimeProfilerTest, ConstantEvaluationCxx20) {
   constexpr StringRef Code = R"(
 void print(double value);
 
@@ -172,7 +172,7 @@
 )";
 
   setupProfiler();
-  ASSERT_TRUE(compileFromString(Code));
+  ASSERT_TRUE(compileFromString(Code, "-std=c++20", "test.cc"));
   std::string Json = teardownProfiler();
   std::string TraceGraph = buildTraceGraph(Json);
   ASSE

[PATCH] D136546: [clang][unittest] Resolve ClangSupportTest link time errors

2022-10-23 Thread Evgeny Shulgin via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGe5032d89e44a: [clang][unittest] Resolve ClangSupportTest 
link time errors (authored by jmciver, committed by Izaron).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136546

Files:
  clang/unittests/Support/CMakeLists.txt


Index: clang/unittests/Support/CMakeLists.txt
===
--- clang/unittests/Support/CMakeLists.txt
+++ clang/unittests/Support/CMakeLists.txt
@@ -8,5 +8,8 @@
 
 clang_target_link_libraries(ClangSupportTests
   PRIVATE
+  clangAST
+  clangBasic
   clangFrontend
+  clangSerialization
   )


Index: clang/unittests/Support/CMakeLists.txt
===
--- clang/unittests/Support/CMakeLists.txt
+++ clang/unittests/Support/CMakeLists.txt
@@ -8,5 +8,8 @@
 
 clang_target_link_libraries(ClangSupportTests
   PRIVATE
+  clangAST
+  clangBasic
   clangFrontend
+  clangSerialization
   )
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D136546: [clang][unittest] Resolve ClangSupportTest link time errors

2022-10-23 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added a comment.

LGTM! I'm sorry that you had to fix CMakeLists.txt. It really "worked on my 
machine", I was running these commands:

  cmake --build build --target ClangSupportTests # build and link the binary
  ./build/tools/clang/unittests/Support/ClangSupportTests # run the binary


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136546

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


[PATCH] D136022: [clang] Add time profile for constant evaluation

2022-10-22 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added a comment.

In D136022#3877399 , @dyung wrote:

> Hi @Izaron, several of our internal tests that run tests using `-ftime-trace` 
> started crashing when run which I bisected back to your change. I have filed 
> issue #58551  for it, can 
> you take a look?

Hi! Thank you for filling the issue! I will fix it as soon as I can!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136022

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


[PATCH] D136022: [clang] Add time profile for constant evaluation

2022-10-21 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added inline comments.



Comment at: clang/unittests/Support/TimeProfilerTest.cpp:11
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Lex/PreprocessorOptions.h"
+

thakis wrote:
> Why is this in clang/unittests/Support (a new binary to boot)? This doesn't 
> use any code form clang/lib/Support as far as I can tell.
It uses code from llvm/Support.

There are already tests with similar names: clang/unittest/CodeGen and 
llvm/unittests/CodeGen, both are pretty close in spirit.

So I decided to make clang/unittests/Support as a counterpart to 
llvm/unittests/Support. There is a time profiler test too - 
https://github.com/llvm/llvm-project/blob/main/llvm/unittests/Support/TimeProfilerTest.cpp


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136022

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


[PATCH] D136022: [clang] Add time profile for constant evaluation

2022-10-21 Thread Evgeny Shulgin 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 rG27d8eedd5a3c: [clang] Add time profile for constant 
evaluation (authored by Izaron).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136022

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/AST/ExprConstant.cpp
  clang/unittests/CMakeLists.txt
  clang/unittests/Support/CMakeLists.txt
  clang/unittests/Support/TimeProfilerTest.cpp

Index: clang/unittests/Support/TimeProfilerTest.cpp
===
--- /dev/null
+++ clang/unittests/Support/TimeProfilerTest.cpp
@@ -0,0 +1,199 @@
+//===- unittests/Support/TimeProfilerTest.cpp -===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Lex/PreprocessorOptions.h"
+
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/TimeProfiler.h"
+
+#include "gtest/gtest.h"
+
+using namespace clang;
+using namespace llvm;
+
+namespace {
+
+// Should be called before testing.
+void setupProfiler() {
+  timeTraceProfilerInitialize(/*TimeTraceGranularity=*/0, "test");
+}
+
+// Should be called after `compileFromString()`.
+// Returns profiler's JSON dump.
+std::string teardownProfiler() {
+  SmallVector SmallVec;
+  raw_svector_ostream OS(SmallVec);
+  timeTraceProfilerWrite(OS);
+  timeTraceProfilerCleanup();
+  return OS.str().str();
+}
+
+// Returns true if code compiles successfully.
+// We only parse AST here. This is enough for constexpr evaluation.
+bool compileFromString(StringRef Code) {
+  CompilerInstance Compiler;
+  Compiler.createDiagnostics();
+
+  auto Invocation = std::make_shared();
+  Invocation->getPreprocessorOpts().addRemappedFile(
+  "test.cc", MemoryBuffer::getMemBuffer(Code).release());
+  const char *Args[] = {"-std=c++20", "test.cc"};
+  CompilerInvocation::CreateFromArgs(*Invocation, Args,
+ Compiler.getDiagnostics());
+  Compiler.setInvocation(std::move(Invocation));
+
+  class TestFrontendAction : public ASTFrontendAction {
+  private:
+std::unique_ptr CreateASTConsumer(CompilerInstance &CI,
+   StringRef InFile) override {
+  return std::make_unique();
+}
+  } Action;
+  return Compiler.ExecuteAction(Action);
+}
+
+// Returns pretty-printed trace graph.
+std::string buildTraceGraph(StringRef Json) {
+  struct EventRecord {
+int64_t TimestampBegin;
+int64_t TimestampEnd;
+StringRef Name;
+StringRef Detail;
+  };
+  std::vector Events;
+
+  // Parse `EventRecord`s from JSON dump.
+  Expected Root = json::parse(Json);
+  if (!Root)
+return "";
+  for (json::Value &TraceEventValue :
+   *Root->getAsObject()->getArray("traceEvents")) {
+json::Object *TraceEventObj = TraceEventValue.getAsObject();
+
+int64_t TimestampBegin = TraceEventObj->getInteger("ts").value_or(0);
+int64_t TimestampEnd =
+TimestampBegin + TraceEventObj->getInteger("dur").value_or(0);
+StringRef Name = TraceEventObj->getString("name").value_or("");
+StringRef Detail = "";
+if (json::Object *Args = TraceEventObj->getObject("args"))
+  Detail = Args->getString("detail").value_or("");
+
+// This is a "summary" event, like "Total PerformPendingInstantiations",
+// skip it
+if (TimestampBegin == 0)
+  continue;
+
+Events.emplace_back(
+EventRecord{TimestampBegin, TimestampEnd, Name, Detail});
+  }
+
+  // There can be nested events that are very fast, for example:
+  // {"name":"EvaluateAsBooleanCondition",... ,"ts":2380,"dur":1}
+  // {"name":"EvaluateAsRValue",... ,"ts":2380,"dur":1}
+  // Therefore we should reverse the events list, so that events that have
+  // started earlier are first in the list.
+  // Then do a stable sort, we need it for the trace graph.
+  std::reverse(Events.begin(), Events.end());
+  std::stable_sort(
+  Events.begin(), Events.end(), [](const auto &lhs, const auto &rhs) {
+return std::make_pair(lhs.TimestampBegin, -lhs.TimestampEnd) <
+   std::make_pair(rhs.TimestampBegin, -rhs.TimestampEnd);
+  });
+
+  std::stringstream Stream;
+  // Write a newline for better testing with multiline string literal.
+  Stream << "\n";
+
+  // Keep the current event stack.
+  std::stack EventStack;
+  for (const auto &Event : Events) {
+// Pop every event in the stack until meeting the parent event.
+while (!EventStack.empty()) {
+  bool InsideCurrentEvent =
+  Event.TimestampBegin >= Ev

[PATCH] D136022: [clang] Add time profile for constant evaluation

2022-10-21 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 469771.
Izaron added a comment.

Mention this in the release notes. Thanks to Aaron for reviewing!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136022

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/AST/ExprConstant.cpp
  clang/unittests/CMakeLists.txt
  clang/unittests/Support/CMakeLists.txt
  clang/unittests/Support/TimeProfilerTest.cpp

Index: clang/unittests/Support/TimeProfilerTest.cpp
===
--- /dev/null
+++ clang/unittests/Support/TimeProfilerTest.cpp
@@ -0,0 +1,199 @@
+//===- unittests/Support/TimeProfilerTest.cpp -===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Lex/PreprocessorOptions.h"
+
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/TimeProfiler.h"
+
+#include "gtest/gtest.h"
+
+using namespace clang;
+using namespace llvm;
+
+namespace {
+
+// Should be called before testing.
+void setupProfiler() {
+  timeTraceProfilerInitialize(/*TimeTraceGranularity=*/0, "test");
+}
+
+// Should be called after `compileFromString()`.
+// Returns profiler's JSON dump.
+std::string teardownProfiler() {
+  SmallVector SmallVec;
+  raw_svector_ostream OS(SmallVec);
+  timeTraceProfilerWrite(OS);
+  timeTraceProfilerCleanup();
+  return OS.str().str();
+}
+
+// Returns true if code compiles successfully.
+// We only parse AST here. This is enough for constexpr evaluation.
+bool compileFromString(StringRef Code) {
+  CompilerInstance Compiler;
+  Compiler.createDiagnostics();
+
+  auto Invocation = std::make_shared();
+  Invocation->getPreprocessorOpts().addRemappedFile(
+  "test.cc", MemoryBuffer::getMemBuffer(Code).release());
+  const char *Args[] = {"-std=c++20", "test.cc"};
+  CompilerInvocation::CreateFromArgs(*Invocation, Args,
+ Compiler.getDiagnostics());
+  Compiler.setInvocation(std::move(Invocation));
+
+  class TestFrontendAction : public ASTFrontendAction {
+  private:
+std::unique_ptr CreateASTConsumer(CompilerInstance &CI,
+   StringRef InFile) override {
+  return std::make_unique();
+}
+  } Action;
+  return Compiler.ExecuteAction(Action);
+}
+
+// Returns pretty-printed trace graph.
+std::string buildTraceGraph(StringRef Json) {
+  struct EventRecord {
+int64_t TimestampBegin;
+int64_t TimestampEnd;
+StringRef Name;
+StringRef Detail;
+  };
+  std::vector Events;
+
+  // Parse `EventRecord`s from JSON dump.
+  Expected Root = json::parse(Json);
+  if (!Root)
+return "";
+  for (json::Value &TraceEventValue :
+   *Root->getAsObject()->getArray("traceEvents")) {
+json::Object *TraceEventObj = TraceEventValue.getAsObject();
+
+int64_t TimestampBegin = TraceEventObj->getInteger("ts").value_or(0);
+int64_t TimestampEnd =
+TimestampBegin + TraceEventObj->getInteger("dur").value_or(0);
+StringRef Name = TraceEventObj->getString("name").value_or("");
+StringRef Detail = "";
+if (json::Object *Args = TraceEventObj->getObject("args"))
+  Detail = Args->getString("detail").value_or("");
+
+// This is a "summary" event, like "Total PerformPendingInstantiations",
+// skip it
+if (TimestampBegin == 0)
+  continue;
+
+Events.emplace_back(
+EventRecord{TimestampBegin, TimestampEnd, Name, Detail});
+  }
+
+  // There can be nested events that are very fast, for example:
+  // {"name":"EvaluateAsBooleanCondition",... ,"ts":2380,"dur":1}
+  // {"name":"EvaluateAsRValue",... ,"ts":2380,"dur":1}
+  // Therefore we should reverse the events list, so that events that have
+  // started earlier are first in the list.
+  // Then do a stable sort, we need it for the trace graph.
+  std::reverse(Events.begin(), Events.end());
+  std::stable_sort(
+  Events.begin(), Events.end(), [](const auto &lhs, const auto &rhs) {
+return std::make_pair(lhs.TimestampBegin, -lhs.TimestampEnd) <
+   std::make_pair(rhs.TimestampBegin, -rhs.TimestampEnd);
+  });
+
+  std::stringstream Stream;
+  // Write a newline for better testing with multiline string literal.
+  Stream << "\n";
+
+  // Keep the current event stack.
+  std::stack EventStack;
+  for (const auto &Event : Events) {
+// Pop every event in the stack until meeting the parent event.
+while (!EventStack.empty()) {
+  bool InsideCurrentEvent =
+  Event.TimestampBegin >= EventStack.top()->TimestampBegin &&
+  Event.TimestampEnd <= EventStack.top()->TimestampEnd;

[PATCH] D136036: [Clang] Add __has_constexpr_builtin support

2022-10-21 Thread Evgeny Shulgin 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 rG5b567637e22b: [Clang] Add __has_constexpr_builtin support 
(authored by Izaron).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136036

Files:
  clang/docs/LanguageExtensions.rst
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/Builtins.def
  clang/include/clang/Basic/Builtins.h
  clang/include/clang/Lex/Preprocessor.h
  clang/lib/AST/ExprConstant.cpp
  clang/lib/Lex/PPMacroExpansion.cpp
  clang/test/Preprocessor/feature_tests.cpp

Index: clang/test/Preprocessor/feature_tests.cpp
===
--- clang/test/Preprocessor/feature_tests.cpp
+++ clang/test/Preprocessor/feature_tests.cpp
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 %s -triple=i686-apple-darwin9 -verify -DVERIFY
-// expected-no-diagnostics
 
 #ifndef __has_feature
 #error Should have __has_feature
@@ -42,3 +41,29 @@
 #if __has_builtin(__builtin_insanity)
 #error Clang should not have this
 #endif
+
+// Check __has_constexpr_builtin
+#if  !__has_constexpr_builtin(__builtin_fmax) || \
+ !__has_constexpr_builtin(__builtin_fmin)
+#error Clang should have these constexpr builtins
+#endif
+
+#if  __has_constexpr_builtin(__builtin_cbrt)
+#error This builtin should not be constexpr in Clang
+#endif
+
+#if  __has_constexpr_builtin(__builtin_insanity)
+#error This is not a builtin in Clang
+#endif
+
+// expected-error@+1 {{missing '(' after '__has_constexpr_builtin'}} expected-error@+1 {{expected value}}
+#if __has_constexpr_builtin
+#endif
+
+// expected-error@+1 {{builtin feature check macro requires a parenthesized identifier}}
+#if  __has_constexpr_builtin("__builtin_fmax")
+#endif
+
+// expected-error@+1 {{too many arguments}}
+#if __has_constexpr_builtin(__builtin_fmax, __builtin_fmin)
+#endif
Index: clang/lib/Lex/PPMacroExpansion.cpp
===
--- clang/lib/Lex/PPMacroExpansion.cpp
+++ clang/lib/Lex/PPMacroExpansion.cpp
@@ -371,6 +371,8 @@
   Ident__has_feature  = RegisterBuiltinMacro(*this, "__has_feature");
   Ident__has_extension= RegisterBuiltinMacro(*this, "__has_extension");
   Ident__has_builtin  = RegisterBuiltinMacro(*this, "__has_builtin");
+  Ident__has_constexpr_builtin =
+  RegisterBuiltinMacro(*this, "__has_constexpr_builtin");
   Ident__has_attribute= RegisterBuiltinMacro(*this, "__has_attribute");
   if (!getLangOpts().CPlusPlus)
 Ident__has_c_attribute = RegisterBuiltinMacro(*this, "__has_c_attribute");
@@ -1735,6 +1737,18 @@
   .Default(false);
 }
   });
+  } else if (II == Ident__has_constexpr_builtin) {
+EvaluateFeatureLikeBuiltinMacro(
+OS, Tok, II, *this, false,
+[this](Token &Tok, bool &HasLexedNextToken) -> int {
+  IdentifierInfo *II = ExpectFeatureIdentifierInfo(
+  Tok, *this, diag::err_feature_check_malformed);
+  if (!II)
+return false;
+  unsigned BuiltinOp = II->getBuiltinID();
+  return BuiltinOp != 0 &&
+ this->getBuiltinInfo().isConstantEvaluated(BuiltinOp);
+});
   } else if (II == Ident__is_identifier) {
 EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this, false,
   [](Token &Tok, bool &HasLexedNextToken) -> int {
Index: clang/lib/AST/ExprConstant.cpp
===
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -1954,8 +1954,8 @@
   return true;
 }
 
-/// Should this call expression be treated as a constant?
-static bool IsConstantCall(const CallExpr *E) {
+/// Should this call expression be treated as a no-op?
+static bool IsNoOpCall(const CallExpr *E) {
   unsigned Builtin = E->getBuiltinCallee();
   return (Builtin == Builtin::BI__builtin___CFStringMakeConstantString ||
   Builtin == Builtin::BI__builtin___NSStringMakeConstantString ||
@@ -2006,7 +2006,7 @@
   case Expr::ObjCBoxedExprClass:
 return cast(E)->isExpressibleAsConstantInitializer();
   case Expr::CallExprClass:
-return IsConstantCall(cast(E));
+return IsNoOpCall(cast(E));
   // For GCC compatibility, &&label has static storage duration.
   case Expr::AddrLabelExprClass:
 return true;
@@ -7405,6 +7405,12 @@
 
   bool ZeroInitialization(const Expr *E) { return Error(E); }
 
+  bool IsConstantEvaluatedBuiltinCall(const CallExpr *E) {
+unsigned BuiltinOp = E->getBuiltinCallee();
+return BuiltinOp != 0 &&
+   Info.Ctx.BuiltinInfo.isConstantEvaluated(BuiltinOp);
+  }
+
 public:
   ExprEvaluatorBase(EvalInfo &Info) : Info(Info) {}
 
@@ -8317,7 +8323,12 @@
 }
 
 bool LValueExprEvaluator::VisitCallExpr(const CallExpr *E) {
+  if (!IsConstantEvaluatedBuiltinCall(E))
+return ExprEvaluatorBaseTy::VisitCallExpr(E);
+
   switch (E->getBuiltin

[PATCH] D136022: [clang] Add time profile for constant evaluation

2022-10-20 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added inline comments.



Comment at: clang/unittests/Support/TimeProfilerTest.cpp:197-198
+
+  // NOTE: If this test is failing, run this test with
+  // `llvm::errs() << TraceGraph;` and change the assert above.
+}

aaron.ballman wrote:
> This bit worries me because I suspect we'll get pretty wide variation between 
> test bots in the build lab. Do you have an idea of how likely it is that this 
> test will have different behavior depending on the machine?
I'd say, the test's outcome varies if behaviour of `CompilerInstance` varies. 
From my (imperfect) understanding of Clang/LLVM's architecture, its interface 
is pretty hermetic and we won't get inconsistent behaviour depending on the 
current machine as soon as we ran `Compiler.ExecuteAction(Action);`.
Since the code is machine-independents, I expect the same behaviour everywhere.

If we look on other tests, there are tests that seemingly take the machine's 
target triple 
https://github.com/llvm/llvm-project/blob/3fee9358baab54e4ed646a106297e7fb6f1b4cff/clang/unittests/CodeGen/TestCompiler.h#L40-L48
 to fill some info in `CompilerInstance`.

But this is not the case in our test. Seems like the AST parsing is 
machine-independent 😃 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136022

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


[PATCH] D136022: [clang] Add time profile for constant evaluation

2022-10-20 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 469159.
Izaron added a comment.

Fix optionals with `value_or`


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136022

Files:
  clang/lib/AST/ExprConstant.cpp
  clang/unittests/CMakeLists.txt
  clang/unittests/Support/CMakeLists.txt
  clang/unittests/Support/TimeProfilerTest.cpp

Index: clang/unittests/Support/TimeProfilerTest.cpp
===
--- /dev/null
+++ clang/unittests/Support/TimeProfilerTest.cpp
@@ -0,0 +1,199 @@
+//===- unittests/Support/TimeProfilerTest.cpp -===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Lex/PreprocessorOptions.h"
+
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/TimeProfiler.h"
+
+#include "gtest/gtest.h"
+
+using namespace clang;
+using namespace llvm;
+
+namespace {
+
+// Should be called before testing.
+void setupProfiler() {
+  timeTraceProfilerInitialize(/*TimeTraceGranularity=*/0, "test");
+}
+
+// Should be called after `compileFromString()`.
+// Returns profiler's JSON dump.
+std::string teardownProfiler() {
+  SmallVector SmallVec;
+  raw_svector_ostream OS(SmallVec);
+  timeTraceProfilerWrite(OS);
+  timeTraceProfilerCleanup();
+  return OS.str().str();
+}
+
+// Returns true if code compiles successfully.
+// We only parse AST here. This is enough for constexpr evaluation.
+bool compileFromString(StringRef Code) {
+  CompilerInstance Compiler;
+  Compiler.createDiagnostics();
+
+  auto Invocation = std::make_shared();
+  Invocation->getPreprocessorOpts().addRemappedFile(
+  "test.cc", MemoryBuffer::getMemBuffer(Code).release());
+  const char *Args[] = {"-std=c++20", "test.cc"};
+  CompilerInvocation::CreateFromArgs(*Invocation, Args,
+ Compiler.getDiagnostics());
+  Compiler.setInvocation(std::move(Invocation));
+
+  class TestFrontendAction : public ASTFrontendAction {
+  private:
+std::unique_ptr CreateASTConsumer(CompilerInstance &CI,
+   StringRef InFile) override {
+  return std::make_unique();
+}
+  } Action;
+  return Compiler.ExecuteAction(Action);
+}
+
+// Returns pretty-printed trace graph.
+std::string buildTraceGraph(StringRef Json) {
+  struct EventRecord {
+int64_t TimestampBegin;
+int64_t TimestampEnd;
+StringRef Name;
+StringRef Detail;
+  };
+  std::vector Events;
+
+  // Parse `EventRecord`s from JSON dump.
+  Expected Root = json::parse(Json);
+  if (!Root)
+return "";
+  for (json::Value &TraceEventValue :
+   *Root->getAsObject()->getArray("traceEvents")) {
+json::Object *TraceEventObj = TraceEventValue.getAsObject();
+
+int64_t TimestampBegin = TraceEventObj->getInteger("ts").value_or(0);
+int64_t TimestampEnd =
+TimestampBegin + TraceEventObj->getInteger("dur").value_or(0);
+StringRef Name = TraceEventObj->getString("name").value_or("");
+StringRef Detail = "";
+if (json::Object *Args = TraceEventObj->getObject("args"))
+  Detail = Args->getString("detail").value_or("");
+
+// This is a "summary" event, like "Total PerformPendingInstantiations",
+// skip it
+if (TimestampBegin == 0)
+  continue;
+
+Events.emplace_back(
+EventRecord{TimestampBegin, TimestampEnd, Name, Detail});
+  }
+
+  // There can be nested events that are very fast, for example:
+  // {"name":"EvaluateAsBooleanCondition",... ,"ts":2380,"dur":1}
+  // {"name":"EvaluateAsRValue",... ,"ts":2380,"dur":1}
+  // Therefore we should reverse the events list, so that events that have
+  // started earlier are first in the list.
+  // Then do a stable sort, we need it for the trace graph.
+  std::reverse(Events.begin(), Events.end());
+  std::stable_sort(
+  Events.begin(), Events.end(), [](const auto &lhs, const auto &rhs) {
+return std::make_pair(lhs.TimestampBegin, -lhs.TimestampEnd) <
+   std::make_pair(rhs.TimestampBegin, -rhs.TimestampEnd);
+  });
+
+  std::stringstream Stream;
+  // Write a newline for better testing with multiline string literal.
+  Stream << "\n";
+
+  // Keep the current event stack.
+  std::stack EventStack;
+  for (const auto &Event : Events) {
+// Pop every event in the stack until meeting the parent event.
+while (!EventStack.empty()) {
+  bool InsideCurrentEvent =
+  Event.TimestampBegin >= EventStack.top()->TimestampBegin &&
+  Event.TimestampEnd <= EventStack.top()->TimestampEnd;
+  if (!InsideCurrentEvent)
+EventStack.pop();
+ 

[PATCH] D136022: [clang] Add time profile for constant evaluation

2022-10-19 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 469098.
Izaron added a comment.

Fix CMakeLists.txt


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136022

Files:
  clang/lib/AST/ExprConstant.cpp
  clang/unittests/CMakeLists.txt
  clang/unittests/Support/CMakeLists.txt
  clang/unittests/Support/TimeProfilerTest.cpp

Index: clang/unittests/Support/TimeProfilerTest.cpp
===
--- /dev/null
+++ clang/unittests/Support/TimeProfilerTest.cpp
@@ -0,0 +1,198 @@
+//===- unittests/Support/TimeProfilerTest.cpp -===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Lex/PreprocessorOptions.h"
+
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/TimeProfiler.h"
+
+#include "gtest/gtest.h"
+
+using namespace clang;
+using namespace llvm;
+
+namespace {
+
+// Should be called before testing.
+void setupProfiler() {
+  timeTraceProfilerInitialize(/*TimeTraceGranularity=*/0, "test");
+}
+
+// Should be called after `compileFromString()`.
+// Returns profiler's JSON dump.
+std::string teardownProfiler() {
+  SmallVector SmallVec;
+  raw_svector_ostream OS(SmallVec);
+  timeTraceProfilerWrite(OS);
+  timeTraceProfilerCleanup();
+  return OS.str().str();
+}
+
+// Returns true if code compiles successfully.
+// We only parse AST here. This is enough for constexpr evaluation.
+bool compileFromString(StringRef Code) {
+  CompilerInstance Compiler;
+  Compiler.createDiagnostics();
+
+  auto Invocation = std::make_shared();
+  Invocation->getPreprocessorOpts().addRemappedFile(
+  "test.cc", MemoryBuffer::getMemBuffer(Code).release());
+  const char *Args[] = {"-std=c++20", "test.cc"};
+  CompilerInvocation::CreateFromArgs(*Invocation, Args,
+ Compiler.getDiagnostics());
+  Compiler.setInvocation(std::move(Invocation));
+
+  class TestFrontendAction : public ASTFrontendAction {
+  private:
+std::unique_ptr CreateASTConsumer(CompilerInstance &CI,
+   StringRef InFile) override {
+  return std::make_unique();
+}
+  } Action;
+  return Compiler.ExecuteAction(Action);
+}
+
+// Returns pretty-printed trace graph.
+std::string buildTraceGraph(StringRef Json) {
+  struct EventRecord {
+int64_t TimestampBegin;
+int64_t TimestampEnd;
+StringRef Name;
+StringRef Detail;
+  };
+  std::vector Events;
+
+  // Parse `EventRecord`s from JSON dump.
+  Expected Root = json::parse(Json);
+  if (!Root)
+return "";
+  for (json::Value &TraceEventValue :
+   *Root->getAsObject()->getArray("traceEvents")) {
+json::Object *TraceEventObj = TraceEventValue.getAsObject();
+
+int64_t TimestampBegin = *TraceEventObj->getInteger("ts");
+int64_t TimestampEnd = TimestampBegin + *TraceEventObj->getInteger("dur");
+StringRef Name = *TraceEventObj->getString("name");
+StringRef Detail = "";
+if (json::Object *Args = TraceEventObj->getObject("args"))
+  Detail = Args->getString("detail").value_or("");
+
+// This is a "summary" event, like "Total PerformPendingInstantiations",
+// skip it
+if (TimestampBegin == 0)
+  continue;
+
+Events.emplace_back(
+EventRecord{TimestampBegin, TimestampEnd, Name, Detail});
+  }
+
+  // There can be nested events that are very fast, for example:
+  // {"name":"EvaluateAsBooleanCondition",... ,"ts":2380,"dur":1}
+  // {"name":"EvaluateAsRValue",... ,"ts":2380,"dur":1}
+  // Therefore we should reverse the events list, so that events that have
+  // started earlier are first in the list.
+  // Then do a stable sort, we need it for the trace graph.
+  std::reverse(Events.begin(), Events.end());
+  std::stable_sort(
+  Events.begin(), Events.end(), [](const auto &lhs, const auto &rhs) {
+return std::make_pair(lhs.TimestampBegin, lhs.TimestampEnd) <
+   std::make_pair(rhs.TimestampBegin, rhs.TimestampEnd);
+  });
+
+  std::stringstream Stream;
+  // Write a newline for better testing with multiline string literal.
+  Stream << "\n";
+
+  // Keep the current event stack.
+  std::stack EventStack;
+  for (const auto &Event : Events) {
+// Pop every event in the stack until meeting the parent event.
+while (!EventStack.empty()) {
+  bool InsideCurrentEvent =
+  Event.TimestampBegin >= EventStack.top()->TimestampBegin &&
+  Event.TimestampEnd <= EventStack.top()->TimestampEnd;
+  if (!InsideCurrentEvent)
+EventStack.pop();
+  else
+break;
+}
+EventStack.push(&Event

[PATCH] D136022: [clang] Add time profile for constant evaluation

2022-10-19 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added a comment.

The test doesn't cover exactly all new traces though. For example I couldn't 
write a code that runs into the `EvaluateAsInt` method 🤔

If you have an idea for some funky constexpr code that can be tested, please 
write here =)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136022

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


[PATCH] D136022: [clang] Add time profile for constant evaluation

2022-10-19 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added a comment.

In D136022#3861245 , @jloser wrote:

> I'd like to see some tests through before I approve.

Thanks for the greenlight!

I added a test that compiles a chunk of code and then checks the time trace 
graph in a human-readable form.




Comment at: clang/lib/Sema/SemaDeclCXX.cpp:1740-1746
+  llvm::TimeTraceScope TimeScope("CheckConstexprFunctionDefinition", [&] {
+std::string Name;
+llvm::raw_string_ostream OS(Name);
+NewFD->getNameForDiagnostic(OS, Context.getPrintingPolicy(),
+/*Qualified=*/true);
+return Name;
+  });

aaron.ballman wrote:
> Huh, I'm a bit surprised that the checking in this function isn't dominated 
> by the time spent in `Expr::isPotentialConstantExpr()` -- if you add the time 
> tracing to all of the constant expression evaluation functions, do you still 
> need a time trace here in Sema?
Thanks! Removed trace here, added to `Expr::isPotentialConstantExpr()`. This 
method is called inside of `CheckConstexprFunctionDefinition` and really takes 
almost all the time.



Comment at: clang/lib/Sema/SemaExpr.cpp:17544
+  {
+llvm::TimeTraceScope TimeScope("EvaluateAsConstantExpr", [&] {
+  return CE->getSourceRange().printToString(SemaRef.getSourceManager());

aaron.ballman wrote:
> Why not push this down into `EvaluateAsConstantExpr()`? (Then the name you 
> give the scope will also be more accurate.)
Thanks! I wrote on this level because I didn't manage to get 
`SemaRef.getSourceManager()` without `SemaRef` (we pass down 
`SemaRef.getASTContext()`).

Anyway I found out that we can use `SemaRef.getASTContext().getSourceManager()` 
=)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136022

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


[PATCH] D136022: [clang] Add time profile for constant evaluation

2022-10-19 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 469096.
Izaron marked 4 inline comments as done.
Izaron added a comment.

Add time profiler test.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136022

Files:
  clang/lib/AST/ExprConstant.cpp
  clang/unittests/CMakeLists.txt
  clang/unittests/Support/CMakeLists.txt
  clang/unittests/Support/TimeProfilerTest.cpp

Index: clang/unittests/Support/TimeProfilerTest.cpp
===
--- /dev/null
+++ clang/unittests/Support/TimeProfilerTest.cpp
@@ -0,0 +1,198 @@
+//===- unittests/Support/TimeProfilerTest.cpp -===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendActions.h"
+#include "clang/Lex/PreprocessorOptions.h"
+
+#include "llvm/Support/JSON.h"
+#include "llvm/Support/TimeProfiler.h"
+
+#include "gtest/gtest.h"
+
+using namespace clang;
+using namespace llvm;
+
+namespace {
+
+// Should be called before testing.
+void setupProfiler() {
+  timeTraceProfilerInitialize(/*TimeTraceGranularity=*/0, "test");
+}
+
+// Should be called after `compileFromString()`.
+// Returns profiler's JSON dump.
+std::string teardownProfiler() {
+  SmallVector SmallVec;
+  raw_svector_ostream OS(SmallVec);
+  timeTraceProfilerWrite(OS);
+  timeTraceProfilerCleanup();
+  return OS.str().str();
+}
+
+// Returns true if code compiles successfully.
+// We only parse AST here. This is enough for constexpr evaluation.
+bool compileFromString(StringRef Code) {
+  CompilerInstance Compiler;
+  Compiler.createDiagnostics();
+
+  auto Invocation = std::make_shared();
+  Invocation->getPreprocessorOpts().addRemappedFile(
+  "test.cc", MemoryBuffer::getMemBuffer(Code).release());
+  const char *Args[] = {"-std=c++20", "test.cc"};
+  CompilerInvocation::CreateFromArgs(*Invocation, Args,
+ Compiler.getDiagnostics());
+  Compiler.setInvocation(std::move(Invocation));
+
+  class TestFrontendAction : public ASTFrontendAction {
+  private:
+std::unique_ptr CreateASTConsumer(CompilerInstance &CI,
+   StringRef InFile) override {
+  return std::make_unique();
+}
+  } Action;
+  return Compiler.ExecuteAction(Action);
+}
+
+// Returns pretty-printed trace graph.
+std::string buildTraceGraph(StringRef Json) {
+  struct EventRecord {
+int64_t TimestampBegin;
+int64_t TimestampEnd;
+StringRef Name;
+StringRef Detail;
+  };
+  std::vector Events;
+
+  // Parse `EventRecord`s from JSON dump.
+  Expected Root = json::parse(Json);
+  if (!Root)
+return "";
+  for (json::Value &TraceEventValue :
+   *Root->getAsObject()->getArray("traceEvents")) {
+json::Object *TraceEventObj = TraceEventValue.getAsObject();
+
+int64_t TimestampBegin = *TraceEventObj->getInteger("ts");
+int64_t TimestampEnd = TimestampBegin + *TraceEventObj->getInteger("dur");
+StringRef Name = *TraceEventObj->getString("name");
+StringRef Detail = "";
+if (json::Object *Args = TraceEventObj->getObject("args"))
+  Detail = Args->getString("detail").value_or("");
+
+// This is a "summary" event, like "Total PerformPendingInstantiations",
+// skip it
+if (TimestampBegin == 0)
+  continue;
+
+Events.emplace_back(
+EventRecord{TimestampBegin, TimestampEnd, Name, Detail});
+  }
+
+  // There can be nested events that are very fast, for example:
+  // {"name":"EvaluateAsBooleanCondition",... ,"ts":2380,"dur":1}
+  // {"name":"EvaluateAsRValue",... ,"ts":2380,"dur":1}
+  // Therefore we should reverse the events list, so that events that have
+  // started earlier are first in the list.
+  // Then do a stable sort, we need it for the trace graph.
+  std::reverse(Events.begin(), Events.end());
+  std::stable_sort(
+  Events.begin(), Events.end(), [](const auto &lhs, const auto &rhs) {
+return std::make_pair(lhs.TimestampBegin, lhs.TimestampEnd) <
+   std::make_pair(rhs.TimestampBegin, rhs.TimestampEnd);
+  });
+
+  std::stringstream Stream;
+  // Write a newline for better testing with multiline string literal.
+  Stream << "\n";
+
+  // Keep the current event stack.
+  std::stack EventStack;
+  for (const auto &Event : Events) {
+// Pop every event in the stack until meeting the parent event.
+while (!EventStack.empty()) {
+  bool InsideCurrentEvent =
+  Event.TimestampBegin >= EventStack.top()->TimestampBegin &&
+  Event.TimestampEnd <= EventStack.top()->TimestampEnd;
+  if (!InsideCurrentEvent)
+EventStack.pop();
+  else
+   

[PATCH] D136036: [Clang] Add __has_constexpr_builtin support

2022-10-17 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added a comment.

> It looks like unrelated formatting changes snuck in to this file.

@aaron.ballman JFYI after I reverted what `git clang-format HEAD~1` did to the 
code, the build has failed

  ERROR   git-clang-format returned an non-zero exit code 1
  Build completed with failures

https://buildkite.com/llvm-project/premerge-checks/builds/117202#0183e7ca-7aa7-4838-aa21-ae5ec717a18a

Can I apply `git clang-format HEAD~1` again?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136036

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


[PATCH] D136036: [Clang] Add __has_constexpr_builtin support

2022-10-17 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added inline comments.



Comment at: clang/docs/LanguageExtensions.rst:96
+the constant evaluation of the corresponding builtin (for example,
+``std::fmax`` calls ``__builtin_fmax``) is supported in Clang.
+

Izaron wrote:
> Just to be clear: this isn't a true statement now (`std::fmax calls 
> __builtin_fmax`), but soon will be, after @philnik commits this patch 
> https://reviews.llvm.org/D134584 part by part
> 
> ```
> inline _LIBCPP_HIDE_FROM_ABI float fmax(float __x, float __y) _NOEXCEPT { 
> return __builtin_fmaxf(__x, __y); }
> ```
BTW in future it could look something like this:
```
inline _LIBCPP_CONSTEXPR_CXX23_IF_CONSTEXPR_BUILTIN(__builtin_fmax) 
_LIBCPP_HIDE_FROM_ABI float fmax(float __x, float __y) _NOEXCEPT { return 
__builtin_fmaxf(__x, __y); }
```


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136036

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


[PATCH] D136036: [Clang] Add __has_constexpr_builtin support

2022-10-17 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added inline comments.



Comment at: clang/docs/LanguageExtensions.rst:96
+the constant evaluation of the corresponding builtin (for example,
+``std::fmax`` calls ``__builtin_fmax``) is supported in Clang.
+

Just to be clear: this isn't a true statement now (`std::fmax calls 
__builtin_fmax`), but soon will be, after @philnik commits this patch 
https://reviews.llvm.org/D134584 part by part

```
inline _LIBCPP_HIDE_FROM_ABI float fmax(float __x, float __y) _NOEXCEPT { 
return __builtin_fmaxf(__x, __y); }
```


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136036

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


[PATCH] D136036: [Clang] Add __has_constexpr_builtin support

2022-10-17 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added a comment.

In D136036#3862065 , @aaron.ballman 
wrote:

> Can you also add documentation and a release note for the new feature testing 
> macro?



In D136036#3862649 , @shafik wrote:

> Please add some of this context to the release notes and/or documentation, 
> thank you.

Hi! Added some text to the docs and to the release notes mentioning ``. 
Please look at my wording =)

In D136036#3862221 , @yaxunl wrote:

> need some Sema tests to verify a constexpr builtin is const evaluated.

Hi! If I understood you correctly, every (or over 95%?) such function already 
has its tests checking its constant evaluation. For example 
test/Sema/constant-builtins-fmax.cpp 

 checks constant `__builtin_fmax`.

In D136036#3862685 , @shafik wrote:

> The changes to the various `Vist*CallExpr` functions don't seem directly 
> related to supporting `__has_constexpr_builtin`, can you explain the purpose 
> of those changes? If they are not directly related maybe it makes more sense 
> for them to be split off into a follow-up PR?

We have a protocol that the `E` character in attributes marks that the builtin 
can be constant evaluated.

But the actual constant evaluation is done in `lib/AST/ExprConstant.cpp` and 
has little to do with builtin attributes.

So how do we keep the consistency of this protocol? In other words, how can we 
guarantee that IF the builtin is constant evaluated, it DOES have the `E` in 
`Builtins.def`?

I solved it with changes to `Visit*CallExpr`. Whenever we support constant 
evaluation in a builtin, we won't forget to mark its attributes with `E` 
(otherwise the evaluator returns early).

I was thinking to make a consistency test (outside the Clang code), but 
couldn't do it =(


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136036

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


[PATCH] D136036: [Clang] Add __has_constexpr_builtin support

2022-10-17 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added inline comments.



Comment at: clang/lib/Lex/PPMacroExpansion.cpp:370
   // Clang Extensions.
-  Ident__FILE_NAME__  = RegisterBuiltinMacro(*this, "__FILE_NAME__");
-  Ident__has_feature  = RegisterBuiltinMacro(*this, "__has_feature");
-  Ident__has_extension= RegisterBuiltinMacro(*this, "__has_extension");
-  Ident__has_builtin  = RegisterBuiltinMacro(*this, "__has_builtin");
-  Ident__has_attribute= RegisterBuiltinMacro(*this, "__has_attribute");
+  Ident__FILE_NAME__ = RegisterBuiltinMacro(*this, "__FILE_NAME__");
+  Ident__has_feature = RegisterBuiltinMacro(*this, "__has_feature");

aaron.ballman wrote:
> It looks like unrelated formatting changes snuck in to this file.
`git clang-format HEAD~1` did it =) I reformatted unrelated changes back to 
original state.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136036

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


[PATCH] D136036: [Clang] Add __has_constexpr_builtin support

2022-10-17 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 468314.
Izaron marked 2 inline comments as done.
Izaron added a comment.

Add more parsing tests. Fix unrelated formatting changes. Add release notes and 
docs.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136036

Files:
  clang/docs/LanguageExtensions.rst
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/Builtins.def
  clang/include/clang/Basic/Builtins.h
  clang/include/clang/Lex/Preprocessor.h
  clang/lib/AST/ExprConstant.cpp
  clang/lib/Lex/PPMacroExpansion.cpp
  clang/test/Preprocessor/feature_tests.cpp

Index: clang/test/Preprocessor/feature_tests.cpp
===
--- clang/test/Preprocessor/feature_tests.cpp
+++ clang/test/Preprocessor/feature_tests.cpp
@@ -1,5 +1,4 @@
 // RUN: %clang_cc1 %s -triple=i686-apple-darwin9 -verify -DVERIFY
-// expected-no-diagnostics
 
 #ifndef __has_feature
 #error Should have __has_feature
@@ -42,3 +41,29 @@
 #if __has_builtin(__builtin_insanity)
 #error Clang should not have this
 #endif
+
+// Check __has_constexpr_builtin
+#if  !__has_constexpr_builtin(__builtin_fmax) || \
+ !__has_constexpr_builtin(__builtin_fmin)
+#error Clang should have these constexpr builtins
+#endif
+
+#if  __has_constexpr_builtin(__builtin_cbrt)
+#error This builtin should not be constexpr in Clang
+#endif
+
+#if  __has_constexpr_builtin(__builtin_insanity)
+#error This is not a builtin in Clang
+#endif
+
+// expected-error@+1 {{missing '(' after '__has_constexpr_builtin'}} expected-error@+1 {{expected value}}
+#if __has_constexpr_builtin
+#endif
+
+// expected-error@+1 {{builtin feature check macro requires a parenthesized identifier}}
+#if  __has_constexpr_builtin("__builtin_fmax")
+#endif
+
+// expected-error@+1 {{too many arguments}}
+#if __has_constexpr_builtin(__builtin_fmax, __builtin_fmin)
+#endif
Index: clang/lib/Lex/PPMacroExpansion.cpp
===
--- clang/lib/Lex/PPMacroExpansion.cpp
+++ clang/lib/Lex/PPMacroExpansion.cpp
@@ -371,6 +371,8 @@
   Ident__has_feature  = RegisterBuiltinMacro(*this, "__has_feature");
   Ident__has_extension= RegisterBuiltinMacro(*this, "__has_extension");
   Ident__has_builtin  = RegisterBuiltinMacro(*this, "__has_builtin");
+  Ident__has_constexpr_builtin =
+  RegisterBuiltinMacro(*this, "__has_constexpr_builtin");
   Ident__has_attribute= RegisterBuiltinMacro(*this, "__has_attribute");
   if (!getLangOpts().CPlusPlus)
 Ident__has_c_attribute = RegisterBuiltinMacro(*this, "__has_c_attribute");
@@ -1735,6 +1737,18 @@
   .Default(false);
 }
   });
+  } else if (II == Ident__has_constexpr_builtin) {
+EvaluateFeatureLikeBuiltinMacro(
+OS, Tok, II, *this, false,
+[this](Token &Tok, bool &HasLexedNextToken) -> int {
+  IdentifierInfo *II = ExpectFeatureIdentifierInfo(
+  Tok, *this, diag::err_feature_check_malformed);
+  if (!II)
+return false;
+  unsigned BuiltinOp = II->getBuiltinID();
+  return BuiltinOp != 0 &&
+ this->getBuiltinInfo().isConstantEvaluated(BuiltinOp);
+});
   } else if (II == Ident__is_identifier) {
 EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this, false,
   [](Token &Tok, bool &HasLexedNextToken) -> int {
Index: clang/lib/AST/ExprConstant.cpp
===
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -1954,8 +1954,8 @@
   return true;
 }
 
-/// Should this call expression be treated as a constant?
-static bool IsConstantCall(const CallExpr *E) {
+/// Should this call expression be treated as a no-op?
+static bool IsNoOpCall(const CallExpr *E) {
   unsigned Builtin = E->getBuiltinCallee();
   return (Builtin == Builtin::BI__builtin___CFStringMakeConstantString ||
   Builtin == Builtin::BI__builtin___NSStringMakeConstantString ||
@@ -2006,7 +2006,7 @@
   case Expr::ObjCBoxedExprClass:
 return cast(E)->isExpressibleAsConstantInitializer();
   case Expr::CallExprClass:
-return IsConstantCall(cast(E));
+return IsNoOpCall(cast(E));
   // For GCC compatibility, &&label has static storage duration.
   case Expr::AddrLabelExprClass:
 return true;
@@ -7405,6 +7405,12 @@
 
   bool ZeroInitialization(const Expr *E) { return Error(E); }
 
+  bool IsConstantEvaluatedBuiltinCall(const CallExpr *E) {
+unsigned BuiltinOp = E->getBuiltinCallee();
+return BuiltinOp != 0 &&
+   Info.Ctx.BuiltinInfo.isConstantEvaluated(BuiltinOp);
+  }
+
 public:
   ExprEvaluatorBase(EvalInfo &Info) : Info(Info) {}
 
@@ -8317,7 +8323,12 @@
 }
 
 bool LValueExprEvaluator::VisitCallExpr(const CallExpr *E) {
+  if (!IsConstantEvaluatedBuiltinCall(E))
+return ExprEvaluatorBaseTy::VisitCallExpr(E);
+
   switch (E->getBuiltinCallee()) {
+  default:
+re

[PATCH] D136036: [Clang] Add __has_constexpr_builtin support

2022-10-16 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 468068.
Izaron added a comment.

Changed `llvm_unreachable` to just `return false`. I thought it is more secure.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136036

Files:
  clang/include/clang/Basic/Builtins.def
  clang/include/clang/Basic/Builtins.h
  clang/include/clang/Lex/Preprocessor.h
  clang/lib/AST/ExprConstant.cpp
  clang/lib/Lex/PPMacroExpansion.cpp
  clang/test/Preprocessor/feature_tests.cpp

Index: clang/test/Preprocessor/feature_tests.cpp
===
--- clang/test/Preprocessor/feature_tests.cpp
+++ clang/test/Preprocessor/feature_tests.cpp
@@ -42,3 +42,17 @@
 #if __has_builtin(__builtin_insanity)
 #error Clang should not have this
 #endif
+
+// Check __has_constexpr_builtin
+#if  !__has_constexpr_builtin(__builtin_fmax) || \
+ !__has_constexpr_builtin(__builtin_fmin)
+#error Clang should have these constexpr builtins
+#endif
+
+#if  __has_constexpr_builtin(__builtin_cbrt)
+#error This builtin should not be constexpr in Clang
+#endif
+
+#if  __has_constexpr_builtin(__builtin_insanity)
+#error This is not a builtin in Clang
+#endif
Index: clang/lib/Lex/PPMacroExpansion.cpp
===
--- clang/lib/Lex/PPMacroExpansion.cpp
+++ clang/lib/Lex/PPMacroExpansion.cpp
@@ -367,11 +367,13 @@
   }
 
   // Clang Extensions.
-  Ident__FILE_NAME__  = RegisterBuiltinMacro(*this, "__FILE_NAME__");
-  Ident__has_feature  = RegisterBuiltinMacro(*this, "__has_feature");
-  Ident__has_extension= RegisterBuiltinMacro(*this, "__has_extension");
-  Ident__has_builtin  = RegisterBuiltinMacro(*this, "__has_builtin");
-  Ident__has_attribute= RegisterBuiltinMacro(*this, "__has_attribute");
+  Ident__FILE_NAME__ = RegisterBuiltinMacro(*this, "__FILE_NAME__");
+  Ident__has_feature = RegisterBuiltinMacro(*this, "__has_feature");
+  Ident__has_extension = RegisterBuiltinMacro(*this, "__has_extension");
+  Ident__has_builtin = RegisterBuiltinMacro(*this, "__has_builtin");
+  Ident__has_constexpr_builtin =
+  RegisterBuiltinMacro(*this, "__has_constexpr_builtin");
+  Ident__has_attribute = RegisterBuiltinMacro(*this, "__has_attribute");
   if (!getLangOpts().CPlusPlus)
 Ident__has_c_attribute = RegisterBuiltinMacro(*this, "__has_c_attribute");
   else
@@ -1735,6 +1737,18 @@
   .Default(false);
 }
   });
+  } else if (II == Ident__has_constexpr_builtin) {
+EvaluateFeatureLikeBuiltinMacro(
+OS, Tok, II, *this, false,
+[this](Token &Tok, bool &HasLexedNextToken) -> int {
+  IdentifierInfo *II = ExpectFeatureIdentifierInfo(
+  Tok, *this, diag::err_feature_check_malformed);
+  if (!II)
+return false;
+  unsigned BuiltinOp = II->getBuiltinID();
+  return BuiltinOp != 0 &&
+ this->getBuiltinInfo().isConstantEvaluated(BuiltinOp);
+});
   } else if (II == Ident__is_identifier) {
 EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this, false,
   [](Token &Tok, bool &HasLexedNextToken) -> int {
@@ -1763,8 +1777,7 @@
 
 return false;
   });
-  } else if (II == Ident__has_cpp_attribute ||
- II == Ident__has_c_attribute) {
+  } else if (II == Ident__has_cpp_attribute || II == Ident__has_c_attribute) {
 bool IsCXX = II == Ident__has_cpp_attribute;
 EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this, true,
 [&](Token &Tok, bool &HasLexedNextToken) -> int {
@@ -1794,8 +1807,7 @@
getLangOpts())
 : 0;
 });
-  } else if (II == Ident__has_include ||
- II == Ident__has_include_next) {
+  } else if (II == Ident__has_include || II == Ident__has_include_next) {
 // The argument to these two builtins should be a parenthesized
 // file name string literal using angle brackets (<>) or
 // double-quotes ("").
Index: clang/lib/AST/ExprConstant.cpp
===
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -1954,8 +1954,8 @@
   return true;
 }
 
-/// Should this call expression be treated as a constant?
-static bool IsConstantCall(const CallExpr *E) {
+/// Should this call expression be treated as a no-op?
+static bool IsNoOpCall(const CallExpr *E) {
   unsigned Builtin = E->getBuiltinCallee();
   return (Builtin == Builtin::BI__builtin___CFStringMakeConstantString ||
   Builtin == Builtin::BI__builtin___NSStringMakeConstantString ||
@@ -2006,7 +2006,7 @@
   case Expr::ObjCBoxedExprClass:
 return cast(E)->isExpressibleAsConstantInitializer();
   case Expr::CallExprClass:
-return IsConstantCall(cast(E));
+return IsNoOpCall(cast(E));
   // For GCC compatibility, &&label has static storage duration.
   case Expr::AddrLabelExprClass:
 

[PATCH] D136036: [Clang] Add __has_builtin_constexpr support

2022-10-16 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 468063.
Izaron added a comment.

Slightly changed the test.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136036

Files:
  clang/include/clang/Basic/Builtins.def
  clang/include/clang/Basic/Builtins.h
  clang/include/clang/Lex/Preprocessor.h
  clang/lib/AST/ExprConstant.cpp
  clang/lib/Lex/PPMacroExpansion.cpp
  clang/test/Preprocessor/feature_tests.cpp

Index: clang/test/Preprocessor/feature_tests.cpp
===
--- clang/test/Preprocessor/feature_tests.cpp
+++ clang/test/Preprocessor/feature_tests.cpp
@@ -42,3 +42,17 @@
 #if __has_builtin(__builtin_insanity)
 #error Clang should not have this
 #endif
+
+// Check __has_constexpr_builtin
+#if  !__has_constexpr_builtin(__builtin_fmax) || \
+ !__has_constexpr_builtin(__builtin_fmin)
+#error Clang should have these constexpr builtins
+#endif
+
+#if  __has_constexpr_builtin(__builtin_cbrt)
+#error This builtin should not be constexpr in Clang
+#endif
+
+#if  __has_constexpr_builtin(__builtin_insanity)
+#error This is not a builtin in Clang
+#endif
Index: clang/lib/Lex/PPMacroExpansion.cpp
===
--- clang/lib/Lex/PPMacroExpansion.cpp
+++ clang/lib/Lex/PPMacroExpansion.cpp
@@ -367,11 +367,13 @@
   }
 
   // Clang Extensions.
-  Ident__FILE_NAME__  = RegisterBuiltinMacro(*this, "__FILE_NAME__");
-  Ident__has_feature  = RegisterBuiltinMacro(*this, "__has_feature");
-  Ident__has_extension= RegisterBuiltinMacro(*this, "__has_extension");
-  Ident__has_builtin  = RegisterBuiltinMacro(*this, "__has_builtin");
-  Ident__has_attribute= RegisterBuiltinMacro(*this, "__has_attribute");
+  Ident__FILE_NAME__ = RegisterBuiltinMacro(*this, "__FILE_NAME__");
+  Ident__has_feature = RegisterBuiltinMacro(*this, "__has_feature");
+  Ident__has_extension = RegisterBuiltinMacro(*this, "__has_extension");
+  Ident__has_builtin = RegisterBuiltinMacro(*this, "__has_builtin");
+  Ident__has_constexpr_builtin =
+  RegisterBuiltinMacro(*this, "__has_constexpr_builtin");
+  Ident__has_attribute = RegisterBuiltinMacro(*this, "__has_attribute");
   if (!getLangOpts().CPlusPlus)
 Ident__has_c_attribute = RegisterBuiltinMacro(*this, "__has_c_attribute");
   else
@@ -1735,6 +1737,18 @@
   .Default(false);
 }
   });
+  } else if (II == Ident__has_constexpr_builtin) {
+EvaluateFeatureLikeBuiltinMacro(
+OS, Tok, II, *this, false,
+[this](Token &Tok, bool &HasLexedNextToken) -> int {
+  IdentifierInfo *II = ExpectFeatureIdentifierInfo(
+  Tok, *this, diag::err_feature_check_malformed);
+  if (!II)
+return false;
+  unsigned BuiltinOp = II->getBuiltinID();
+  return BuiltinOp != 0 &&
+ this->getBuiltinInfo().isConstantEvaluated(BuiltinOp);
+});
   } else if (II == Ident__is_identifier) {
 EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this, false,
   [](Token &Tok, bool &HasLexedNextToken) -> int {
@@ -1763,8 +1777,7 @@
 
 return false;
   });
-  } else if (II == Ident__has_cpp_attribute ||
- II == Ident__has_c_attribute) {
+  } else if (II == Ident__has_cpp_attribute || II == Ident__has_c_attribute) {
 bool IsCXX = II == Ident__has_cpp_attribute;
 EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this, true,
 [&](Token &Tok, bool &HasLexedNextToken) -> int {
@@ -1794,8 +1807,7 @@
getLangOpts())
 : 0;
 });
-  } else if (II == Ident__has_include ||
- II == Ident__has_include_next) {
+  } else if (II == Ident__has_include || II == Ident__has_include_next) {
 // The argument to these two builtins should be a parenthesized
 // file name string literal using angle brackets (<>) or
 // double-quotes ("").
Index: clang/lib/AST/ExprConstant.cpp
===
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -1954,8 +1954,8 @@
   return true;
 }
 
-/// Should this call expression be treated as a constant?
-static bool IsConstantCall(const CallExpr *E) {
+/// Should this call expression be treated as a no-op?
+static bool IsNoOpCall(const CallExpr *E) {
   unsigned Builtin = E->getBuiltinCallee();
   return (Builtin == Builtin::BI__builtin___CFStringMakeConstantString ||
   Builtin == Builtin::BI__builtin___NSStringMakeConstantString ||
@@ -2006,7 +2006,7 @@
   case Expr::ObjCBoxedExprClass:
 return cast(E)->isExpressibleAsConstantInitializer();
   case Expr::CallExprClass:
-return IsConstantCall(cast(E));
+return IsNoOpCall(cast(E));
   // For GCC compatibility, &&label has static storage duration.
   case Expr::AddrLabelExprClass:
 return true;
@@ -7405,6 +7405,12 @@
 
   bool ZeroIni

[PATCH] D136036: [Clang] Add __has_builtin_constexpr support

2022-10-16 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added a comment.

A builtin is considered "constexpr" if it has `E` in its attributes in 
`Builtins.def`.

The list of constexpr builtins is consistent, the code in `ExprConstant.cpp` 
(where the actual constant evaluation of builtins is being done) guards it.
If builtin is not marked with `E`, it surely won't be evaluated, and vice versa 
- if builtin is marked but there is no code for evaluating it, there is a 
`llvm_unreachable`.

This macro will be needed because we are making constexpr `` and 
``. We will conditionally make the functions constexpr until all 
supported compilers have full support.

We had a discussion where we found out that we need `__has_builtin_constexpr`: 
https://discourse.llvm.org/t/how-do-we-plan-to-make-constexpr-cmath-and-cstdlib/65930
 Please read it if you wonder why we need it =) Thank you for your attention!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136036

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


[PATCH] D136036: [Clang] Add __has_builtin_constexpr support

2022-10-16 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron created this revision.
Izaron added reviewers: rsmith, aaron.ballman, cor3ntin, philnik, yaxunl, tra, 
cjdb.
Herald added a project: All.
Izaron requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

The `__has_builtin_constexpr` macro can be used to check
whether the builtin in constant-evaluated by Clang frontend.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D136036

Files:
  clang/include/clang/Basic/Builtins.def
  clang/include/clang/Basic/Builtins.h
  clang/include/clang/Lex/Preprocessor.h
  clang/lib/AST/ExprConstant.cpp
  clang/lib/Lex/PPMacroExpansion.cpp
  clang/test/Preprocessor/feature_tests.cpp

Index: clang/test/Preprocessor/feature_tests.cpp
===
--- clang/test/Preprocessor/feature_tests.cpp
+++ clang/test/Preprocessor/feature_tests.cpp
@@ -42,3 +42,17 @@
 #if __has_builtin(__builtin_insanity)
 #error Clang should not have this
 #endif
+
+// Check __has_constexpr_builtin
+#if  !__has_constexpr_builtin(__builtin_fmax) || \
+ !__has_builtin(__builtin_fmin)
+#error Clang should have these constexpr builtins
+#endif
+
+#if  __has_constexpr_builtin(__builtin_cbrt)
+#error This builtin should not be constexpr in Clang
+#endif
+
+#if  __has_constexpr_builtin(__builtin_insanity)
+#error This is not a builtin in Clang
+#endif
Index: clang/lib/Lex/PPMacroExpansion.cpp
===
--- clang/lib/Lex/PPMacroExpansion.cpp
+++ clang/lib/Lex/PPMacroExpansion.cpp
@@ -367,11 +367,13 @@
   }
 
   // Clang Extensions.
-  Ident__FILE_NAME__  = RegisterBuiltinMacro(*this, "__FILE_NAME__");
-  Ident__has_feature  = RegisterBuiltinMacro(*this, "__has_feature");
-  Ident__has_extension= RegisterBuiltinMacro(*this, "__has_extension");
-  Ident__has_builtin  = RegisterBuiltinMacro(*this, "__has_builtin");
-  Ident__has_attribute= RegisterBuiltinMacro(*this, "__has_attribute");
+  Ident__FILE_NAME__ = RegisterBuiltinMacro(*this, "__FILE_NAME__");
+  Ident__has_feature = RegisterBuiltinMacro(*this, "__has_feature");
+  Ident__has_extension = RegisterBuiltinMacro(*this, "__has_extension");
+  Ident__has_builtin = RegisterBuiltinMacro(*this, "__has_builtin");
+  Ident__has_constexpr_builtin =
+  RegisterBuiltinMacro(*this, "__has_constexpr_builtin");
+  Ident__has_attribute = RegisterBuiltinMacro(*this, "__has_attribute");
   if (!getLangOpts().CPlusPlus)
 Ident__has_c_attribute = RegisterBuiltinMacro(*this, "__has_c_attribute");
   else
@@ -1735,6 +1737,18 @@
   .Default(false);
 }
   });
+  } else if (II == Ident__has_constexpr_builtin) {
+EvaluateFeatureLikeBuiltinMacro(
+OS, Tok, II, *this, false,
+[this](Token &Tok, bool &HasLexedNextToken) -> int {
+  IdentifierInfo *II = ExpectFeatureIdentifierInfo(
+  Tok, *this, diag::err_feature_check_malformed);
+  if (!II)
+return false;
+  unsigned BuiltinOp = II->getBuiltinID();
+  return BuiltinOp != 0 &&
+ this->getBuiltinInfo().isConstantEvaluated(BuiltinOp);
+});
   } else if (II == Ident__is_identifier) {
 EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this, false,
   [](Token &Tok, bool &HasLexedNextToken) -> int {
@@ -1763,8 +1777,7 @@
 
 return false;
   });
-  } else if (II == Ident__has_cpp_attribute ||
- II == Ident__has_c_attribute) {
+  } else if (II == Ident__has_cpp_attribute || II == Ident__has_c_attribute) {
 bool IsCXX = II == Ident__has_cpp_attribute;
 EvaluateFeatureLikeBuiltinMacro(OS, Tok, II, *this, true,
 [&](Token &Tok, bool &HasLexedNextToken) -> int {
@@ -1794,8 +1807,7 @@
getLangOpts())
 : 0;
 });
-  } else if (II == Ident__has_include ||
- II == Ident__has_include_next) {
+  } else if (II == Ident__has_include || II == Ident__has_include_next) {
 // The argument to these two builtins should be a parenthesized
 // file name string literal using angle brackets (<>) or
 // double-quotes ("").
Index: clang/lib/AST/ExprConstant.cpp
===
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -1954,8 +1954,8 @@
   return true;
 }
 
-/// Should this call expression be treated as a constant?
-static bool IsConstantCall(const CallExpr *E) {
+/// Should this call expression be treated as a no-op?
+static bool IsNoOpCall(const CallExpr *E) {
   unsigned Builtin = E->getBuiltinCallee();
   return (Builtin == Builtin::BI__builtin___CFStringMakeConstantString ||
   Builtin == Builtin::BI__builtin___NSStringMakeConstantString ||
@@ -2006,7 +2006,7 @@
   case Expr::ObjCBoxedExprClass:
 return cast(E)->isExpressibleAsConstantInitializer();
   case Expr::CallExprClass:
-return IsConstantCal

[PATCH] D136022: [clang] Add time profile for constant evaluation

2022-10-15 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added a comment.

We can use this file as an example: `ConstProfiler.cpp` 
https://reviews.llvm.org/P8296
The code does a really big constant evaluation.

This is the generated json **before** the patch: `before.json` 
https://reviews.llvm.org/P8294
Giving this json to https://www.speedscope.app/, we get a big empty gap where 
the constant evaluation is being done.
link to screenshot 


This is the generated json **after** the patch: `after.json` 
https://reviews.llvm.org/P8295
The empty gap is filled with four events.
link to screenshot 


You can use this command for generating the json:

  clang++ ConstProfiler.cpp -std=c++20 -c -ftime-trace 
-ftime-trace-granularity=50

P.S. I'm not sure how to write tests to cover the patch, but I'll find this out 
=)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136022

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


[PATCH] D136022: [clang] Add time profile for constant evaluation

2022-10-15 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron created this revision.
Izaron added reviewers: aaron.ballman, cor3ntin, anton-afanasyev, mbs-modular, 
jloser.
Herald added a project: All.
Izaron requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Add time profiler for various constexpr evaluation events
so that slow event could be visible on the visualized flame chart.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D136022

Files:
  clang/lib/AST/ExprConstant.cpp
  clang/lib/Sema/SemaDeclCXX.cpp
  clang/lib/Sema/SemaExpr.cpp


Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -55,6 +55,7 @@
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/ConvertUTF.h"
 #include "llvm/Support/SaveAndRestore.h"
+#include "llvm/Support/TimeProfiler.h"
 #include "llvm/Support/TypeSize.h"
 
 using namespace clang;
@@ -17538,8 +17539,14 @@
   Expr::EvalResult Eval;
   Eval.Diag = &Notes;
   ConstantExpr *CE = Candidate.getPointer();
-  bool Result = CE->EvaluateAsConstantExpr(
-  Eval, SemaRef.getASTContext(), ConstantExprKind::ImmediateInvocation);
+  bool Result;
+  {
+llvm::TimeTraceScope TimeScope("EvaluateAsConstantExpr", [&] {
+  return CE->getSourceRange().printToString(SemaRef.getSourceManager());
+});
+Result = CE->EvaluateAsConstantExpr(Eval, SemaRef.getASTContext(),
+ConstantExprKind::ImmediateInvocation);
+  }
   if (!Result || !Notes.empty()) {
 Expr *InnerExpr = CE->getSubExpr()->IgnoreImplicit();
 if (auto *FunctionalCast = dyn_cast(InnerExpr))
Index: clang/lib/Sema/SemaDeclCXX.cpp
===
--- clang/lib/Sema/SemaDeclCXX.cpp
+++ clang/lib/Sema/SemaDeclCXX.cpp
@@ -41,10 +41,11 @@
 #include "clang/Sema/ScopeInfo.h"
 #include "clang/Sema/SemaInternal.h"
 #include "clang/Sema/Template.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/TimeProfiler.h"
 #include 
 #include 
 
@@ -1736,6 +1737,14 @@
 // This implements C++11 [dcl.constexpr]p3,4, as amended by DR1360.
 bool Sema::CheckConstexprFunctionDefinition(const FunctionDecl *NewFD,
 CheckConstexprKind Kind) {
+  llvm::TimeTraceScope TimeScope("CheckConstexprFunctionDefinition", [&] {
+std::string Name;
+llvm::raw_string_ostream OS(Name);
+NewFD->getNameForDiagnostic(OS, Context.getPrintingPolicy(),
+/*Qualified=*/true);
+return Name;
+  });
+
   const CXXMethodDecl *MD = dyn_cast(NewFD);
   if (MD && MD->isInstance()) {
 // C++11 [dcl.constexpr]p4:
Index: clang/lib/AST/ExprConstant.cpp
===
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -56,6 +56,7 @@
 #include "llvm/ADT/SmallBitVector.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/SaveAndRestore.h"
+#include "llvm/Support/TimeProfiler.h"
 #include "llvm/Support/raw_ostream.h"
 #include 
 #include 
@@ -15247,6 +15248,13 @@
   assert(!isValueDependent() &&
  "Expression evaluator can't be called on a dependent expression.");
 
+  llvm::TimeTraceScope TimeScope("EvaluateAsInitializer", [&] {
+std::string Name;
+llvm::raw_string_ostream OS(Name);
+VD->printQualifiedName(OS);
+return Name;
+  });
+
   // FIXME: Evaluating initializers for large array and record types can cause
   // performance problems. Only do so in C++11 for now.
   if (isPRValue() && (getType()->isArrayType() || getType()->isRecordType()) &&


Index: clang/lib/Sema/SemaExpr.cpp
===
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -55,6 +55,7 @@
 #include "llvm/Support/Casting.h"
 #include "llvm/Support/ConvertUTF.h"
 #include "llvm/Support/SaveAndRestore.h"
+#include "llvm/Support/TimeProfiler.h"
 #include "llvm/Support/TypeSize.h"
 
 using namespace clang;
@@ -17538,8 +17539,14 @@
   Expr::EvalResult Eval;
   Eval.Diag = &Notes;
   ConstantExpr *CE = Candidate.getPointer();
-  bool Result = CE->EvaluateAsConstantExpr(
-  Eval, SemaRef.getASTContext(), ConstantExprKind::ImmediateInvocation);
+  bool Result;
+  {
+llvm::TimeTraceScope TimeScope("EvaluateAsConstantExpr", [&] {
+  return CE->getSourceRange().printToString(SemaRef.getSourceManager());
+});
+Result = CE->EvaluateAsConstantExpr(Eval, SemaRef.getASTContext(),
+ConstantExprKind::ImmediateInvocation);
+  }
   if (!Result || !Notes.empty()) {
 Expr *InnerExpr = CE->getSubExpr()->IgnoreImplicit();
 if (auto *FunctionalCast = dyn_cast(InnerExpr))
Index: clang/lib/Sema/SemaDeclCXX.cpp

[PATCH] D135822: [clang-tidy] Add option `IgnoreVoidReturnType` to `modernize-use-trailing-return-type`

2022-10-13 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 467590.
Izaron added a comment.

Change `IgnoreVoidReturnType` to `RewriteVoidReturn` type.
Check the cheaper condition first.

A big thank to @bernhardmgruber for nice comments!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D135822

Files:
  clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/modernize/use-trailing-return-type.rst
  
clang-tools-extra/test/clang-tidy/checkers/modernize/use-trailing-return-type-cxx20.cpp
  
clang-tools-extra/test/clang-tidy/checkers/modernize/use-trailing-return-type-void.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-trailing-return-type-void.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-trailing-return-type-void.cpp
@@ -0,0 +1,25 @@
+// RUN: %check_clang_tidy %s modernize-use-trailing-return-type %t -- \
+// RUN:   -config="{CheckOptions: [{key: modernize-use-trailing-return-type.RewriteVoidReturnType, value: true}]}"
+
+void c();
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto c() -> void;{{$}}
+void c(int arg);
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto c(int arg) -> void;{{$}}
+void c(int arg) { return; }
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto c(int arg) -> void { return; }{{$}}
+
+//
+// Samples which do not trigger the check
+//
+
+auto f() -> void;
+auto f(int arg) -> void;
+auto f(int arg) -> void { return; }
+
+class C {
+C() {}
+~C() {}
+};
Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-trailing-return-type-cxx20.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/use-trailing-return-type-cxx20.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-trailing-return-type-cxx20.cpp
@@ -67,6 +67,7 @@
   static strong_ordering const greater;
 
   constexpr strong_ordering(value_type v) : val(v) {}
+  constexpr ~strong_ordering() = default;
   template 
   requires(T{0}) friend constexpr auto
   operator==(strong_ordering v, T u) noexcept -> bool {
Index: clang-tools-extra/docs/clang-tidy/checks/modernize/use-trailing-return-type.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/modernize/use-trailing-return-type.rst
+++ clang-tools-extra/docs/clang-tidy/checks/modernize/use-trailing-return-type.rst
@@ -66,3 +66,11 @@
 This code fails to compile because the S in the context of f refers to the equally named function parameter.
 Similarly, the S in the context of m refers to the equally named class member.
 The check can currently only detect and avoid a clash with a function parameter name.
+
+Options
+---
+
+.. option:: RewriteVoidReturnType
+
+   When `true`, the check will rewrite function signature for functions
+   with void return type. Default is `false`.
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -175,6 +175,12 @@
   The check now skips concept definitions since redundant expressions still make sense
   inside them.
 
+- Improved :doc:`modernize-use-trailing-return-type `
+  check.
+
+  The check now has a new option `RewriteVoidReturnType` which indicates if the
+  check should rewrite function signature for functions with void return type.
+
 Removed checks
 ^^
 
Index: clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.h
===
--- clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.h
+++ clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.h
@@ -28,11 +28,11 @@
 /// http://clang.llvm.org/extra/clang-tidy/checks/modernize/use-trailing-type-return.html
 class UseTrailingReturnTypeCheck : public ClangTidyCheck {
 public:
-  UseTrailingReturnTypeCheck(StringRef Name, ClangTidyContext *Context)
-  : ClangTidyCheck(Name, Context) {}
+  UseTrailingReturnTypeCheck(StringRef Name, ClangTidyContext *Context);
   bool isLanguageVersionSupported(const LangOptions &LangOpts) const override {
 return LangOpts.CPlusPlus11;
   }
+  void storeOptions(ClangTidyOptions::OptionMap &Opts) override;
   void registerMatchers(ast_matchers::MatchFinder *Finder) override;
   void regi

[PATCH] D135822: [clang-tidy] Add option `IgnoreVoidReturnType` to `modernize-use-trailing-return-type`

2022-10-12 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added inline comments.



Comment at: 
clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp:398-400
+  auto F = functionDecl(unless(anyOf(hasTrailingReturn(), cxxConstructorDecl(),
+ cxxDestructorDecl(), cxxConversionDecl(),
+ cxxMethodDecl(isImplicit()

ctors/dtors are `voidType`, so we need to add filters for them when removing 
filter for `voidType`


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D135822

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


[PATCH] D135822: [clang-tidy] Add option `IgnoreVoidReturnType` to `modernize-use-trailing-return-type`

2022-10-12 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron created this revision.
Izaron added reviewers: salman-javed-nz, aaron.ballman, bernhardmgruber, 
bkramer, kbobyrev.
Herald added subscribers: carlosgalvezp, xazax.hun.
Herald added a project: All.
Izaron requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

The check doesn't trigger for functions returning void. The new options
is added to allow to have a complete homogeneous code.

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


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D135822

Files:
  clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  
clang-tools-extra/docs/clang-tidy/checks/modernize/use-trailing-return-type.rst
  
clang-tools-extra/test/clang-tidy/checkers/modernize/use-trailing-return-type-cxx20.cpp
  
clang-tools-extra/test/clang-tidy/checkers/modernize/use-trailing-return-type-void.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-trailing-return-type-void.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-trailing-return-type-void.cpp
@@ -0,0 +1,25 @@
+// RUN: %check_clang_tidy %s modernize-use-trailing-return-type %t -- \
+// RUN:   -config="{CheckOptions: [{key: modernize-use-trailing-return-type.IgnoreVoidReturnType, value: false}]}"
+
+void c();
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto c() -> void;{{$}}
+void c(int arg);
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto c(int arg) -> void;{{$}}
+void c(int arg) { return; }
+// CHECK-MESSAGES: :[[@LINE-1]]:6: warning: use a trailing return type for this function [modernize-use-trailing-return-type]
+// CHECK-FIXES: {{^}}auto c(int arg) -> void { return; }{{$}}
+
+//
+// Samples which do not trigger the check
+//
+
+auto f() -> void;
+auto f(int arg) -> void;
+auto f(int arg) -> void { return; }
+
+class C {
+C() {}
+~C() {}
+};
Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-trailing-return-type-cxx20.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/modernize/use-trailing-return-type-cxx20.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-trailing-return-type-cxx20.cpp
@@ -67,6 +67,7 @@
   static strong_ordering const greater;
 
   constexpr strong_ordering(value_type v) : val(v) {}
+  constexpr ~strong_ordering() = default;
   template 
   requires(T{0}) friend constexpr auto
   operator==(strong_ordering v, T u) noexcept -> bool {
Index: clang-tools-extra/docs/clang-tidy/checks/modernize/use-trailing-return-type.rst
===
--- clang-tools-extra/docs/clang-tidy/checks/modernize/use-trailing-return-type.rst
+++ clang-tools-extra/docs/clang-tidy/checks/modernize/use-trailing-return-type.rst
@@ -66,3 +66,11 @@
 This code fails to compile because the S in the context of f refers to the equally named function parameter.
 Similarly, the S in the context of m refers to the equally named class member.
 The check can currently only detect and avoid a clash with a function parameter name.
+
+Options
+---
+
+.. option:: IgnoreVoidReturnType
+
+   When `true`, the check will not rewrite function signature for functions
+   with void return type. Default is `true`.
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -175,6 +175,12 @@
   The check now skips concept definitions since redundant expressions still make sense
   inside them.
 
+- Improved :doc:`modernize-use-trailing-return-type `
+  check.
+
+  The check now has a new option `IgnoreVoidReturnType` which indicates if the
+  check should rewrite function signature for functions with void return type.
+
 Removed checks
 ^^
 
Index: clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.h
===
--- clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.h
+++ clang-tools-extra/clang-tidy/modernize/UseTrailingReturnTypeCheck.h
@@ -28,11 +28,11 @@
 /// http://clang.llvm.org/extra/clang-tidy/checks/modernize/use-trailing-type-return.html
 class UseTrailingReturnTypeCheck : public ClangTidyCheck {
 public:
-  UseTrailingReturnTypeCheck(StringRef Name, ClangTidyContext *Context)
-  : ClangTidyCheck(Name, Context) {}
+  UseTrailingReturnTypeCheck(StringRef Name, ClangTidyContext *Context);
   bool isLanguageVersionSupported(c

[PATCH] D118743: [clang-tidy] Add `modernize-use-inline-const-variables-in-headers` check

2022-10-10 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 41.
Izaron added a comment.

Removed excessive newline.

Thanks to @Eugene.Zelenko!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D118743

Files:
  clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
  clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
  
clang-tools-extra/clang-tidy/modernize/UseInlineConstVariablesInHeadersCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseInlineConstVariablesInHeadersCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/docs/clang-tidy/checks/modernize/use-inline-const-variables-in-headers.rst
  
clang-tools-extra/test/clang-tidy/checkers/modernize/use-inline-const-variables-in-headers.hpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-inline-const-variables-in-headers.hpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-inline-const-variables-in-headers.hpp
@@ -0,0 +1,43 @@
+// RUN: %check_clang_tidy %s -std=c++17 modernize-use-inline-const-variables-in-headers %t
+
+const int ConstFoo = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: global constant 'ConstFoo' should be marked as 'inline' [modernize-use-inline-const-variables-in-headers]
+// CHECK-FIXES: {{^}}inline const int ConstFoo = 1;{{$}}
+
+namespace N {
+constexpr int NamespaceFoo = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: global constant 'NamespaceFoo' should be marked as 'inline' [modernize-use-inline-const-variables-in-headers]
+// CHECK-FIXES: {{^}}inline constexpr int NamespaceFoo = 1;{{$}}
+} // namespace N
+
+extern const int ExternFoo;
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: global constant 'ExternFoo' should be converted to C++17 'inline variable' [modernize-use-inline-const-variables-in-headers]
+
+struct S {
+  // no warning: the variable is not at file scope
+  static const int StructFoo = 1;
+};
+
+// no warning: non-const global variables have external linkage
+int NonConstFoo = 1;
+
+// no warning: volatile global variables have external linkage
+const volatile int VolatileFoo = 1;
+
+// no warning: templates and their instantiations have external linkage
+template 
+const auto TemplateFoo = sizeof(T);
+
+// no warning: already fixed
+inline const int InlineFoo = 1;
+
+// no warning: C has no 'inline variables'
+extern "C" {
+const int CFoo0 = 1;
+}
+extern "C" const int CFoo1 = 1;
+
+// no warning: 'inline' is invisible when within an unnamed namespace
+namespace {
+const int AnonNamespaceFoo = 1;
+} // namespace
Index: clang-tools-extra/docs/clang-tidy/checks/modernize/use-inline-const-variables-in-headers.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/modernize/use-inline-const-variables-in-headers.rst
@@ -0,0 +1,68 @@
+.. title:: clang-tidy - modernize-use-inline-const-variables-in-headers
+
+modernize-use-inline-const-variables-in-headers
+===
+
+Suggests switching to C++17 ``inline variables`` for non-inline const
+variable definitions and extern const variable declarations in header files.
+Non-inline const variables make a separate instance of the variable for each
+translation unit that includes the header, which can lead to subtle violation
+of the ODR. Extern const variables are a deprecated way to define a constant
+since C++17.
+
+.. code-block:: c++
+
+   // Foo.h
+   const int ConstFoo = 1; // Warning: should be marked as 'inline'
+
+   namespace N {
+ constexpr int NamespaceFoo = 1; // Warning: should be marked as 'inline'
+   }
+
+   extern const int ExternFoo; // Warning: should be converted to C++17 'inline variable'
+
+   struct S {
+ static const int StructFoo = 1; // OK: the variable is not at file scope
+   };
+
+   int NonConstFoo = 1; // No warning: non-const global variables have external linkage
+
+   const volatile int VolatileFoo = 1; // No warning: volatile global variables have external linkage
+
+   template
+   const auto TemplateFoo = sizeof(T); // OK: templates and their instantiations have external linkage
+
+   inline const int InlineFoo = 1; // no warning: already fixed
+
+   // No warning: C has no 'inline variables'
+   extern "C" {
+ const int CFoo0 = 1;
+   }
+   extern "C" const int CFoo1 = 1;
+
+   // No warning: 'inline' is invisible when within an unnamed namespace
+   namespace {
+ const int AnonNamespaceFoo = 1;
+   }
+
+Options
+---
+
+.. option:: HeaderFileExtensions
+
+   A comma-separated list of filename extensions of header files (the filename
+   extensions should not include "." prefix). Default is `h,hh,hpp,hxx`.
+   For header files without an extension, use an empty string (if there are no
+   other desired extensions) or leave an empty element in the list. 

[PATCH] D118743: [clang-tidy] Add `modernize-use-inline-const-variables-in-headers` check

2022-10-10 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 40.
Izaron added a comment.

Rebased onto main (after a long long time).

Thanks to @LegalizeAdulthood for instructions!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D118743

Files:
  clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
  clang-tools-extra/clang-tidy/modernize/ModernizeTidyModule.cpp
  
clang-tools-extra/clang-tidy/modernize/UseInlineConstVariablesInHeadersCheck.cpp
  clang-tools-extra/clang-tidy/modernize/UseInlineConstVariablesInHeadersCheck.h
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/docs/clang-tidy/checks/list.rst
  
clang-tools-extra/docs/clang-tidy/checks/modernize/use-inline-const-variables-in-headers.rst
  
clang-tools-extra/test/clang-tidy/checkers/modernize/use-inline-const-variables-in-headers.hpp

Index: clang-tools-extra/test/clang-tidy/checkers/modernize/use-inline-const-variables-in-headers.hpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/modernize/use-inline-const-variables-in-headers.hpp
@@ -0,0 +1,43 @@
+// RUN: %check_clang_tidy %s -std=c++17 modernize-use-inline-const-variables-in-headers %t
+
+const int ConstFoo = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:11: warning: global constant 'ConstFoo' should be marked as 'inline' [modernize-use-inline-const-variables-in-headers]
+// CHECK-FIXES: {{^}}inline const int ConstFoo = 1;{{$}}
+
+namespace N {
+constexpr int NamespaceFoo = 1;
+// CHECK-MESSAGES: :[[@LINE-1]]:15: warning: global constant 'NamespaceFoo' should be marked as 'inline' [modernize-use-inline-const-variables-in-headers]
+// CHECK-FIXES: {{^}}inline constexpr int NamespaceFoo = 1;{{$}}
+} // namespace N
+
+extern const int ExternFoo;
+// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: global constant 'ExternFoo' should be converted to C++17 'inline variable' [modernize-use-inline-const-variables-in-headers]
+
+struct S {
+  // no warning: the variable is not at file scope
+  static const int StructFoo = 1;
+};
+
+// no warning: non-const global variables have external linkage
+int NonConstFoo = 1;
+
+// no warning: volatile global variables have external linkage
+const volatile int VolatileFoo = 1;
+
+// no warning: templates and their instantiations have external linkage
+template 
+const auto TemplateFoo = sizeof(T);
+
+// no warning: already fixed
+inline const int InlineFoo = 1;
+
+// no warning: C has no 'inline variables'
+extern "C" {
+const int CFoo0 = 1;
+}
+extern "C" const int CFoo1 = 1;
+
+// no warning: 'inline' is invisible when within an unnamed namespace
+namespace {
+const int AnonNamespaceFoo = 1;
+} // namespace
Index: clang-tools-extra/docs/clang-tidy/checks/modernize/use-inline-const-variables-in-headers.rst
===
--- /dev/null
+++ clang-tools-extra/docs/clang-tidy/checks/modernize/use-inline-const-variables-in-headers.rst
@@ -0,0 +1,69 @@
+.. title:: clang-tidy - modernize-use-inline-const-variables-in-headers
+
+modernize-use-inline-const-variables-in-headers
+===
+
+
+Suggests switching to C++17 ``inline variables`` for non-inline const
+variable definitions and extern const variable declarations in header files.
+Non-inline const variables make a separate instance of the variable for each
+translation unit that includes the header, which can lead to subtle violation
+of the ODR. Extern const variables are a deprecated way to define a constant
+since C++17.
+
+.. code-block:: c++
+
+   // Foo.h
+   const int ConstFoo = 1; // Warning: should be marked as 'inline'
+
+   namespace N {
+ constexpr int NamespaceFoo = 1; // Warning: should be marked as 'inline'
+   }
+
+   extern const int ExternFoo; // Warning: should be converted to C++17 'inline variable'
+
+   struct S {
+ static const int StructFoo = 1; // OK: the variable is not at file scope
+   };
+
+   int NonConstFoo = 1; // No warning: non-const global variables have external linkage
+
+   const volatile int VolatileFoo = 1; // No warning: volatile global variables have external linkage
+
+   template
+   const auto TemplateFoo = sizeof(T); // OK: templates and their instantiations have external linkage
+
+   inline const int InlineFoo = 1; // no warning: already fixed
+
+   // No warning: C has no 'inline variables'
+   extern "C" {
+ const int CFoo0 = 1;
+   }
+   extern "C" const int CFoo1 = 1;
+
+   // No warning: 'inline' is invisible when within an unnamed namespace
+   namespace {
+ const int AnonNamespaceFoo = 1;
+   }
+
+Options
+---
+
+.. option:: HeaderFileExtensions
+
+   A comma-separated list of filename extensions of header files (the filename
+   extensions should not include "." prefix). Default is `h,hh,hpp,hxx`.
+   For header files without an extension, use an empty string (if there are no
+   other desired extensions) 

[PATCH] D135493: [Clang] Support constexpr builtin fmin

2022-10-10 Thread Evgeny Shulgin via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGec3238640440: [Clang] Support constexpr builtin fmin 
(authored by Izaron).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D135493

Files:
  clang/docs/LanguageExtensions.rst
  clang/lib/AST/ExprConstant.cpp
  clang/test/Sema/constant-builtins-fmin.cpp


Index: clang/test/Sema/constant-builtins-fmin.cpp
===
--- /dev/null
+++ clang/test/Sema/constant-builtins-fmin.cpp
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+constexpr double NaN = __builtin_nan("");
+constexpr double Inf = __builtin_inf();
+constexpr double NegInf = -__builtin_inf();
+
+#define FMIN_TEST_SIMPLE(T, FUNC)   \
+static_assert(T(1.2345) == FUNC(T(1.2345), T(6.7890))); \
+static_assert(T(1.2345) == FUNC(T(6.7890), T(1.2345)));
+
+#define FMIN_TEST_NAN(T, FUNC)  \
+static_assert(Inf == FUNC(NaN, Inf));   \
+static_assert(NegInf == FUNC(NegInf, NaN)); \
+static_assert(0.0 == FUNC(NaN, 0.0));   \
+static_assert(-0.0 == FUNC(-0.0, NaN)); \
+static_assert(T(-1.2345) == FUNC(NaN, T(-1.2345))); \
+static_assert(T(1.2345) == FUNC(T(1.2345), NaN));   \
+static_assert(__builtin_isnan(FUNC(NaN, NaN)));
+
+#define FMIN_TEST_INF(T, FUNC)\
+static_assert(NegInf == FUNC(NegInf, Inf));   \
+static_assert(0.0 == FUNC(Inf, 0.0)); \
+static_assert(-0.0 == FUNC(-0.0, Inf));   \
+static_assert(T(1.2345) == FUNC(Inf, T(1.2345))); \
+static_assert(T(-1.2345) == FUNC(T(-1.2345), Inf));
+
+#define FMIN_TEST_NEG_INF(T, FUNC) \
+static_assert(NegInf == FUNC(Inf, NegInf));\
+static_assert(NegInf == FUNC(NegInf, 0.0));\
+static_assert(NegInf == FUNC(-0.0, NegInf));   \
+static_assert(NegInf == FUNC(NegInf, T(-1.2345))); \
+static_assert(NegInf == FUNC(T(1.2345), NegInf));
+
+#define FMIN_TEST_BOTH_ZERO(T, FUNC) \
+static_assert(__builtin_copysign(1.0, FUNC(0.0, 0.0)) == 1.0);   \
+static_assert(__builtin_copysign(1.0, FUNC(-0.0, 0.0)) == -1.0); \
+static_assert(__builtin_copysign(1.0, FUNC(0.0, -0.0)) == -1.0); \
+static_assert(__builtin_copysign(1.0, FUNC(-0.0, -0.0)) == -1.0);
+
+#define LIST_FMIN_TESTS(T, FUNC) \
+FMIN_TEST_SIMPLE(T, FUNC)\
+FMIN_TEST_NAN(T, FUNC)   \
+FMIN_TEST_INF(T, FUNC)   \
+FMIN_TEST_NEG_INF(T, FUNC)   \
+FMIN_TEST_BOTH_ZERO(T, FUNC)
+
+LIST_FMIN_TESTS(double, __builtin_fmin)
+LIST_FMIN_TESTS(float, __builtin_fminf)
+LIST_FMIN_TESTS((long double), __builtin_fminl)
+LIST_FMIN_TESTS(__fp16, __builtin_fminf16)
+#ifdef __FLOAT128__
+LIST_FMIN_TESTS(__float128, __builtin_fminf128)
+#endif
Index: clang/lib/AST/ExprConstant.cpp
===
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -14041,6 +14041,24 @@
   Result = RHS;
 return true;
   }
+
+  case Builtin::BI__builtin_fmin:
+  case Builtin::BI__builtin_fminf:
+  case Builtin::BI__builtin_fminl:
+  case Builtin::BI__builtin_fminf16:
+  case Builtin::BI__builtin_fminf128: {
+// TODO: Handle sNaN.
+APFloat RHS(0.);
+if (!EvaluateFloat(E->getArg(0), Result, Info) ||
+!EvaluateFloat(E->getArg(1), RHS, Info))
+  return false;
+// When comparing zeroes, return -0.0 if one of the zeroes is negative.
+if (Result.isZero() && RHS.isZero() && RHS.isNegative())
+  Result = RHS;
+else if (Result.isNaN() || RHS < Result)
+  Result = RHS;
+return true;
+  }
   }
 }
 
Index: clang/docs/LanguageExtensions.rst
===
--- clang/docs/LanguageExtensions.rst
+++ clang/docs/LanguageExtensions.rst
@@ -4661,6 +4661,7 @@
 * ``__builtin_ffsl``
 * ``__builtin_ffsll``
 * ``__builtin_fmax``
+* ``__builtin_fmin``
 * ``__builtin_fpclassify``
 * ``__builtin_inf``
 * ``__builtin_isinf``


Index: clang/test/Sema/constant-builtins-fmin.cpp
===
--- /dev/null
+++ clang/test/Sema/constant-builtins-fmin.cpp
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+constexpr double NaN = __builtin_nan("");
+constexpr double Inf = __builtin_inf();
+constexpr double NegInf = -__builtin_inf();
+
+#define FMIN_TEST_SIMPLE(T, FUNC)   \
+static_assert(T(1.2345) == FUNC(T(1.2345), T(6.7890))); \
+static_assert(T(1.2345) == FUNC(T(6.7890), T(1.2345)));
+
+#define FMIN_TEST_NAN(T, FUNC)  \
+static_assert(Inf == FUNC(NaN, Inf));   \
+static_asser

[PATCH] D122078: [clang-tidy] Ignore concepts in `misc-redundant-expression`

2022-10-08 Thread Evgeny Shulgin via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGa8fbd1157deb: [clang-tidy] Ignore concepts in 
`misc-redundant-expression` (authored by Izaron).

Changed prior to commit:
  https://reviews.llvm.org/D122078?vs=466271&id=466273#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D122078

Files:
  clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression-cxx20.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression-cxx20.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression-cxx20.cpp
@@ -0,0 +1,11 @@
+// RUN: clang-tidy %s -checks=-*,misc-redundant-expression -- -std=c++20 | count 0
+
+namespace concepts {
+// redundant expressions inside concepts make sense, ignore them
+template 
+concept TestConcept = requires(I i) {
+  {i - i};
+  {i && i};
+  {i ? i : i};
+};
+} // namespace concepts
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -164,6 +164,12 @@
   :doc:`readability-simplify-boolean-expr `
   when using a C++23 ``if consteval`` statement.
 
+- Improved :doc:`misc-redundant-expression `
+  check.
+
+  The check now skips concept definitions since redundant expressions still make sense
+  inside them.
+
 Removed checks
 ^^
 
Index: clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
===
--- clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
+++ clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
@@ -10,6 +10,7 @@
 #include "../utils/Matchers.h"
 #include "../utils/OptionsUtils.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/ExprConcepts.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/SourceLocation.h"
@@ -440,6 +441,8 @@
   return Node.isIntegerConstantExpr(Finder->getASTContext());
 }
 
+AST_MATCHER(Expr, isRequiresExpr) { return isa(Node); }
+
 AST_MATCHER(BinaryOperator, operandsAreEquivalent) {
   return areEquivalentExpr(Node.getLHS(), Node.getRHS());
 }
@@ -858,6 +861,7 @@
 
   const auto BannedIntegerLiteral =
   integerLiteral(expandedByMacro(KnownBannedMacroNames));
+  const auto BannedAncestor = expr(isRequiresExpr());
 
   // Binary with equivalent operands, like (X != 2 && X != 2).
   Finder->addMatcher(
@@ -873,7 +877,8 @@
unless(hasType(realFloatingPointType())),
unless(hasEitherOperand(hasType(realFloatingPointType(,
unless(hasLHS(AnyLiteralExpr)),
-   unless(hasDescendant(BannedIntegerLiteral)))
+   unless(hasDescendant(BannedIntegerLiteral)),
+   unless(hasAncestor(BannedAncestor)))
.bind("binary")),
   this);
 
@@ -886,7 +891,8 @@
  unless(isInTemplateInstantiation()),
  unless(binaryOperatorIsInMacro()),
  // TODO: if the banned macros are themselves duplicated
- unless(hasDescendant(BannedIntegerLiteral)))
+ unless(hasDescendant(BannedIntegerLiteral)),
+ unless(hasAncestor(BannedAncestor)))
   .bind("nested-duplicates"),
   this);
 
@@ -896,7 +902,8 @@
conditionalOperator(expressionsAreEquivalent(),
// Filter noisy false positives.
unless(conditionalOperatorIsInMacro()),
-   unless(isInTemplateInstantiation()))
+   unless(isInTemplateInstantiation()),
+   unless(hasAncestor(BannedAncestor)))
.bind("cond")),
   this);
 
@@ -909,7 +916,8 @@
 ">=", "&&", "||", "="),
parametersAreEquivalent(),
// Filter noisy false positives.
-   unless(isMacro()), unless(isInTemplateInstantiation()))
+   unless(isMacro()), unless(isInTemplateInstantiation()),
+   unless(hasAncestor(BannedAncestor)))
.bind("call")),
   this);
 
@@ -919,7 +927,8 @@
   hasAnyOverloadedOperatorName("|", "&", "||", "&&", "^"),
   nestedParametersAreEquivalent(), argumentCountIs(2),
   // Filter noisy false positives.
-  unless(isMacro()), unless(isInTemplateInstantiation()))
+  unless(isMacro()), unless(isInTemplateInstantiation()),
+  unless(hasAncest

[PATCH] D122078: [clang-tidy] Ignore concepts in `misc-redundant-expression`

2022-10-08 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 466271.
Izaron added a comment.

Removed redundant comment


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D122078

Files:
  clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression-cxx20.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression-cxx20.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression-cxx20.cpp
@@ -0,0 +1,11 @@
+// RUN: clang-tidy %s -checks=-*,misc-redundant-expression -- -std=c++20 | count 0
+
+namespace concepts {
+// redundant expressions inside concepts make sense, ignore them
+template 
+concept TestConcept = requires(I i) {
+  {i - i};
+  {i && i};
+  {i ? i : i};
+};
+} // namespace concepts
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -149,6 +149,12 @@
   copy assignment operators with nonstandard return types. The check is restricted to
   c++11-or-later.
 
+- Improved :doc:`misc-redundant-expression `
+  check.
+
+  The check now skips concept definitions since redundant expressions still make sense
+  inside them.
+
 Removed checks
 ^^
 
Index: clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
===
--- clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
+++ clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
@@ -10,6 +10,7 @@
 #include "../utils/Matchers.h"
 #include "../utils/OptionsUtils.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/ExprConcepts.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/SourceLocation.h"
@@ -440,6 +441,8 @@
   return Node.isIntegerConstantExpr(Finder->getASTContext());
 }
 
+AST_MATCHER(Expr, isRequiresExpr) { return isa(Node); }
+
 AST_MATCHER(BinaryOperator, operandsAreEquivalent) {
   return areEquivalentExpr(Node.getLHS(), Node.getRHS());
 }
@@ -858,6 +861,7 @@
 
   const auto BannedIntegerLiteral =
   integerLiteral(expandedByMacro(KnownBannedMacroNames));
+  const auto BannedAncestor = expr(isRequiresExpr());
 
   // Binary with equivalent operands, like (X != 2 && X != 2).
   Finder->addMatcher(
@@ -873,7 +877,8 @@
unless(hasType(realFloatingPointType())),
unless(hasEitherOperand(hasType(realFloatingPointType(,
unless(hasLHS(AnyLiteralExpr)),
-   unless(hasDescendant(BannedIntegerLiteral)))
+   unless(hasDescendant(BannedIntegerLiteral)),
+   unless(hasAncestor(BannedAncestor)))
.bind("binary")),
   this);
 
@@ -886,7 +891,8 @@
  unless(isInTemplateInstantiation()),
  unless(binaryOperatorIsInMacro()),
  // TODO: if the banned macros are themselves duplicated
- unless(hasDescendant(BannedIntegerLiteral)))
+ unless(hasDescendant(BannedIntegerLiteral)),
+ unless(hasAncestor(BannedAncestor)))
   .bind("nested-duplicates"),
   this);
 
@@ -896,7 +902,8 @@
conditionalOperator(expressionsAreEquivalent(),
// Filter noisy false positives.
unless(conditionalOperatorIsInMacro()),
-   unless(isInTemplateInstantiation()))
+   unless(isInTemplateInstantiation()),
+   unless(hasAncestor(BannedAncestor)))
.bind("cond")),
   this);
 
@@ -909,7 +916,8 @@
 ">=", "&&", "||", "="),
parametersAreEquivalent(),
// Filter noisy false positives.
-   unless(isMacro()), unless(isInTemplateInstantiation()))
+   unless(isMacro()), unless(isInTemplateInstantiation()),
+   unless(hasAncestor(BannedAncestor)))
.bind("call")),
   this);
 
@@ -919,7 +927,8 @@
   hasAnyOverloadedOperatorName("|", "&", "||", "&&", "^"),
   nestedParametersAreEquivalent(), argumentCountIs(2),
   // Filter noisy false positives.
-  unless(isMacro()), unless(isInTemplateInstantiation()))
+  unless(isMacro()), unless(isInTemplateInstantiation()),
+  unless(hasAncestor(BannedAncestor)))
   .bind("nested-duplicates"),
   this);
 
@@ -936,7 +945,8 @@
binaryOperator(hasAnyOperatorName("

[PATCH] D122078: [clang-tidy] Ignore concepts in `misc-redundant-expression`

2022-10-07 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added a comment.

Hi! A friendly ping =)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D122078

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


[PATCH] D135493: [Clang] Support constexpr builtin fmin

2022-10-07 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 466193.
Izaron added a comment.

Aligned slashes in defines


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D135493

Files:
  clang/docs/LanguageExtensions.rst
  clang/lib/AST/ExprConstant.cpp
  clang/test/Sema/constant-builtins-fmin.cpp


Index: clang/test/Sema/constant-builtins-fmin.cpp
===
--- /dev/null
+++ clang/test/Sema/constant-builtins-fmin.cpp
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+constexpr double NaN = __builtin_nan("");
+constexpr double Inf = __builtin_inf();
+constexpr double NegInf = -__builtin_inf();
+
+#define FMIN_TEST_SIMPLE(T, FUNC)   \
+static_assert(T(1.2345) == FUNC(T(1.2345), T(6.7890))); \
+static_assert(T(1.2345) == FUNC(T(6.7890), T(1.2345)));
+
+#define FMIN_TEST_NAN(T, FUNC)  \
+static_assert(Inf == FUNC(NaN, Inf));   \
+static_assert(NegInf == FUNC(NegInf, NaN)); \
+static_assert(0.0 == FUNC(NaN, 0.0));   \
+static_assert(-0.0 == FUNC(-0.0, NaN)); \
+static_assert(T(-1.2345) == FUNC(NaN, T(-1.2345))); \
+static_assert(T(1.2345) == FUNC(T(1.2345), NaN));   \
+static_assert(__builtin_isnan(FUNC(NaN, NaN)));
+
+#define FMIN_TEST_INF(T, FUNC)\
+static_assert(NegInf == FUNC(NegInf, Inf));   \
+static_assert(0.0 == FUNC(Inf, 0.0)); \
+static_assert(-0.0 == FUNC(-0.0, Inf));   \
+static_assert(T(1.2345) == FUNC(Inf, T(1.2345))); \
+static_assert(T(-1.2345) == FUNC(T(-1.2345), Inf));
+
+#define FMIN_TEST_NEG_INF(T, FUNC) \
+static_assert(NegInf == FUNC(Inf, NegInf));\
+static_assert(NegInf == FUNC(NegInf, 0.0));\
+static_assert(NegInf == FUNC(-0.0, NegInf));   \
+static_assert(NegInf == FUNC(NegInf, T(-1.2345))); \
+static_assert(NegInf == FUNC(T(1.2345), NegInf));
+
+#define FMIN_TEST_BOTH_ZERO(T, FUNC) \
+static_assert(__builtin_copysign(1.0, FUNC(0.0, 0.0)) == 1.0);   \
+static_assert(__builtin_copysign(1.0, FUNC(-0.0, 0.0)) == -1.0); \
+static_assert(__builtin_copysign(1.0, FUNC(0.0, -0.0)) == -1.0); \
+static_assert(__builtin_copysign(1.0, FUNC(-0.0, -0.0)) == -1.0);
+
+#define LIST_FMIN_TESTS(T, FUNC) \
+FMIN_TEST_SIMPLE(T, FUNC)\
+FMIN_TEST_NAN(T, FUNC)   \
+FMIN_TEST_INF(T, FUNC)   \
+FMIN_TEST_NEG_INF(T, FUNC)   \
+FMIN_TEST_BOTH_ZERO(T, FUNC)
+
+LIST_FMIN_TESTS(double, __builtin_fmin)
+LIST_FMIN_TESTS(float, __builtin_fminf)
+LIST_FMIN_TESTS((long double), __builtin_fminl)
+LIST_FMIN_TESTS(__fp16, __builtin_fminf16)
+#ifdef __FLOAT128__
+LIST_FMIN_TESTS(__float128, __builtin_fminf128)
+#endif
Index: clang/lib/AST/ExprConstant.cpp
===
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -14041,6 +14041,24 @@
   Result = RHS;
 return true;
   }
+
+  case Builtin::BI__builtin_fmin:
+  case Builtin::BI__builtin_fminf:
+  case Builtin::BI__builtin_fminl:
+  case Builtin::BI__builtin_fminf16:
+  case Builtin::BI__builtin_fminf128: {
+// TODO: Handle sNaN.
+APFloat RHS(0.);
+if (!EvaluateFloat(E->getArg(0), Result, Info) ||
+!EvaluateFloat(E->getArg(1), RHS, Info))
+  return false;
+// When comparing zeroes, return -0.0 if one of the zeroes is negative.
+if (Result.isZero() && RHS.isZero() && RHS.isNegative())
+  Result = RHS;
+else if (Result.isNaN() || RHS < Result)
+  Result = RHS;
+return true;
+  }
   }
 }
 
Index: clang/docs/LanguageExtensions.rst
===
--- clang/docs/LanguageExtensions.rst
+++ clang/docs/LanguageExtensions.rst
@@ -4661,6 +4661,7 @@
 * ``__builtin_ffsl``
 * ``__builtin_ffsll``
 * ``__builtin_fmax``
+* ``__builtin_fmin``
 * ``__builtin_fpclassify``
 * ``__builtin_inf``
 * ``__builtin_isinf``


Index: clang/test/Sema/constant-builtins-fmin.cpp
===
--- /dev/null
+++ clang/test/Sema/constant-builtins-fmin.cpp
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+constexpr double NaN = __builtin_nan("");
+constexpr double Inf = __builtin_inf();
+constexpr double NegInf = -__builtin_inf();
+
+#define FMIN_TEST_SIMPLE(T, FUNC)   \
+static_assert(T(1.2345) == FUNC(T(1.2345), T(6.7890))); \
+static_assert(T(1.2345) == FUNC(T(6.7890), T(1.2345)));
+
+#define FMIN_TEST_NAN(T, FUNC)  \
+static_assert(Inf == FUNC(NaN, Inf));   \
+static_assert(NegInf == FUNC(NegInf, NaN)); \
+static_assert(0.0 == FUN

[PATCH] D135493: [Clang] Support constexpr builtin fmin

2022-10-07 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added a comment.

This is a mirror of my previous patch about builtin **max**. I promised to make 
the patch for builtin **min** =) Here: https://reviews.llvm.org/D134369#3806131


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D135493

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


[PATCH] D135493: [Clang] Support constexpr builtin fmin

2022-10-07 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron created this revision.
Izaron added reviewers: efriedma, jcranmer-intel, aaron.ballman, cor3ntin.
Herald added a project: All.
Izaron requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Support constexpr version of __builtin_fmin and its variations.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D135493

Files:
  clang/docs/LanguageExtensions.rst
  clang/lib/AST/ExprConstant.cpp
  clang/test/Sema/constant-builtins-fmin.cpp


Index: clang/test/Sema/constant-builtins-fmin.cpp
===
--- /dev/null
+++ clang/test/Sema/constant-builtins-fmin.cpp
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+constexpr double NaN = __builtin_nan("");
+constexpr double Inf = __builtin_inf();
+constexpr double NegInf = -__builtin_inf();
+
+#define FMIN_TEST_SIMPLE(T, FUNC)   \
+static_assert(T(1.2345) == FUNC(T(1.2345), T(6.7890))); \
+static_assert(T(1.2345) == FUNC(T(6.7890), T(1.2345)));
+
+#define FMIN_TEST_NAN(T, FUNC)  \
+static_assert(Inf == FUNC(NaN, Inf));   \
+static_assert(NegInf == FUNC(NegInf, NaN)); \
+static_assert(0.0 == FUNC(NaN, 0.0));   \
+static_assert(-0.0 == FUNC(-0.0, NaN)); \
+static_assert(T(-1.2345) == FUNC(NaN, T(-1.2345))); \
+static_assert(T(1.2345) == FUNC(T(1.2345), NaN));   \
+static_assert(__builtin_isnan(FUNC(NaN, NaN)));
+
+#define FMIN_TEST_INF(T, FUNC)  \
+static_assert(NegInf == FUNC(NegInf, Inf));\
+static_assert(0.0 == FUNC(Inf, 0.0));   \
+static_assert(-0.0 == FUNC(-0.0, Inf));  \
+static_assert(T(1.2345) == FUNC(Inf, T(1.2345))); \
+static_assert(T(-1.2345) == FUNC(T(-1.2345), Inf));
+
+#define FMIN_TEST_NEG_INF(T, FUNC) \
+static_assert(NegInf == FUNC(Inf, NegInf));   \
+static_assert(NegInf == FUNC(NegInf, 0.0));   \
+static_assert(NegInf == FUNC(-0.0, NegInf)); \
+static_assert(NegInf == FUNC(NegInf, T(-1.2345))); \
+static_assert(NegInf == FUNC(T(1.2345), NegInf));
+
+#define FMIN_TEST_BOTH_ZERO(T, FUNC)   \
+static_assert(__builtin_copysign(1.0, FUNC(0.0, 0.0)) == 1.0);  \
+static_assert(__builtin_copysign(1.0, FUNC(-0.0, 0.0)) == -1.0);  \
+static_assert(__builtin_copysign(1.0, FUNC(0.0, -0.0)) == -1.0);  \
+static_assert(__builtin_copysign(1.0, FUNC(-0.0, -0.0)) == -1.0);
+
+#define LIST_FMIN_TESTS(T, FUNC) \
+FMIN_TEST_SIMPLE(T, FUNC)\
+FMIN_TEST_NAN(T, FUNC)   \
+FMIN_TEST_INF(T, FUNC)   \
+FMIN_TEST_NEG_INF(T, FUNC)   \
+FMIN_TEST_BOTH_ZERO(T, FUNC)
+
+LIST_FMIN_TESTS(double, __builtin_fmin)
+LIST_FMIN_TESTS(float, __builtin_fminf)
+LIST_FMIN_TESTS((long double), __builtin_fminl)
+LIST_FMIN_TESTS(__fp16, __builtin_fminf16)
+#ifdef __FLOAT128__
+LIST_FMIN_TESTS(__float128, __builtin_fminf128)
+#endif
Index: clang/lib/AST/ExprConstant.cpp
===
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -14041,6 +14041,24 @@
   Result = RHS;
 return true;
   }
+
+  case Builtin::BI__builtin_fmin:
+  case Builtin::BI__builtin_fminf:
+  case Builtin::BI__builtin_fminl:
+  case Builtin::BI__builtin_fminf16:
+  case Builtin::BI__builtin_fminf128: {
+// TODO: Handle sNaN.
+APFloat RHS(0.);
+if (!EvaluateFloat(E->getArg(0), Result, Info) ||
+!EvaluateFloat(E->getArg(1), RHS, Info))
+  return false;
+// When comparing zeroes, return -0.0 if one of the zeroes is negative.
+if (Result.isZero() && RHS.isZero() && RHS.isNegative())
+  Result = RHS;
+else if (Result.isNaN() || RHS < Result)
+  Result = RHS;
+return true;
+  }
   }
 }
 
Index: clang/docs/LanguageExtensions.rst
===
--- clang/docs/LanguageExtensions.rst
+++ clang/docs/LanguageExtensions.rst
@@ -4661,6 +4661,7 @@
 * ``__builtin_ffsl``
 * ``__builtin_ffsll``
 * ``__builtin_fmax``
+* ``__builtin_fmin``
 * ``__builtin_fpclassify``
 * ``__builtin_inf``
 * ``__builtin_isinf``


Index: clang/test/Sema/constant-builtins-fmin.cpp
===
--- /dev/null
+++ clang/test/Sema/constant-builtins-fmin.cpp
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+constexpr double NaN = __builtin_nan("");
+constexpr double Inf = __builtin_inf();
+constexpr double NegInf = -__builtin_inf();
+
+#define FMIN_TEST_SIMPLE(T, FUNC)   \
+static_assert(T(1.2345) == FUNC(T(1.2345), T(6.7890))); \
+static_assert(T(1.2345) == FUNC(T(6.7890), T(1.2345)));
+
+#define FMIN_TEST_NAN(T, FUNC)  \
+static_assert(I

[PATCH] D135486: [Clang] Use C++17 in constant-builtins-fmax.cpp test

2022-10-07 Thread Evgeny Shulgin via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGc585a44651f4: [Clang] Use C++17 in 
constant-builtins-fmax.cpp test (authored by Izaron).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D135486

Files:
  clang/test/Sema/constant-builtins-fmax.cpp


Index: clang/test/Sema/constant-builtins-fmax.cpp
===
--- clang/test/Sema/constant-builtins-fmax.cpp
+++ clang/test/Sema/constant-builtins-fmax.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s
 // expected-no-diagnostics
 
 constexpr double NaN = __builtin_nan("");


Index: clang/test/Sema/constant-builtins-fmax.cpp
===
--- clang/test/Sema/constant-builtins-fmax.cpp
+++ clang/test/Sema/constant-builtins-fmax.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s
 // expected-no-diagnostics
 
 constexpr double NaN = __builtin_nan("");
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D135486: [Clang] Use C++17 in constant-builtins-fmax.cpp test

2022-10-07 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added a comment.

Thanks, will land the patch after `Build 288902: pre-merge checks` is passed =)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D135486

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


[PATCH] D135476: [clang-tidy] Support concepts in `bugprone-forwarding-reference-overload`

2022-10-07 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron marked an inline comment as done.
Izaron added inline comments.



Comment at: 
clang-tools-extra/docs/clang-tidy/checks/bugprone/forwarding-reference-overload.rst:54
 constructor could hide in this case. We also suppress warnings for constructors
-like C3 and C4 that are guarded with an ``enable_if``, assuming the programmer 
was
+like C3-C6 that are guarded with an ``enable_if`` or a concept, assuming the 
programmer was
 aware of the possible hiding.

Eugene.Zelenko wrote:
> Please follow 80 characters limit.
Thanks! I ran `git clang-format HEAD~1` before commiting, but it didn't modify 
this file. Seems like it doesn't see `.rst` files.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D135476

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


[PATCH] D135476: [clang-tidy] Support concepts in `bugprone-forwarding-reference-overload`

2022-10-07 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 466175.
Izaron added a comment.

Follow 80 characters limit. Thanks to @Eugene.Zelenko!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D135476

Files:
  clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp
  
clang-tools-extra/docs/clang-tidy/checks/bugprone/forwarding-reference-overload.rst
  
clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp


Index: 
clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp
===
--- 
clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp
+++ 
clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s bugprone-forwarding-reference-overload %t
+// RUN: %check_clang_tidy -std=c++20 %s bugprone-forwarding-reference-overload 
%t
 
 namespace std {
 template  struct enable_if { typedef T type; };
@@ -251,3 +251,20 @@
   Test10(T &&Item, E e)
   : e(e){}
 };
+
+class Test11 {
+public:
+  // Guarded with requires expression.
+  template 
+  requires requires { just_true; }
+  Test11(T &&n);
+};
+
+template
+concept JustTrueConcept = requires { just_true; };
+
+class Test12 {
+public:
+  // Guarded with concept requirement.
+  template  Test12(T &&n);
+};
Index: 
clang-tools-extra/docs/clang-tidy/checks/bugprone/forwarding-reference-overload.rst
===
--- 
clang-tools-extra/docs/clang-tidy/checks/bugprone/forwarding-reference-overload.rst
+++ 
clang-tools-extra/docs/clang-tidy/checks/bugprone/forwarding-reference-overload.rst
@@ -34,6 +34,15 @@
 enable_if_t, A&&...>, int> = 0>
   explicit Person(A&&... a) {}
 
+  // C5: perfect forwarding ctor guarded with requires expression
+  template
+  requires requires { is_special; }
+  explicit Person(T&& n) {}
+
+  // C6: perfect forwarding ctor guarded with concept requirement
+  template
+  explicit Person(T&& n) {}
+
   // (possibly compiler generated) copy ctor
   Person(const Person& rhs);
 };
@@ -42,8 +51,8 @@
 constructors. We suppress warnings if the copy and the move constructors are 
both
 disabled (deleted or private), because there is nothing the perfect forwarding
 constructor could hide in this case. We also suppress warnings for constructors
-like C3 and C4 that are guarded with an ``enable_if``, assuming the programmer 
was
-aware of the possible hiding.
+like C3-C6 that are guarded with an ``enable_if`` or a concept, assuming the
+programmer was aware of the possible hiding.
 
 Background
 --
Index: 
clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp
===
--- clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp
@@ -58,6 +58,9 @@
   return Node.hasDefaultArgument() &&
  TypeMatcher.matches(Node.getDefaultArgument(), Finder, Builder);
 }
+AST_MATCHER(TemplateDecl, hasAssociatedConstraints) {
+  return Node.hasAssociatedConstraints();
+}
 } // namespace
 
 void ForwardingReferenceOverloadCheck::registerMatchers(MatchFinder *Finder) {
@@ -76,6 +79,9 @@
   // No warning: enable_if as constructor parameter.
   parmVarDecl(hasType(isEnableIf(),
   unless(hasParent(functionTemplateDecl(anyOf(
+  // No warning: has associated constraints (like requires
+  // expression).
+  hasAssociatedConstraints(),
   // No warning: enable_if as type parameter.
   has(templateTypeParmDecl(hasDefaultArgument(isEnableIf(,
   // No warning: enable_if as non-type template parameter.


Index: clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s bugprone-forwarding-reference-overload %t
+// RUN: %check_clang_tidy -std=c++20 %s bugprone-forwarding-reference-overload %t
 
 namespace std {
 template  struct enable_if { typedef T type; };
@@ -251,3 +251,20 @@
   Test10(T &&Item, E e)
   : e(e){}
 };
+
+class Test11 {
+public:
+  // Guarded with requires expression.
+  template 
+  requires requires { just_true; }
+  Test11(T &&n);
+};
+
+template
+concept JustTrueConcept = requires { just_true; };
+
+class Test12 {
+public:
+  // Guarded with concept requirement.
+  template  Test12(T &&n);
+};
Index: clang-tools-extra/docs/clang-tid

[PATCH] D134369: [Clang] Support constexpr builtin fmax

2022-10-07 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added a comment.

In D134369#3843824 , @efriedma wrote:

> You might need to explicitly specify -std=c++17 in the RUN line.  (That bot 
> has a different target triple, and I think with that triple the default C++ 
> standard isn't C++17?)

Thanks @efriedma! Could you please take a look at my fix with added 
`-std=c++17`? https://reviews.llvm.org/D135486

Sorry for inconvenience, it was a sad surprise =(


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134369

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


[PATCH] D135486: [Clang] Use C++17 in constant-builtins-fmax.cpp test

2022-10-07 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added a comment.

ASAP fix from previous review request, see comment: 
https://reviews.llvm.org/D134369#3843824


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D135486

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


[PATCH] D135486: [Clang] Use C++17 in constant-builtins-fmax.cpp test

2022-10-07 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron created this revision.
Izaron added reviewers: efriedma, jcranmer-intel, aaron.ballman, cor3ntin.
Herald added a project: All.
Izaron requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Add `-std=c++17` to the test so that buildbot won't fail


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D135486

Files:
  clang/test/Sema/constant-builtins-fmax.cpp


Index: clang/test/Sema/constant-builtins-fmax.cpp
===
--- clang/test/Sema/constant-builtins-fmax.cpp
+++ clang/test/Sema/constant-builtins-fmax.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s
 // expected-no-diagnostics
 
 constexpr double NaN = __builtin_nan("");


Index: clang/test/Sema/constant-builtins-fmax.cpp
===
--- clang/test/Sema/constant-builtins-fmax.cpp
+++ clang/test/Sema/constant-builtins-fmax.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s
 // expected-no-diagnostics
 
 constexpr double NaN = __builtin_nan("");
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D134369: [Clang] Support constexpr builtin fmax

2022-10-07 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added a comment.

I've got an email about "Buildbot failure" with this link: 
https://lab.llvm.org/buildbot/#/builders/216/builds/10955

  Line 51: 'static_assert' with no message is a C++17 extension

Why is it failing if pre-merge checks has been passed? =(


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134369

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


[PATCH] D134369: [Clang] Support constexpr builtin fmax

2022-10-07 Thread Evgeny Shulgin via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG0edff6faa266: [Clang] Support constexpr builtin fmax 
(authored by Izaron).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134369

Files:
  clang/docs/LanguageExtensions.rst
  clang/lib/AST/ExprConstant.cpp
  clang/test/Sema/constant-builtins-fmax.cpp


Index: clang/test/Sema/constant-builtins-fmax.cpp
===
--- /dev/null
+++ clang/test/Sema/constant-builtins-fmax.cpp
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+constexpr double NaN = __builtin_nan("");
+constexpr double Inf = __builtin_inf();
+constexpr double NegInf = -__builtin_inf();
+
+#define FMAX_TEST_SIMPLE(T, FUNC)   \
+static_assert(T(6.7890) == FUNC(T(1.2345), T(6.7890))); \
+static_assert(T(6.7890) == FUNC(T(6.7890), T(1.2345)));
+
+#define FMAX_TEST_NAN(T, FUNC)  \
+static_assert(Inf == FUNC(NaN, Inf));   \
+static_assert(NegInf == FUNC(NegInf, NaN)); \
+static_assert(0.0 == FUNC(NaN, 0.0));   \
+static_assert(-0.0 == FUNC(-0.0, NaN)); \
+static_assert(T(-1.2345) == FUNC(NaN, T(-1.2345))); \
+static_assert(T(1.2345) == FUNC(T(1.2345), NaN));   \
+static_assert(__builtin_isnan(FUNC(NaN, NaN)));
+
+#define FMAX_TEST_INF(T, FUNC)  \
+static_assert(Inf == FUNC(NegInf, Inf));\
+static_assert(Inf == FUNC(Inf, 0.0));   \
+static_assert(Inf == FUNC(-0.0, Inf));  \
+static_assert(Inf == FUNC(Inf, T(1.2345))); \
+static_assert(Inf == FUNC(T(-1.2345), Inf));
+
+#define FMAX_TEST_NEG_INF(T, FUNC) \
+static_assert(Inf == FUNC(Inf, NegInf));   \
+static_assert(0.0 == FUNC(NegInf, 0.0));   \
+static_assert(-0.0 == FUNC(-0.0, NegInf)); \
+static_assert(T(-1.2345) == FUNC(NegInf, T(-1.2345))); \
+static_assert(T(1.2345) == FUNC(T(1.2345), NegInf));
+
+#define FMAX_TEST_BOTH_ZERO(T, FUNC)   \
+static_assert(__builtin_copysign(1.0, FUNC(0.0, 0.0)) == 1.0);  \
+static_assert(__builtin_copysign(1.0, FUNC(-0.0, 0.0)) == 1.0);  \
+static_assert(__builtin_copysign(1.0, FUNC(0.0, -0.0)) == 1.0);  \
+static_assert(__builtin_copysign(1.0, FUNC(-0.0, -0.0)) == -1.0);
+
+#define LIST_FMAX_TESTS(T, FUNC) \
+FMAX_TEST_SIMPLE(T, FUNC)\
+FMAX_TEST_NAN(T, FUNC)   \
+FMAX_TEST_INF(T, FUNC)   \
+FMAX_TEST_NEG_INF(T, FUNC)   \
+FMAX_TEST_BOTH_ZERO(T, FUNC)
+
+LIST_FMAX_TESTS(double, __builtin_fmax)
+LIST_FMAX_TESTS(float, __builtin_fmaxf)
+LIST_FMAX_TESTS((long double), __builtin_fmaxl)
+LIST_FMAX_TESTS(__fp16, __builtin_fmaxf16)
+#ifdef __FLOAT128__
+LIST_FMAX_TESTS(__float128, __builtin_fmaxf128)
+#endif
Index: clang/lib/AST/ExprConstant.cpp
===
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -14023,6 +14023,24 @@
 Result.copySign(RHS);
 return true;
   }
+
+  case Builtin::BI__builtin_fmax:
+  case Builtin::BI__builtin_fmaxf:
+  case Builtin::BI__builtin_fmaxl:
+  case Builtin::BI__builtin_fmaxf16:
+  case Builtin::BI__builtin_fmaxf128: {
+// TODO: Handle sNaN.
+APFloat RHS(0.);
+if (!EvaluateFloat(E->getArg(0), Result, Info) ||
+!EvaluateFloat(E->getArg(1), RHS, Info))
+  return false;
+// When comparing zeroes, return +0.0 if one of the zeroes is positive.
+if (Result.isZero() && RHS.isZero() && Result.isNegative())
+  Result = RHS;
+else if (Result.isNaN() || RHS > Result)
+  Result = RHS;
+return true;
+  }
   }
 }
 
Index: clang/docs/LanguageExtensions.rst
===
--- clang/docs/LanguageExtensions.rst
+++ clang/docs/LanguageExtensions.rst
@@ -4660,6 +4660,7 @@
 * ``__builtin_ffs``
 * ``__builtin_ffsl``
 * ``__builtin_ffsll``
+* ``__builtin_fmax``
 * ``__builtin_fpclassify``
 * ``__builtin_inf``
 * ``__builtin_isinf``


Index: clang/test/Sema/constant-builtins-fmax.cpp
===
--- /dev/null
+++ clang/test/Sema/constant-builtins-fmax.cpp
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+constexpr double NaN = __builtin_nan("");
+constexpr double Inf = __builtin_inf();
+constexpr double NegInf = -__builtin_inf();
+
+#define FMAX_TEST_SIMPLE(T, FUNC)   \
+static_assert(T(6.7890) == FUNC(T(1.2345), T(6.7890))); \
+static_assert(T(6.7890) == FUNC(T(6.7890), T(1.2345)));
+
+#define FMAX_TEST_NAN(T, FUNC)  \
+static_assert(Inf == FUNC(NaN, Inf));   \
+static_assert(NegInf == FUNC(NegInf, NaN)); \
+static_a

[PATCH] D134369: [Clang] Support constexpr builtin fmax

2022-10-07 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 466151.
Izaron added a comment.

Add TODO comment about sNaN. Thanks to @jcranmer-intel!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134369

Files:
  clang/docs/LanguageExtensions.rst
  clang/lib/AST/ExprConstant.cpp
  clang/test/Sema/constant-builtins-fmax.cpp


Index: clang/test/Sema/constant-builtins-fmax.cpp
===
--- /dev/null
+++ clang/test/Sema/constant-builtins-fmax.cpp
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+constexpr double NaN = __builtin_nan("");
+constexpr double Inf = __builtin_inf();
+constexpr double NegInf = -__builtin_inf();
+
+#define FMAX_TEST_SIMPLE(T, FUNC)   \
+static_assert(T(6.7890) == FUNC(T(1.2345), T(6.7890))); \
+static_assert(T(6.7890) == FUNC(T(6.7890), T(1.2345)));
+
+#define FMAX_TEST_NAN(T, FUNC)  \
+static_assert(Inf == FUNC(NaN, Inf));   \
+static_assert(NegInf == FUNC(NegInf, NaN)); \
+static_assert(0.0 == FUNC(NaN, 0.0));   \
+static_assert(-0.0 == FUNC(-0.0, NaN)); \
+static_assert(T(-1.2345) == FUNC(NaN, T(-1.2345))); \
+static_assert(T(1.2345) == FUNC(T(1.2345), NaN));   \
+static_assert(__builtin_isnan(FUNC(NaN, NaN)));
+
+#define FMAX_TEST_INF(T, FUNC)  \
+static_assert(Inf == FUNC(NegInf, Inf));\
+static_assert(Inf == FUNC(Inf, 0.0));   \
+static_assert(Inf == FUNC(-0.0, Inf));  \
+static_assert(Inf == FUNC(Inf, T(1.2345))); \
+static_assert(Inf == FUNC(T(-1.2345), Inf));
+
+#define FMAX_TEST_NEG_INF(T, FUNC) \
+static_assert(Inf == FUNC(Inf, NegInf));   \
+static_assert(0.0 == FUNC(NegInf, 0.0));   \
+static_assert(-0.0 == FUNC(-0.0, NegInf)); \
+static_assert(T(-1.2345) == FUNC(NegInf, T(-1.2345))); \
+static_assert(T(1.2345) == FUNC(T(1.2345), NegInf));
+
+#define FMAX_TEST_BOTH_ZERO(T, FUNC)   \
+static_assert(__builtin_copysign(1.0, FUNC(0.0, 0.0)) == 1.0);  \
+static_assert(__builtin_copysign(1.0, FUNC(-0.0, 0.0)) == 1.0);  \
+static_assert(__builtin_copysign(1.0, FUNC(0.0, -0.0)) == 1.0);  \
+static_assert(__builtin_copysign(1.0, FUNC(-0.0, -0.0)) == -1.0);
+
+#define LIST_FMAX_TESTS(T, FUNC) \
+FMAX_TEST_SIMPLE(T, FUNC)\
+FMAX_TEST_NAN(T, FUNC)   \
+FMAX_TEST_INF(T, FUNC)   \
+FMAX_TEST_NEG_INF(T, FUNC)   \
+FMAX_TEST_BOTH_ZERO(T, FUNC)
+
+LIST_FMAX_TESTS(double, __builtin_fmax)
+LIST_FMAX_TESTS(float, __builtin_fmaxf)
+LIST_FMAX_TESTS((long double), __builtin_fmaxl)
+LIST_FMAX_TESTS(__fp16, __builtin_fmaxf16)
+#ifdef __FLOAT128__
+LIST_FMAX_TESTS(__float128, __builtin_fmaxf128)
+#endif
Index: clang/lib/AST/ExprConstant.cpp
===
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -14021,6 +14021,24 @@
 Result.copySign(RHS);
 return true;
   }
+
+  case Builtin::BI__builtin_fmax:
+  case Builtin::BI__builtin_fmaxf:
+  case Builtin::BI__builtin_fmaxl:
+  case Builtin::BI__builtin_fmaxf16:
+  case Builtin::BI__builtin_fmaxf128: {
+// TODO: Handle sNaN.
+APFloat RHS(0.);
+if (!EvaluateFloat(E->getArg(0), Result, Info) ||
+!EvaluateFloat(E->getArg(1), RHS, Info))
+  return false;
+// When comparing zeroes, return +0.0 if one of the zeroes is positive.
+if (Result.isZero() && RHS.isZero() && Result.isNegative())
+  Result = RHS;
+else if (Result.isNaN() || RHS > Result)
+  Result = RHS;
+return true;
+  }
   }
 }
 
Index: clang/docs/LanguageExtensions.rst
===
--- clang/docs/LanguageExtensions.rst
+++ clang/docs/LanguageExtensions.rst
@@ -4660,6 +4660,7 @@
 * ``__builtin_ffs``
 * ``__builtin_ffsl``
 * ``__builtin_ffsll``
+* ``__builtin_fmax``
 * ``__builtin_fpclassify``
 * ``__builtin_inf``
 * ``__builtin_isinf``


Index: clang/test/Sema/constant-builtins-fmax.cpp
===
--- /dev/null
+++ clang/test/Sema/constant-builtins-fmax.cpp
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+constexpr double NaN = __builtin_nan("");
+constexpr double Inf = __builtin_inf();
+constexpr double NegInf = -__builtin_inf();
+
+#define FMAX_TEST_SIMPLE(T, FUNC)   \
+static_assert(T(6.7890) == FUNC(T(1.2345), T(6.7890))); \
+static_assert(T(6.7890) == FUNC(T(6.7890), T(1.2345)));
+
+#define FMAX_TEST_NAN(T, FUNC)  \
+static_assert(Inf == FUNC(NaN, Inf));   \
+static_assert(NegInf == FUNC(NegInf, NaN)); \
+static_assert(0.0 == FUNC(NaN, 0.0)); 

[PATCH] D135476: [clang-tidy] Support concepts in `bugprone-forwarding-reference-overload`

2022-10-07 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 466147.
Izaron added a comment.

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


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D135476

Files:
  clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp
  
clang-tools-extra/docs/clang-tidy/checks/bugprone/forwarding-reference-overload.rst
  
clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp


Index: 
clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp
===
--- 
clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp
+++ 
clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s bugprone-forwarding-reference-overload %t
+// RUN: %check_clang_tidy -std=c++20 %s bugprone-forwarding-reference-overload 
%t
 
 namespace std {
 template  struct enable_if { typedef T type; };
@@ -251,3 +251,20 @@
   Test10(T &&Item, E e)
   : e(e){}
 };
+
+class Test11 {
+public:
+  // Guarded with requires expression.
+  template 
+  requires requires { just_true; }
+  Test11(T &&n);
+};
+
+template
+concept JustTrueConcept = requires { just_true; };
+
+class Test12 {
+public:
+  // Guarded with concept requirement.
+  template  Test12(T &&n);
+};
Index: 
clang-tools-extra/docs/clang-tidy/checks/bugprone/forwarding-reference-overload.rst
===
--- 
clang-tools-extra/docs/clang-tidy/checks/bugprone/forwarding-reference-overload.rst
+++ 
clang-tools-extra/docs/clang-tidy/checks/bugprone/forwarding-reference-overload.rst
@@ -34,6 +34,15 @@
 enable_if_t, A&&...>, int> = 0>
   explicit Person(A&&... a) {}
 
+  // C5: perfect forwarding ctor guarded with requires expression
+  template
+  requires requires { is_special; }
+  explicit Person(T&& n) {}
+
+  // C6: perfect forwarding ctor guarded with concept requirement
+  template
+  explicit Person(T&& n) {}
+
   // (possibly compiler generated) copy ctor
   Person(const Person& rhs);
 };
@@ -42,7 +51,7 @@
 constructors. We suppress warnings if the copy and the move constructors are 
both
 disabled (deleted or private), because there is nothing the perfect forwarding
 constructor could hide in this case. We also suppress warnings for constructors
-like C3 and C4 that are guarded with an ``enable_if``, assuming the programmer 
was
+like C3-C6 that are guarded with an ``enable_if`` or a concept, assuming the 
programmer was
 aware of the possible hiding.
 
 Background
Index: 
clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp
===
--- clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp
@@ -58,6 +58,9 @@
   return Node.hasDefaultArgument() &&
  TypeMatcher.matches(Node.getDefaultArgument(), Finder, Builder);
 }
+AST_MATCHER(TemplateDecl, hasAssociatedConstraints) {
+  return Node.hasAssociatedConstraints();
+}
 } // namespace
 
 void ForwardingReferenceOverloadCheck::registerMatchers(MatchFinder *Finder) {
@@ -76,6 +79,9 @@
   // No warning: enable_if as constructor parameter.
   parmVarDecl(hasType(isEnableIf(),
   unless(hasParent(functionTemplateDecl(anyOf(
+  // No warning: has associated constraints (like requires
+  // expression).
+  hasAssociatedConstraints(),
   // No warning: enable_if as type parameter.
   has(templateTypeParmDecl(hasDefaultArgument(isEnableIf(,
   // No warning: enable_if as non-type template parameter.


Index: clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s bugprone-forwarding-reference-overload %t
+// RUN: %check_clang_tidy -std=c++20 %s bugprone-forwarding-reference-overload %t
 
 namespace std {
 template  struct enable_if { typedef T type; };
@@ -251,3 +251,20 @@
   Test10(T &&Item, E e)
   : e(e){}
 };
+
+class Test11 {
+public:
+  // Guarded with requires expression.
+  template 
+  requires requires { just_true; }
+  Test11(T &&n);
+};
+
+template
+concept JustTrueConcept = requires { just_true; };
+
+class Test12 {
+public:
+  // Guarded with concept requirement.
+  template  Test12(T &&n);
+};
Index: clang-tools-extra/docs/clang-tidy/checks/bugprone/forwarding-reference-ov

[PATCH] D135476: [clang-tidy] Support concepts in `bugprone-forwarding-reference-overload`

2022-10-07 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron created this revision.
Izaron added reviewers: hokein, aaron.ballman, LegalizeAdulthood, njames93.
Herald added subscribers: carlosgalvezp, xazax.hun.
Herald added a project: All.
Izaron requested review of this revision.
Herald added a project: clang-tools-extra.
Herald added a subscriber: cfe-commits.

Ignore constrained perfect forwarding constructors.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D135476

Files:
  clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp
  
clang-tools-extra/docs/clang-tidy/checks/bugprone/forwarding-reference-overload.rst
  
clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp


Index: 
clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp
===
--- 
clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp
+++ 
clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s bugprone-forwarding-reference-overload %t
+// RUN: %check_clang_tidy -std=c++20 %s bugprone-forwarding-reference-overload 
%t
 
 namespace std {
 template  struct enable_if { typedef T type; };
@@ -251,3 +251,20 @@
   Test10(T &&Item, E e)
   : e(e){}
 };
+
+class Test11 {
+public:
+  // Guarded with requires expression.
+  template 
+  requires requires { just_true; }
+  Test11(T &&n);
+};
+
+template
+concept JustTrueConcept = requires { just_true; };
+
+class Test12 {
+public:
+  // Guarded with concept requirement.
+  template  Test12(T &&n);
+};
Index: 
clang-tools-extra/docs/clang-tidy/checks/bugprone/forwarding-reference-overload.rst
===
--- 
clang-tools-extra/docs/clang-tidy/checks/bugprone/forwarding-reference-overload.rst
+++ 
clang-tools-extra/docs/clang-tidy/checks/bugprone/forwarding-reference-overload.rst
@@ -34,6 +34,15 @@
 enable_if_t, A&&...>, int> = 0>
   explicit Person(A&&... a) {}
 
+  // C5: perfect forwarding ctor guarded with requires expression
+  template
+  requires requires { is_special; }
+  explicit Person(T&& n) {}
+
+  // C6: perfect forwarding ctor guarded with concept requirement
+  template
+  explicit Person(T&& n) {}
+
   // (possibly compiler generated) copy ctor
   Person(const Person& rhs);
 };
@@ -42,7 +51,7 @@
 constructors. We suppress warnings if the copy and the move constructors are 
both
 disabled (deleted or private), because there is nothing the perfect forwarding
 constructor could hide in this case. We also suppress warnings for constructors
-like C3 and C4 that are guarded with an ``enable_if``, assuming the programmer 
was
+like C3-C6 that are guarded with an ``enable_if`` or a concept, assuming the 
programmer was
 aware of the possible hiding.
 
 Background
Index: 
clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp
===
--- clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp
+++ clang-tools-extra/clang-tidy/bugprone/ForwardingReferenceOverloadCheck.cpp
@@ -58,6 +58,9 @@
   return Node.hasDefaultArgument() &&
  TypeMatcher.matches(Node.getDefaultArgument(), Finder, Builder);
 }
+AST_MATCHER(TemplateDecl, hasAssociatedConstraints) {
+  return Node.hasAssociatedConstraints();
+}
 } // namespace
 
 void ForwardingReferenceOverloadCheck::registerMatchers(MatchFinder *Finder) {
@@ -76,6 +79,9 @@
   // No warning: enable_if as constructor parameter.
   parmVarDecl(hasType(isEnableIf(),
   unless(hasParent(functionTemplateDecl(anyOf(
+  // No warning: has associated constraints (like requires
+  // expression).
+  hasAssociatedConstraints(),
   // No warning: enable_if as type parameter.
   has(templateTypeParmDecl(hasDefaultArgument(isEnableIf(,
   // No warning: enable_if as non-type template parameter.


Index: clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp
===
--- clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp
+++ clang-tools-extra/test/clang-tidy/checkers/bugprone/forwarding-reference-overload.cpp
@@ -1,4 +1,4 @@
-// RUN: %check_clang_tidy %s bugprone-forwarding-reference-overload %t
+// RUN: %check_clang_tidy -std=c++20 %s bugprone-forwarding-reference-overload %t
 
 namespace std {
 template  struct enable_if { typedef T type; };
@@ -251,3 +251,20 @@
   Test10(T &&Item, E e)
   : e(e){}
 };
+
+class Test11 {
+public:
+  // Guarded with requires expression.
+  template 
+  requires requires { just_true; }
+  Test11(T &&n);
+};
+
+template
+concept JustTrueConcept = requires { just_true; };
+
+clas

[PATCH] D134369: [Clang] Support constexpr builtin fmax

2022-10-04 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 465106.
Izaron added a comment.

Fix comment wording.

Thanks to @aaron.ballman!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134369

Files:
  clang/docs/LanguageExtensions.rst
  clang/lib/AST/ExprConstant.cpp
  clang/test/Sema/constant-builtins-fmax.cpp


Index: clang/test/Sema/constant-builtins-fmax.cpp
===
--- /dev/null
+++ clang/test/Sema/constant-builtins-fmax.cpp
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+constexpr double NaN = __builtin_nan("");
+constexpr double Inf = __builtin_inf();
+constexpr double NegInf = -__builtin_inf();
+
+#define FMAX_TEST_SIMPLE(T, FUNC)   \
+static_assert(T(6.7890) == FUNC(T(1.2345), T(6.7890))); \
+static_assert(T(6.7890) == FUNC(T(6.7890), T(1.2345)));
+
+#define FMAX_TEST_NAN(T, FUNC)  \
+static_assert(Inf == FUNC(NaN, Inf));   \
+static_assert(NegInf == FUNC(NegInf, NaN)); \
+static_assert(0.0 == FUNC(NaN, 0.0));   \
+static_assert(-0.0 == FUNC(-0.0, NaN)); \
+static_assert(T(-1.2345) == FUNC(NaN, T(-1.2345))); \
+static_assert(T(1.2345) == FUNC(T(1.2345), NaN));   \
+static_assert(__builtin_isnan(FUNC(NaN, NaN)));
+
+#define FMAX_TEST_INF(T, FUNC)  \
+static_assert(Inf == FUNC(NegInf, Inf));\
+static_assert(Inf == FUNC(Inf, 0.0));   \
+static_assert(Inf == FUNC(-0.0, Inf));  \
+static_assert(Inf == FUNC(Inf, T(1.2345))); \
+static_assert(Inf == FUNC(T(-1.2345), Inf));
+
+#define FMAX_TEST_NEG_INF(T, FUNC) \
+static_assert(Inf == FUNC(Inf, NegInf));   \
+static_assert(0.0 == FUNC(NegInf, 0.0));   \
+static_assert(-0.0 == FUNC(-0.0, NegInf)); \
+static_assert(T(-1.2345) == FUNC(NegInf, T(-1.2345))); \
+static_assert(T(1.2345) == FUNC(T(1.2345), NegInf));
+
+#define FMAX_TEST_BOTH_ZERO(T, FUNC)   \
+static_assert(__builtin_copysign(1.0, FUNC(0.0, 0.0)) == 1.0);  \
+static_assert(__builtin_copysign(1.0, FUNC(-0.0, 0.0)) == 1.0);  \
+static_assert(__builtin_copysign(1.0, FUNC(0.0, -0.0)) == 1.0);  \
+static_assert(__builtin_copysign(1.0, FUNC(-0.0, -0.0)) == -1.0);
+
+#define LIST_FMAX_TESTS(T, FUNC) \
+FMAX_TEST_SIMPLE(T, FUNC)\
+FMAX_TEST_NAN(T, FUNC)   \
+FMAX_TEST_INF(T, FUNC)   \
+FMAX_TEST_NEG_INF(T, FUNC)   \
+FMAX_TEST_BOTH_ZERO(T, FUNC)
+
+LIST_FMAX_TESTS(double, __builtin_fmax)
+LIST_FMAX_TESTS(float, __builtin_fmaxf)
+LIST_FMAX_TESTS((long double), __builtin_fmaxl)
+LIST_FMAX_TESTS(__fp16, __builtin_fmaxf16)
+#ifdef __FLOAT128__
+LIST_FMAX_TESTS(__float128, __builtin_fmaxf128)
+#endif
Index: clang/lib/AST/ExprConstant.cpp
===
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -14021,6 +14021,23 @@
 Result.copySign(RHS);
 return true;
   }
+
+  case Builtin::BI__builtin_fmax:
+  case Builtin::BI__builtin_fmaxf:
+  case Builtin::BI__builtin_fmaxl:
+  case Builtin::BI__builtin_fmaxf16:
+  case Builtin::BI__builtin_fmaxf128: {
+APFloat RHS(0.);
+if (!EvaluateFloat(E->getArg(0), Result, Info) ||
+!EvaluateFloat(E->getArg(1), RHS, Info))
+  return false;
+// When comparing zeroes, return +0.0 if one of the zeroes is positive.
+if (Result.isZero() && RHS.isZero() && Result.isNegative())
+  Result = RHS;
+else if (Result.isNaN() || RHS > Result)
+  Result = RHS;
+return true;
+  }
   }
 }
 
Index: clang/docs/LanguageExtensions.rst
===
--- clang/docs/LanguageExtensions.rst
+++ clang/docs/LanguageExtensions.rst
@@ -4660,6 +4660,7 @@
 * ``__builtin_ffs``
 * ``__builtin_ffsl``
 * ``__builtin_ffsll``
+* ``__builtin_fmax``
 * ``__builtin_fpclassify``
 * ``__builtin_inf``
 * ``__builtin_isinf``


Index: clang/test/Sema/constant-builtins-fmax.cpp
===
--- /dev/null
+++ clang/test/Sema/constant-builtins-fmax.cpp
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+constexpr double NaN = __builtin_nan("");
+constexpr double Inf = __builtin_inf();
+constexpr double NegInf = -__builtin_inf();
+
+#define FMAX_TEST_SIMPLE(T, FUNC)   \
+static_assert(T(6.7890) == FUNC(T(1.2345), T(6.7890))); \
+static_assert(T(6.7890) == FUNC(T(6.7890), T(1.2345)));
+
+#define FMAX_TEST_NAN(T, FUNC)  \
+static_assert(Inf == FUNC(NaN, Inf));   \
+static_assert(NegInf == FUNC(NegInf, NaN)); \
+static_assert(0.0 == FUNC(NaN, 0.0));   \
+static_assert(-0.0 == FUNC

[PATCH] D134369: [Clang] Support constexpr builtin fmax

2022-10-04 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 464990.
Izaron added a comment.

Fix corner case with pos/neg zeroes

Fix tests for pos/neg zeroes with __builtin_copysign

Thanks to @efriedma and @jcranmer-intel!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134369

Files:
  clang/docs/LanguageExtensions.rst
  clang/lib/AST/ExprConstant.cpp
  clang/test/Sema/constant-builtins-fmax.cpp


Index: clang/test/Sema/constant-builtins-fmax.cpp
===
--- /dev/null
+++ clang/test/Sema/constant-builtins-fmax.cpp
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+constexpr double NaN = __builtin_nan("");
+constexpr double Inf = __builtin_inf();
+constexpr double NegInf = -__builtin_inf();
+
+#define FMAX_TEST_SIMPLE(T, FUNC)   \
+static_assert(T(6.7890) == FUNC(T(1.2345), T(6.7890))); \
+static_assert(T(6.7890) == FUNC(T(6.7890), T(1.2345)));
+
+#define FMAX_TEST_NAN(T, FUNC)  \
+static_assert(Inf == FUNC(NaN, Inf));   \
+static_assert(NegInf == FUNC(NegInf, NaN)); \
+static_assert(0.0 == FUNC(NaN, 0.0));   \
+static_assert(-0.0 == FUNC(-0.0, NaN)); \
+static_assert(T(-1.2345) == FUNC(NaN, T(-1.2345))); \
+static_assert(T(1.2345) == FUNC(T(1.2345), NaN));   \
+static_assert(__builtin_isnan(FUNC(NaN, NaN)));
+
+#define FMAX_TEST_INF(T, FUNC)  \
+static_assert(Inf == FUNC(NegInf, Inf));\
+static_assert(Inf == FUNC(Inf, 0.0));   \
+static_assert(Inf == FUNC(-0.0, Inf));  \
+static_assert(Inf == FUNC(Inf, T(1.2345))); \
+static_assert(Inf == FUNC(T(-1.2345), Inf));
+
+#define FMAX_TEST_NEG_INF(T, FUNC) \
+static_assert(Inf == FUNC(Inf, NegInf));   \
+static_assert(0.0 == FUNC(NegInf, 0.0));   \
+static_assert(-0.0 == FUNC(-0.0, NegInf)); \
+static_assert(T(-1.2345) == FUNC(NegInf, T(-1.2345))); \
+static_assert(T(1.2345) == FUNC(T(1.2345), NegInf));
+
+#define FMAX_TEST_BOTH_ZERO(T, FUNC)   \
+static_assert(__builtin_copysign(1.0, FUNC(0.0, 0.0)) == 1.0);  \
+static_assert(__builtin_copysign(1.0, FUNC(-0.0, 0.0)) == 1.0);  \
+static_assert(__builtin_copysign(1.0, FUNC(0.0, -0.0)) == 1.0);  \
+static_assert(__builtin_copysign(1.0, FUNC(-0.0, -0.0)) == -1.0);
+
+#define LIST_FMAX_TESTS(T, FUNC) \
+FMAX_TEST_SIMPLE(T, FUNC)\
+FMAX_TEST_NAN(T, FUNC)   \
+FMAX_TEST_INF(T, FUNC)   \
+FMAX_TEST_NEG_INF(T, FUNC)   \
+FMAX_TEST_BOTH_ZERO(T, FUNC)
+
+LIST_FMAX_TESTS(double, __builtin_fmax)
+LIST_FMAX_TESTS(float, __builtin_fmaxf)
+LIST_FMAX_TESTS((long double), __builtin_fmaxl)
+LIST_FMAX_TESTS(__fp16, __builtin_fmaxf16)
+#ifdef __FLOAT128__
+LIST_FMAX_TESTS(__float128, __builtin_fmaxf128)
+#endif
Index: clang/lib/AST/ExprConstant.cpp
===
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -14021,6 +14021,23 @@
 Result.copySign(RHS);
 return true;
   }
+
+  case Builtin::BI__builtin_fmax:
+  case Builtin::BI__builtin_fmaxf:
+  case Builtin::BI__builtin_fmaxl:
+  case Builtin::BI__builtin_fmaxf16:
+  case Builtin::BI__builtin_fmaxf128: {
+APFloat RHS(0.);
+if (!EvaluateFloat(E->getArg(0), Result, Info) ||
+!EvaluateFloat(E->getArg(1), RHS, Info))
+  return false;
+// when comparing zeroes, return +0.0 if one of the zeroes is positive
+if (Result.isZero() && RHS.isZero() && Result.isNegative())
+  Result = RHS;
+else if (Result.isNaN() || RHS > Result)
+  Result = RHS;
+return true;
+  }
   }
 }
 
Index: clang/docs/LanguageExtensions.rst
===
--- clang/docs/LanguageExtensions.rst
+++ clang/docs/LanguageExtensions.rst
@@ -4660,6 +4660,7 @@
 * ``__builtin_ffs``
 * ``__builtin_ffsl``
 * ``__builtin_ffsll``
+* ``__builtin_fmax``
 * ``__builtin_fpclassify``
 * ``__builtin_inf``
 * ``__builtin_isinf``


Index: clang/test/Sema/constant-builtins-fmax.cpp
===
--- /dev/null
+++ clang/test/Sema/constant-builtins-fmax.cpp
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+constexpr double NaN = __builtin_nan("");
+constexpr double Inf = __builtin_inf();
+constexpr double NegInf = -__builtin_inf();
+
+#define FMAX_TEST_SIMPLE(T, FUNC)   \
+static_assert(T(6.7890) == FUNC(T(1.2345), T(6.7890))); \
+static_assert(T(6.7890) == FUNC(T(6.7890), T(1.2345)));
+
+#define FMAX_TEST_NAN(T, FUNC)  \
+static_assert(Inf == FUNC(NaN, Inf));   \
+static_assert(NegInf == FUNC(NegInf, NaN)); \
+st

[PATCH] D134369: [Clang] Support constexpr builtin fmax

2022-09-28 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 463715.
Izaron added a comment.

Rebase and fix windows __float128 failure


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134369

Files:
  clang/docs/LanguageExtensions.rst
  clang/lib/AST/ExprConstant.cpp
  clang/test/Sema/constant-builtins-fmax.cpp


Index: clang/test/Sema/constant-builtins-fmax.cpp
===
--- /dev/null
+++ clang/test/Sema/constant-builtins-fmax.cpp
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+constexpr double NaN = __builtin_nan("");
+constexpr double Inf = __builtin_inf();
+constexpr double NegInf = -__builtin_inf();
+
+#define FMAX_TEST_SIMPLE(T, FUNC)   \
+static_assert(T(6.7890) == FUNC(T(1.2345), T(6.7890))); \
+static_assert(T(6.7890) == FUNC(T(6.7890), T(1.2345)));
+
+#define FMAX_TEST_NAN(T, FUNC)  \
+static_assert(Inf == FUNC(NaN, Inf));   \
+static_assert(NegInf == FUNC(NegInf, NaN)); \
+static_assert(0.0 == FUNC(NaN, 0.0));   \
+static_assert(-0.0 == FUNC(-0.0, NaN)); \
+static_assert(T(-1.2345) == FUNC(NaN, T(-1.2345))); \
+static_assert(T(1.2345) == FUNC(T(1.2345), NaN));   \
+static_assert(__builtin_isnan(FUNC(NaN, NaN)));
+
+#define FMAX_TEST_INF(T, FUNC)  \
+static_assert(Inf == FUNC(NegInf, Inf));\
+static_assert(Inf == FUNC(Inf, 0.0));   \
+static_assert(Inf == FUNC(-0.0, Inf));  \
+static_assert(Inf == FUNC(Inf, T(1.2345))); \
+static_assert(Inf == FUNC(T(-1.2345), Inf));
+
+#define FMAX_TEST_NEG_INF(T, FUNC) \
+static_assert(Inf == FUNC(Inf, NegInf));   \
+static_assert(0.0 == FUNC(NegInf, 0.0));   \
+static_assert(-0.0 == FUNC(-0.0, NegInf)); \
+static_assert(T(-1.2345) == FUNC(NegInf, T(-1.2345))); \
+static_assert(T(1.2345) == FUNC(T(1.2345), NegInf));
+
+#define FMAX_TEST_BOTH_ZERO(T, FUNC)   \
+static_assert(0.0 == FUNC(0.0, 0.0));  \
+static_assert(0.0 == FUNC(-0.0, 0.0)); \
+static_assert(0.0 == FUNC(0.0, -0.0)); \
+static_assert(0.0 == FUNC(-0.0, -0.0));
+
+#define LIST_FMAX_TESTS(T, FUNC) \
+FMAX_TEST_SIMPLE(T, FUNC)\
+FMAX_TEST_NAN(T, FUNC)   \
+FMAX_TEST_INF(T, FUNC)   \
+FMAX_TEST_NEG_INF(T, FUNC)   \
+FMAX_TEST_BOTH_ZERO(T, FUNC)
+
+LIST_FMAX_TESTS(double, __builtin_fmax)
+LIST_FMAX_TESTS(float, __builtin_fmaxf)
+LIST_FMAX_TESTS((long double), __builtin_fmaxl)
+LIST_FMAX_TESTS(__fp16, __builtin_fmaxf16)
+#ifdef __FLOAT128__
+LIST_FMAX_TESTS(__float128, __builtin_fmaxf128)
+#endif
Index: clang/lib/AST/ExprConstant.cpp
===
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -14021,6 +14021,20 @@
 Result.copySign(RHS);
 return true;
   }
+
+  case Builtin::BI__builtin_fmax:
+  case Builtin::BI__builtin_fmaxf:
+  case Builtin::BI__builtin_fmaxl:
+  case Builtin::BI__builtin_fmaxf16:
+  case Builtin::BI__builtin_fmaxf128: {
+APFloat RHS(0.);
+if (!EvaluateFloat(E->getArg(0), Result, Info) ||
+!EvaluateFloat(E->getArg(1), RHS, Info))
+  return false;
+if (Result.isNaN() || RHS > Result)
+  Result = RHS;
+return true;
+  }
   }
 }
 
Index: clang/docs/LanguageExtensions.rst
===
--- clang/docs/LanguageExtensions.rst
+++ clang/docs/LanguageExtensions.rst
@@ -4660,6 +4660,7 @@
 * ``__builtin_ffs``
 * ``__builtin_ffsl``
 * ``__builtin_ffsll``
+* ``__builtin_fmax``
 * ``__builtin_fpclassify``
 * ``__builtin_inf``
 * ``__builtin_isinf``


Index: clang/test/Sema/constant-builtins-fmax.cpp
===
--- /dev/null
+++ clang/test/Sema/constant-builtins-fmax.cpp
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+constexpr double NaN = __builtin_nan("");
+constexpr double Inf = __builtin_inf();
+constexpr double NegInf = -__builtin_inf();
+
+#define FMAX_TEST_SIMPLE(T, FUNC)   \
+static_assert(T(6.7890) == FUNC(T(1.2345), T(6.7890))); \
+static_assert(T(6.7890) == FUNC(T(6.7890), T(1.2345)));
+
+#define FMAX_TEST_NAN(T, FUNC)  \
+static_assert(Inf == FUNC(NaN, Inf));   \
+static_assert(NegInf == FUNC(NegInf, NaN)); \
+static_assert(0.0 == FUNC(NaN, 0.0));   \
+static_assert(-0.0 == FUNC(-0.0, NaN)); \
+static_assert(T(-1.2345) == FUNC(NaN, T(-1.2345))); \
+static_assert(T(1.2345) == FUNC(T(1.2345), NaN));   \
+static_assert(__builtin_isnan(FUNC(NaN, NaN)));
+
+#define FMAX_TEST_INF(T, FUNC)  \
+static_assert(Inf ==

[PATCH] D134369: [Clang] Support constexpr builtin fmax

2022-09-28 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added inline comments.



Comment at: clang/lib/AST/ExprConstant.cpp:14033-14034
+!EvaluateFloat(E->getArg(1), RHS, Info))
+  return false;
+if (Result.isNaN() || RHS > Result)
+  Result = RHS;

jcranmer-intel wrote:
> If I'm reading APFloat's source correctly, this doesn't suffice to 
> consistently make __builtin_fmax(±0.0, ±0.0) return +0.0 if one of the zeroes 
> is positive. (We're not required to return +0.0 in this case, but most libm 
> implementations seem to endeavor to return +0.0 in this situation, even if 
> the LLVM intrinsic we lower to doesn't).
These cases are covered in tests (in a wrong manner though as I see), I was 
"checking" that we have `+0.0` if one of the zeroes is positive



Comment at: clang/test/Sema/constant-builtins-fmax.cpp:35-39
+#define FMAX_TEST_BOTH_ZERO(T, FUNC)   \
+static_assert(0.0 == FUNC(0.0, 0.0));  \
+static_assert(0.0 == FUNC(-0.0, 0.0)); \
+static_assert(0.0 == FUNC(0.0, -0.0)); \
+static_assert(0.0 == FUNC(-0.0, -0.0));

jcranmer-intel wrote:
> These tests aren't covering what the sign of zero is in these cases.
Cool! Thank you, today I learned that this compiles:
```
static_assert(0.0 == 0.0);
static_assert(0.0 == -0.0);
static_assert(0.0 == +0.0);
```

So I think I need to test the `+0.0` cases with the `__builtin_signbit` (I 
didn't find another way), BUT this function is not constexpr yet. So I need to 
implement a constexpr `__builtin_signbit` first... In a new pull request.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134369

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


[PATCH] D134207: [Clang] Support case and default labels at end of compound statement

2022-09-21 Thread Evgeny Shulgin 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 rG3285f9a2392f: [Clang] Support case and default labels at end 
of compound statement (authored by Izaron).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134207

Files:
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/include/clang/Parse/Parser.h
  clang/lib/Parse/ParseStmt.cpp
  clang/test/AST/ast-dump-stmt.c
  clang/test/C/C2x/n2508.c
  clang/test/FixIt/fixit.c
  clang/test/Parser/c2x-label.c
  clang/test/Parser/cxx2b-label.cpp
  clang/test/Parser/switch-recovery.cpp
  clang/www/c_status.html

Index: clang/www/c_status.html
===
--- clang/www/c_status.html
+++ clang/www/c_status.html
@@ -763,13 +763,7 @@
 
   Free positioning of labels inside compound statements
   https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2508.pdf";>N2508
-
-  Partial
-Clang supports labels at the end of compound statements but does
-not yet support case or default labels at
-the end of a switch statement's compound block.
-  
-
+  Clang 16
 
 
   Clarification request for C17 example of undefined behavior
Index: clang/test/Parser/switch-recovery.cpp
===
--- clang/test/Parser/switch-recovery.cpp
+++ clang/test/Parser/switch-recovery.cpp
@@ -160,15 +160,15 @@
 void missing_statement_case(int x) {
   switch (x) {
 case 1:
-case 0: // expected-error {{label at end of switch compound statement: expected statement}}
-  }
+case 0:
+  } // expected-warning {{label at end of compound statement is a C++2b extension}}
 }
 
 void missing_statement_default(int x) {
   switch (x) {
 case 0:
-default: // expected-error {{label at end of switch compound statement: expected statement}}
-  }
+default:
+  } // expected-warning {{label at end of compound statement is a C++2b extension}}
 }
 
 void pr19022_1() {
@@ -178,9 +178,8 @@
 
 void pr19022_1a(int x) {
   switch(x) {
-  case 1  // expected-error{{expected ':' after 'case'}} \
-  // expected-error{{label at end of switch compound statement: expected statement}}
-  }
+  case 1  // expected-error{{expected ':' after 'case'}}
+  } // expected-warning {{label at end of compound statement is a C++2b extension}}
 }
 
 void pr19022_1b(int x) {
@@ -210,9 +209,9 @@
 
 void pr19022_5(int x) {
   switch(x) {
-  case 1: case // expected-error{{expected ':' after 'case'}} \
-   // expected-error{{expected statement}}
-  }  // expected-error{{expected expression}}
+  case 1: case // expected-error{{expected ':' after 'case'}}
+  }  // expected-error{{expected expression}} \
+ // expected-warning {{label at end of compound statement is a C++2b extension}}
 }
 
 namespace pr19022 {
Index: clang/test/Parser/cxx2b-label.cpp
===
--- clang/test/Parser/cxx2b-label.cpp
+++ clang/test/Parser/cxx2b-label.cpp
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx2b -std=c++2b -Wpre-c++2b-compat %s
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx20 -std=c++20 %s
 
-void foo() {
+void test_label_in_func() {
 label1:
 int x;
 label2:
@@ -9,3 +9,23 @@
 label3: label4: label5:
 } // cxx20-warning {{label at end of compound statement is a C++2b extension}} \
  cxx2b-warning {{label at end of compound statement is incompatible with C++ standards before C++2b}}
+
+int test_label_in_switch(int v) {
+switch (v) {
+case 1:
+return 1;
+case 2:
+return 2;
+case 3: case 4: case 5:
+} // cxx20-warning {{label at end of compound statement is a C++2b extension}} \
+ cxx2b-warning {{label at end of compound statement is incompatible with C++ standards before C++2b}}
+
+switch (v) {
+case 6:
+return 6;
+default:
+} // cxx20-warning {{label at end of compound statement is a C++2b extension}} \
+ cxx2b-warning {{label at end of compound statement is incompatible with C++ standards before C++2b}}
+
+return 0;
+}
Index: clang/test/Parser/c2x-label.c
===
--- clang/test/Parser/c2x-label.c
+++ clang/test/Parser/c2x-label.c
@@ -1,10 +1,30 @@
 // RUN: %clang_cc1 -fsyntax-only -std=c17 -Wc2x-compat -verify=c17 %s
 // RUN: %clang_cc1 -fsyntax-only -std=c2x -Wpre-c2x-compat -verify=c2x %s
 
-void foo() {
+void test_label_in_func() {
 int x;
 label1:
 x = 1;
 label2: label3: label4:
 } // c17-warning {{label at end of compound statement is a C2x extension}} \
  c2x-warning {{label at end of compound statement is incompatible with C standards before C2x}}
+
+int test_label_in_switch(int v) {
+s

[PATCH] D134207: [Clang] Support case and default labels at end of compound statement

2022-09-21 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 461942.
Izaron added a comment.

Add helper method `DiagnoseLabelAtEndOfCompoundStatement`


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134207

Files:
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/include/clang/Parse/Parser.h
  clang/lib/Parse/ParseStmt.cpp
  clang/test/AST/ast-dump-stmt.c
  clang/test/C/C2x/n2508.c
  clang/test/FixIt/fixit.c
  clang/test/Parser/c2x-label.c
  clang/test/Parser/cxx2b-label.cpp
  clang/test/Parser/switch-recovery.cpp
  clang/www/c_status.html

Index: clang/www/c_status.html
===
--- clang/www/c_status.html
+++ clang/www/c_status.html
@@ -763,13 +763,7 @@
 
   Free positioning of labels inside compound statements
   https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2508.pdf";>N2508
-
-  Partial
-Clang supports labels at the end of compound statements but does
-not yet support case or default labels at
-the end of a switch statement's compound block.
-  
-
+  Clang 16
 
 
   Clarification request for C17 example of undefined behavior
Index: clang/test/Parser/switch-recovery.cpp
===
--- clang/test/Parser/switch-recovery.cpp
+++ clang/test/Parser/switch-recovery.cpp
@@ -160,15 +160,15 @@
 void missing_statement_case(int x) {
   switch (x) {
 case 1:
-case 0: // expected-error {{label at end of switch compound statement: expected statement}}
-  }
+case 0:
+  } // expected-warning {{label at end of compound statement is a C++2b extension}}
 }
 
 void missing_statement_default(int x) {
   switch (x) {
 case 0:
-default: // expected-error {{label at end of switch compound statement: expected statement}}
-  }
+default:
+  } // expected-warning {{label at end of compound statement is a C++2b extension}}
 }
 
 void pr19022_1() {
@@ -178,9 +178,8 @@
 
 void pr19022_1a(int x) {
   switch(x) {
-  case 1  // expected-error{{expected ':' after 'case'}} \
-  // expected-error{{label at end of switch compound statement: expected statement}}
-  }
+  case 1  // expected-error{{expected ':' after 'case'}}
+  } // expected-warning {{label at end of compound statement is a C++2b extension}}
 }
 
 void pr19022_1b(int x) {
@@ -210,9 +209,9 @@
 
 void pr19022_5(int x) {
   switch(x) {
-  case 1: case // expected-error{{expected ':' after 'case'}} \
-   // expected-error{{expected statement}}
-  }  // expected-error{{expected expression}}
+  case 1: case // expected-error{{expected ':' after 'case'}}
+  }  // expected-error{{expected expression}} \
+ // expected-warning {{label at end of compound statement is a C++2b extension}}
 }
 
 namespace pr19022 {
Index: clang/test/Parser/cxx2b-label.cpp
===
--- clang/test/Parser/cxx2b-label.cpp
+++ clang/test/Parser/cxx2b-label.cpp
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx2b -std=c++2b -Wpre-c++2b-compat %s
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx20 -std=c++20 %s
 
-void foo() {
+void test_label_in_func() {
 label1:
 int x;
 label2:
@@ -9,3 +9,23 @@
 label3: label4: label5:
 } // cxx20-warning {{label at end of compound statement is a C++2b extension}} \
  cxx2b-warning {{label at end of compound statement is incompatible with C++ standards before C++2b}}
+
+int test_label_in_switch(int v) {
+switch (v) {
+case 1:
+return 1;
+case 2:
+return 2;
+case 3: case 4: case 5:
+} // cxx20-warning {{label at end of compound statement is a C++2b extension}} \
+ cxx2b-warning {{label at end of compound statement is incompatible with C++ standards before C++2b}}
+
+switch (v) {
+case 6:
+return 6;
+default:
+} // cxx20-warning {{label at end of compound statement is a C++2b extension}} \
+ cxx2b-warning {{label at end of compound statement is incompatible with C++ standards before C++2b}}
+
+return 0;
+}
Index: clang/test/Parser/c2x-label.c
===
--- clang/test/Parser/c2x-label.c
+++ clang/test/Parser/c2x-label.c
@@ -1,10 +1,30 @@
 // RUN: %clang_cc1 -fsyntax-only -std=c17 -Wc2x-compat -verify=c17 %s
 // RUN: %clang_cc1 -fsyntax-only -std=c2x -Wpre-c2x-compat -verify=c2x %s
 
-void foo() {
+void test_label_in_func() {
 int x;
 label1:
 x = 1;
 label2: label3: label4:
 } // c17-warning {{label at end of compound statement is a C2x extension}} \
  c2x-warning {{label at end of compound statement is incompatible with C standards before C2x}}
+
+int test_label_in_switch(int v) {
+switch (v) {
+case 1:
+return 1;
+case 2:
+return 2;
+case 3: case 4: case 5:
+} // c17-warning

[PATCH] D134369: [Clang] Support constexpr builtin fmax

2022-09-21 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added a comment.

This patch is derived from https://reviews.llvm.org/D134136 (which was 
abandoned due to poor tests and overcomplication)

The constexpr version of `fmax` matches the libc realization: the libc 
realization is here 
.

It is verified with test that matches libc test: the libc test is here 
.

If this patch is approved, I promise to do a similar patch for the `fmin` 
function 😀


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134369

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


[PATCH] D134369: [Clang] Support constexpr builtin fmax

2022-09-21 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron created this revision.
Izaron added reviewers: efriedma, cor3ntin, aaron.ballman.
Herald added a project: All.
Izaron requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Support constexpr version of __builtin_fmax and its variations.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D134369

Files:
  clang/docs/LanguageExtensions.rst
  clang/lib/AST/ExprConstant.cpp
  clang/test/Sema/constant-builtins-fmax.cpp


Index: clang/test/Sema/constant-builtins-fmax.cpp
===
--- /dev/null
+++ clang/test/Sema/constant-builtins-fmax.cpp
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+constexpr double NaN = __builtin_nan("");
+constexpr double Inf = __builtin_inf();
+constexpr double NegInf = -__builtin_inf();
+
+#define FMAX_TEST_SIMPLE(T, FUNC)   \
+static_assert(T(6.7890) == FUNC(T(1.2345), T(6.7890))); \
+static_assert(T(6.7890) == FUNC(T(6.7890), T(1.2345)));
+
+#define FMAX_TEST_NAN(T, FUNC)  \
+static_assert(Inf == FUNC(NaN, Inf));   \
+static_assert(NegInf == FUNC(NegInf, NaN)); \
+static_assert(0.0 == FUNC(NaN, 0.0));   \
+static_assert(-0.0 == FUNC(-0.0, NaN)); \
+static_assert(T(-1.2345) == FUNC(NaN, T(-1.2345))); \
+static_assert(T(1.2345) == FUNC(T(1.2345), NaN));   \
+static_assert(__builtin_isnan(FUNC(NaN, NaN)));
+
+#define FMAX_TEST_INF(T, FUNC)  \
+static_assert(Inf == FUNC(NegInf, Inf));\
+static_assert(Inf == FUNC(Inf, 0.0));   \
+static_assert(Inf == FUNC(-0.0, Inf));  \
+static_assert(Inf == FUNC(Inf, T(1.2345))); \
+static_assert(Inf == FUNC(T(-1.2345), Inf));
+
+#define FMAX_TEST_NEG_INF(T, FUNC) \
+static_assert(Inf == FUNC(Inf, NegInf));   \
+static_assert(0.0 == FUNC(NegInf, 0.0));   \
+static_assert(-0.0 == FUNC(-0.0, NegInf)); \
+static_assert(T(-1.2345) == FUNC(NegInf, T(-1.2345))); \
+static_assert(T(1.2345) == FUNC(T(1.2345), NegInf));
+
+#define FMAX_TEST_BOTH_ZERO(T, FUNC)   \
+static_assert(0.0 == FUNC(0.0, 0.0));  \
+static_assert(0.0 == FUNC(-0.0, 0.0)); \
+static_assert(0.0 == FUNC(0.0, -0.0)); \
+static_assert(0.0 == FUNC(-0.0, -0.0));
+
+#define LIST_FMAX_TESTS(T, FUNC) \
+FMAX_TEST_SIMPLE(T, FUNC)\
+FMAX_TEST_NAN(T, FUNC)   \
+FMAX_TEST_INF(T, FUNC)   \
+FMAX_TEST_NEG_INF(T, FUNC)   \
+FMAX_TEST_BOTH_ZERO(T, FUNC)
+
+LIST_FMAX_TESTS(double, __builtin_fmax)
+LIST_FMAX_TESTS(float, __builtin_fmaxf)
+LIST_FMAX_TESTS((long double), __builtin_fmaxl)
+LIST_FMAX_TESTS(__fp16, __builtin_fmaxf16)
+LIST_FMAX_TESTS(__float128, __builtin_fmaxf128)
Index: clang/lib/AST/ExprConstant.cpp
===
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -14021,6 +14021,20 @@
 Result.copySign(RHS);
 return true;
   }
+
+  case Builtin::BI__builtin_fmax:
+  case Builtin::BI__builtin_fmaxf:
+  case Builtin::BI__builtin_fmaxl:
+  case Builtin::BI__builtin_fmaxf16:
+  case Builtin::BI__builtin_fmaxf128: {
+APFloat RHS(0.);
+if (!EvaluateFloat(E->getArg(0), Result, Info) ||
+!EvaluateFloat(E->getArg(1), RHS, Info))
+  return false;
+if (Result.isNaN() || RHS > Result)
+  Result = RHS;
+return true;
+  }
   }
 }
 
Index: clang/docs/LanguageExtensions.rst
===
--- clang/docs/LanguageExtensions.rst
+++ clang/docs/LanguageExtensions.rst
@@ -4659,6 +4659,7 @@
 * ``__builtin_ffs``
 * ``__builtin_ffsl``
 * ``__builtin_ffsll``
+* ``__builtin_fmax``
 * ``__builtin_fpclassify``
 * ``__builtin_inf``
 * ``__builtin_isinf``


Index: clang/test/Sema/constant-builtins-fmax.cpp
===
--- /dev/null
+++ clang/test/Sema/constant-builtins-fmax.cpp
@@ -0,0 +1,52 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+constexpr double NaN = __builtin_nan("");
+constexpr double Inf = __builtin_inf();
+constexpr double NegInf = -__builtin_inf();
+
+#define FMAX_TEST_SIMPLE(T, FUNC)   \
+static_assert(T(6.7890) == FUNC(T(1.2345), T(6.7890))); \
+static_assert(T(6.7890) == FUNC(T(6.7890), T(1.2345)));
+
+#define FMAX_TEST_NAN(T, FUNC)  \
+static_assert(Inf == FUNC(NaN, Inf));   \
+static_assert(NegInf == FUNC(NegInf, NaN)); \
+static_assert(0.0 == FUNC(NaN, 0.0));   \
+static_assert(-0.0 == FUNC(-0.0, NaN)); \
+static_assert(T(-1.2345) == FUNC(NaN, T(-1.2345))); \
+static_assert(T(1.2345) == FUNC(T(1.2345), NaN));   \
+static_assert(__builtin_isnan(FUNC(NaN

[PATCH] D134136: [Clang] Support constexpr for builtin fmax, fmin, ilogb, logb, scalbn

2022-09-20 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron abandoned this revision.
Izaron added a comment.

In D134136#3801495 , @efriedma wrote:

> These patches are hard to review, yes; the reviewer has to go through and 
> verify for each function that the substitutes you've written actually match 
> the C library semantics.  (It's very easy to make mistakes with that sort of 
> thing.)
>
> On that front, I'm pretty sure the NaN handling in your fmin/fmax 
> implementations are wrong.

Thanks! I'm abandoning this patch, will make new smaller but better patches.

> each function that the substitutes you've written actually match the C 
> library semantics

I think this can be verified with libc++/libc tests that would substitute 
either `std::fmax` or (constant) `__builtin_fmax` on same checks and assert 
that they behave in the same way.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134136

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


[PATCH] D134207: [Clang] Support case and default labels at end of compound statement

2022-09-19 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 461347.
Izaron added a comment.

Fix corresponding FixIt clang test


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134207

Files:
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/lib/Parse/ParseStmt.cpp
  clang/test/AST/ast-dump-stmt.c
  clang/test/C/C2x/n2508.c
  clang/test/FixIt/fixit.c
  clang/test/Parser/c2x-label.c
  clang/test/Parser/cxx2b-label.cpp
  clang/test/Parser/switch-recovery.cpp
  clang/www/c_status.html

Index: clang/www/c_status.html
===
--- clang/www/c_status.html
+++ clang/www/c_status.html
@@ -763,13 +763,7 @@
 
   Free positioning of labels inside compound statements
   https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2508.pdf";>N2508
-
-  Partial
-Clang supports labels at the end of compound statements but does
-not yet support case or default labels at
-the end of a switch statement's compound block.
-  
-
+  Clang 16
 
 
   Clarification request for C17 example of undefined behavior
Index: clang/test/Parser/switch-recovery.cpp
===
--- clang/test/Parser/switch-recovery.cpp
+++ clang/test/Parser/switch-recovery.cpp
@@ -160,15 +160,15 @@
 void missing_statement_case(int x) {
   switch (x) {
 case 1:
-case 0: // expected-error {{label at end of switch compound statement: expected statement}}
-  }
+case 0:
+  } // expected-warning {{label at end of compound statement is a C++2b extension}}
 }
 
 void missing_statement_default(int x) {
   switch (x) {
 case 0:
-default: // expected-error {{label at end of switch compound statement: expected statement}}
-  }
+default:
+  } // expected-warning {{label at end of compound statement is a C++2b extension}}
 }
 
 void pr19022_1() {
@@ -178,9 +178,8 @@
 
 void pr19022_1a(int x) {
   switch(x) {
-  case 1  // expected-error{{expected ':' after 'case'}} \
-  // expected-error{{label at end of switch compound statement: expected statement}}
-  }
+  case 1  // expected-error{{expected ':' after 'case'}}
+  } // expected-warning {{label at end of compound statement is a C++2b extension}}
 }
 
 void pr19022_1b(int x) {
@@ -210,9 +209,9 @@
 
 void pr19022_5(int x) {
   switch(x) {
-  case 1: case // expected-error{{expected ':' after 'case'}} \
-   // expected-error{{expected statement}}
-  }  // expected-error{{expected expression}}
+  case 1: case // expected-error{{expected ':' after 'case'}}
+  }  // expected-error{{expected expression}} \
+ // expected-warning {{label at end of compound statement is a C++2b extension}}
 }
 
 namespace pr19022 {
Index: clang/test/Parser/cxx2b-label.cpp
===
--- clang/test/Parser/cxx2b-label.cpp
+++ clang/test/Parser/cxx2b-label.cpp
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx2b -std=c++2b -Wpre-c++2b-compat %s
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx20 -std=c++20 %s
 
-void foo() {
+void test_label_in_func() {
 label1:
 int x;
 label2:
@@ -9,3 +9,23 @@
 label3: label4: label5:
 } // cxx20-warning {{label at end of compound statement is a C++2b extension}} \
  cxx2b-warning {{label at end of compound statement is incompatible with C++ standards before C++2b}}
+
+int test_label_in_switch(int v) {
+switch (v) {
+case 1:
+return 1;
+case 2:
+return 2;
+case 3: case 4: case 5:
+} // cxx20-warning {{label at end of compound statement is a C++2b extension}} \
+ cxx2b-warning {{label at end of compound statement is incompatible with C++ standards before C++2b}}
+
+switch (v) {
+case 6:
+return 6;
+default:
+} // cxx20-warning {{label at end of compound statement is a C++2b extension}} \
+ cxx2b-warning {{label at end of compound statement is incompatible with C++ standards before C++2b}}
+
+return 0;
+}
Index: clang/test/Parser/c2x-label.c
===
--- clang/test/Parser/c2x-label.c
+++ clang/test/Parser/c2x-label.c
@@ -1,10 +1,30 @@
 // RUN: %clang_cc1 -fsyntax-only -std=c17 -Wc2x-compat -verify=c17 %s
 // RUN: %clang_cc1 -fsyntax-only -std=c2x -Wpre-c2x-compat -verify=c2x %s
 
-void foo() {
+void test_label_in_func() {
 int x;
 label1:
 x = 1;
 label2: label3: label4:
 } // c17-warning {{label at end of compound statement is a C2x extension}} \
  c2x-warning {{label at end of compound statement is incompatible with C standards before C2x}}
+
+int test_label_in_switch(int v) {
+switch (v) {
+case 1:
+return 1;
+case 2:
+return 2;
+case 3: case 4: case 5:
+} // c17-warning {{label at end of compound statement is a C2x extension}} \

[PATCH] D134136: [Clang] Support constexpr for builtin fmax, fmin, ilogb, logb, scalbn

2022-09-19 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 461312.
Izaron added a comment.

Removed whitespaces in comments.

P.S. I wonder if smaller review requests will make things better? Say a review 
request for `fmax`+`fmin`, then a new one for `ilogb`+`logb`, then for `scalbn`.
This may lead to a more understandable and robust review process =)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134136

Files:
  clang/docs/LanguageExtensions.rst
  clang/lib/AST/ExprConstant.cpp
  clang/test/Sema/constant-builtins-math.cpp
  llvm/include/llvm/ADT/APFloat.h
  llvm/lib/Support/APFloat.cpp

Index: llvm/lib/Support/APFloat.cpp
===
--- llvm/lib/Support/APFloat.cpp
+++ llvm/lib/Support/APFloat.cpp
@@ -4198,6 +4198,19 @@
   return Normalized.exponent - SignificandBits;
 }
 
+IEEEFloat logb(const IEEEFloat &Arg) {
+  IEEEFloat Result(Arg.getSemantics());
+  if (Arg.isNaN())
+Result.makeNaN();
+  else if (Arg.isZero())
+Result.makeInf(/*Negative=*/true);
+  else if (Arg.isInfinity())
+Result.makeInf(/*Negative=*/false);
+  else
+Result = IEEEFloat(static_cast(ilogb(Arg)));
+  return Result;
+}
+
 IEEEFloat scalbn(IEEEFloat X, int Exp, IEEEFloat::roundingMode RoundingMode) {
   auto MaxExp = X.getSemantics().maxExponent;
   auto MinExp = X.getSemantics().minExponent;
Index: llvm/include/llvm/ADT/APFloat.h
===
--- llvm/include/llvm/ADT/APFloat.h
+++ llvm/include/llvm/ADT/APFloat.h
@@ -592,6 +592,7 @@
 
 hash_code hash_value(const IEEEFloat &Arg);
 int ilogb(const IEEEFloat &Arg);
+IEEEFloat logb(const IEEEFloat &Arg);
 IEEEFloat scalbn(IEEEFloat X, int Exp, IEEEFloat::roundingMode);
 IEEEFloat frexp(const IEEEFloat &Val, int &Exp, IEEEFloat::roundingMode RM);
 
@@ -1248,6 +1249,9 @@
 
   friend hash_code hash_value(const APFloat &Arg);
   friend int ilogb(const APFloat &Arg) { return ilogb(Arg.getIEEE()); }
+  friend APFloat logb(const APFloat &Arg) {
+return APFloat(logb(Arg.getIEEE()), Arg.getSemantics());
+  }
   friend APFloat scalbn(APFloat X, int Exp, roundingMode RM);
   friend APFloat frexp(const APFloat &X, int &Exp, roundingMode RM);
   friend IEEEFloat;
Index: clang/test/Sema/constant-builtins-math.cpp
===
--- /dev/null
+++ clang/test/Sema/constant-builtins-math.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+static_assert(__builtin_fmax(12.34, 56.78) == 56.78);
+static_assert(__builtin_fmaxf(12.34f, 56.78f) == 56.78f);
+static_assert(__builtin_fmaxl(12.34, 56.78) == 56.78);
+static_assert(__builtin_fmaxf16(12.0, 56.0) == 56.0);
+static_assert(__builtin_fmaxf128(12.34, 56.78) == 56.78);
+
+static_assert(__builtin_fmin(12.34, 56.78) == 12.34);
+static_assert(__builtin_fminf(12.34f, 56.78f) == 12.34f);
+static_assert(__builtin_fminl(12.34, 56.78) == 12.34);
+static_assert(__builtin_fminf16(12.0, 56.0) == 12.0);
+static_assert(__builtin_fminf128(12.34, 56.78) == 12.34);
+
+// TODO: investigate why this is `INT_MIN + 1` instead of `INT_MIN`
+static_assert(__builtin_ilogb(0.0) == -2147483647);
+static_assert(__builtin_ilogb(__builtin_inf()) == 2147483647);
+static_assert(__builtin_ilogb(__builtin_nan("")) == -2147483648);
+static_assert(__builtin_ilogb(1.0) == 0);
+static_assert(__builtin_ilogb(32.0) == 5);
+static_assert(__builtin_ilogb(1024.0) == 10);
+static_assert(__builtin_ilogb(-1024.0) == 10);
+static_assert(__builtin_ilogb(0.1) == -4);
+static_assert(__builtin_ilogb(0.1) == -44);
+
+static_assert(__builtin_logb(0.0) == -__builtin_inf());
+static_assert(__builtin_logb(__builtin_inf()) == __builtin_inf());
+static_assert(__builtin_isnan(__builtin_logb(__builtin_nan("";
+static_assert(__builtin_logb(1.0) == 0.0);
+static_assert(__builtin_logb(32.0) == 5.0);
+static_assert(__builtin_logb(1024.0) == 10.0);
+static_assert(__builtin_logb(-1024.0) == 10.0);
+static_assert(__builtin_logb(0.1) == -4.0);
+static_assert(__builtin_logb(0.1) == -44.0);
+
+static_assert(__builtin_scalbn(12.5, 0) == 12.5);
+static_assert(__builtin_scalbn(12.5, 1) == 25);
+static_assert(__builtin_scalbn(12.5, 3) == 100.0);
+static_assert(__builtin_scalbn(0.0, 100) == 0);
+static_assert(__builtin_scalbn(__builtin_inf(), 100) == __builtin_inf());
+static_assert(__builtin_isnan(__builtin_scalbn(__builtin_nan(""), 100)));
Index: clang/lib/AST/ExprConstant.cpp
===
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -12410,6 +12410,19 @@
   return false;
 return Success(DidOverflow, E);
   }
+
+  case Builtin::BI__builtin_ilogb:
+  case Builtin::BI__builtin_ilogbf:
+  case Builtin::BI__builtin_ilogbl:
+  case Builtin::BI__builtin_ilogbf128: {
+APFloat F(0.0);
+if (!EvaluateFloat(E->getArg(0), F

[PATCH] D134207: [Clang] Support case and default labels at end of compound statement

2022-09-19 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added inline comments.



Comment at: clang/include/clang/Basic/DiagnosticParseKinds.td:298-299
   "and have an empty entry in the selector">;
-def err_switch_label_end_of_compound_statement : Error<
-  "label at end of switch compound statement: expected statement">;
 def ext_c_label_end_of_compound_statement : ExtWarn<

This is not an error anymore



Comment at: clang/lib/Parse/ParseStmt.cpp:948-956
+if (getLangOpts().CPlusPlus) {
+  Diag(Tok, getLangOpts().CPlusPlus2b
+? diag::warn_cxx20_compat_label_end_of_compound_statement
+: diag::ext_cxx_label_end_of_compound_statement);
+} else {
+  Diag(Tok, getLangOpts().C2x
+? diag::warn_c2x_compat_label_end_of_compound_statement

We have copy-pasted this piece of code in 3 places (simple label, case label, 
default label). Does it make sense to have a method for label diags?



Comment at: clang/test/Parser/c2x-label.c:12-30
+int test_label_in_switch(int v) {
+switch (v) {
+case 1:
+return 1;
+case 2:
+return 2;
+case 3: case 4: case 5:

I feel like we may be having redundant tests, because `Parser/c2x-label.c` and 
`C2x/n2508.c` test the same things...


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134207

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


[PATCH] D134207: [Clang] Support case and default labels at end of compound statement

2022-09-19 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron created this revision.
Izaron added reviewers: clang-language-wg, aaron.ballman, cor3ntin.
Herald added a project: All.
Izaron requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Direct continuation of https://reviews.llvm.org/D133887


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D134207

Files:
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/lib/Parse/ParseStmt.cpp
  clang/test/AST/ast-dump-stmt.c
  clang/test/C/C2x/n2508.c
  clang/test/Parser/c2x-label.c
  clang/test/Parser/cxx2b-label.cpp
  clang/test/Parser/switch-recovery.cpp
  clang/www/c_status.html

Index: clang/www/c_status.html
===
--- clang/www/c_status.html
+++ clang/www/c_status.html
@@ -763,13 +763,7 @@
 
   Free positioning of labels inside compound statements
   https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2508.pdf";>N2508
-
-  Partial
-Clang supports labels at the end of compound statements but does
-not yet support case or default labels at
-the end of a switch statement's compound block.
-  
-
+  Clang 16
 
 
   Clarification request for C17 example of undefined behavior
Index: clang/test/Parser/switch-recovery.cpp
===
--- clang/test/Parser/switch-recovery.cpp
+++ clang/test/Parser/switch-recovery.cpp
@@ -160,15 +160,15 @@
 void missing_statement_case(int x) {
   switch (x) {
 case 1:
-case 0: // expected-error {{label at end of switch compound statement: expected statement}}
-  }
+case 0:
+  } // expected-warning {{label at end of compound statement is a C++2b extension}}
 }
 
 void missing_statement_default(int x) {
   switch (x) {
 case 0:
-default: // expected-error {{label at end of switch compound statement: expected statement}}
-  }
+default:
+  } // expected-warning {{label at end of compound statement is a C++2b extension}}
 }
 
 void pr19022_1() {
@@ -178,9 +178,8 @@
 
 void pr19022_1a(int x) {
   switch(x) {
-  case 1  // expected-error{{expected ':' after 'case'}} \
-  // expected-error{{label at end of switch compound statement: expected statement}}
-  }
+  case 1  // expected-error{{expected ':' after 'case'}}
+  } // expected-warning {{label at end of compound statement is a C++2b extension}}
 }
 
 void pr19022_1b(int x) {
@@ -210,9 +209,9 @@
 
 void pr19022_5(int x) {
   switch(x) {
-  case 1: case // expected-error{{expected ':' after 'case'}} \
-   // expected-error{{expected statement}}
-  }  // expected-error{{expected expression}}
+  case 1: case // expected-error{{expected ':' after 'case'}}
+  }  // expected-error{{expected expression}} \
+ // expected-warning {{label at end of compound statement is a C++2b extension}}
 }
 
 namespace pr19022 {
Index: clang/test/Parser/cxx2b-label.cpp
===
--- clang/test/Parser/cxx2b-label.cpp
+++ clang/test/Parser/cxx2b-label.cpp
@@ -1,7 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx2b -std=c++2b -Wpre-c++2b-compat %s
 // RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx20 -std=c++20 %s
 
-void foo() {
+void test_label_in_func() {
 label1:
 int x;
 label2:
@@ -9,3 +9,23 @@
 label3: label4: label5:
 } // cxx20-warning {{label at end of compound statement is a C++2b extension}} \
  cxx2b-warning {{label at end of compound statement is incompatible with C++ standards before C++2b}}
+
+int test_label_in_switch(int v) {
+switch (v) {
+case 1:
+return 1;
+case 2:
+return 2;
+case 3: case 4: case 5:
+} // cxx20-warning {{label at end of compound statement is a C++2b extension}} \
+ cxx2b-warning {{label at end of compound statement is incompatible with C++ standards before C++2b}}
+
+switch (v) {
+case 6:
+return 6;
+default:
+} // cxx20-warning {{label at end of compound statement is a C++2b extension}} \
+ cxx2b-warning {{label at end of compound statement is incompatible with C++ standards before C++2b}}
+
+return 0;
+}
Index: clang/test/Parser/c2x-label.c
===
--- clang/test/Parser/c2x-label.c
+++ clang/test/Parser/c2x-label.c
@@ -1,10 +1,30 @@
 // RUN: %clang_cc1 -fsyntax-only -std=c17 -Wc2x-compat -verify=c17 %s
 // RUN: %clang_cc1 -fsyntax-only -std=c2x -Wpre-c2x-compat -verify=c2x %s
 
-void foo() {
+void test_label_in_func() {
 int x;
 label1:
 x = 1;
 label2: label3: label4:
 } // c17-warning {{label at end of compound statement is a C2x extension}} \
  c2x-warning {{label at end of compound statement is incompatible with C standards before C2x}}
+
+int test_label_in_switch(int v) {
+switch (v) {
+case 1:
+return 1;
+case 2:
+return 2;
+case 3:

[PATCH] D133887: [Clang] Support label at end of compound statement

2022-09-19 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added a comment.

In D133887#3799399 , @aaron.ballman 
wrote:

> I can fix up the C++ status page as well if you'd like, or I can hold off if 
> you're already working on this, it's up to you!

Thank you! I'll support empty labels in switch statements in a new pull request 
as soon as I can 😁


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133887

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


[PATCH] D133887: [Clang] Support label at end of compound statement

2022-09-19 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added a comment.

In D133887#3799310 , @aaron.ballman 
wrote:

> Thank you for working on this! I spotted an issue where we're not quite 
> complete with this implementation work. I pushed up a new test case in 
> https://github.com/llvm/llvm-project/commit/a244194f73788de6dfd6d753ff09be3625613f9f
>  that shows it (and set the C status page back to Partial in case this takes 
> a while to address), but `case` and `default` labels should be accepted the 
> same as any other label at the end of a compound statement.
>
> Btw, when working on C standards features, I've started adding test coverage 
> that demonstrates we fully implement the paper into the `clang/test/C/` 
> directory, under the correct standard version. This helps us to track the 
> status of proposals a bit more easily within the code base.

Hi! Thanks for this information! How did you find out that we should accept 
labels at end of statement in **C**, but not in **C++**? That is not obvious 
for me unfortunately. If C supports it, why would C++ not support it?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133887

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


[PATCH] D134136: [Clang] Support constexpr for builtin fmax, fmin, ilogb, logb, scalbn

2022-09-18 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added inline comments.



Comment at: clang/test/Sema/constant-builtins-math.cpp:16-17
+
+// TODO: investigate why this is `INT_MIN + 1` instead of `INT_MIN`
+static_assert(__builtin_ilogb(0.0) == -2147483647);
+static_assert(__builtin_ilogb(__builtin_inf()) == 2147483647);

Izaron wrote:
> runtime version of `__builtin_ilogb/std::ilogb` returns `INT_MIN` 
> (`-2147483647`) on this argument, while constexpr version returns `INT_MIN+1` 
> 🤔 
> 
> This constant is here:
> https://llvm.org/doxygen/APFloat_8cpp_source.html#l04187
> https://llvm.org/doxygen/APFloat_8h_source.html#l00229
> (I guess we shouldn't change this)
quick fix: `INT_MIN` is `-2147483648`, `INT_MIN+1` is `2147483647`


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134136

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


[PATCH] D134136: [Clang] Support constexpr for builtin fmax, fmin, ilogb, logb, scalbn

2022-09-18 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added inline comments.



Comment at: clang/test/Sema/constant-builtins-math.cpp:16-17
+
+// TODO: investigate why this is `INT_MIN + 1` instead of `INT_MIN`
+static_assert(__builtin_ilogb(0.0) == -2147483647);
+static_assert(__builtin_ilogb(__builtin_inf()) == 2147483647);

runtime version of `__builtin_ilogb/std::ilogb` returns `INT_MIN` 
(`-2147483647`) on this argument, while constexpr version returns `INT_MIN+1` 🤔 

This constant is here:
https://llvm.org/doxygen/APFloat_8cpp_source.html#l04187
https://llvm.org/doxygen/APFloat_8h_source.html#l00229
(I guess we shouldn't change this)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134136

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


[PATCH] D134136: [Clang] Support constexpr for builtin fmax, fmin, ilogb, logb, scalbn

2022-09-18 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added a comment.

libc++ doesn't support constexpr-related patches from C++20 in ``: see 
issue https://github.com/llvm/llvm-project/issues/55370

I reviewed the code in `` and found out that since we use a dozen of 
math functions, we need to support more constexpr builtin math function.

I implemented constexpr versions for five functions. This will be enough to 
implement a 2017 paper: 
https://www.open-std.org/JTC1/SC22/WG21/docs/papers/2017/p0415r1.html (in a new 
pull request)

(Also there is a 2019 paper with more constexpr functions for ``: 
https://www.open-std.org/JTC1/SC22/WG21/docs/papers/2019/p1383r0.pdf)

Also builtin implementations will be useful for new C++23 constexpr functions: 
for example https://en.cppreference.com/w/cpp/numeric/math/scalbn


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D134136

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


[PATCH] D134136: [Clang] Support constexpr for builtin fmax, fmin, ilogb, logb, scalbn

2022-09-18 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron created this revision.
Izaron added reviewers: cor3ntin, aaron.ballman.
Herald added a subscriber: hiraditya.
Herald added a project: All.
Izaron requested review of this revision.
Herald added projects: clang, LLVM.
Herald added subscribers: llvm-commits, cfe-commits.

Support constexpr versions of __builtin_fmax, __builtin_fmin,
__builtin_ilogb, __builtin_logb, __builtin_scalbn and their
variations.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D134136

Files:
  clang/docs/LanguageExtensions.rst
  clang/lib/AST/ExprConstant.cpp
  clang/test/Sema/constant-builtins-math.cpp
  llvm/include/llvm/ADT/APFloat.h
  llvm/lib/Support/APFloat.cpp

Index: llvm/lib/Support/APFloat.cpp
===
--- llvm/lib/Support/APFloat.cpp
+++ llvm/lib/Support/APFloat.cpp
@@ -4198,6 +4198,19 @@
   return Normalized.exponent - SignificandBits;
 }
 
+IEEEFloat logb(const IEEEFloat &Arg) {
+  IEEEFloat Result(Arg.getSemantics());
+  if (Arg.isNaN())
+Result.makeNaN();
+  else if (Arg.isZero())
+Result.makeInf(/* Negative = */ true);
+  else if (Arg.isInfinity())
+Result.makeInf(/* Negative = */ false);
+  else
+Result = IEEEFloat(static_cast(ilogb(Arg)));
+  return Result;
+}
+
 IEEEFloat scalbn(IEEEFloat X, int Exp, IEEEFloat::roundingMode RoundingMode) {
   auto MaxExp = X.getSemantics().maxExponent;
   auto MinExp = X.getSemantics().minExponent;
Index: llvm/include/llvm/ADT/APFloat.h
===
--- llvm/include/llvm/ADT/APFloat.h
+++ llvm/include/llvm/ADT/APFloat.h
@@ -592,6 +592,7 @@
 
 hash_code hash_value(const IEEEFloat &Arg);
 int ilogb(const IEEEFloat &Arg);
+IEEEFloat logb(const IEEEFloat &Arg);
 IEEEFloat scalbn(IEEEFloat X, int Exp, IEEEFloat::roundingMode);
 IEEEFloat frexp(const IEEEFloat &Val, int &Exp, IEEEFloat::roundingMode RM);
 
@@ -1248,6 +1249,9 @@
 
   friend hash_code hash_value(const APFloat &Arg);
   friend int ilogb(const APFloat &Arg) { return ilogb(Arg.getIEEE()); }
+  friend APFloat logb(const APFloat &Arg) {
+return APFloat(logb(Arg.getIEEE()), Arg.getSemantics());
+  }
   friend APFloat scalbn(APFloat X, int Exp, roundingMode RM);
   friend APFloat frexp(const APFloat &X, int &Exp, roundingMode RM);
   friend IEEEFloat;
Index: clang/test/Sema/constant-builtins-math.cpp
===
--- /dev/null
+++ clang/test/Sema/constant-builtins-math.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+static_assert(__builtin_fmax(12.34, 56.78) == 56.78);
+static_assert(__builtin_fmaxf(12.34f, 56.78f) == 56.78f);
+static_assert(__builtin_fmaxl(12.34, 56.78) == 56.78);
+static_assert(__builtin_fmaxf16(12.0, 56.0) == 56.0);
+static_assert(__builtin_fmaxf128(12.34, 56.78) == 56.78);
+
+static_assert(__builtin_fmin(12.34, 56.78) == 12.34);
+static_assert(__builtin_fminf(12.34f, 56.78f) == 12.34f);
+static_assert(__builtin_fminl(12.34, 56.78) == 12.34);
+static_assert(__builtin_fminf16(12.0, 56.0) == 12.0);
+static_assert(__builtin_fminf128(12.34, 56.78) == 12.34);
+
+// TODO: investigate why this is `INT_MIN + 1` instead of `INT_MIN`
+static_assert(__builtin_ilogb(0.0) == -2147483647);
+static_assert(__builtin_ilogb(__builtin_inf()) == 2147483647);
+static_assert(__builtin_ilogb(__builtin_nan("")) == -2147483648);
+static_assert(__builtin_ilogb(1.0) == 0);
+static_assert(__builtin_ilogb(32.0) == 5);
+static_assert(__builtin_ilogb(1024.0) == 10);
+static_assert(__builtin_ilogb(-1024.0) == 10);
+static_assert(__builtin_ilogb(0.1) == -4);
+static_assert(__builtin_ilogb(0.1) == -44);
+
+static_assert(__builtin_logb(0.0) == -__builtin_inf());
+static_assert(__builtin_logb(__builtin_inf()) == __builtin_inf());
+static_assert(__builtin_isnan(__builtin_logb(__builtin_nan("";
+static_assert(__builtin_logb(1.0) == 0.0);
+static_assert(__builtin_logb(32.0) == 5.0);
+static_assert(__builtin_logb(1024.0) == 10.0);
+static_assert(__builtin_logb(-1024.0) == 10.0);
+static_assert(__builtin_logb(0.1) == -4.0);
+static_assert(__builtin_logb(0.1) == -44.0);
+
+static_assert(__builtin_scalbn(12.5, 0) == 12.5);
+static_assert(__builtin_scalbn(12.5, 1) == 25);
+static_assert(__builtin_scalbn(12.5, 3) == 100.0);
+static_assert(__builtin_scalbn(0.0, 100) == 0);
+static_assert(__builtin_scalbn(__builtin_inf(), 100) == __builtin_inf());
+static_assert(__builtin_isnan(__builtin_scalbn(__builtin_nan(""), 100)));
Index: clang/lib/AST/ExprConstant.cpp
===
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -12410,6 +12410,19 @@
   return false;
 return Success(DidOverflow, E);
   }
+
+  case Builtin::BI__builtin_ilogb:
+  case Builtin::BI__builtin_ilogbf:
+  case Builtin::BI__builtin_ilogbl:
+  case Builtin::BI__builtin_ilogbf128: {
+APFloat F(0.0);
+if (!EvaluateF

[PATCH] D133887: [Clang] Support label at end of compound statement

2022-09-17 Thread Evgeny Shulgin 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 rG510383626fe1: [Clang] Support label at end of compound 
statement (authored by Izaron).

Changed prior to commit:
  https://reviews.llvm.org/D133887?vs=461006&id=461008#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133887

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/lib/Parse/ParseStmt.cpp
  clang/test/AST/ast-dump-stmt.c
  clang/test/Parser/c2x-label.c
  clang/test/Parser/cxx2b-label.cpp
  clang/test/Parser/switch-recovery.cpp
  clang/www/c_status.html
  clang/www/cxx_status.html

Index: clang/www/cxx_status.html
===
--- clang/www/cxx_status.html
+++ clang/www/cxx_status.html
@@ -1456,7 +1456,7 @@
 
   Labels at the end of compound statements
   https://wg21.link/P2324R2";>P2324R2
-  No
+  Clang 16
 
 
   Delimited escape sequences
Index: clang/www/c_status.html
===
--- clang/www/c_status.html
+++ clang/www/c_status.html
@@ -763,7 +763,7 @@
 
   Free positioning of labels inside compound statements
   https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2508.pdf";>N2508
-  No
+  Clang 16
 
 
   Clarification request for C17 example of undefined behavior
Index: clang/test/Parser/switch-recovery.cpp
===
--- clang/test/Parser/switch-recovery.cpp
+++ clang/test/Parser/switch-recovery.cpp
@@ -160,14 +160,14 @@
 void missing_statement_case(int x) {
   switch (x) {
 case 1:
-case 0: // expected-error {{label at end of compound statement: expected statement}}
+case 0: // expected-error {{label at end of switch compound statement: expected statement}}
   }
 }
 
 void missing_statement_default(int x) {
   switch (x) {
 case 0:
-default: // expected-error {{label at end of compound statement: expected statement}}
+default: // expected-error {{label at end of switch compound statement: expected statement}}
   }
 }
 
@@ -179,7 +179,7 @@
 void pr19022_1a(int x) {
   switch(x) {
   case 1  // expected-error{{expected ':' after 'case'}} \
-  // expected-error{{label at end of compound statement: expected statement}}
+  // expected-error{{label at end of switch compound statement: expected statement}}
   }
 }
 
Index: clang/test/Parser/cxx2b-label.cpp
===
--- /dev/null
+++ clang/test/Parser/cxx2b-label.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx2b -std=c++2b -Wpre-c++2b-compat %s
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx20 -std=c++20 %s
+
+void foo() {
+label1:
+int x;
+label2:
+x = 1;
+label3: label4: label5:
+} // cxx20-warning {{label at end of compound statement is a C++2b extension}} \
+ cxx2b-warning {{label at end of compound statement is incompatible with C++ standards before C++2b}}
Index: clang/test/Parser/c2x-label.c
===
--- /dev/null
+++ clang/test/Parser/c2x-label.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c17 -Wc2x-compat -verify=c17 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c2x -Wpre-c2x-compat -verify=c2x %s
+
+void foo() {
+int x;
+label1:
+x = 1;
+label2: label3: label4:
+} // c17-warning {{label at end of compound statement is a C2x extension}} \
+ c2x-warning {{label at end of compound statement is incompatible with C standards before C2x}}
Index: clang/test/AST/ast-dump-stmt.c
===
--- clang/test/AST/ast-dump-stmt.c
+++ clang/test/AST/ast-dump-stmt.c
@@ -161,6 +161,10 @@
   // CHECK-NEXT: ImplicitCastExpr
   // CHECK-NEXT: ImplicitCastExpr
   // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}}  'void *' lvalue Var 0x{{[^ ]*}} 'ptr' 'void *'
+
+label3:
+  // CHECK-NEXT: LabelStmt 0x{{[^ ]*}}  'label3'
+  // CHECK-NEXT: NullStmt 0x{{[^ ]*}} 
 }
 
 void TestSwitch(int i) {
Index: clang/lib/Parse/ParseStmt.cpp
===
--- clang/lib/Parse/ParseStmt.cpp
+++ clang/lib/Parse/ParseStmt.cpp
@@ -679,9 +679,12 @@
 
 /// ParseLabeledStatement - We have an identifier and a ':' after it.
 ///
+///   label:
+/// identifier ':'
+/// [GNU]   identifier ':' attributes[opt]
+///
 ///   labeled-statement:
-/// identifier ':' statement
-/// [GNU]   identifier ':' attributes[opt] statement
+/// label statement
 ///
 StmtResult Parser::ParseLabeledStatement(ParsedAttributes &Attrs,
  ParsedStmtContext StmtCtx) {
@@ -725,6 +728,20 @@
 }
   }
 
+  // The label m

[PATCH] D133887: [Clang] Support label at end of compound statement

2022-09-17 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 461006.
Izaron added a comment.

Fix diagnostics for C. Thanks to @cor3ntin and @aaron.ballman!


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133887

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/lib/Parse/ParseStmt.cpp
  clang/test/AST/ast-dump-stmt.c
  clang/test/Parser/c2x-label.c
  clang/test/Parser/cxx2b-label.cpp
  clang/test/Parser/switch-recovery.cpp
  clang/www/c_status.html
  clang/www/cxx_status.html

Index: clang/www/cxx_status.html
===
--- clang/www/cxx_status.html
+++ clang/www/cxx_status.html
@@ -1456,7 +1456,7 @@
 
   Labels at the end of compound statements
   https://wg21.link/P2324R2";>P2324R2
-  No
+  Clang 16
 
 
   Delimited escape sequences
Index: clang/www/c_status.html
===
--- clang/www/c_status.html
+++ clang/www/c_status.html
@@ -763,7 +763,7 @@
 
   Free positioning of labels inside compound statements
   https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2508.pdf";>N2508
-  No
+  Clang 16
 
 
   Clarification request for C17 example of undefined behavior
Index: clang/test/Parser/switch-recovery.cpp
===
--- clang/test/Parser/switch-recovery.cpp
+++ clang/test/Parser/switch-recovery.cpp
@@ -160,14 +160,14 @@
 void missing_statement_case(int x) {
   switch (x) {
 case 1:
-case 0: // expected-error {{label at end of compound statement: expected statement}}
+case 0: // expected-error {{label at end of switch compound statement: expected statement}}
   }
 }
 
 void missing_statement_default(int x) {
   switch (x) {
 case 0:
-default: // expected-error {{label at end of compound statement: expected statement}}
+default: // expected-error {{label at end of switch compound statement: expected statement}}
   }
 }
 
@@ -179,7 +179,7 @@
 void pr19022_1a(int x) {
   switch(x) {
   case 1  // expected-error{{expected ':' after 'case'}} \
-  // expected-error{{label at end of compound statement: expected statement}}
+  // expected-error{{label at end of switch compound statement: expected statement}}
   }
 }
 
Index: clang/test/Parser/cxx2b-label.cpp
===
--- /dev/null
+++ clang/test/Parser/cxx2b-label.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx2b -std=c++2b -Wpre-c++2b-compat %s
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx20 -std=c++20 %s
+
+void foo() {
+label1:
+int x;
+label2:
+x = 1;
+label3: label4: label5:
+} // cxx20-warning {{label at end of compound statement is a C++2b extension}} \
+ cxx2b-warning {{label at end of compound statement is incompatible with C++ standards before C++2b}}
Index: clang/test/Parser/c2x-label.c
===
--- /dev/null
+++ clang/test/Parser/c2x-label.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c17 -Wc2x-compat -verify=c17 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c2x -Wpre-c2x-compat -verify=c2x %s
+
+void foo() {
+int x;
+label1:
+x = 1;
+label2: label3: label4:
+} // c17-warning {{label at end of compound statement is a C2x extension}} \
+ c2x-warning {{label at end of compound statement is incompatible with C standards before C2x}}
Index: clang/test/AST/ast-dump-stmt.c
===
--- clang/test/AST/ast-dump-stmt.c
+++ clang/test/AST/ast-dump-stmt.c
@@ -161,6 +161,10 @@
   // CHECK-NEXT: ImplicitCastExpr
   // CHECK-NEXT: ImplicitCastExpr
   // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}}  'void *' lvalue Var 0x{{[^ ]*}} 'ptr' 'void *'
+
+label3:
+  // CHECK-NEXT: LabelStmt 0x{{[^ ]*}}  'label3'
+  // CHECK-NEXT: NullStmt 0x{{[^ ]*}} 
 }
 
 void TestSwitch(int i) {
Index: clang/lib/Parse/ParseStmt.cpp
===
--- clang/lib/Parse/ParseStmt.cpp
+++ clang/lib/Parse/ParseStmt.cpp
@@ -679,9 +679,12 @@
 
 /// ParseLabeledStatement - We have an identifier and a ':' after it.
 ///
+///   label:
+/// identifier ':'
+/// [GNU]   identifier ':' attributes[opt]
+///
 ///   labeled-statement:
-/// identifier ':' statement
-/// [GNU]   identifier ':' attributes[opt] statement
+/// label statement
 ///
 StmtResult Parser::ParseLabeledStatement(ParsedAttributes &Attrs,
  ParsedStmtContext StmtCtx) {
@@ -725,6 +728,20 @@
 }
   }
 
+  // The label may have no statement following it
+  if (SubStmt.isUnset() && Tok.is(tok::r_brace)) {
+if (getLangOpts().CPlusPlus) {
+  Diag(Tok, getLangOpts().CPlusPlus2b
+? 

[PATCH] D133887: [Clang] Support label at end of compound statement

2022-09-17 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added a comment.

> Why checking getLangOpts().C99 instead of just C

There is no `getLangOpts().C`. Here are possible C/C++ opt flags:
https://github.com/llvm/llvm-project/blob/7914e53e312074828293356f569d190ac6eae3bd/clang/include/clang/Basic/LangOptions.def#L86-L100
I have no understanding why there is no `getLangOpts().C` flag. Maybe the C89 
standard is a subset of all other C/C++/ObjC standards, so we don't need the 
flag?..

> Whyt no compatibility warning in C23 mode

@aaron.ballman said so in https://reviews.llvm.org/D133887#3793027

  It should definitely be without warning in C23 mode and give an extension 
warning in earlier modes.

I don't know much about extension/incompatible warnings policy (when to apply 
and not apply them), could you please help me to figure this out with Aaron? 😃


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133887

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


[PATCH] D122078: [clang-tidy] Ignore concepts in `misc-redundant-expression`

2022-09-17 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 461003.
Izaron added a comment.

Fix test with `count 0`, thanks to @njames93 !


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D122078

Files:
  clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression-cxx20.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression-cxx20.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression-cxx20.cpp
@@ -0,0 +1,14 @@
+// RUN: clang-tidy %s -checks=-*,misc-redundant-expression -- -std=c++20 | count 0
+
+// Note: this test expects no diagnostics, but FileCheck cannot handle that,
+// hence the use of | count 0.
+
+namespace concepts {
+// redundant expressions inside concepts make sense, ignore them
+template 
+concept TestConcept = requires(I i) {
+  {i - i};
+  {i && i};
+  {i ? i : i};
+};
+} // namespace concepts
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -149,6 +149,12 @@
   copy assignment operators with nonstandard return types. The check is restricted to
   c++11-or-later.
 
+- Improved :doc:`misc-redundant-expression `
+  check.
+
+  The check now skips concept definitions since redundant expressions still make sense
+  inside them.
+
 Removed checks
 ^^
 
Index: clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
===
--- clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
+++ clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
@@ -10,6 +10,7 @@
 #include "../utils/Matchers.h"
 #include "../utils/OptionsUtils.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/ExprConcepts.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/SourceLocation.h"
@@ -440,6 +441,8 @@
   return Node.isIntegerConstantExpr(Finder->getASTContext());
 }
 
+AST_MATCHER(Expr, isRequiresExpr) { return isa(Node); }
+
 AST_MATCHER(BinaryOperator, operandsAreEquivalent) {
   return areEquivalentExpr(Node.getLHS(), Node.getRHS());
 }
@@ -858,6 +861,7 @@
 
   const auto BannedIntegerLiteral =
   integerLiteral(expandedByMacro(KnownBannedMacroNames));
+  const auto BannedAncestor = expr(isRequiresExpr());
 
   // Binary with equivalent operands, like (X != 2 && X != 2).
   Finder->addMatcher(
@@ -873,7 +877,8 @@
unless(hasType(realFloatingPointType())),
unless(hasEitherOperand(hasType(realFloatingPointType(,
unless(hasLHS(AnyLiteralExpr)),
-   unless(hasDescendant(BannedIntegerLiteral)))
+   unless(hasDescendant(BannedIntegerLiteral)),
+   unless(hasAncestor(BannedAncestor)))
.bind("binary")),
   this);
 
@@ -886,7 +891,8 @@
  unless(isInTemplateInstantiation()),
  unless(binaryOperatorIsInMacro()),
  // TODO: if the banned macros are themselves duplicated
- unless(hasDescendant(BannedIntegerLiteral)))
+ unless(hasDescendant(BannedIntegerLiteral)),
+ unless(hasAncestor(BannedAncestor)))
   .bind("nested-duplicates"),
   this);
 
@@ -896,7 +902,8 @@
conditionalOperator(expressionsAreEquivalent(),
// Filter noisy false positives.
unless(conditionalOperatorIsInMacro()),
-   unless(isInTemplateInstantiation()))
+   unless(isInTemplateInstantiation()),
+   unless(hasAncestor(BannedAncestor)))
.bind("cond")),
   this);
 
@@ -909,7 +916,8 @@
 ">=", "&&", "||", "="),
parametersAreEquivalent(),
// Filter noisy false positives.
-   unless(isMacro()), unless(isInTemplateInstantiation()))
+   unless(isMacro()), unless(isInTemplateInstantiation()),
+   unless(hasAncestor(BannedAncestor)))
.bind("call")),
   this);
 
@@ -919,7 +927,8 @@
   hasAnyOverloadedOperatorName("|", "&", "||", "&&", "^"),
   nestedParametersAreEquivalent(), argumentCountIs(2),
   // Filter noisy false positives.
-  unless(isMacro()), unless(isInTemplateInstantiation()))
+  unless(isMacro()), unless(isInTemplateInstantiation()),
+  unless(hasAncestor(BannedAncestor)))
   .b

[PATCH] D133887: [Clang] Support label at end of compound statement

2022-09-17 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 461002.
Izaron added a comment.

Add diagnostics for C language


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133887

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/DiagnosticParseKinds.td
  clang/lib/Parse/ParseStmt.cpp
  clang/test/AST/ast-dump-stmt.c
  clang/test/Parser/c2x-label.c
  clang/test/Parser/cxx2b-label.cpp
  clang/test/Parser/switch-recovery.cpp
  clang/www/c_status.html
  clang/www/cxx_status.html

Index: clang/www/cxx_status.html
===
--- clang/www/cxx_status.html
+++ clang/www/cxx_status.html
@@ -1456,7 +1456,7 @@
 
   Labels at the end of compound statements
   https://wg21.link/P2324R2";>P2324R2
-  No
+  Clang 16
 
 
   Delimited escape sequences
Index: clang/www/c_status.html
===
--- clang/www/c_status.html
+++ clang/www/c_status.html
@@ -763,7 +763,7 @@
 
   Free positioning of labels inside compound statements
   https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2508.pdf";>N2508
-  No
+  Clang 16
 
 
   Clarification request for C17 example of undefined behavior
Index: clang/test/Parser/switch-recovery.cpp
===
--- clang/test/Parser/switch-recovery.cpp
+++ clang/test/Parser/switch-recovery.cpp
@@ -160,14 +160,14 @@
 void missing_statement_case(int x) {
   switch (x) {
 case 1:
-case 0: // expected-error {{label at end of compound statement: expected statement}}
+case 0: // expected-error {{label at end of switch compound statement: expected statement}}
   }
 }
 
 void missing_statement_default(int x) {
   switch (x) {
 case 0:
-default: // expected-error {{label at end of compound statement: expected statement}}
+default: // expected-error {{label at end of switch compound statement: expected statement}}
   }
 }
 
@@ -179,7 +179,7 @@
 void pr19022_1a(int x) {
   switch(x) {
   case 1  // expected-error{{expected ':' after 'case'}} \
-  // expected-error{{label at end of compound statement: expected statement}}
+  // expected-error{{label at end of switch compound statement: expected statement}}
   }
 }
 
Index: clang/test/Parser/cxx2b-label.cpp
===
--- /dev/null
+++ clang/test/Parser/cxx2b-label.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx2b -std=c++2b -Wpre-c++2b-compat %s
+// RUN: %clang_cc1 -fsyntax-only -verify=expected,cxx20 -std=c++20 %s
+
+void foo() {
+label1:
+int x;
+label2:
+x = 1;
+label3: label4: label5:
+} // cxx20-warning {{label at end of compound statement is a C++2b extension}} \
+ cxx2b-warning {{label at end of compound statement is incompatible with C++ standards before C++2b}}
Index: clang/test/Parser/c2x-label.c
===
--- /dev/null
+++ clang/test/Parser/c2x-label.c
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c17 -Wc2x-compat -verify=c17 %s
+// RUN: %clang_cc1 -fsyntax-only -std=c2x -Wpre-c2x-compat -verify=c2x %s
+
+// c2x-no-diagnostics
+
+void foo() {
+int x;
+label1:
+x = 1;
+label2: label3: label4:
+} // c17-warning {{label at end of compound statement is a C2x extension}}
Index: clang/test/AST/ast-dump-stmt.c
===
--- clang/test/AST/ast-dump-stmt.c
+++ clang/test/AST/ast-dump-stmt.c
@@ -161,6 +161,10 @@
   // CHECK-NEXT: ImplicitCastExpr
   // CHECK-NEXT: ImplicitCastExpr
   // CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}}  'void *' lvalue Var 0x{{[^ ]*}} 'ptr' 'void *'
+
+label3:
+  // CHECK-NEXT: LabelStmt 0x{{[^ ]*}}  'label3'
+  // CHECK-NEXT: NullStmt 0x{{[^ ]*}} 
 }
 
 void TestSwitch(int i) {
Index: clang/lib/Parse/ParseStmt.cpp
===
--- clang/lib/Parse/ParseStmt.cpp
+++ clang/lib/Parse/ParseStmt.cpp
@@ -679,9 +679,12 @@
 
 /// ParseLabeledStatement - We have an identifier and a ':' after it.
 ///
+///   label:
+/// identifier ':'
+/// [GNU]   identifier ':' attributes[opt]
+///
 ///   labeled-statement:
-/// identifier ':' statement
-/// [GNU]   identifier ':' attributes[opt] statement
+/// label statement
 ///
 StmtResult Parser::ParseLabeledStatement(ParsedAttributes &Attrs,
  ParsedStmtContext StmtCtx) {
@@ -725,6 +728,18 @@
 }
   }
 
+  // The label may have no statement following it
+  if (SubStmt.isUnset() && Tok.is(tok::r_brace)) {
+if (getLangOpts().CPlusPlus) {
+  Diag(Tok, getLangOpts().CPlusPlus2b
+? diag::warn_cxx20_compat_label_end_of_compound_statement
+: diag::ext_cxx_label_end_of_comp

[PATCH] D122078: [clang-tidy] Ignore concepts in `misc-redundant-expression`

2022-09-17 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron updated this revision to Diff 460990.
Izaron added a comment.

The new file was failing with message

  CHECK-FIXES, CHECK-MESSAGES or CHECK-NOTES not found in the input

So I had to add an additional urrelevant check.
I added a check for consteval function (there were no such tests previously).


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D122078

Files:
  clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
  clang-tools-extra/docs/ReleaseNotes.rst
  clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression-cxx20.cpp

Index: clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression-cxx20.cpp
===
--- /dev/null
+++ clang-tools-extra/test/clang-tidy/checkers/misc/redundant-expression-cxx20.cpp
@@ -0,0 +1,17 @@
+// RUN: %check_clang_tidy %s misc-redundant-expression -std=c++20 %t -- -- -fno-delayed-template-parsing
+
+consteval int TestOperatorConfusion(int X) {
+  X = (X << 8) & 0xff;
+  // CHECK-MESSAGES: :[[@LINE-1]]:16: warning: ineffective bitwise and operation
+  return X;
+}
+
+namespace concepts {
+// redundant expressions inside concepts make sense, ignore them
+template 
+concept TestConcept = requires(I i) {
+  {i - i};
+  {i && i};
+  {i ? i : i};
+};
+} // namespace concepts
Index: clang-tools-extra/docs/ReleaseNotes.rst
===
--- clang-tools-extra/docs/ReleaseNotes.rst
+++ clang-tools-extra/docs/ReleaseNotes.rst
@@ -149,6 +149,12 @@
   copy assignment operators with nonstandard return types. The check is restricted to
   c++11-or-later.
 
+- Improved :doc:`misc-redundant-expression `
+  check.
+
+  The check now skips concept definitions since redundant expressions still make sense
+  inside them.
+
 Removed checks
 ^^
 
Index: clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
===
--- clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
+++ clang-tools-extra/clang-tidy/misc/RedundantExpressionCheck.cpp
@@ -10,6 +10,7 @@
 #include "../utils/Matchers.h"
 #include "../utils/OptionsUtils.h"
 #include "clang/AST/ASTContext.h"
+#include "clang/AST/ExprConcepts.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/SourceLocation.h"
@@ -440,6 +441,8 @@
   return Node.isIntegerConstantExpr(Finder->getASTContext());
 }
 
+AST_MATCHER(Expr, isRequiresExpr) { return isa(Node); }
+
 AST_MATCHER(BinaryOperator, operandsAreEquivalent) {
   return areEquivalentExpr(Node.getLHS(), Node.getRHS());
 }
@@ -858,6 +861,7 @@
 
   const auto BannedIntegerLiteral =
   integerLiteral(expandedByMacro(KnownBannedMacroNames));
+  const auto BannedAncestor = expr(isRequiresExpr());
 
   // Binary with equivalent operands, like (X != 2 && X != 2).
   Finder->addMatcher(
@@ -873,7 +877,8 @@
unless(hasType(realFloatingPointType())),
unless(hasEitherOperand(hasType(realFloatingPointType(,
unless(hasLHS(AnyLiteralExpr)),
-   unless(hasDescendant(BannedIntegerLiteral)))
+   unless(hasDescendant(BannedIntegerLiteral)),
+   unless(hasAncestor(BannedAncestor)))
.bind("binary")),
   this);
 
@@ -886,7 +891,8 @@
  unless(isInTemplateInstantiation()),
  unless(binaryOperatorIsInMacro()),
  // TODO: if the banned macros are themselves duplicated
- unless(hasDescendant(BannedIntegerLiteral)))
+ unless(hasDescendant(BannedIntegerLiteral)),
+ unless(hasAncestor(BannedAncestor)))
   .bind("nested-duplicates"),
   this);
 
@@ -896,7 +902,8 @@
conditionalOperator(expressionsAreEquivalent(),
// Filter noisy false positives.
unless(conditionalOperatorIsInMacro()),
-   unless(isInTemplateInstantiation()))
+   unless(isInTemplateInstantiation()),
+   unless(hasAncestor(BannedAncestor)))
.bind("cond")),
   this);
 
@@ -909,7 +916,8 @@
 ">=", "&&", "||", "="),
parametersAreEquivalent(),
// Filter noisy false positives.
-   unless(isMacro()), unless(isInTemplateInstantiation()))
+   unless(isMacro()), unless(isInTemplateInstantiation()),
+   unless(hasAncestor(BannedAncestor)))
.bind("call")),
   this);
 
@@ -919,7 +927,8 @@
   hasAnyOverloadedOperatorName("|", "&", "||", "&&", "^"),
   nestedParametersAreEquiva

[PATCH] D133887: [Clang] Support label at end of compound statement

2022-09-17 Thread Evgeny Shulgin via Phabricator via cfe-commits
Izaron added a comment.

> It should definitely be without warning in C23 mode and give an extension 
> warning in earlier modes.

@aaron.ballman we have this extension warning for pre-C++23:

  def ext_label_end_of_compound_statement : ExtWarn<
"label at end of compound statement is a C++2b extension">,
 InGroup;

Should I add a new warning for pre-C23? We could have two warnings for each 
language:

  ext_cxx_label_end_of_compound_statement
  ext_c_label_end_of_compound_statement


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D133887

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


  1   2   >