[PATCH] D152403: [Clang][CUDA] Disable diagnostics for neon attrs for GPU-side CUDA compilation

2023-06-09 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG8b0ea4874093: [Clang][CUDA] Disable diagnostics for neon 
attrs for GPU-side CUDA compilation (authored by alexander-shaposhnikov).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D152403

Files:
  clang/lib/Sema/SemaType.cpp
  clang/test/SemaCUDA/neon-attrs.cu


Index: clang/test/SemaCUDA/neon-attrs.cu
===
--- /dev/null
+++ clang/test/SemaCUDA/neon-attrs.cu
@@ -0,0 +1,21 @@
+// CPU-side compilation on ARM with neon enabled (no errors expected).
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature +neon -aux-triple 
nvptx64 -x cuda -fsyntax-only -verify=quiet %s
+
+// CPU-side compilation on ARM with neon disabled.
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature -neon -aux-triple 
nvptx64 -x cuda -fsyntax-only -verify %s
+
+// GPU-side compilation on ARM (no errors expected).
+// RUN: %clang_cc1 -triple nvptx64 -aux-triple arm64-linux-gnu 
-fcuda-is-device -x cuda -fsyntax-only -verify=quiet %s
+
+// Regular C++ compilation on ARM with neon enabled (no errors expected).
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature +neon -x c++ 
-fsyntax-only -verify=quiet %s
+
+// Regular C++ compilation on ARM with neon disabled.
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature -neon -x c++ 
-fsyntax-only -verify %s
+
+// quiet-no-diagnostics
+typedef __attribute__((neon_vector_type(4))) float float32x4_t;
+// expected-error@-1 {{'neon_vector_type' attribute is not supported on 
targets missing 'neon' or 'mve'}}
+typedef unsigned char poly8_t;
+typedef __attribute__((neon_polyvector_type(8))) poly8_t poly8x8_t;
+// expected-error@-1 {{'neon_polyvector_type' attribute is not supported on 
targets missing 'neon' or 'mve'}}
Index: clang/lib/Sema/SemaType.cpp
===
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -8169,10 +8169,18 @@
 /// match one of the standard Neon vector types.
 static void HandleNeonVectorTypeAttr(QualType , const ParsedAttr ,
  Sema , VectorType::VectorKind VecKind) {
+  bool IsTargetCUDAAndHostARM = false;
+  if (S.getLangOpts().CUDAIsDevice) {
+const TargetInfo *AuxTI = S.getASTContext().getAuxTargetInfo();
+IsTargetCUDAAndHostARM =
+AuxTI && (AuxTI->getTriple().isAArch64() || 
AuxTI->getTriple().isARM());
+  }
+
   // Target must have NEON (or MVE, whose vectors are similar enough
   // not to need a separate attribute)
-  if (!S.Context.getTargetInfo().hasFeature("neon") &&
-  !S.Context.getTargetInfo().hasFeature("mve")) {
+  if (!(S.Context.getTargetInfo().hasFeature("neon") ||
+S.Context.getTargetInfo().hasFeature("mve") ||
+IsTargetCUDAAndHostARM)) {
 S.Diag(Attr.getLoc(), diag::err_attribute_unsupported)
 << Attr << "'neon' or 'mve'";
 Attr.setInvalid();
@@ -8180,8 +8188,8 @@
   }
   // Check the attribute arguments.
   if (Attr.getNumArgs() != 1) {
-S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Attr
-  << 1;
+S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+<< Attr << 1;
 Attr.setInvalid();
 return;
   }
@@ -8191,7 +8199,8 @@
 return;
 
   // Only certain element types are supported for Neon vectors.
-  if (!isPermittedNeonBaseType(CurType, VecKind, S)) {
+  if (!isPermittedNeonBaseType(CurType, VecKind, S) &&
+  !IsTargetCUDAAndHostARM) {
 S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
 Attr.setInvalid();
 return;


Index: clang/test/SemaCUDA/neon-attrs.cu
===
--- /dev/null
+++ clang/test/SemaCUDA/neon-attrs.cu
@@ -0,0 +1,21 @@
+// CPU-side compilation on ARM with neon enabled (no errors expected).
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature +neon -aux-triple nvptx64 -x cuda -fsyntax-only -verify=quiet %s
+
+// CPU-side compilation on ARM with neon disabled.
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature -neon -aux-triple nvptx64 -x cuda -fsyntax-only -verify %s
+
+// GPU-side compilation on ARM (no errors expected).
+// RUN: %clang_cc1 -triple nvptx64 -aux-triple arm64-linux-gnu -fcuda-is-device -x cuda -fsyntax-only -verify=quiet %s
+
+// Regular C++ compilation on ARM with neon enabled (no errors expected).
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature +neon -x c++ -fsyntax-only -verify=quiet %s
+
+// Regular C++ compilation on ARM with neon disabled.
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature -neon -x c++ -fsyntax-only -verify %s
+
+// quiet-no-diagnostics
+typedef __attribute__((neon_vector_type(4))) float float32x4_t;
+// expected-error@-1 

[PATCH] D152403: [Clang][CUDA] Disable diagnostics for neon attrs for GPU-side CUDA compilation

2023-06-08 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov updated this revision to Diff 529801.
alexander-shaposhnikov added a comment.

Add missing parentheses


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D152403

Files:
  clang/lib/Sema/SemaType.cpp
  clang/test/SemaCUDA/neon-attrs.cu


Index: clang/test/SemaCUDA/neon-attrs.cu
===
--- /dev/null
+++ clang/test/SemaCUDA/neon-attrs.cu
@@ -0,0 +1,21 @@
+// CPU-side compilation on ARM with neon enabled (no errors expected).
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature +neon -aux-triple 
nvptx64 -x cuda -fsyntax-only -verify=quiet %s
+
+// CPU-side compilation on ARM with neon disabled.
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature -neon -aux-triple 
nvptx64 -x cuda -fsyntax-only -verify %s
+
+// GPU-side compilation on ARM (no errors expected).
+// RUN: %clang_cc1 -triple nvptx64 -aux-triple arm64-linux-gnu 
-fcuda-is-device -x cuda -fsyntax-only -verify=quiet %s
+
+// Regular C++ compilation on ARM with neon enabled (no errors expected).
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature +neon -x c++ 
-fsyntax-only -verify=quiet %s
+
+// Regular C++ compilation on ARM with neon disabled.
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature -neon -x c++ 
-fsyntax-only -verify %s
+
+// quiet-no-diagnostics
+typedef __attribute__((neon_vector_type(4))) float float32x4_t;
+// expected-error@-1 {{'neon_vector_type' attribute is not supported on 
targets missing 'neon' or 'mve'}}
+typedef unsigned char poly8_t;
+typedef __attribute__((neon_polyvector_type(8))) poly8_t poly8x8_t;
+// expected-error@-1 {{'neon_polyvector_type' attribute is not supported on 
targets missing 'neon' or 'mve'}}
Index: clang/lib/Sema/SemaType.cpp
===
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -8161,10 +8161,18 @@
 /// match one of the standard Neon vector types.
 static void HandleNeonVectorTypeAttr(QualType , const ParsedAttr ,
  Sema , VectorType::VectorKind VecKind) {
+  bool IsTargetCUDAAndHostARM = false;
+  if (S.getLangOpts().CUDAIsDevice) {
+const TargetInfo *AuxTI = S.getASTContext().getAuxTargetInfo();
+IsTargetCUDAAndHostARM =
+AuxTI && (AuxTI->getTriple().isAArch64() || 
AuxTI->getTriple().isARM());
+  }
+
   // Target must have NEON (or MVE, whose vectors are similar enough
   // not to need a separate attribute)
-  if (!S.Context.getTargetInfo().hasFeature("neon") &&
-  !S.Context.getTargetInfo().hasFeature("mve")) {
+  if (!(S.Context.getTargetInfo().hasFeature("neon") ||
+S.Context.getTargetInfo().hasFeature("mve") ||
+IsTargetCUDAAndHostARM)) {
 S.Diag(Attr.getLoc(), diag::err_attribute_unsupported)
 << Attr << "'neon' or 'mve'";
 Attr.setInvalid();
@@ -8172,8 +8180,8 @@
   }
   // Check the attribute arguments.
   if (Attr.getNumArgs() != 1) {
-S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Attr
-  << 1;
+S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+<< Attr << 1;
 Attr.setInvalid();
 return;
   }
@@ -8183,7 +8191,8 @@
 return;
 
   // Only certain element types are supported for Neon vectors.
-  if (!isPermittedNeonBaseType(CurType, VecKind, S)) {
+  if (!isPermittedNeonBaseType(CurType, VecKind, S) &&
+  !IsTargetCUDAAndHostARM) {
 S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
 Attr.setInvalid();
 return;


Index: clang/test/SemaCUDA/neon-attrs.cu
===
--- /dev/null
+++ clang/test/SemaCUDA/neon-attrs.cu
@@ -0,0 +1,21 @@
+// CPU-side compilation on ARM with neon enabled (no errors expected).
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature +neon -aux-triple nvptx64 -x cuda -fsyntax-only -verify=quiet %s
+
+// CPU-side compilation on ARM with neon disabled.
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature -neon -aux-triple nvptx64 -x cuda -fsyntax-only -verify %s
+
+// GPU-side compilation on ARM (no errors expected).
+// RUN: %clang_cc1 -triple nvptx64 -aux-triple arm64-linux-gnu -fcuda-is-device -x cuda -fsyntax-only -verify=quiet %s
+
+// Regular C++ compilation on ARM with neon enabled (no errors expected).
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature +neon -x c++ -fsyntax-only -verify=quiet %s
+
+// Regular C++ compilation on ARM with neon disabled.
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature -neon -x c++ -fsyntax-only -verify %s
+
+// quiet-no-diagnostics
+typedef __attribute__((neon_vector_type(4))) float float32x4_t;
+// expected-error@-1 {{'neon_vector_type' attribute is not supported on targets missing 'neon' or 'mve'}}
+typedef 

[PATCH] D152403: [Clang][CUDA] Disable diagnostics for neon attrs for GPU-side CUDA compilation

2023-06-08 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov updated this revision to Diff 529795.
alexander-shaposhnikov marked 3 inline comments as done.

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D152403

Files:
  clang/lib/Sema/SemaType.cpp
  clang/test/SemaCUDA/neon-attrs.cu


Index: clang/test/SemaCUDA/neon-attrs.cu
===
--- /dev/null
+++ clang/test/SemaCUDA/neon-attrs.cu
@@ -0,0 +1,21 @@
+// CPU-side compilation on ARM with neon enabled (no errors expected).
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature +neon -aux-triple 
nvptx64 -x cuda -fsyntax-only -verify=quiet %s
+
+// CPU-side compilation on ARM with neon disabled.
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature -neon -aux-triple 
nvptx64 -x cuda -fsyntax-only -verify %s
+
+// GPU-side compilation on ARM (no errors expected).
+// RUN: %clang_cc1 -triple nvptx64 -aux-triple arm64-linux-gnu 
-fcuda-is-device -x cuda -fsyntax-only -verify=quiet %s
+
+// Regular C++ compilation on ARM with neon enabled (no errors expected).
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature +neon -x c++ 
-fsyntax-only -verify=quiet %s
+
+// Regular C++ compilation on ARM with neon disabled.
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature -neon -x c++ 
-fsyntax-only -verify %s
+
+// quiet-no-diagnostics
+typedef __attribute__((neon_vector_type(4))) float float32x4_t;
+// expected-error@-1 {{'neon_vector_type' attribute is not supported on 
targets missing 'neon' or 'mve'}}
+typedef unsigned char poly8_t;
+typedef __attribute__((neon_polyvector_type(8))) poly8_t poly8x8_t;
+// expected-error@-1 {{'neon_polyvector_type' attribute is not supported on 
targets missing 'neon' or 'mve'}}
Index: clang/lib/Sema/SemaType.cpp
===
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -8161,10 +8161,18 @@
 /// match one of the standard Neon vector types.
 static void HandleNeonVectorTypeAttr(QualType , const ParsedAttr ,
  Sema , VectorType::VectorKind VecKind) {
+  bool IsTargetCUDAAndHostARM = false;
+  if (S.getLangOpts().CUDAIsDevice) {
+const TargetInfo *AuxTI = S.getASTContext().getAuxTargetInfo();
+IsTargetCUDAAndHostARM =
+AuxTI && AuxTI->getTriple().isAArch64() || AuxTI->getTriple().isARM();
+  }
+
   // Target must have NEON (or MVE, whose vectors are similar enough
   // not to need a separate attribute)
-  if (!S.Context.getTargetInfo().hasFeature("neon") &&
-  !S.Context.getTargetInfo().hasFeature("mve")) {
+  if (!(S.Context.getTargetInfo().hasFeature("neon") ||
+S.Context.getTargetInfo().hasFeature("mve") ||
+IsTargetCUDAAndHostARM)) {
 S.Diag(Attr.getLoc(), diag::err_attribute_unsupported)
 << Attr << "'neon' or 'mve'";
 Attr.setInvalid();
@@ -8172,8 +8180,8 @@
   }
   // Check the attribute arguments.
   if (Attr.getNumArgs() != 1) {
-S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << Attr
-  << 1;
+S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments)
+<< Attr << 1;
 Attr.setInvalid();
 return;
   }
@@ -8183,7 +8191,8 @@
 return;
 
   // Only certain element types are supported for Neon vectors.
-  if (!isPermittedNeonBaseType(CurType, VecKind, S)) {
+  if (!isPermittedNeonBaseType(CurType, VecKind, S) &&
+  !IsTargetCUDAAndHostARM) {
 S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
 Attr.setInvalid();
 return;


Index: clang/test/SemaCUDA/neon-attrs.cu
===
--- /dev/null
+++ clang/test/SemaCUDA/neon-attrs.cu
@@ -0,0 +1,21 @@
+// CPU-side compilation on ARM with neon enabled (no errors expected).
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature +neon -aux-triple nvptx64 -x cuda -fsyntax-only -verify=quiet %s
+
+// CPU-side compilation on ARM with neon disabled.
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature -neon -aux-triple nvptx64 -x cuda -fsyntax-only -verify %s
+
+// GPU-side compilation on ARM (no errors expected).
+// RUN: %clang_cc1 -triple nvptx64 -aux-triple arm64-linux-gnu -fcuda-is-device -x cuda -fsyntax-only -verify=quiet %s
+
+// Regular C++ compilation on ARM with neon enabled (no errors expected).
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature +neon -x c++ -fsyntax-only -verify=quiet %s
+
+// Regular C++ compilation on ARM with neon disabled.
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature -neon -x c++ -fsyntax-only -verify %s
+
+// quiet-no-diagnostics
+typedef __attribute__((neon_vector_type(4))) float float32x4_t;
+// expected-error@-1 {{'neon_vector_type' attribute is not supported on targets missing 'neon' or 'mve'}}
+typedef unsigned char 

[PATCH] D152403: [Clang][CUDA] Disable diagnostics for neon attrs for GPU-side CUDA compilation

2023-06-08 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov updated this revision to Diff 529794.
alexander-shaposhnikov added a comment.

Address comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D152403

Files:
  clang/lib/Sema/SemaType.cpp
  clang/test/SemaCUDA/neon-attrs.cu


Index: clang/test/SemaCUDA/neon-attrs.cu
===
--- /dev/null
+++ clang/test/SemaCUDA/neon-attrs.cu
@@ -0,0 +1,21 @@
+// CPU-side compilation on ARM with neon enabled (no errors expected).
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature +neon -aux-triple 
nvptx64 -x cuda -fsyntax-only -verify=quiet %s
+
+// CPU-side compilation on ARM with neon disabled.
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature -neon -aux-triple 
nvptx64 -x cuda -fsyntax-only -verify %s
+
+// GPU-side compilation on ARM (no errors expected).
+// RUN: %clang_cc1 -triple nvptx64 -aux-triple arm64-linux-gnu 
-fcuda-is-device -x cuda -fsyntax-only -verify=quiet %s
+
+// Regular C++ compilation on ARM with neon enabled (no errors expected).
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature +neon -x c++ 
-fsyntax-only -verify=quiet %s
+
+// Regular C++ compilation on ARM with neon disabled.
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature -neon -x c++ 
-fsyntax-only -verify %s
+
+// quiet-no-diagnostics
+typedef __attribute__((neon_vector_type(4))) float float32x4_t;
+// expected-error@-1 {{'neon_vector_type' attribute is not supported on 
targets missing 'neon' or 'mve'}}
+typedef unsigned char poly8_t;
+typedef __attribute__((neon_polyvector_type(8))) poly8_t poly8x8_t;
+// expected-error@-1 {{'neon_polyvector_type' attribute is not supported on 
targets missing 'neon' or 'mve'}}
Index: clang/lib/Sema/SemaType.cpp
===
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -8161,10 +8161,17 @@
 /// match one of the standard Neon vector types.
 static void HandleNeonVectorTypeAttr(QualType , const ParsedAttr ,
  Sema , VectorType::VectorKind VecKind) {
+  bool IsTargetCUDAAndHostARM = false;
+  if (S.getLangOpts().CUDAIsDevice) {
+const TargetInfo *AuxTI = S.getASTContext().getAuxTargetInfo();
+IsTargetCUDAAndHostARM =
+AuxTI && AuxTI->getTriple().isAArch64() || AuxTI->getTriple().isARM();
+  }
+
   // Target must have NEON (or MVE, whose vectors are similar enough
   // not to need a separate attribute)
   if (!S.Context.getTargetInfo().hasFeature("neon") &&
-  !S.Context.getTargetInfo().hasFeature("mve")) {
+  !S.Context.getTargetInfo().hasFeature("mve") && !IsTargetCUDAAndHostARM) 
{
 S.Diag(Attr.getLoc(), diag::err_attribute_unsupported)
 << Attr << "'neon' or 'mve'";
 Attr.setInvalid();
@@ -8183,7 +8190,8 @@
 return;
 
   // Only certain element types are supported for Neon vectors.
-  if (!isPermittedNeonBaseType(CurType, VecKind, S)) {
+  if (!isPermittedNeonBaseType(CurType, VecKind, S) &&
+  !IsTargetCUDAAndHostARM) {
 S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
 Attr.setInvalid();
 return;


Index: clang/test/SemaCUDA/neon-attrs.cu
===
--- /dev/null
+++ clang/test/SemaCUDA/neon-attrs.cu
@@ -0,0 +1,21 @@
+// CPU-side compilation on ARM with neon enabled (no errors expected).
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature +neon -aux-triple nvptx64 -x cuda -fsyntax-only -verify=quiet %s
+
+// CPU-side compilation on ARM with neon disabled.
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature -neon -aux-triple nvptx64 -x cuda -fsyntax-only -verify %s
+
+// GPU-side compilation on ARM (no errors expected).
+// RUN: %clang_cc1 -triple nvptx64 -aux-triple arm64-linux-gnu -fcuda-is-device -x cuda -fsyntax-only -verify=quiet %s
+
+// Regular C++ compilation on ARM with neon enabled (no errors expected).
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature +neon -x c++ -fsyntax-only -verify=quiet %s
+
+// Regular C++ compilation on ARM with neon disabled.
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature -neon -x c++ -fsyntax-only -verify %s
+
+// quiet-no-diagnostics
+typedef __attribute__((neon_vector_type(4))) float float32x4_t;
+// expected-error@-1 {{'neon_vector_type' attribute is not supported on targets missing 'neon' or 'mve'}}
+typedef unsigned char poly8_t;
+typedef __attribute__((neon_polyvector_type(8))) poly8_t poly8x8_t;
+// expected-error@-1 {{'neon_polyvector_type' attribute is not supported on targets missing 'neon' or 'mve'}}
Index: clang/lib/Sema/SemaType.cpp
===
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -8161,10 +8161,17 @@
 /// match one of the standard Neon vector types.
 static void 

[PATCH] D152403: [Clang][CUDA] Disable diagnostics for neon attrs for GPU-side CUDA compilation

2023-06-07 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added inline comments.



Comment at: clang/lib/Sema/SemaType.cpp:8168
+IsTargetCUDAAndHostARM =
+!AuxTI || AuxTI->getTriple().isAArch64() || AuxTI->getTriple().isARM();
+  }

tra wrote:
> Should it be `AuxTI && (AuxTI->getTriple().isAArch64() || 
> AuxTI->getTriple().isARM();)` ?
> 
> I don't think we want IsTargetCUDAAndHostARM to be set to true if there's no 
> auxTargetInfo (e.g. during any C++ compilation, regardless of the target).
we get here only if S.getLangOpts().CUDAIsDevice is true, so not for an 
arbitrary c++ compilation,
iirc AuxTI was null for some tests, but I'm happy to double check,
AuxTI && ... looks better to me too.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D152403

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


[PATCH] D152403: [Clang][CUDA] Disable diagnostics for neon attrs for GPU-side CUDA compilation

2023-06-07 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added inline comments.



Comment at: clang/test/SemaCUDA/neon-attrs.cu:2
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature +neon -x cuda 
-fsyntax-only -DNO_DIAG -verify %s
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature -neon -x cuda 
-fsyntax-only -verify %s
+

tra wrote:
> You should also pass `-aux-triple nvptx64...`.
> 
> This also needs more test cases. This only tests host-side CUDA compilation.
> We also need:
> ```
> // GPU-side compilation on ARM (no errors expected)
> // RUN: %clang_cc1 -aux-triple arm64-linux-gnu -triple nvptx64 
> -fcuda-is-device  -x cuda -fsyntax-only -DNO_DIAG -verify %s
> // Regular C++ compilation on x86 and ARM without neon (should produce 
> diagnostics) 
> // RUN: %clang_cc1  -triple x86 -x c++ -fsyntax-only -verify %s
> // RUN: %clang_cc1  -triple arm64... -x c++ -target-feature -neon 
> -fsyntax-only -verify %s
> // C++ on ARM w/ neon (no diagnostics)
> // RUN: %clang_cc1  -triple arm64... -x c++ -target-feature +neon 
> -fsyntax-only -DNO_DIAG -verify %s
> ``` 
regular C++ compilation is covered by other in-tree tests, do we really need it 
here ?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D152403

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


[PATCH] D152403: [Clang][CUDA] Disable diagnostics for neon attrs for GPU-side CUDA compilation

2023-06-07 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov created this revision.
alexander-shaposhnikov added a reviewer: tra.
alexander-shaposhnikov created this object with visibility "All Users".
Herald added subscribers: mattd, carlosgalvezp, yaxunl.
Herald added a project: All.
alexander-shaposhnikov requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Disable diagnostics for neon attrs for GPU-side CUDA compilation.

Test plan: ninja check-all


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D152403

Files:
  clang/lib/Sema/SemaType.cpp
  clang/test/SemaCUDA/neon-attrs.cu


Index: clang/test/SemaCUDA/neon-attrs.cu
===
--- /dev/null
+++ clang/test/SemaCUDA/neon-attrs.cu
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature +neon -x cuda 
-fsyntax-only -DNO_DIAG -verify %s
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature -neon -x cuda 
-fsyntax-only -verify %s
+
+#ifdef NO_DIAG
+// expected-no-diagnostics
+typedef __attribute__((neon_vector_type(4))) float float32x4_t;
+typedef unsigned char poly8_t;
+typedef __attribute__((neon_polyvector_type(8))) poly8_t poly8x8_t;
+#else
+typedef __attribute__((neon_vector_type(4))) float float32x4_t;
+// expected-error@-1 {{'neon_vector_type' attribute is not supported on 
targets missing 'neon' or 'mve'}}
+typedef unsigned char poly8_t;
+typedef __attribute__((neon_polyvector_type(8))) poly8_t poly8x8_t;
+// expected-error@-1 {{'neon_polyvector_type' attribute is not supported on 
targets missing 'neon' or 'mve'}}
+#endif
Index: clang/lib/Sema/SemaType.cpp
===
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -8161,10 +8161,17 @@
 /// match one of the standard Neon vector types.
 static void HandleNeonVectorTypeAttr(QualType , const ParsedAttr ,
  Sema , VectorType::VectorKind VecKind) {
+  bool IsTargetCUDAAndHostARM = false;
+  if (S.getLangOpts().CUDAIsDevice) {
+const TargetInfo *AuxTI = S.getASTContext().getAuxTargetInfo();
+IsTargetCUDAAndHostARM =
+!AuxTI || AuxTI->getTriple().isAArch64() || AuxTI->getTriple().isARM();
+  }
+
   // Target must have NEON (or MVE, whose vectors are similar enough
   // not to need a separate attribute)
   if (!S.Context.getTargetInfo().hasFeature("neon") &&
-  !S.Context.getTargetInfo().hasFeature("mve")) {
+  !S.Context.getTargetInfo().hasFeature("mve") && !IsTargetCUDAAndHostARM) 
{
 S.Diag(Attr.getLoc(), diag::err_attribute_unsupported)
 << Attr << "'neon' or 'mve'";
 Attr.setInvalid();
@@ -8183,7 +8190,8 @@
 return;
 
   // Only certain element types are supported for Neon vectors.
-  if (!isPermittedNeonBaseType(CurType, VecKind, S)) {
+  if (!isPermittedNeonBaseType(CurType, VecKind, S) &&
+  !IsTargetCUDAAndHostARM) {
 S.Diag(Attr.getLoc(), diag::err_attribute_invalid_vector_type) << CurType;
 Attr.setInvalid();
 return;


Index: clang/test/SemaCUDA/neon-attrs.cu
===
--- /dev/null
+++ clang/test/SemaCUDA/neon-attrs.cu
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature +neon -x cuda -fsyntax-only -DNO_DIAG -verify %s
+// RUN: %clang_cc1 -triple arm64-linux-gnu -target-feature -neon -x cuda -fsyntax-only -verify %s
+
+#ifdef NO_DIAG
+// expected-no-diagnostics
+typedef __attribute__((neon_vector_type(4))) float float32x4_t;
+typedef unsigned char poly8_t;
+typedef __attribute__((neon_polyvector_type(8))) poly8_t poly8x8_t;
+#else
+typedef __attribute__((neon_vector_type(4))) float float32x4_t;
+// expected-error@-1 {{'neon_vector_type' attribute is not supported on targets missing 'neon' or 'mve'}}
+typedef unsigned char poly8_t;
+typedef __attribute__((neon_polyvector_type(8))) poly8_t poly8x8_t;
+// expected-error@-1 {{'neon_polyvector_type' attribute is not supported on targets missing 'neon' or 'mve'}}
+#endif
Index: clang/lib/Sema/SemaType.cpp
===
--- clang/lib/Sema/SemaType.cpp
+++ clang/lib/Sema/SemaType.cpp
@@ -8161,10 +8161,17 @@
 /// match one of the standard Neon vector types.
 static void HandleNeonVectorTypeAttr(QualType , const ParsedAttr ,
  Sema , VectorType::VectorKind VecKind) {
+  bool IsTargetCUDAAndHostARM = false;
+  if (S.getLangOpts().CUDAIsDevice) {
+const TargetInfo *AuxTI = S.getASTContext().getAuxTargetInfo();
+IsTargetCUDAAndHostARM =
+!AuxTI || AuxTI->getTriple().isAArch64() || AuxTI->getTriple().isARM();
+  }
+
   // Target must have NEON (or MVE, whose vectors are similar enough
   // not to need a separate attribute)
   if (!S.Context.getTargetInfo().hasFeature("neon") &&
-  !S.Context.getTargetInfo().hasFeature("mve")) {
+  !S.Context.getTargetInfo().hasFeature("mve") && 

[PATCH] D149906: [Clang] Update release notes

2023-05-18 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGcd4677f20704: [Clang] Update release notes (authored by 
alexander-shaposhnikov).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D149906

Files:
  clang/docs/ReleaseNotes.rst


Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -77,8 +77,13 @@
 
 C++20 Feature Support
 ^
-- Support for out-of-line definitions of constrained templates has been 
improved.
-  This partially fixes `#49620 
`_.
+- Implemented the rule introduced by `CA104 `_  for 
comparison of
+  constraint-expressions. Improved support for out-of-line definitions of 
constrained templates.
+  This fixes:
+  `#49620 `_,
+  `#60231 `_,
+  `#61414 `_,
+  `#61809 `_.
 - Lambda templates with a requires clause directly after the template 
parameters now parse
   correctly if the requires clause consists of a variable with a dependent 
type.
   (`#61278 `_)


Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -77,8 +77,13 @@
 
 C++20 Feature Support
 ^
-- Support for out-of-line definitions of constrained templates has been improved.
-  This partially fixes `#49620 `_.
+- Implemented the rule introduced by `CA104 `_  for comparison of
+  constraint-expressions. Improved support for out-of-line definitions of constrained templates.
+  This fixes:
+  `#49620 `_,
+  `#60231 `_,
+  `#61414 `_,
+  `#61809 `_.
 - Lambda templates with a requires clause directly after the template parameters now parse
   correctly if the requires clause consists of a variable with a dependent type.
   (`#61278 `_)
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D150730: [Clang][Sema] Substitute constraints only for declarations with different lexical contexts

2023-05-17 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG122b938944ce: [Clang][Sema] Substitute constraints only for 
declarations with different… (authored by alexander-shaposhnikov).

Changed prior to commit:
  https://reviews.llvm.org/D150730?vs=522856=523179#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D150730

Files:
  clang/lib/Sema/SemaConcept.cpp
  clang/test/SemaTemplate/concepts-no-early-substitution.cpp


Index: clang/test/SemaTemplate/concepts-no-early-substitution.cpp
===
--- /dev/null
+++ clang/test/SemaTemplate/concepts-no-early-substitution.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -std=c++20 -x c++ %s -verify -fsyntax-only
+// expected-no-diagnostics
+
+template 
+concept HasMemberBegin = requires(T0 t) { t.begin(); };
+
+struct GetBegin {
+  template 
+  void operator()(T1);
+};
+
+GetBegin begin;
+
+template 
+concept Concept = requires(T2 t) { begin(t); };
+
+struct Subrange;
+
+template 
+struct View {
+  Subrange ();
+
+  operator bool()
+requires true;
+
+  operator bool()
+requires requires { begin(getSubrange()); };
+
+  void begin();
+};
+
+struct Subrange : View {};
+static_assert(Concept);
Index: clang/lib/Sema/SemaConcept.cpp
===
--- clang/lib/Sema/SemaConcept.cpp
+++ clang/lib/Sema/SemaConcept.cpp
@@ -780,7 +780,9 @@
  const Expr *NewConstr) {
   if (OldConstr == NewConstr)
 return true;
-  if (Old && New && Old != New) {
+  // C++ [temp.constr.decl]p4
+  if (Old && New && Old != New &&
+  Old->getLexicalDeclContext() != New->getLexicalDeclContext()) {
 if (const Expr *SubstConstr =
 SubstituteConstraintExpression(*this, Old, OldConstr))
   OldConstr = SubstConstr;


Index: clang/test/SemaTemplate/concepts-no-early-substitution.cpp
===
--- /dev/null
+++ clang/test/SemaTemplate/concepts-no-early-substitution.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -std=c++20 -x c++ %s -verify -fsyntax-only
+// expected-no-diagnostics
+
+template 
+concept HasMemberBegin = requires(T0 t) { t.begin(); };
+
+struct GetBegin {
+  template 
+  void operator()(T1);
+};
+
+GetBegin begin;
+
+template 
+concept Concept = requires(T2 t) { begin(t); };
+
+struct Subrange;
+
+template 
+struct View {
+  Subrange ();
+
+  operator bool()
+requires true;
+
+  operator bool()
+requires requires { begin(getSubrange()); };
+
+  void begin();
+};
+
+struct Subrange : View {};
+static_assert(Concept);
Index: clang/lib/Sema/SemaConcept.cpp
===
--- clang/lib/Sema/SemaConcept.cpp
+++ clang/lib/Sema/SemaConcept.cpp
@@ -780,7 +780,9 @@
  const Expr *NewConstr) {
   if (OldConstr == NewConstr)
 return true;
-  if (Old && New && Old != New) {
+  // C++ [temp.constr.decl]p4
+  if (Old && New && Old != New &&
+  Old->getLexicalDeclContext() != New->getLexicalDeclContext()) {
 if (const Expr *SubstConstr =
 SubstituteConstraintExpression(*this, Old, OldConstr))
   OldConstr = SubstConstr;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D150730: [Clang][Sema] Substitute constraints only for declarations with different lexical contexts

2023-05-16 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov updated this revision to Diff 522856.
alexander-shaposhnikov added a comment.

Include context.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D150730

Files:
  clang/lib/Sema/SemaConcept.cpp
  clang/test/SemaTemplate/concepts-no-early-substitution.cpp


Index: clang/test/SemaTemplate/concepts-no-early-substitution.cpp
===
--- /dev/null
+++ clang/test/SemaTemplate/concepts-no-early-substitution.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -std=c++20 -x c++ %s -verify -fsyntax-only
+// expected-no-diagnostics
+
+template 
+concept HasMemberBegin = requires(T0 t) { t.begin(); };
+
+struct GetBegin {
+  template 
+  void operator()(T1);
+};
+
+GetBegin begin;
+
+template 
+concept Concept = requires(T2 t) { begin(t); };
+
+struct Subrange;
+
+template 
+struct View {
+  Subrange ();
+
+  operator bool()
+requires true;
+
+  operator bool()
+requires requires { begin(getSubrange()); };
+
+  void begin();
+};
+
+struct Subrange : View {};
+static_assert(Concept);
Index: clang/lib/Sema/SemaConcept.cpp
===
--- clang/lib/Sema/SemaConcept.cpp
+++ clang/lib/Sema/SemaConcept.cpp
@@ -780,7 +780,8 @@
  const Expr *NewConstr) {
   if (OldConstr == NewConstr)
 return true;
-  if (Old && New && Old != New) {
+  if (Old && New && Old != New &&
+  Old->getLexicalDeclContext() != New->getLexicalDeclContext()) {
 if (const Expr *SubstConstr =
 SubstituteConstraintExpression(*this, Old, OldConstr))
   OldConstr = SubstConstr;


Index: clang/test/SemaTemplate/concepts-no-early-substitution.cpp
===
--- /dev/null
+++ clang/test/SemaTemplate/concepts-no-early-substitution.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -std=c++20 -x c++ %s -verify -fsyntax-only
+// expected-no-diagnostics
+
+template 
+concept HasMemberBegin = requires(T0 t) { t.begin(); };
+
+struct GetBegin {
+  template 
+  void operator()(T1);
+};
+
+GetBegin begin;
+
+template 
+concept Concept = requires(T2 t) { begin(t); };
+
+struct Subrange;
+
+template 
+struct View {
+  Subrange ();
+
+  operator bool()
+requires true;
+
+  operator bool()
+requires requires { begin(getSubrange()); };
+
+  void begin();
+};
+
+struct Subrange : View {};
+static_assert(Concept);
Index: clang/lib/Sema/SemaConcept.cpp
===
--- clang/lib/Sema/SemaConcept.cpp
+++ clang/lib/Sema/SemaConcept.cpp
@@ -780,7 +780,8 @@
  const Expr *NewConstr) {
   if (OldConstr == NewConstr)
 return true;
-  if (Old && New && Old != New) {
+  if (Old && New && Old != New &&
+  Old->getLexicalDeclContext() != New->getLexicalDeclContext()) {
 if (const Expr *SubstConstr =
 SubstituteConstraintExpression(*this, Old, OldConstr))
   OldConstr = SubstConstr;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D150730: [Clang][Sema] Substitute constraints only for declarations with different lexical contexts

2023-05-16 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov created this revision.
alexander-shaposhnikov added a reviewer: erichkeane.
alexander-shaposhnikov created this object with visibility "All Users".
Herald added a project: All.
alexander-shaposhnikov requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Substitute constraints only for declarations with different lexical contexts.
This results in avoiding the substitution of constraints during the 
redeclaration check inside a class (and by product caching the wrong 
substitution result).

Test plan: ninja check-all


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D150730

Files:
  clang/lib/Sema/SemaConcept.cpp
  clang/test/SemaTemplate/concepts-no-early-substitution.cpp


Index: clang/test/SemaTemplate/concepts-no-early-substitution.cpp
===
--- /dev/null
+++ clang/test/SemaTemplate/concepts-no-early-substitution.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -std=c++20 -x c++ %s -verify -fsyntax-only
+// expected-no-diagnostics
+
+template 
+concept HasMemberBegin = requires(T0 t) { t.begin(); };
+
+struct GetBegin {
+  template 
+  void operator()(T1);
+};
+
+GetBegin begin;
+
+template 
+concept Concept = requires(T2 t) { begin(t); };
+
+struct Subrange;
+
+template 
+struct View {
+  Subrange ();
+
+  operator bool()
+requires true;
+
+  operator bool()
+requires requires { begin(getSubrange()); };
+
+  void begin();
+};
+
+struct Subrange : View {};
+static_assert(Concept);
Index: clang/lib/Sema/SemaConcept.cpp
===
--- clang/lib/Sema/SemaConcept.cpp
+++ clang/lib/Sema/SemaConcept.cpp
@@ -780,7 +780,8 @@
  const Expr *NewConstr) {
   if (OldConstr == NewConstr)
 return true;
-  if (Old && New && Old != New) {
+  if (Old && New && Old != New &&
+  Old->getLexicalDeclContext() != New->getLexicalDeclContext()) {
 if (const Expr *SubstConstr =
 SubstituteConstraintExpression(*this, Old, OldConstr))
   OldConstr = SubstConstr;


Index: clang/test/SemaTemplate/concepts-no-early-substitution.cpp
===
--- /dev/null
+++ clang/test/SemaTemplate/concepts-no-early-substitution.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -std=c++20 -x c++ %s -verify -fsyntax-only
+// expected-no-diagnostics
+
+template 
+concept HasMemberBegin = requires(T0 t) { t.begin(); };
+
+struct GetBegin {
+  template 
+  void operator()(T1);
+};
+
+GetBegin begin;
+
+template 
+concept Concept = requires(T2 t) { begin(t); };
+
+struct Subrange;
+
+template 
+struct View {
+  Subrange ();
+
+  operator bool()
+requires true;
+
+  operator bool()
+requires requires { begin(getSubrange()); };
+
+  void begin();
+};
+
+struct Subrange : View {};
+static_assert(Concept);
Index: clang/lib/Sema/SemaConcept.cpp
===
--- clang/lib/Sema/SemaConcept.cpp
+++ clang/lib/Sema/SemaConcept.cpp
@@ -780,7 +780,8 @@
  const Expr *NewConstr) {
   if (OldConstr == NewConstr)
 return true;
-  if (Old && New && Old != New) {
+  if (Old && New && Old != New &&
+  Old->getLexicalDeclContext() != New->getLexicalDeclContext()) {
 if (const Expr *SubstConstr =
 SubstituteConstraintExpression(*this, Old, OldConstr))
   OldConstr = SubstConstr;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-05-15 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added a comment.

@erichkeane - I took your example and tried to reduce it further
https://godbolt.org/z/jEx9vdj7K

It's kind of a difficult situation - both gcc and msvc accept it, yet /* very 
very cautiously */ it might happen that the code is actually invalid ...
(i'd need to think about it more), but this is based on the insights from 
@rsmith  and http://eel.is/c++draft/temp.constr#atomic-3.sentence-5 .


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-05-15 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added a comment.

@erichkeane - I'll have stable internet ~soon and will try to look into the 
reported issue (but help would be greatly appreciated).
To the best of my knowledge there are other problems with libstdc++'s ranges 
(even without this diff), but yeah, this regression is unfortunate.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D150285: Fix CRTP partial specialization instantiation crash.

2023-05-10 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov accepted this revision.
alexander-shaposhnikov added a comment.
This revision is now accepted and ready to land.

LG


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

https://reviews.llvm.org/D150285

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-05-05 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added inline comments.



Comment at: clang/lib/Sema/SemaTemplateInstantiate.cpp:133
 }
 
+Response HandlePartialClassTemplateSpec(

alexander-shaposhnikov wrote:
> alexander-shaposhnikov wrote:
> > alexander-shaposhnikov wrote:
> > > HandlePartialClassTemplateSpec is from Erich's diff 
> > > (https://reviews.llvm.org/D147722)
> > @erichkeane : previously (see https://reviews.llvm.org/D147722) we were 
> > producing a real layer of arguments (if the depth is greater than 1), to 
> > the best of my knowledge this is incorrect since it'd trigger unexpected 
> > depth adjustment, we should produce retained layers instead.
> (depth adjustment during the substitution)
to make it a bit easier to reason about I've changed the names in the test case:

```
//enum class Enum { E1 };

template 
concept some_concept = true;
//inline constexpr bool some_concept = true;

template 
struct S {
  template 
  requires(some_concept)
  void func(const T2 &);
};

template 
struct S {
  template 
  requires(some_concept)
  void func(const T22 &);
};

template 
template 
requires (some_concept)
inline void S::func(const T222 &) {}
```

Previously the code was doing the following:
```
PartialClassTemplSpec->getTemplateDepth() = 1
NumRetainedOuterLevels: 0
0: <>
before subst:
ParenExpr 0x558fb90be6a8 '_Bool'
`-ConceptSpecializationExpr 0x558fb90be640 '_Bool' Concept 0x558fb909fbd8 
'some_concept'
  |-ImplicitConceptSpecializationDecl 0x558fb90be5d0 
  | `-TemplateArgument type 'type-parameter-1-0'
  |   `-TemplateTypeParmType 0x558fb90a01d0 'type-parameter-1-0' dependent 
depth 1 index 0
  `-TemplateArgument type 'T22'
`-TemplateTypeParmType 0x558fb90be590 'T22' dependent depth 1 index 0
  `-TemplateTypeParm 0x558fb90be540 'T22'
after subst:
ParenExpr 0x558fb90bf168 '_Bool'
`-ConceptSpecializationExpr 0x558fb90bf100 '_Bool' Concept 0x558fb909fbd8 
'some_concept'
  |-ImplicitConceptSpecializationDecl 0x558fb90bf090 
  | `-TemplateArgument type 'type-parameter-0-0'
  |   `-TemplateTypeParmType 0x558fb909fb50 'type-parameter-0-0' dependent 
depth 0 index 0
  `-TemplateArgument type 'T22'
`-TemplateTypeParmType 0x558fb90bf050 'T22' dependent depth 0 index 0
  `-TemplateTypeParm 0x558fb90be540 'T22'
```
(as one can see the depths have changed)

now:
```
PartialClassTemplSpec->getTemplateDepth() = 1
NumRetainedOuterLevels: 1
before subst:
ParenExpr 0x55f7813ae6a8 '_Bool'
`-ConceptSpecializationExpr 0x55f7813ae640 '_Bool' Concept 0x55f78138fbd8 
'some_concept'
  |-ImplicitConceptSpecializationDecl 0x55f7813ae5d0 
  | `-TemplateArgument type 'type-parameter-1-0'
  |   `-TemplateTypeParmType 0x55f7813901d0 'type-parameter-1-0' dependent 
depth 1 index 0
  `-TemplateArgument type 'T22'
`-TemplateTypeParmType 0x55f7813ae590 'T22' dependent depth 1 index 0
  `-TemplateTypeParm 0x55f7813ae540 'T22'
after subst:
ParenExpr 0x55f7813af138 '_Bool'
`-ConceptSpecializationExpr 0x55f7813af0d0 '_Bool' Concept 0x55f78138fbd8 
'some_concept'
  |-ImplicitConceptSpecializationDecl 0x55f7813af060 
  | `-TemplateArgument type 'type-parameter-1-0'
  |   `-TemplateTypeParmType 0x55f7813901d0 'type-parameter-1-0' dependent 
depth 1 index 0
  `-TemplateArgument type 'T22'
`-TemplateTypeParmType 0x55f7813ae590 'T22' dependent depth 1 index 0
  `-TemplateTypeParm 0x55f7813ae540 'T22'
```




Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-05-04 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added inline comments.



Comment at: clang/lib/Sema/SemaTemplateInstantiate.cpp:133
 }
 
+Response HandlePartialClassTemplateSpec(

alexander-shaposhnikov wrote:
> alexander-shaposhnikov wrote:
> > HandlePartialClassTemplateSpec is from Erich's diff 
> > (https://reviews.llvm.org/D147722)
> @erichkeane : previously (see https://reviews.llvm.org/D147722) we were 
> producing a real layer of arguments (if the depth is greater than 1), to the 
> best of my knowledge this is incorrect since it'd trigger unexpected depth 
> adjustment, we should produce retained layers instead.
(depth adjustment during the substitution)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-05-04 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added a comment.

@davidtgoldblatt - thanks for the report.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-05-04 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added inline comments.



Comment at: clang/test/SemaTemplate/concepts-out-of-line-def.cpp:348
+
+namespace MultilevelTemplateWithPartialSpecialization {
+template 

(new tests)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-05-04 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added inline comments.



Comment at: clang/lib/Sema/SemaTemplateInstantiate.cpp:133
 }
 
+Response HandlePartialClassTemplateSpec(

alexander-shaposhnikov wrote:
> HandlePartialClassTemplateSpec is from Erich's diff 
> (https://reviews.llvm.org/D147722)
@erichkeane : previously (see https://reviews.llvm.org/D147722) we were 
producing a real layer of arguments (if the depth is greater than 1), to the 
best of my knowledge this is incorrect since it'd trigger unexpected depth 
adjustment, we should produce retained layers instead.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-05-04 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov updated this revision to Diff 519711.
alexander-shaposhnikov added a comment.

Remove dead code.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

Files:
  clang/include/clang/AST/DeclTemplate.h
  clang/include/clang/Sema/Template.h
  clang/lib/Sema/SemaConcept.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/SemaTemplateDeduction.cpp
  clang/lib/Sema/SemaTemplateInstantiate.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/SemaTemplate/concepts-friends.cpp
  clang/test/SemaTemplate/concepts-out-of-line-def.cpp
  clang/test/SemaTemplate/concepts.cpp

Index: clang/test/SemaTemplate/concepts.cpp
===
--- clang/test/SemaTemplate/concepts.cpp
+++ clang/test/SemaTemplate/concepts.cpp
@@ -816,3 +816,101 @@
 static_assert(Parent::TakesBinary::i == 0);
 }
 
+namespace TemplateInsideNonTemplateClass {
+template concept C = true;
+
+template auto L = [] U>() {};
+
+struct Q {
+  template U> friend constexpr auto decltype(L)::operator()() const;
+};
+
+template 
+concept C1 = false;
+
+struct Foo {
+  template 
+  struct Bar {};
+
+  template 
+requires(C1)
+  struct Bar;
+};
+
+Foo::Bar BarInstance;
+} // namespace TemplateInsideNonTemplateClass
+
+namespace GH61959 {
+template 
+concept C = (sizeof(T0) >= 4);
+
+template
+struct Orig { };
+
+template
+struct Orig {
+  template requires C
+  void f() { }
+
+  template requires true
+  void f() { }
+};
+
+template  struct Mod {};
+
+template 
+struct Mod {
+  template  requires C
+  constexpr static int f() { return 1; }
+
+  template  requires C
+  constexpr static int f() { return 2; }
+};
+
+static_assert(Mod::f() == 1);
+static_assert(Mod::f() == 2);
+
+template
+struct Outer {
+  template
+  struct Inner {};
+
+  template
+  struct Inner {
+template
+void foo()  requires C && C && C{}
+template
+void foo()  requires true{}
+  };
+};
+
+void bar() {
+  Outer::Inner I;
+  I.foo();
+}
+} // namespace GH61959
+
+
+namespace TemplateInsideTemplateInsideTemplate {
+template
+concept C1 = false;
+
+template 
+struct W0 {
+  template 
+  struct W1 {
+template 
+struct F {
+  enum { value = 1 };
+};
+
+template 
+  requires C1
+struct F {
+  enum { value = 2 };
+};
+  };
+};
+
+static_assert(W0<0>::W1<1>::F::value == 1);
+} // TemplateInsideTemplateInsideTemplate
Index: clang/test/SemaTemplate/concepts-out-of-line-def.cpp
===
--- clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -127,3 +127,275 @@
 static_assert(S::specialization("str") == SPECIALIZATION_REQUIRES);
 
 } // namespace multiple_template_parameter_lists
+
+static constexpr int CONSTRAINED_METHOD_1 = 1;
+static constexpr int CONSTRAINED_METHOD_2 = 2;
+
+namespace constrained_members {
+
+template 
+struct S {
+  template 
+  static constexpr int constrained_method();
+};
+
+template <>
+template 
+constexpr int S<1>::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  template T4>
+  static constexpr int constrained_method();
+};
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained members
+
+namespace constrained_members_of_nested_types {
+
+template 
+struct S {
+  struct Inner0 {
+struct Inner1 {
+  template 
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template <>
+template 
+constexpr int S<1>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  struct Inner0 {
+struct Inner1 {
+  template T4>
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+

[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-05-04 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov updated this revision to Diff 519708.
alexander-shaposhnikov added a comment.

Add more tests,
Fix HandlePartialClassTemplateSpec.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

Files:
  clang/include/clang/AST/DeclTemplate.h
  clang/include/clang/Sema/Template.h
  clang/lib/Sema/SemaConcept.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/SemaTemplateDeduction.cpp
  clang/lib/Sema/SemaTemplateInstantiate.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/SemaTemplate/concepts-friends.cpp
  clang/test/SemaTemplate/concepts-out-of-line-def.cpp
  clang/test/SemaTemplate/concepts.cpp

Index: clang/test/SemaTemplate/concepts.cpp
===
--- clang/test/SemaTemplate/concepts.cpp
+++ clang/test/SemaTemplate/concepts.cpp
@@ -816,3 +816,101 @@
 static_assert(Parent::TakesBinary::i == 0);
 }
 
+namespace TemplateInsideNonTemplateClass {
+template concept C = true;
+
+template auto L = [] U>() {};
+
+struct Q {
+  template U> friend constexpr auto decltype(L)::operator()() const;
+};
+
+template 
+concept C1 = false;
+
+struct Foo {
+  template 
+  struct Bar {};
+
+  template 
+requires(C1)
+  struct Bar;
+};
+
+Foo::Bar BarInstance;
+} // namespace TemplateInsideNonTemplateClass
+
+namespace GH61959 {
+template 
+concept C = (sizeof(T0) >= 4);
+
+template
+struct Orig { };
+
+template
+struct Orig {
+  template requires C
+  void f() { }
+
+  template requires true
+  void f() { }
+};
+
+template  struct Mod {};
+
+template 
+struct Mod {
+  template  requires C
+  constexpr static int f() { return 1; }
+
+  template  requires C
+  constexpr static int f() { return 2; }
+};
+
+static_assert(Mod::f() == 1);
+static_assert(Mod::f() == 2);
+
+template
+struct Outer {
+  template
+  struct Inner {};
+
+  template
+  struct Inner {
+template
+void foo()  requires C && C && C{}
+template
+void foo()  requires true{}
+  };
+};
+
+void bar() {
+  Outer::Inner I;
+  I.foo();
+}
+} // namespace GH61959
+
+
+namespace TemplateInsideTemplateInsideTemplate {
+template
+concept C1 = false;
+
+template 
+struct W0 {
+  template 
+  struct W1 {
+template 
+struct F {
+  enum { value = 1 };
+};
+
+template 
+  requires C1
+struct F {
+  enum { value = 2 };
+};
+  };
+};
+
+static_assert(W0<0>::W1<1>::F::value == 1);
+} // TemplateInsideTemplateInsideTemplate
Index: clang/test/SemaTemplate/concepts-out-of-line-def.cpp
===
--- clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -127,3 +127,275 @@
 static_assert(S::specialization("str") == SPECIALIZATION_REQUIRES);
 
 } // namespace multiple_template_parameter_lists
+
+static constexpr int CONSTRAINED_METHOD_1 = 1;
+static constexpr int CONSTRAINED_METHOD_2 = 2;
+
+namespace constrained_members {
+
+template 
+struct S {
+  template 
+  static constexpr int constrained_method();
+};
+
+template <>
+template 
+constexpr int S<1>::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  template T4>
+  static constexpr int constrained_method();
+};
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained members
+
+namespace constrained_members_of_nested_types {
+
+template 
+struct S {
+  struct Inner0 {
+struct Inner1 {
+  template 
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template <>
+template 
+constexpr int S<1>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  struct Inner0 {
+struct Inner1 {
+  template T4>
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { 

[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-05-04 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added a comment.

Reverted in 
https://github.com/llvm/llvm-project/commit/3b9ed6e5323176550925f3b0a2c50ced1b61438d,
it'll take time to investigate this case.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D149906: [Clang] Update release notes

2023-05-04 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov updated this revision to Diff 519660.

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D149906

Files:
  clang/docs/ReleaseNotes.rst


Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -78,8 +78,13 @@
 
 C++20 Feature Support
 ^
-- Support for out-of-line definitions of constrained templates has been 
improved.
-  This partially fixes `#49620 
`_.
+- Implemented the rule introduced by `CA104 `_  for 
comparison of
+  constraint-expressions. Improved support for out-of-line definitions of 
constrained templates.
+  This fixes:
+  `#49620 `_,
+  `#60231 `_,
+  `#61414 `_,
+  `#61809 `_.
 - Lambda templates with a requires clause directly after the template 
parameters now parse
   correctly if the requires clause consists of a variable with a dependent 
type.
   (`#61278 `_)


Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -78,8 +78,13 @@
 
 C++20 Feature Support
 ^
-- Support for out-of-line definitions of constrained templates has been improved.
-  This partially fixes `#49620 `_.
+- Implemented the rule introduced by `CA104 `_  for comparison of
+  constraint-expressions. Improved support for out-of-line definitions of constrained templates.
+  This fixes:
+  `#49620 `_,
+  `#60231 `_,
+  `#61414 `_,
+  `#61809 `_.
 - Lambda templates with a requires clause directly after the template parameters now parse
   correctly if the requires clause consists of a variable with a dependent type.
   (`#61278 `_)
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D149906: [Clang] Update release notes

2023-05-04 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov created this revision.
alexander-shaposhnikov added reviewers: rsmith, erichkeane, ilya-biryukov.
alexander-shaposhnikov created this object with visibility "All Users".
Herald added a project: All.
alexander-shaposhnikov requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Update release notes.
This is a follow-up to https://reviews.llvm.org/D146178


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D149906

Files:
  clang/docs/ReleaseNotes.rst


Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -78,8 +78,13 @@
 
 C++20 Feature Support
 ^
-- Support for out-of-line definitions of constrained templates has been 
improved.
-  This partially fixes `#49620 
`_.
+- Implemented the rule introduced by `CA104 `_  for 
comparison of
+  constraints expressions. Improved support for out-of-line definitions of 
constrained templates.
+  This fixes:
+  `#49620 `_,
+  `#60231 `_,
+  `#61414 `_,
+  `#61809 `_.
 - Lambda templates with a requires clause directly after the template 
parameters now parse
   correctly if the requires clause consists of a variable with a dependent 
type.
   (`#61278 `_)


Index: clang/docs/ReleaseNotes.rst
===
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -78,8 +78,13 @@
 
 C++20 Feature Support
 ^
-- Support for out-of-line definitions of constrained templates has been improved.
-  This partially fixes `#49620 `_.
+- Implemented the rule introduced by `CA104 `_  for comparison of
+  constraints expressions. Improved support for out-of-line definitions of constrained templates.
+  This fixes:
+  `#49620 `_,
+  `#60231 `_,
+  `#61414 `_,
+  `#61809 `_.
 - Lambda templates with a requires clause directly after the template parameters now parse
   correctly if the requires clause consists of a variable with a dependent type.
   (`#61278 `_)
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-05-03 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added a comment.

P.S. Landed. If it survives in the trunk this time - I'll send a follow-up diff 
with the release notes.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-05-03 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added a comment.

@erichkeane - thanks, then I'm going to give it another try.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-05-03 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added inline comments.



Comment at: clang/lib/Sema/SemaTemplateInstantiate.cpp:133
 }
 
+Response HandlePartialClassTemplateSpec(

HandlePartialClassTemplateSpec is from Erich's diff 
(https://reviews.llvm.org/D147722)



Comment at: clang/lib/Sema/SemaTemplateInstantiate.cpp:344
  Innermost->asArray(), Final);
-
-  const Decl *CurDecl = ND;
+  CurDecl = Response::UseNextDecl(ND).NextDecl;
+  }

this bit is important.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-05-03 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov updated this revision to Diff 518990.
alexander-shaposhnikov added a comment.

Simplify code a little bit.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

Files:
  clang/include/clang/AST/DeclTemplate.h
  clang/include/clang/Sema/Template.h
  clang/lib/Sema/SemaConcept.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/SemaTemplateDeduction.cpp
  clang/lib/Sema/SemaTemplateInstantiate.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/SemaTemplate/concepts-friends.cpp
  clang/test/SemaTemplate/concepts-out-of-line-def.cpp
  clang/test/SemaTemplate/concepts.cpp

Index: clang/test/SemaTemplate/concepts.cpp
===
--- clang/test/SemaTemplate/concepts.cpp
+++ clang/test/SemaTemplate/concepts.cpp
@@ -816,3 +816,101 @@
 static_assert(Parent::TakesBinary::i == 0);
 }
 
+namespace TemplateInsideNonTemplateClass {
+template concept C = true;
+
+template auto L = [] U>() {};
+
+struct Q {
+  template U> friend constexpr auto decltype(L)::operator()() const;
+};
+
+template 
+concept C1 = false;
+
+struct Foo {
+  template 
+  struct Bar {};
+
+  template 
+requires(C1)
+  struct Bar;
+};
+
+Foo::Bar BarInstance;
+} // namespace TemplateInsideNonTemplateClass
+
+namespace GH61959 {
+template 
+concept C = (sizeof(T0) >= 4);
+
+template
+struct Orig { };
+
+template
+struct Orig {
+  template requires C
+  void f() { }
+
+  template requires true
+  void f() { }
+};
+
+template  struct Mod {};
+
+template 
+struct Mod {
+  template  requires C
+  constexpr static int f() { return 1; }
+
+  template  requires C
+  constexpr static int f() { return 2; }
+};
+
+static_assert(Mod::f() == 1);
+static_assert(Mod::f() == 2);
+
+template
+struct Outer {
+  template
+  struct Inner {};
+
+  template
+  struct Inner {
+template
+void foo()  requires C && C && C{}
+template
+void foo()  requires true{}
+  };
+};
+
+void bar() {
+  Outer::Inner I;
+  I.foo();
+}
+} // namespace GH61959
+
+
+namespace TemplateInsideTemplateInsideTemplate {
+template
+concept C1 = false;
+
+template 
+struct W0 {
+  template 
+  struct W1 {
+template 
+struct F {
+  enum { value = 1 };
+};
+
+template 
+  requires C1
+struct F {
+  enum { value = 2 };
+};
+  };
+};
+
+static_assert(W0<0>::W1<1>::F::value == 1);
+} // TemplateInsideTemplateInsideTemplate
Index: clang/test/SemaTemplate/concepts-out-of-line-def.cpp
===
--- clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -127,3 +127,220 @@
 static_assert(S::specialization("str") == SPECIALIZATION_REQUIRES);
 
 } // namespace multiple_template_parameter_lists
+
+static constexpr int CONSTRAINED_METHOD_1 = 1;
+static constexpr int CONSTRAINED_METHOD_2 = 2;
+
+namespace constrained_members {
+
+template 
+struct S {
+  template 
+  static constexpr int constrained_method();
+};
+
+template <>
+template 
+constexpr int S<1>::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  template T4>
+  static constexpr int constrained_method();
+};
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained members
+
+namespace constrained_members_of_nested_types {
+
+template 
+struct S {
+  struct Inner0 {
+struct Inner1 {
+  template 
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template <>
+template 
+constexpr int S<1>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  struct Inner0 {
+struct Inner1 {
+  template T4>
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return 

[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-05-02 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov updated this revision to Diff 518966.
alexander-shaposhnikov added a comment.

1. If innermost != nullptr (in getTemplateInstantiationArgs) and NS is a 
ClassTemplatePartialSpecializationDecl we were incorrectly adding the inner 
level of template args twice (once as an array of arguments and once as a 
retained level inside HandlePartialClassTemplateSpec )
2. Add more tests.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

Files:
  clang/include/clang/AST/DeclTemplate.h
  clang/include/clang/Sema/Template.h
  clang/lib/Sema/SemaConcept.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/SemaTemplateDeduction.cpp
  clang/lib/Sema/SemaTemplateInstantiate.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/SemaTemplate/concepts-friends.cpp
  clang/test/SemaTemplate/concepts-out-of-line-def.cpp
  clang/test/SemaTemplate/concepts.cpp

Index: clang/test/SemaTemplate/concepts.cpp
===
--- clang/test/SemaTemplate/concepts.cpp
+++ clang/test/SemaTemplate/concepts.cpp
@@ -816,3 +816,101 @@
 static_assert(Parent::TakesBinary::i == 0);
 }
 
+namespace TemplateInsideNonTemplateClass {
+template concept C = true;
+
+template auto L = [] U>() {};
+
+struct Q {
+  template U> friend constexpr auto decltype(L)::operator()() const;
+};
+
+template 
+concept C1 = false;
+
+struct Foo {
+  template 
+  struct Bar {};
+
+  template 
+requires(C1)
+  struct Bar;
+};
+
+Foo::Bar BarInstance;
+} // namespace TemplateInsideNonTemplateClass
+
+namespace GH61959 {
+template 
+concept C = (sizeof(T0) >= 4);
+
+template
+struct Orig { };
+
+template
+struct Orig {
+  template requires C
+  void f() { }
+
+  template requires true
+  void f() { }
+};
+
+template  struct Mod {};
+
+template 
+struct Mod {
+  template  requires C
+  constexpr static int f() { return 1; }
+
+  template  requires C
+  constexpr static int f() { return 2; }
+};
+
+static_assert(Mod::f() == 1);
+static_assert(Mod::f() == 2);
+
+template
+struct Outer {
+  template
+  struct Inner {};
+
+  template
+  struct Inner {
+template
+void foo()  requires C && C && C{}
+template
+void foo()  requires true{}
+  };
+};
+
+void bar() {
+  Outer::Inner I;
+  I.foo();
+}
+} // namespace GH61959
+
+
+namespace TemplateInsideTemplateInsideTemplate {
+template
+concept C1 = false;
+
+template 
+struct W0 {
+  template 
+  struct W1 {
+template 
+struct F {
+  enum { value = 1 };
+};
+
+template 
+  requires C1
+struct F {
+  enum { value = 2 };
+};
+  };
+};
+
+static_assert(W0<0>::W1<1>::F::value == 1);
+} // TemplateInsideTemplateInsideTemplate
Index: clang/test/SemaTemplate/concepts-out-of-line-def.cpp
===
--- clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -127,3 +127,220 @@
 static_assert(S::specialization("str") == SPECIALIZATION_REQUIRES);
 
 } // namespace multiple_template_parameter_lists
+
+static constexpr int CONSTRAINED_METHOD_1 = 1;
+static constexpr int CONSTRAINED_METHOD_2 = 2;
+
+namespace constrained_members {
+
+template 
+struct S {
+  template 
+  static constexpr int constrained_method();
+};
+
+template <>
+template 
+constexpr int S<1>::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  template T4>
+  static constexpr int constrained_method();
+};
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained members
+
+namespace constrained_members_of_nested_types {
+
+template 
+struct S {
+  struct Inner0 {
+struct Inner1 {
+  template 
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template <>
+template 
+constexpr int S<1>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  struct Inner0 {
+struct Inner1 {
+  template T4>
+  static constexpr int 

[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-05-02 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added a comment.

upd.
In the reduced example above MLTAL is incorrect

  (lldb) p MLTAL.dump()
  NumRetainedOuterLevels: 1
  1: 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-05-02 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added a comment.

reduced test case:

  template 
  concept Concept = false;
  
  struct Foo {
template 
struct result {};
  
template 
  requires(Concept<_Tp>)
struct result<_Tp>;
  };


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-05-02 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added a comment.

@erichkeane  - feel free to take over this patch.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-05-01 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added a comment.

@erichkeane - thanks! I'll send a diff for the release notes ~soon (~this 
week).  (P.S.  just in case - I'll be out of office for ~2 weeks)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-04-27 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
This revision was not accepted when it landed; it landed in state "Needs 
Review".
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGe3b1083e00e6: [Clang][Sema] Fix comparison of constraint 
expressions (authored by alexander-shaposhnikov).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

Files:
  clang/include/clang/AST/DeclTemplate.h
  clang/include/clang/Sema/Template.h
  clang/lib/Sema/SemaConcept.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/SemaTemplateDeduction.cpp
  clang/lib/Sema/SemaTemplateInstantiate.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/SemaTemplate/concepts-friends.cpp
  clang/test/SemaTemplate/concepts-out-of-line-def.cpp
  clang/test/SemaTemplate/concepts.cpp

Index: clang/test/SemaTemplate/concepts.cpp
===
--- clang/test/SemaTemplate/concepts.cpp
+++ clang/test/SemaTemplate/concepts.cpp
@@ -816,3 +816,62 @@
 static_assert(Parent::TakesBinary::i == 0);
 }
 
+namespace TemplateInsideNonTemplateClass {
+template concept C = true;
+
+template auto L = [] U>() {};
+
+struct Q {
+  template U> friend constexpr auto decltype(L)::operator()() const;
+};
+} // namespace TemplateInsideNonTemplateClass
+
+namespace GH61959 {
+template 
+concept C = (sizeof(T0) >= 4);
+
+template
+struct Orig { };
+
+template
+struct Orig {
+  template requires C
+  void f() { }
+
+  template requires true
+  void f() { }
+};
+
+template  struct Mod {};
+
+template 
+struct Mod {
+  template  requires C
+  constexpr static int f() { return 1; }
+
+  template  requires C
+  constexpr static int f() { return 2; }
+};
+
+static_assert(Mod::f() == 1);
+static_assert(Mod::f() == 2);
+
+template
+struct Outer {
+  template
+  struct Inner {};
+
+  template
+  struct Inner {
+template
+void foo()  requires C && C && C{}
+template
+void foo()  requires true{}
+  };
+};
+
+void bar() {
+  Outer::Inner I;
+  I.foo();
+}
+}
Index: clang/test/SemaTemplate/concepts-out-of-line-def.cpp
===
--- clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -127,3 +127,220 @@
 static_assert(S::specialization("str") == SPECIALIZATION_REQUIRES);
 
 } // namespace multiple_template_parameter_lists
+
+static constexpr int CONSTRAINED_METHOD_1 = 1;
+static constexpr int CONSTRAINED_METHOD_2 = 2;
+
+namespace constrained_members {
+
+template 
+struct S {
+  template 
+  static constexpr int constrained_method();
+};
+
+template <>
+template 
+constexpr int S<1>::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  template T4>
+  static constexpr int constrained_method();
+};
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained members
+
+namespace constrained_members_of_nested_types {
+
+template 
+struct S {
+  struct Inner0 {
+struct Inner1 {
+  template 
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template <>
+template 
+constexpr int S<1>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  struct Inner0 {
+struct Inner1 {
+  template T4>
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained_members_of_nested_types
+
+namespace constrained_member_sfinae {
+
+template struct S {
+  template
+  static constexpr int constrained_method() requires 

[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-04-27 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov updated this revision to Diff 517513.
alexander-shaposhnikov added a comment.

Add more tests


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

Files:
  clang/include/clang/AST/DeclTemplate.h
  clang/include/clang/Sema/Template.h
  clang/lib/Sema/SemaConcept.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/SemaTemplateDeduction.cpp
  clang/lib/Sema/SemaTemplateInstantiate.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/SemaTemplate/concepts-friends.cpp
  clang/test/SemaTemplate/concepts-out-of-line-def.cpp
  clang/test/SemaTemplate/concepts.cpp

Index: clang/test/SemaTemplate/concepts.cpp
===
--- clang/test/SemaTemplate/concepts.cpp
+++ clang/test/SemaTemplate/concepts.cpp
@@ -816,3 +816,62 @@
 static_assert(Parent::TakesBinary::i == 0);
 }
 
+namespace TemplateInsideNonTemplateClass {
+template concept C = true;
+
+template auto L = [] U>() {};
+
+struct Q {
+  template U> friend constexpr auto decltype(L)::operator()() const;
+};
+} // namespace TemplateInsideNonTemplateClass
+
+namespace GH61959 {
+template 
+concept C = (sizeof(T0) >= 4);
+
+template
+struct Orig { };
+
+template
+struct Orig {
+  template requires C
+  void f() { }
+
+  template requires true
+  void f() { }
+};
+
+template  struct Mod {};
+
+template 
+struct Mod {
+  template  requires C
+  constexpr static int f() { return 1; }
+
+  template  requires C
+  constexpr static int f() { return 2; }
+};
+
+static_assert(Mod::f() == 1);
+static_assert(Mod::f() == 2);
+
+template
+struct Outer {
+  template
+  struct Inner {};
+
+  template
+  struct Inner {
+template
+void foo()  requires C && C && C{}
+template
+void foo()  requires true{}
+  };
+};
+
+void bar() {
+  Outer::Inner I;
+  I.foo();
+}
+}
Index: clang/test/SemaTemplate/concepts-out-of-line-def.cpp
===
--- clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -127,3 +127,220 @@
 static_assert(S::specialization("str") == SPECIALIZATION_REQUIRES);
 
 } // namespace multiple_template_parameter_lists
+
+static constexpr int CONSTRAINED_METHOD_1 = 1;
+static constexpr int CONSTRAINED_METHOD_2 = 2;
+
+namespace constrained_members {
+
+template 
+struct S {
+  template 
+  static constexpr int constrained_method();
+};
+
+template <>
+template 
+constexpr int S<1>::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  template T4>
+  static constexpr int constrained_method();
+};
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained members
+
+namespace constrained_members_of_nested_types {
+
+template 
+struct S {
+  struct Inner0 {
+struct Inner1 {
+  template 
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template <>
+template 
+constexpr int S<1>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  struct Inner0 {
+struct Inner1 {
+  template T4>
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained_members_of_nested_types
+
+namespace constrained_member_sfinae {
+
+template struct S {
+  template
+  static constexpr int constrained_method() requires (sizeof(int[N * 1073741824 + 4]) == 16) {
+return CONSTRAINED_METHOD_1;
+  }
+
+  template
+  static constexpr int constrained_method() requires (sizeof(int[N]) == 16);
+};
+
+template<>
+template
+constexpr int 

[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-04-26 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added a comment.

/* will update the diff ~soon */


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-04-26 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov planned changes to this revision.
alexander-shaposhnikov added a comment.

/* working on it */


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-04-21 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added a comment.

reduced test case (that is currently blocking this diff) :

  namespace outer::internal {
  
  template 
  concept myconcept = true;
  
  }
  
  namespace outer {
  
  template  class Foo;
  
  template  struct Bar {
template  friend class Foo;
  };
  
  Bar S;
  
  namespace internal {
  int f(Foo);
  }
  
  template  struct Foo {
friend int internal::f(Foo);
  };
  
  } // namespace outer


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-04-19 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added a comment.

Yeah, things appear to work for the current version of this diff (including 
GH62110).
However, while doing some internal testing I've discovered one suspicious issue 
(sigh, sigh), but haven't been able to create a standalone repro yet.
Need more time for debugging.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-04-18 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added inline comments.



Comment at: clang/lib/Sema/SemaConcept.cpp:263
 
+  if (SubstitutedAtomicExpr.get()->isValueDependent())
+return SubstitutedAtomicExpr;

alexander-shaposhnikov wrote:
> alexander-shaposhnikov wrote:
> > erichkeane wrote:
> > > alexander-shaposhnikov wrote:
> > > > erichkeane wrote:
> > > > > alexander-shaposhnikov wrote:
> > > > > > erichkeane wrote:
> > > > > > > So this bit is concerning to me... we have been catching a ton of 
> > > > > > > bugs in the MLTAL stuff by trying to constant evaluate an 
> > > > > > > expression that isn't correctly constexpr, and this will defeat 
> > > > > > > it.  We shouldn't be calling this function at all on 
> > > > > > > non-fully-instantiated expressions.  What is the case that ends 
> > > > > > > up coming through here, and should be be calling this at all?
> > > > > > This happens e.g. for concepts-PR54629.cpp
> > > > > > 
> > > > > > ```
> > > > > > Old:
> > > > > > FunctionDecl 0x64d90378 
> > > > > > llvm-project/clang/test/SemaTemplate/concepts-PR54629.cpp:30:1, 
> > > > > > line:32:2> line:30:6 foo 'void ()'
> > > > > > |-RequiresExpr 0x64d90318  'bool'
> > > > > > | |-ParmVarDecl 0x64d90150  col:24 referenced t 
> > > > > > 'T &'
> > > > > > | `-NestedRequirement 0x64d902d8 dependent
> > > > > > |   `-BinaryOperator 0x64d902b8  'bool' '<'
> > > > > > | |-UnaryExprOrTypeTraitExpr 0x64d90260  
> > > > > > 'unsigned long' sizeof
> > > > > > | | `-ParenExpr 0x64d90240  'T' lvalue
> > > > > > | |   `-DeclRefExpr 0x64d90220  'T' lvalue ParmVar 
> > > > > > 0x64d90150 't' 'T &' non_odr_use_unevaluated
> > > > > > | `-ImplicitCastExpr 0x64d902a0  'unsigned long' 
> > > > > > 
> > > > > > |   `-IntegerLiteral 0x64d90280  'int' 4
> > > > > > `-CompoundStmt 0x64d90f70 
> > > > > > 
> > > > > > while MLTAL is empty.
> > > > > > ```
> > > > > > (clang::Sema::CheckOverload calls clang::Sema::IsOverload, while 
> > > > > > clang::Sema::IsOverload invokes 
> > > > > > clang::Sema::AreConstraintExpressionsEqual)
> > > > > Hmm that seems wrong for me, but I'm not sure how.  It doesn't 
> > > > > seem right for `AreConstraintExpressionsEqual`to try to calculate the 
> > > > > constraint satisfaction...
> > > > I think we get there from 
> > > > https://github.com/llvm/llvm-project/blob/main/clang/lib/Sema/SemaTemplateInstantiate.cpp#L2375
> > > So I still think this is an incorrect change.  I don't understand why 
> > > we'd get here without the 'final' check, but perhaps there is something 
> > > missing elsewhere?
> > unfortunately, I don't have enough context - will revisit this change (iirc 
> > one test was failing without it and Clang was calling 
> > CheckConstraintSatisfaction from an unexpected place). There is some 
> > accumulated technical debt (without the current diff) / it takes to 
> > untangle.  
> reduced test case (extracted from concepts-PR54629.cpp):
> 
> ```
> template 
> void foo()
>   requires requires(T ) { requires sizeof(t) < 4; }
> {}
> 
> template 
> void foo()
>   requires requires(T ) { requires sizeof(t) > 4; }
> {}
> 
> void test() {
>   foo();
> }
> ```
so I've investigated a bit how things work right now (without this diff),
the following code is somewhat (but not directly) relevant:
https://github.com/llvm/llvm-project/blob/main/clang/lib/Sema/SemaConcept.cpp#L417
 
(from 
https://github.com/llvm/llvm-project/commit/b25902736c2e330429278e1929cc5afd2201fb77)
 
however, previously, the issues above (for the previous version of this diff) 
(e.g. for concepts-PR54629.cpp) were triggered when Clang was trying to 
substitute an empty MLTAL, while in our case it's unnecessary. 
It might happen though that there is another problem lingering around but it 
looks like at the moment the tests are passing without changes to 
```
calculateConstraintSatisfaction
```
(=> dropped them)
 


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-04-18 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added inline comments.



Comment at: clang/lib/Sema/SemaConcept.cpp:781
+  /*ForConstraintInstantiation=*/true, /*SkipForSpecialization*/ false);
+  Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/false);
+  std::optional ThisScope;

alexander-shaposhnikov wrote:
> rsmith wrote:
> > Just a small optimization: there's no point doing the transform if we have 
> > nothing to substitute.
> > Just a small optimization: there's no point doing the transform if we have 
> > nothing to substitute.
> 
> 
do not try to substitute empty MLTAL (suggested above by @rsmith)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-04-18 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added inline comments.



Comment at: clang/lib/Sema/SemaConcept.cpp:781
+  /*ForConstraintInstantiation=*/true, /*SkipForSpecialization*/ false);
+  Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/false);
+  std::optional ThisScope;

rsmith wrote:
> Just a small optimization: there's no point doing the transform if we have 
> nothing to substitute.
> Just a small optimization: there's no point doing the transform if we have 
> nothing to substitute.




Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-04-18 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov updated this revision to Diff 514745.
alexander-shaposhnikov added a comment.

New version (address some comments)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

Files:
  clang/include/clang/Sema/Template.h
  clang/lib/Sema/SemaConcept.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/SemaTemplateDeduction.cpp
  clang/lib/Sema/SemaTemplateInstantiate.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/SemaTemplate/concepts-out-of-line-def.cpp
  clang/test/SemaTemplate/concepts.cpp

Index: clang/test/SemaTemplate/concepts.cpp
===
--- clang/test/SemaTemplate/concepts.cpp
+++ clang/test/SemaTemplate/concepts.cpp
@@ -816,3 +816,62 @@
 static_assert(Parent::TakesBinary::i == 0);
 }
 
+namespace TemplateInsideNonTemplateClass {
+template concept C = true;
+
+template auto L = [] U>() {};
+
+struct Q {
+  template U> friend constexpr auto decltype(L)::operator()() const;
+};
+} // namespace TemplateInsideNonTemplateClass
+
+namespace GH61959 {
+template 
+concept C = (sizeof(T0) >= 4);
+
+template
+struct Orig { };
+
+template
+struct Orig {
+  template requires C
+  void f() { }
+
+  template requires true
+  void f() { }
+};
+
+template  struct Mod {};
+
+template 
+struct Mod {
+  template  requires C
+  constexpr static int f() { return 1; }
+
+  template  requires C
+  constexpr static int f() { return 2; }
+};
+
+static_assert(Mod::f() == 1);
+static_assert(Mod::f() == 2);
+
+template
+struct Outer {
+  template
+  struct Inner {};
+
+  template
+  struct Inner {
+template
+void foo()  requires C && C && C{}
+template
+void foo()  requires true{}
+  };
+};
+
+void bar() {
+  Outer::Inner I;
+  I.foo();
+}
+}
Index: clang/test/SemaTemplate/concepts-out-of-line-def.cpp
===
--- clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -127,3 +127,220 @@
 static_assert(S::specialization("str") == SPECIALIZATION_REQUIRES);
 
 } // namespace multiple_template_parameter_lists
+
+static constexpr int CONSTRAINED_METHOD_1 = 1;
+static constexpr int CONSTRAINED_METHOD_2 = 2;
+
+namespace constrained_members {
+
+template 
+struct S {
+  template 
+  static constexpr int constrained_method();
+};
+
+template <>
+template 
+constexpr int S<1>::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  template T4>
+  static constexpr int constrained_method();
+};
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained members
+
+namespace constrained_members_of_nested_types {
+
+template 
+struct S {
+  struct Inner0 {
+struct Inner1 {
+  template 
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template <>
+template 
+constexpr int S<1>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  struct Inner0 {
+struct Inner1 {
+  template T4>
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained_members_of_nested_types
+
+namespace constrained_member_sfinae {
+
+template struct S {
+  template
+  static constexpr int constrained_method() requires (sizeof(int[N * 1073741824 + 4]) == 16) {
+return CONSTRAINED_METHOD_1;
+  }
+
+  template
+  static constexpr int constrained_method() requires (sizeof(int[N]) == 16);
+};
+
+template<>
+template
+constexpr int S<4>::constrained_method() requires (sizeof(int[4]) == 16) {
+  return 

[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-04-17 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added inline comments.



Comment at: clang/lib/Sema/SemaConcept.cpp:263
 
+  if (SubstitutedAtomicExpr.get()->isValueDependent())
+return SubstitutedAtomicExpr;

alexander-shaposhnikov wrote:
> erichkeane wrote:
> > alexander-shaposhnikov wrote:
> > > erichkeane wrote:
> > > > alexander-shaposhnikov wrote:
> > > > > erichkeane wrote:
> > > > > > So this bit is concerning to me... we have been catching a ton of 
> > > > > > bugs in the MLTAL stuff by trying to constant evaluate an 
> > > > > > expression that isn't correctly constexpr, and this will defeat it. 
> > > > > >  We shouldn't be calling this function at all on 
> > > > > > non-fully-instantiated expressions.  What is the case that ends up 
> > > > > > coming through here, and should be be calling this at all?
> > > > > This happens e.g. for concepts-PR54629.cpp
> > > > > 
> > > > > ```
> > > > > Old:
> > > > > FunctionDecl 0x64d90378 
> > > > > llvm-project/clang/test/SemaTemplate/concepts-PR54629.cpp:30:1, 
> > > > > line:32:2> line:30:6 foo 'void ()'
> > > > > |-RequiresExpr 0x64d90318  'bool'
> > > > > | |-ParmVarDecl 0x64d90150  col:24 referenced t 
> > > > > 'T &'
> > > > > | `-NestedRequirement 0x64d902d8 dependent
> > > > > |   `-BinaryOperator 0x64d902b8  'bool' '<'
> > > > > | |-UnaryExprOrTypeTraitExpr 0x64d90260  
> > > > > 'unsigned long' sizeof
> > > > > | | `-ParenExpr 0x64d90240  'T' lvalue
> > > > > | |   `-DeclRefExpr 0x64d90220  'T' lvalue ParmVar 
> > > > > 0x64d90150 't' 'T &' non_odr_use_unevaluated
> > > > > | `-ImplicitCastExpr 0x64d902a0  'unsigned long' 
> > > > > 
> > > > > |   `-IntegerLiteral 0x64d90280  'int' 4
> > > > > `-CompoundStmt 0x64d90f70 
> > > > > 
> > > > > while MLTAL is empty.
> > > > > ```
> > > > > (clang::Sema::CheckOverload calls clang::Sema::IsOverload, while 
> > > > > clang::Sema::IsOverload invokes 
> > > > > clang::Sema::AreConstraintExpressionsEqual)
> > > > Hmm that seems wrong for me, but I'm not sure how.  It doesn't seem 
> > > > right for `AreConstraintExpressionsEqual`to try to calculate the 
> > > > constraint satisfaction...
> > > I think we get there from 
> > > https://github.com/llvm/llvm-project/blob/main/clang/lib/Sema/SemaTemplateInstantiate.cpp#L2375
> > So I still think this is an incorrect change.  I don't understand why we'd 
> > get here without the 'final' check, but perhaps there is something missing 
> > elsewhere?
> unfortunately, I don't have enough context - will revisit this change (iirc 
> one test was failing without it and Clang was calling 
> CheckConstraintSatisfaction from an unexpected place). There is some 
> accumulated technical debt (without the current diff) / it takes to untangle. 
>  
reduced test case (extracted from concepts-PR54629.cpp):

```
template 
void foo()
  requires requires(T ) { requires sizeof(t) < 4; }
{}

template 
void foo()
  requires requires(T ) { requires sizeof(t) > 4; }
{}

void test() {
  foo();
}
```


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-04-17 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added inline comments.



Comment at: clang/lib/Sema/SemaConcept.cpp:263
 
+  if (SubstitutedAtomicExpr.get()->isValueDependent())
+return SubstitutedAtomicExpr;

erichkeane wrote:
> alexander-shaposhnikov wrote:
> > erichkeane wrote:
> > > alexander-shaposhnikov wrote:
> > > > erichkeane wrote:
> > > > > So this bit is concerning to me... we have been catching a ton of 
> > > > > bugs in the MLTAL stuff by trying to constant evaluate an expression 
> > > > > that isn't correctly constexpr, and this will defeat it.  We 
> > > > > shouldn't be calling this function at all on non-fully-instantiated 
> > > > > expressions.  What is the case that ends up coming through here, and 
> > > > > should be be calling this at all?
> > > > This happens e.g. for concepts-PR54629.cpp
> > > > 
> > > > ```
> > > > Old:
> > > > FunctionDecl 0x64d90378 
> > > > llvm-project/clang/test/SemaTemplate/concepts-PR54629.cpp:30:1, 
> > > > line:32:2> line:30:6 foo 'void ()'
> > > > |-RequiresExpr 0x64d90318  'bool'
> > > > | |-ParmVarDecl 0x64d90150  col:24 referenced t 'T 
> > > > &'
> > > > | `-NestedRequirement 0x64d902d8 dependent
> > > > |   `-BinaryOperator 0x64d902b8  'bool' '<'
> > > > | |-UnaryExprOrTypeTraitExpr 0x64d90260  
> > > > 'unsigned long' sizeof
> > > > | | `-ParenExpr 0x64d90240  'T' lvalue
> > > > | |   `-DeclRefExpr 0x64d90220  'T' lvalue ParmVar 
> > > > 0x64d90150 't' 'T &' non_odr_use_unevaluated
> > > > | `-ImplicitCastExpr 0x64d902a0  'unsigned long' 
> > > > 
> > > > |   `-IntegerLiteral 0x64d90280  'int' 4
> > > > `-CompoundStmt 0x64d90f70 
> > > > 
> > > > while MLTAL is empty.
> > > > ```
> > > > (clang::Sema::CheckOverload calls clang::Sema::IsOverload, while 
> > > > clang::Sema::IsOverload invokes 
> > > > clang::Sema::AreConstraintExpressionsEqual)
> > > Hmm that seems wrong for me, but I'm not sure how.  It doesn't seem 
> > > right for `AreConstraintExpressionsEqual`to try to calculate the 
> > > constraint satisfaction...
> > I think we get there from 
> > https://github.com/llvm/llvm-project/blob/main/clang/lib/Sema/SemaTemplateInstantiate.cpp#L2375
> So I still think this is an incorrect change.  I don't understand why we'd 
> get here without the 'final' check, but perhaps there is something missing 
> elsewhere?
unfortunately, I don't have enough context - will revisit this change (iirc one 
test was failing without it and Clang was calling CheckConstraintSatisfaction 
from an unexpected place). There is some accumulated technical debt (without 
the current diff) / it takes to untangle.  


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-04-17 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added inline comments.



Comment at: clang/lib/Sema/SemaTemplateInstantiate.cpp:227
+(TSTy = Ty->getAs()))
+  Result.addOuterTemplateArguments(const_cast(FTD),
+   TSTy->template_arguments(),

erichkeane wrote:
> So I'd come up with something similar, but this ends up being a little goofy? 
>  And I thought it didn't really work in 1 of the cases.  I wonder if we're 
> better off looking at the decl contexts to try to figure out WHICH of the 
> cases we are, and just set the next decl context based on that?
sure, we can try. In the meantime - regarding GH62110 - do you happen to have 
any thoughts on that ?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-04-16 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added a comment.

https://github.com/llvm/llvm-project/issues/62110 is still a blocker for this 
diff though (haven't investigated it yet)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-04-16 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov updated this revision to Diff 514095.

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

Files:
  clang/include/clang/Sema/Template.h
  clang/lib/Sema/SemaConcept.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/SemaTemplateDeduction.cpp
  clang/lib/Sema/SemaTemplateInstantiate.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/SemaTemplate/concepts-out-of-line-def.cpp
  clang/test/SemaTemplate/concepts.cpp

Index: clang/test/SemaTemplate/concepts.cpp
===
--- clang/test/SemaTemplate/concepts.cpp
+++ clang/test/SemaTemplate/concepts.cpp
@@ -816,3 +816,62 @@
 static_assert(Parent::TakesBinary::i == 0);
 }
 
+namespace TemplateInsideNonTemplateClass {
+template concept C = true;
+
+template auto L = [] U>() {};
+
+struct Q {
+  template U> friend constexpr auto decltype(L)::operator()() const;
+};
+} // namespace TemplateInsideNonTemplateClass
+
+namespace GH61959 {
+template 
+concept C = (sizeof(T0) >= 4);
+
+template
+struct Orig { };
+
+template
+struct Orig {
+  template requires C
+  void f() { }
+
+  template requires true
+  void f() { }
+};
+
+template  struct Mod {};
+
+template 
+struct Mod {
+  template  requires C
+  constexpr static int f() { return 1; }
+
+  template  requires C
+  constexpr static int f() { return 2; }
+};
+
+static_assert(Mod::f() == 1);
+static_assert(Mod::f() == 2);
+
+template
+struct Outer {
+  template
+  struct Inner {};
+
+  template
+  struct Inner {
+template
+void foo()  requires C && C && C{}
+template
+void foo()  requires true{}
+  };
+};
+
+void bar() {
+  Outer::Inner I;
+  I.foo();
+}
+}
Index: clang/test/SemaTemplate/concepts-out-of-line-def.cpp
===
--- clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -127,3 +127,220 @@
 static_assert(S::specialization("str") == SPECIALIZATION_REQUIRES);
 
 } // namespace multiple_template_parameter_lists
+
+static constexpr int CONSTRAINED_METHOD_1 = 1;
+static constexpr int CONSTRAINED_METHOD_2 = 2;
+
+namespace constrained_members {
+
+template 
+struct S {
+  template 
+  static constexpr int constrained_method();
+};
+
+template <>
+template 
+constexpr int S<1>::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  template T4>
+  static constexpr int constrained_method();
+};
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained members
+
+namespace constrained_members_of_nested_types {
+
+template 
+struct S {
+  struct Inner0 {
+struct Inner1 {
+  template 
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template <>
+template 
+constexpr int S<1>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  struct Inner0 {
+struct Inner1 {
+  template T4>
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained_members_of_nested_types
+
+namespace constrained_member_sfinae {
+
+template struct S {
+  template
+  static constexpr int constrained_method() requires (sizeof(int[N * 1073741824 + 4]) == 16) {
+return CONSTRAINED_METHOD_1;
+  }
+
+  template
+  static constexpr int constrained_method() requires (sizeof(int[N]) == 16);
+};
+
+template<>
+template
+constexpr int S<4>::constrained_method() requires (sizeof(int[4]) == 16) {
+  return CONSTRAINED_METHOD_2;
+}
+
+// Verify that there is no amiguity in this case.

[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-04-13 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov planned changes to this revision.
alexander-shaposhnikov added inline comments.



Comment at: clang/lib/Sema/SemaConcept.cpp:773
+  // ConstrExpr for the inner template will properly adjust the depths.
+  if (isa(ND) && isa(OtherND))
+ForConstraintInstantiation = true;

erichkeane wrote:
> erichkeane wrote:
> > erichkeane wrote:
> > > alexander-shaposhnikov wrote:
> > > > erichkeane wrote:
> > > > > alexander-shaposhnikov wrote:
> > > > > > erichkeane wrote:
> > > > > > > alexander-shaposhnikov wrote:
> > > > > > > > erichkeane wrote:
> > > > > > > > > Hmm... this seems really strange to have to do. 
> > > > > > > > > `ForConstraintInstantiation` shouldn't be used here, the 
> > > > > > > > > point of that is to make sure we 'keep looking upward' once 
> > > > > > > > > we hit a spot we normally stop with.  What exactly is the 
> > > > > > > > > issue that you end up running into here?  Perhaps I can spend 
> > > > > > > > > some time debugging what we should really be doign.
> > > > > > > > yeah, I agree. I haven't found a proper solution or at least a 
> > > > > > > > better workaround (but would be happy to).
> > > > > > > > This kicks in for the case 
> > > > > > > > 
> > > > > > > > ```
> > > > > > > > template 
> > > > > > > > concept Constraint = true;
> > > > > > > > 
> > > > > > > > 
> > > > > > > > template
> > > > > > > > struct Iterator {
> > > > > > > > template 
> > > > > > > > friend class Iterator;
> > > > > > > > void operator*();
> > > > > > > > };
> > > > > > > > 
> > > > > > > > Iterator I2;
> > > > > > > > ```
> > > > > > > > yeah, I agree. I haven't found a proper solution or at least a 
> > > > > > > > better workaround (but would be happy to).
> > > > > > > > This kicks in for the case 
> > > > > > > > 
> > > > > > > > ```
> > > > > > > > template 
> > > > > > > > concept Constraint = true;
> > > > > > > > 
> > > > > > > > 
> > > > > > > > template
> > > > > > > > struct Iterator {
> > > > > > > > template 
> > > > > > > > friend class Iterator;
> > > > > > > > void operator*();
> > > > > > > > };
> > > > > > > > 
> > > > > > > > Iterator I2;
> > > > > > > > ```
> > > > > > > 
> > > > > > > Alright, well, I should have time later in the week to poke at 
> > > > > > > this, perhaps I can come up with something better?  I DO remember 
> > > > > > > self-friend is a little wacky, and I spent a bunch of time on it 
> > > > > > > last time.
> > > > > > Ok, sounds good + maybe Richard will give it another look.
> > > > > So IMO, `ForConstraintInstantiation` should be 'true' always, and 
> > > > > that makes those examples pass.  However, I'm now seeing that it 
> > > > > causes a failure in the concepts-out-of-line-def.cpp file.  
> > > > > 
> > > > > I took the example of `foo3`:
> > > > > 
> > > > > ```
> > > > >template concept C = true;
> > > > >template 
> > > > >struct S {
> > > > >  template  requires C
> > > > >  void foo3(F3 f); // #1
> > > > >};
> > > > >template 
> > > > >template  requires C
> > > > >void S::foo3(F6 f) {} // #3
> > > > > ```
> > > > > 
> > > > > Which, seems to require `ForConstraintInstantiation` to be false to 
> > > > > pass.  However, I don't think this is correct.  This is only working 
> > > > > because when evaluating the in-line one (#1 above!) its skipping the 
> > > > > application of `T1`, which is wrong.  
> > > > > 
> > > > > However, I think the problem here is that the `out of line` version 
> > > > > (#3) is not applying the T4 like it should be. SO, I think the 
> > > > > `HandleFunctionTemplateDecl` I provided you earlier needs 
> > > > > modification.
> > > > > 
> > > > > FIRST, though not related to this, I think we might need to add 
> > > > > `FunctionTemplateDecl::getInjectedTemplateArgs` to the `Result`, but 
> > > > > only because that 'sounds right' to me?  IDK what other problem that 
> > > > > would cause, but it is worth evaluating/saving for later.  It might 
> > > > > just not matter, since we're treating them as equal at the moment, I 
> > > > > don't think injecting them would cause anything.
> > > > > 
> > > > > Secondly: I see that the we can get to the `T4` via the 
> > > > > `FTD->getTemplatedDecl()->getQualifier()->getAsType()->getAs()->template_arguments()`.
> > > > >   
> > > > > 
> > > > > HOWEVER, the problem that comes with picking THOSE up, is that it 
> > > > > ALSO applies with a `FunctionTemplateDecl` inside of an out-of-line 
> > > > > `ClassTemplateSpecializationDecl` (which doesn't NEED the 
> > > > > specialization's template args).  
> > > > > 
> > > > > SO I think the fix here is something in `HandleFunctionTemplateDecl` 
> > > > > to make sure we pick up the right list of template arguments.  I 
> > > > > haven't figured out the magic incantation to make it work 
> > > > > unfortunately, perhaps @rsmith has some hints?  Else I'll keep poking 
> > > > > at it.
> > > > > 
> > > > > BUT, my 

[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-04-13 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added inline comments.



Comment at: clang/lib/Sema/SemaConcept.cpp:773
+  // ConstrExpr for the inner template will properly adjust the depths.
+  if (isa(ND) && isa(OtherND))
+ForConstraintInstantiation = true;

erichkeane wrote:
> alexander-shaposhnikov wrote:
> > erichkeane wrote:
> > > alexander-shaposhnikov wrote:
> > > > erichkeane wrote:
> > > > > Hmm... this seems really strange to have to do. 
> > > > > `ForConstraintInstantiation` shouldn't be used here, the point of 
> > > > > that is to make sure we 'keep looking upward' once we hit a spot we 
> > > > > normally stop with.  What exactly is the issue that you end up 
> > > > > running into here?  Perhaps I can spend some time debugging what we 
> > > > > should really be doign.
> > > > yeah, I agree. I haven't found a proper solution or at least a better 
> > > > workaround (but would be happy to).
> > > > This kicks in for the case 
> > > > 
> > > > ```
> > > > template 
> > > > concept Constraint = true;
> > > > 
> > > > 
> > > > template
> > > > struct Iterator {
> > > > template 
> > > > friend class Iterator;
> > > > void operator*();
> > > > };
> > > > 
> > > > Iterator I2;
> > > > ```
> > > > yeah, I agree. I haven't found a proper solution or at least a better 
> > > > workaround (but would be happy to).
> > > > This kicks in for the case 
> > > > 
> > > > ```
> > > > template 
> > > > concept Constraint = true;
> > > > 
> > > > 
> > > > template
> > > > struct Iterator {
> > > > template 
> > > > friend class Iterator;
> > > > void operator*();
> > > > };
> > > > 
> > > > Iterator I2;
> > > > ```
> > > 
> > > Alright, well, I should have time later in the week to poke at this, 
> > > perhaps I can come up with something better?  I DO remember self-friend 
> > > is a little wacky, and I spent a bunch of time on it last time.
> > Ok, sounds good + maybe Richard will give it another look.
> So IMO, `ForConstraintInstantiation` should be 'true' always, and that makes 
> those examples pass.  However, I'm now seeing that it causes a failure in the 
> concepts-out-of-line-def.cpp file.  
> 
> I took the example of `foo3`:
> 
> ```
>template concept C = true;
>template 
>struct S {
>  template  requires C
>  void foo3(F3 f); // #1
>};
>template 
>template  requires C
>void S::foo3(F6 f) {} // #3
> ```
> 
> Which, seems to require `ForConstraintInstantiation` to be false to pass.  
> However, I don't think this is correct.  This is only working because when 
> evaluating the in-line one (#1 above!) its skipping the application of `T1`, 
> which is wrong.  
> 
> However, I think the problem here is that the `out of line` version (#3) is 
> not applying the T4 like it should be. SO, I think the 
> `HandleFunctionTemplateDecl` I provided you earlier needs modification.
> 
> FIRST, though not related to this, I think we might need to add 
> `FunctionTemplateDecl::getInjectedTemplateArgs` to the `Result`, but only 
> because that 'sounds right' to me?  IDK what other problem that would cause, 
> but it is worth evaluating/saving for later.  It might just not matter, since 
> we're treating them as equal at the moment, I don't think injecting them 
> would cause anything.
> 
> Secondly: I see that the we can get to the `T4` via the 
> `FTD->getTemplatedDecl()->getQualifier()->getAsType()->getAs()->template_arguments()`.
>   
> 
> HOWEVER, the problem that comes with picking THOSE up, is that it ALSO 
> applies with a `FunctionTemplateDecl` inside of an out-of-line 
> `ClassTemplateSpecializationDecl` (which doesn't NEED the specialization's 
> template args).  
> 
> SO I think the fix here is something in `HandleFunctionTemplateDecl` to make 
> sure we pick up the right list of template arguments.  I haven't figured out 
> the magic incantation to make it work unfortunately, perhaps @rsmith has some 
> hints?  Else I'll keep poking at it.
> 
> BUT, my debugging has shown me that I'm quite convinced the setting 
> `ForConstraintInstantiation ` to false is incorrect.
p.s. Richard is on vacation.

to quote his comment above (where the story began):

>The right way to fix that and the issue being addressed here is that, rather 
>than adjusting the depths, we ?>should substitute the outer template arguments 
>from the scope specifier (A::) into the constraint before >performing the 
>comparison. (In the special case where none of the outer template parameters 
>are used by the >inner template, that does effectively just adjust the depths 
>of any inner template parameters.)

A. the formal meaning of ForConstraintInstantiation=true/false is unclear, 
@eirchkean - if you happen to understand it - mind expanding the comment a bit 
? (and we can add this to the documentation)

B.  T1 - maybe it should be collected as a retained layer ? 



Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  

[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-04-12 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added a comment.

https://github.com/llvm/llvm-project/issues/62110 (in addition to the 
self-friendship case)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-04-10 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added inline comments.



Comment at: clang/lib/Sema/SemaConcept.cpp:263
 
+  if (SubstitutedAtomicExpr.get()->isValueDependent())
+return SubstitutedAtomicExpr;

erichkeane wrote:
> alexander-shaposhnikov wrote:
> > erichkeane wrote:
> > > So this bit is concerning to me... we have been catching a ton of bugs in 
> > > the MLTAL stuff by trying to constant evaluate an expression that isn't 
> > > correctly constexpr, and this will defeat it.  We shouldn't be calling 
> > > this function at all on non-fully-instantiated expressions.  What is the 
> > > case that ends up coming through here, and should be be calling this at 
> > > all?
> > This happens e.g. for concepts-PR54629.cpp
> > 
> > ```
> > Old:
> > FunctionDecl 0x64d90378 
> > llvm-project/clang/test/SemaTemplate/concepts-PR54629.cpp:30:1, line:32:2> 
> > line:30:6 foo 'void ()'
> > |-RequiresExpr 0x64d90318  'bool'
> > | |-ParmVarDecl 0x64d90150  col:24 referenced t 'T &'
> > | `-NestedRequirement 0x64d902d8 dependent
> > |   `-BinaryOperator 0x64d902b8  'bool' '<'
> > | |-UnaryExprOrTypeTraitExpr 0x64d90260  'unsigned 
> > long' sizeof
> > | | `-ParenExpr 0x64d90240  'T' lvalue
> > | |   `-DeclRefExpr 0x64d90220  'T' lvalue ParmVar 
> > 0x64d90150 't' 'T &' non_odr_use_unevaluated
> > | `-ImplicitCastExpr 0x64d902a0  'unsigned long' 
> > 
> > |   `-IntegerLiteral 0x64d90280  'int' 4
> > `-CompoundStmt 0x64d90f70 
> > 
> > while MLTAL is empty.
> > ```
> > (clang::Sema::CheckOverload calls clang::Sema::IsOverload, while 
> > clang::Sema::IsOverload invokes clang::Sema::AreConstraintExpressionsEqual)
> Hmm that seems wrong for me, but I'm not sure how.  It doesn't seem right 
> for `AreConstraintExpressionsEqual`to try to calculate the constraint 
> satisfaction...
I think we get there from 
https://github.com/llvm/llvm-project/blob/main/clang/lib/Sema/SemaTemplateInstantiate.cpp#L2375


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-04-10 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added inline comments.



Comment at: clang/lib/Sema/SemaConcept.cpp:773
+  // ConstrExpr for the inner template will properly adjust the depths.
+  if (isa(ND) && isa(OtherND))
+ForConstraintInstantiation = true;

erichkeane wrote:
> alexander-shaposhnikov wrote:
> > erichkeane wrote:
> > > Hmm... this seems really strange to have to do. 
> > > `ForConstraintInstantiation` shouldn't be used here, the point of that is 
> > > to make sure we 'keep looking upward' once we hit a spot we normally stop 
> > > with.  What exactly is the issue that you end up running into here?  
> > > Perhaps I can spend some time debugging what we should really be doign.
> > yeah, I agree. I haven't found a proper solution or at least a better 
> > workaround (but would be happy to).
> > This kicks in for the case 
> > 
> > ```
> > template 
> > concept Constraint = true;
> > 
> > 
> > template
> > struct Iterator {
> > template 
> > friend class Iterator;
> > void operator*();
> > };
> > 
> > Iterator I2;
> > ```
> > yeah, I agree. I haven't found a proper solution or at least a better 
> > workaround (but would be happy to).
> > This kicks in for the case 
> > 
> > ```
> > template 
> > concept Constraint = true;
> > 
> > 
> > template
> > struct Iterator {
> > template 
> > friend class Iterator;
> > void operator*();
> > };
> > 
> > Iterator I2;
> > ```
> 
> Alright, well, I should have time later in the week to poke at this, perhaps 
> I can come up with something better?  I DO remember self-friend is a little 
> wacky, and I spent a bunch of time on it last time.
Ok, sounds good + maybe Richard will give it another look.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-04-10 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added inline comments.



Comment at: clang/lib/Sema/SemaConcept.cpp:773
+  // ConstrExpr for the inner template will properly adjust the depths.
+  if (isa(ND) && isa(OtherND))
+ForConstraintInstantiation = true;

erichkeane wrote:
> Hmm... this seems really strange to have to do. `ForConstraintInstantiation` 
> shouldn't be used here, the point of that is to make sure we 'keep looking 
> upward' once we hit a spot we normally stop with.  What exactly is the issue 
> that you end up running into here?  Perhaps I can spend some time debugging 
> what we should really be doign.
yeah, I agree. I haven't found a proper solution or at least a better 
workaround (but would be happy to).
This kicks in for the case 

```
template 
concept Constraint = true;


template
struct Iterator {
template 
friend class Iterator;
void operator*();
};

Iterator I2;
```


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-04-10 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added inline comments.



Comment at: clang/lib/Sema/SemaConcept.cpp:263
 
+  if (SubstitutedAtomicExpr.get()->isValueDependent())
+return SubstitutedAtomicExpr;

erichkeane wrote:
> So this bit is concerning to me... we have been catching a ton of bugs in the 
> MLTAL stuff by trying to constant evaluate an expression that isn't correctly 
> constexpr, and this will defeat it.  We shouldn't be calling this function at 
> all on non-fully-instantiated expressions.  What is the case that ends up 
> coming through here, and should be be calling this at all?
This happens e.g. for concepts-PR54629.cpp

```
Old:
FunctionDecl 0x64d90378 
llvm-project/clang/test/SemaTemplate/concepts-PR54629.cpp:30:1, line:32:2> 
line:30:6 foo 'void ()'
|-RequiresExpr 0x64d90318  'bool'
| |-ParmVarDecl 0x64d90150  col:24 referenced t 'T &'
| `-NestedRequirement 0x64d902d8 dependent
|   `-BinaryOperator 0x64d902b8  'bool' '<'
| |-UnaryExprOrTypeTraitExpr 0x64d90260  'unsigned 
long' sizeof
| | `-ParenExpr 0x64d90240  'T' lvalue
| |   `-DeclRefExpr 0x64d90220  'T' lvalue ParmVar 
0x64d90150 't' 'T &' non_odr_use_unevaluated
| `-ImplicitCastExpr 0x64d902a0  'unsigned long' 
|   `-IntegerLiteral 0x64d90280  'int' 4
`-CompoundStmt 0x64d90f70 

while MLTAL is empty.
```
(clang::Sema::CheckOverload calls clang::Sema::IsOverload, while 
clang::Sema::IsOverload invokes clang::Sema::AreConstraintExpressionsEqual)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-04-08 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov updated this revision to Diff 511854.
alexander-shaposhnikov added a comment.

This version is partially based on https://reviews.llvm.org/D147722.
The case with self-friendship is problematic (had to add a workaround, any 
suggestions would be greatly appreciated).
Added more tests.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

Files:
  clang/include/clang/Sema/Template.h
  clang/lib/Sema/SemaConcept.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/SemaTemplateDeduction.cpp
  clang/lib/Sema/SemaTemplateInstantiate.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/SemaTemplate/concepts-out-of-line-def.cpp
  clang/test/SemaTemplate/concepts.cpp

Index: clang/test/SemaTemplate/concepts.cpp
===
--- clang/test/SemaTemplate/concepts.cpp
+++ clang/test/SemaTemplate/concepts.cpp
@@ -816,3 +816,62 @@
 static_assert(Parent::TakesBinary::i == 0);
 }
 
+namespace TemplateInsideNonTemplateClass {
+template concept C = true;
+
+template auto L = [] U>() {};
+
+struct Q {
+  template U> friend constexpr auto decltype(L)::operator()() const;
+};
+} // namespace TemplateInsideNonTemplateClass
+
+namespace GH61959 {
+template 
+concept C = (sizeof(T0) >= 4);
+
+template
+struct Orig { };
+
+template
+struct Orig {
+  template requires C
+  void f() { }
+
+  template requires true
+  void f() { }
+};
+
+template  struct Mod {};
+
+template 
+struct Mod {
+  template  requires C
+  constexpr static int f() { return 1; }
+
+  template  requires C
+  constexpr static int f() { return 2; }
+};
+
+static_assert(Mod::f() == 1);
+static_assert(Mod::f() == 2);
+
+template
+struct Outer {
+  template
+  struct Inner {};
+
+  template
+  struct Inner {
+template
+void foo()  requires C && C && C{}
+template
+void foo()  requires true{}
+  };
+};
+
+void bar() {
+  Outer::Inner I;
+  I.foo();
+}
+}
Index: clang/test/SemaTemplate/concepts-out-of-line-def.cpp
===
--- clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -127,3 +127,220 @@
 static_assert(S::specialization("str") == SPECIALIZATION_REQUIRES);
 
 } // namespace multiple_template_parameter_lists
+
+static constexpr int CONSTRAINED_METHOD_1 = 1;
+static constexpr int CONSTRAINED_METHOD_2 = 2;
+
+namespace constrained_members {
+
+template 
+struct S {
+  template 
+  static constexpr int constrained_method();
+};
+
+template <>
+template 
+constexpr int S<1>::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  template T4>
+  static constexpr int constrained_method();
+};
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained members
+
+namespace constrained_members_of_nested_types {
+
+template 
+struct S {
+  struct Inner0 {
+struct Inner1 {
+  template 
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template <>
+template 
+constexpr int S<1>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  struct Inner0 {
+struct Inner1 {
+  template T4>
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained_members_of_nested_types
+
+namespace constrained_member_sfinae {
+
+template struct S {
+  template
+  static constexpr int constrained_method() requires (sizeof(int[N * 1073741824 + 4]) == 16) {
+return CONSTRAINED_METHOD_1;
+  }
+
+  template
+  static constexpr int 

[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-04-07 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added a comment.

I've debugged a bit what's going on in https://godbolt.org/z/7h3sPe85h
we pass ForConstaintInstantiation=true and this causes 
us for the in-class FunctionTemplateDecl pick up the outer layer of template 
args (i.e. MLTAL will contain NumRetainedOuterLevels: 0 0: ), while for the 
out-of-line FunctionTemplateDecl MLTAL is empty. This breaks the comparison 
(after the substitution) since Clang thinks that it's removing one layer of 
template args. For example, if we pass ForConstaintInstantiation=true the code 
will compile.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D147744: [clang][Sema] Add MultiLevelTemplateArgumentList::dump()

2023-04-07 Thread Alexander Shaposhnikov 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 rGf799901c06c0: [Clang][Sema] Add 
MultiLevelTemplateArgumentList::dump (authored by alexander-shaposhnikov).

Changed prior to commit:
  https://reviews.llvm.org/D147744?vs=511551=511775#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D147744

Files:
  clang/include/clang/Sema/Template.h


Index: clang/include/clang/Sema/Template.h
===
--- clang/include/clang/Sema/Template.h
+++ clang/include/clang/Sema/Template.h
@@ -261,6 +261,23 @@
 }
 ArgListsIterator end() { return TemplateArgumentLists.end(); }
 ConstArgListsIterator end() const { return TemplateArgumentLists.end(); }
+
+LLVM_DUMP_METHOD void dump() const {
+  LangOptions LO;
+  LO.CPlusPlus = true;
+  LO.Bool = true;
+  PrintingPolicy PP(LO);
+  llvm::errs() << "NumRetainedOuterLevels: " << NumRetainedOuterLevels
+   << "\n";
+  for (unsigned Depth = NumRetainedOuterLevels; Depth < getNumLevels();
+   ++Depth) {
+llvm::errs() << Depth << ": ";
+printTemplateArgumentList(
+llvm::errs(),
+TemplateArgumentLists[getNumLevels() - Depth - 1].Args, PP);
+llvm::errs() << "\n";
+  }
+}
   };
 
   /// The context in which partial ordering of function templates occurs.


Index: clang/include/clang/Sema/Template.h
===
--- clang/include/clang/Sema/Template.h
+++ clang/include/clang/Sema/Template.h
@@ -261,6 +261,23 @@
 }
 ArgListsIterator end() { return TemplateArgumentLists.end(); }
 ConstArgListsIterator end() const { return TemplateArgumentLists.end(); }
+
+LLVM_DUMP_METHOD void dump() const {
+  LangOptions LO;
+  LO.CPlusPlus = true;
+  LO.Bool = true;
+  PrintingPolicy PP(LO);
+  llvm::errs() << "NumRetainedOuterLevels: " << NumRetainedOuterLevels
+   << "\n";
+  for (unsigned Depth = NumRetainedOuterLevels; Depth < getNumLevels();
+   ++Depth) {
+llvm::errs() << Depth << ": ";
+printTemplateArgumentList(
+llvm::errs(),
+TemplateArgumentLists[getNumLevels() - Depth - 1].Args, PP);
+llvm::errs() << "\n";
+  }
+}
   };
 
   /// The context in which partial ordering of function templates occurs.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D147722: [Concepts] Fix Function Template Concepts comparisons

2023-04-06 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added a subscriber: ilya-biryukov.
alexander-shaposhnikov added a comment.

fwiw - I can revert https://reviews.llvm.org/D146178 for now till we fix the 
newly discovered cases (at the moment I'm aware of GH61959 and the one reported 
by @ilya-biryukov. 
Basically let me know what you think - i'm looking into the issue reported by 
Ilya, but it will take time.


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

https://reviews.llvm.org/D147722

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


[PATCH] D147744: [clang][Sema] Add MultiLevelTemplateArgumentList::dump()

2023-04-06 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added a comment.

for

  template 
  struct X {
template 
struct Y {
  int f()
requires(I2 == 1)
  {
return 1;
  }
  int f()
requires(I2 == 2)
  {
return 1;
  }
};
  };

this would print the following:

  NumRetainedOuterLevels: 0
  0: 
  1: 




Comment at: clang/include/clang/Sema/Template.h:271
+  llvm::errs() << "NumRetainedOuterLevels: " << NumRetainedOuterLevels << 
"\n";
+  for (unsigned Depth = NumRetainedOuterLevels; Depth < getNumLevels(); 
++Depth) {
+llvm::errs() << Depth << ": ";

https://github.com/llvm/llvm-project/blob/2279f77d2855d9caa0ece466462d34bcfdf4fb3d/clang/include/clang/Sema/Template.h#L155
 (just in case)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D147744

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


[PATCH] D147744: [clang][Sema] Add MultiLevelTemplateArgumentList::dump()

2023-04-06 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov updated this revision to Diff 511551.
alexander-shaposhnikov added a comment.

Address comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D147744

Files:
  clang/include/clang/Sema/Template.h


Index: clang/include/clang/Sema/Template.h
===
--- clang/include/clang/Sema/Template.h
+++ clang/include/clang/Sema/Template.h
@@ -261,6 +261,19 @@
 }
 ArgListsIterator end() { return TemplateArgumentLists.end(); }
 ConstArgListsIterator end() const { return TemplateArgumentLists.end(); }
+
+LLVM_DUMP_METHOD void dump() const {
+  LangOptions LO;
+  LO.CPlusPlus = true;
+  LO.Bool = true;
+  PrintingPolicy PP(LO);
+  llvm::errs() << "NumRetainedOuterLevels: " << NumRetainedOuterLevels << 
"\n";
+  for (unsigned Depth = NumRetainedOuterLevels; Depth < getNumLevels(); 
++Depth) {
+llvm::errs() << Depth << ": ";
+printTemplateArgumentList(llvm::errs(), 
TemplateArgumentLists[getNumLevels() - Depth - 1].Args, PP);
+llvm::errs() << "\n";
+  }
+}
   };
 
   /// The context in which partial ordering of function templates occurs.


Index: clang/include/clang/Sema/Template.h
===
--- clang/include/clang/Sema/Template.h
+++ clang/include/clang/Sema/Template.h
@@ -261,6 +261,19 @@
 }
 ArgListsIterator end() { return TemplateArgumentLists.end(); }
 ConstArgListsIterator end() const { return TemplateArgumentLists.end(); }
+
+LLVM_DUMP_METHOD void dump() const {
+  LangOptions LO;
+  LO.CPlusPlus = true;
+  LO.Bool = true;
+  PrintingPolicy PP(LO);
+  llvm::errs() << "NumRetainedOuterLevels: " << NumRetainedOuterLevels << "\n";
+  for (unsigned Depth = NumRetainedOuterLevels; Depth < getNumLevels(); ++Depth) {
+llvm::errs() << Depth << ": ";
+printTemplateArgumentList(llvm::errs(), TemplateArgumentLists[getNumLevels() - Depth - 1].Args, PP);
+llvm::errs() << "\n";
+  }
+}
   };
 
   /// The context in which partial ordering of function templates occurs.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D147744: [clang][Sema] Add MultiLevelTemplateArgumentList::dump()

2023-04-06 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov created this revision.
alexander-shaposhnikov added reviewers: erichkeane, rsmith.
alexander-shaposhnikov created this object with visibility "All Users".
Herald added a project: All.
alexander-shaposhnikov requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Add MultiLevelTemplateArgumentList::dump() (similarly to 
TemplateArgument::dump). NFC.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D147744

Files:
  clang/include/clang/Sema/Template.h


Index: clang/include/clang/Sema/Template.h
===
--- clang/include/clang/Sema/Template.h
+++ clang/include/clang/Sema/Template.h
@@ -261,6 +261,17 @@
 }
 ArgListsIterator end() { return TemplateArgumentLists.end(); }
 ConstArgListsIterator end() const { return TemplateArgumentLists.end(); }
+
+LLVM_DUMP_METHOD void dump() const {
+  LangOptions LO;
+  LO.CPlusPlus = true;
+  LO.Bool = true;
+  PrintingPolicy PP(LO);
+  for (const ArgumentListLevel  : TemplateArgumentLists) {
+printTemplateArgumentList(llvm::errs(), ArgListLevel.Args, PP);
+llvm::errs() << "\n";
+  }
+}
   };
 
   /// The context in which partial ordering of function templates occurs.


Index: clang/include/clang/Sema/Template.h
===
--- clang/include/clang/Sema/Template.h
+++ clang/include/clang/Sema/Template.h
@@ -261,6 +261,17 @@
 }
 ArgListsIterator end() { return TemplateArgumentLists.end(); }
 ConstArgListsIterator end() const { return TemplateArgumentLists.end(); }
+
+LLVM_DUMP_METHOD void dump() const {
+  LangOptions LO;
+  LO.CPlusPlus = true;
+  LO.Bool = true;
+  PrintingPolicy PP(LO);
+  for (const ArgumentListLevel  : TemplateArgumentLists) {
+printTemplateArgumentList(llvm::errs(), ArgListLevel.Args, PP);
+llvm::errs() << "\n";
+  }
+}
   };
 
   /// The context in which partial ordering of function templates occurs.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D147722: [Concepts] Fix Function Template Concepts comparisons

2023-04-06 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added inline comments.



Comment at: clang/lib/Sema/SemaTemplateInstantiate.cpp:291
 /// encountering a lambda generic call operator, and continue looking for
 /// arguments on an enclosing class template.
 

/* not directly related to this patch, just one thought while we are here */ 
it would be useful to add missing documentation (comments) for the last 
parameter
(SkipForSpecialization)
p.s. perhaps, expanding the comment (or even adding some examples) would be 
super helpful as well (for future readers)


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

https://reviews.llvm.org/D147722

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-04-03 Thread Alexander Shaposhnikov 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 rG60bee9ff5445: [Clang][Sema] Fix comparison of constraint 
expressions (authored by alexander-shaposhnikov).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

Files:
  clang/lib/Sema/SemaConcept.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/SemaTemplateInstantiate.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/SemaTemplate/concepts-out-of-line-def.cpp
  clang/test/SemaTemplate/concepts.cpp
  clang/www/cxx_status.html

Index: clang/www/cxx_status.html
===
--- clang/www/cxx_status.html
+++ clang/www/cxx_status.html
@@ -947,9 +947,6 @@
   
 https://wg21.link/p1980r0;>P1980R0
   
-   
-https://wg21.link/p2103r0;>P2103R0
-  

 https://wg21.link/p2493r0;>P2493R0
   
@@ -961,6 +958,9 @@
 https://wg21.link/p2113r0;>P2113R0
 Clang 16
   
+  
+https://wg21.link/p2103r0;>P2103R0
+  
 
 
   Range-based for statements with initializer
Index: clang/test/SemaTemplate/concepts.cpp
===
--- clang/test/SemaTemplate/concepts.cpp
+++ clang/test/SemaTemplate/concepts.cpp
@@ -816,3 +816,12 @@
 static_assert(Parent::TakesBinary::i == 0);
 }
 
+namespace TemplateInsideNonTemplateClass {
+template concept C = true;
+
+template auto L = [] U>() {};
+
+struct Q {
+  template U> friend constexpr auto decltype(L)::operator()() const;
+};
+} // namespace TemplateInsideNonTemplateClass
Index: clang/test/SemaTemplate/concepts-out-of-line-def.cpp
===
--- clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -127,3 +127,153 @@
 static_assert(S::specialization("str") == SPECIALIZATION_REQUIRES);
 
 } // namespace multiple_template_parameter_lists
+
+static constexpr int CONSTRAINED_METHOD_1 = 1;
+static constexpr int CONSTRAINED_METHOD_2 = 2;
+
+namespace constrained_members {
+
+template 
+struct S {
+  template 
+  static constexpr int constrained_method();
+};
+
+template <>
+template 
+constexpr int S<1>::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  template T4>
+  static constexpr int constrained_method();
+};
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained members
+
+namespace constrained_members_of_nested_types {
+
+template 
+struct S {
+  struct Inner0 {
+struct Inner1 {
+  template 
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template <>
+template 
+constexpr int S<1>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  struct Inner0 {
+struct Inner1 {
+  template T4>
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained_members_of_nested_types
+
+namespace constrained_member_sfinae {
+
+template struct S {
+  template
+  static constexpr int constrained_method() requires (sizeof(int[N * 1073741824 + 4]) == 16) {
+return CONSTRAINED_METHOD_1;
+  }
+
+  template
+  static constexpr int constrained_method() requires (sizeof(int[N]) == 16);
+};
+
+template<>
+template
+constexpr int S<4>::constrained_method() requires (sizeof(int[4]) == 16) {
+  return CONSTRAINED_METHOD_2;
+}
+
+// Verify that there is no amiguity in this case.

[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-04-03 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov updated this revision to Diff 510662.
alexander-shaposhnikov added a comment.

Add test & minor optimization


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

https://reviews.llvm.org/D146178

Files:
  clang/lib/Sema/SemaConcept.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/SemaTemplateInstantiate.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/SemaTemplate/concepts-out-of-line-def.cpp
  clang/test/SemaTemplate/concepts.cpp
  clang/www/cxx_status.html

Index: clang/www/cxx_status.html
===
--- clang/www/cxx_status.html
+++ clang/www/cxx_status.html
@@ -947,9 +947,6 @@
   
 https://wg21.link/p1980r0;>P1980R0
   
-   
-https://wg21.link/p2103r0;>P2103R0
-  

 https://wg21.link/p2493r0;>P2493R0
   
@@ -961,6 +958,9 @@
 https://wg21.link/p2113r0;>P2113R0
 Clang 16
   
+  
+https://wg21.link/p2103r0;>P2103R0
+  
 
 
   Range-based for statements with initializer
Index: clang/test/SemaTemplate/concepts.cpp
===
--- clang/test/SemaTemplate/concepts.cpp
+++ clang/test/SemaTemplate/concepts.cpp
@@ -816,3 +816,12 @@
 static_assert(Parent::TakesBinary::i == 0);
 }
 
+namespace TemplateInsideNonTemplateClass {
+template concept C = true;
+
+template auto L = [] U>() {};
+
+struct Q {
+  template U> friend constexpr auto decltype(L)::operator()() const;
+};
+} // namespace TemplateInsideNonTemplateClass
Index: clang/test/SemaTemplate/concepts-out-of-line-def.cpp
===
--- clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -127,3 +127,153 @@
 static_assert(S::specialization("str") == SPECIALIZATION_REQUIRES);
 
 } // namespace multiple_template_parameter_lists
+
+static constexpr int CONSTRAINED_METHOD_1 = 1;
+static constexpr int CONSTRAINED_METHOD_2 = 2;
+
+namespace constrained_members {
+
+template 
+struct S {
+  template 
+  static constexpr int constrained_method();
+};
+
+template <>
+template 
+constexpr int S<1>::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  template T4>
+  static constexpr int constrained_method();
+};
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained members
+
+namespace constrained_members_of_nested_types {
+
+template 
+struct S {
+  struct Inner0 {
+struct Inner1 {
+  template 
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template <>
+template 
+constexpr int S<1>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  struct Inner0 {
+struct Inner1 {
+  template T4>
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained_members_of_nested_types
+
+namespace constrained_member_sfinae {
+
+template struct S {
+  template
+  static constexpr int constrained_method() requires (sizeof(int[N * 1073741824 + 4]) == 16) {
+return CONSTRAINED_METHOD_1;
+  }
+
+  template
+  static constexpr int constrained_method() requires (sizeof(int[N]) == 16);
+};
+
+template<>
+template
+constexpr int S<4>::constrained_method() requires (sizeof(int[4]) == 16) {
+  return CONSTRAINED_METHOD_2;
+}
+
+// Verify that there is no amiguity in this case.
+static_assert(S<4>::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained_member_sfinae
+
+namespace requires_expression_references_members {
+
+void 

[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-04-03 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov updated this revision to Diff 510637.

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

Files:
  clang/lib/Sema/SemaConcept.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/SemaTemplateInstantiate.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/SemaTemplate/concepts-out-of-line-def.cpp
  clang/www/cxx_status.html

Index: clang/www/cxx_status.html
===
--- clang/www/cxx_status.html
+++ clang/www/cxx_status.html
@@ -947,9 +947,6 @@
   
 https://wg21.link/p1980r0;>P1980R0
   
-   
-https://wg21.link/p2103r0;>P2103R0
-  

 https://wg21.link/p2493r0;>P2493R0
   
@@ -961,6 +958,9 @@
 https://wg21.link/p2113r0;>P2113R0
 Clang 16
   
+  
+https://wg21.link/p2103r0;>P2103R0
+  
 
 
   Range-based for statements with initializer
Index: clang/test/SemaTemplate/concepts-out-of-line-def.cpp
===
--- clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -127,3 +127,153 @@
 static_assert(S::specialization("str") == SPECIALIZATION_REQUIRES);
 
 } // namespace multiple_template_parameter_lists
+
+static constexpr int CONSTRAINED_METHOD_1 = 1;
+static constexpr int CONSTRAINED_METHOD_2 = 2;
+
+namespace constrained_members {
+
+template 
+struct S {
+  template 
+  static constexpr int constrained_method();
+};
+
+template <>
+template 
+constexpr int S<1>::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  template T4>
+  static constexpr int constrained_method();
+};
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained members
+
+namespace constrained_members_of_nested_types {
+
+template 
+struct S {
+  struct Inner0 {
+struct Inner1 {
+  template 
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template <>
+template 
+constexpr int S<1>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  struct Inner0 {
+struct Inner1 {
+  template T4>
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained_members_of_nested_types
+
+namespace constrained_member_sfinae {
+
+template struct S {
+  template
+  static constexpr int constrained_method() requires (sizeof(int[N * 1073741824 + 4]) == 16) {
+return CONSTRAINED_METHOD_1;
+  }
+
+  template
+  static constexpr int constrained_method() requires (sizeof(int[N]) == 16);
+};
+
+template<>
+template
+constexpr int S<4>::constrained_method() requires (sizeof(int[4]) == 16) {
+  return CONSTRAINED_METHOD_2;
+}
+
+// Verify that there is no amiguity in this case.
+static_assert(S<4>::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained_member_sfinae
+
+namespace requires_expression_references_members {
+
+void accept1(int x);
+void accept2(XY xy);
+
+template  struct S {
+  T Field = T();
+
+  constexpr int constrained_method()
+  requires requires { accept1(Field); };
+
+  constexpr int constrained_method()
+  requires requires { accept2(Field); };
+};
+
+template 
+constexpr int S::constrained_method()
+  requires requires { accept1(Field); } {
+  return CONSTRAINED_METHOD_1;
+}
+
+template 
+constexpr int S::constrained_method()
+  requires requires { accept2(Field); } {
+  return CONSTRAINED_METHOD_2;
+}
+
+static_assert(S().constrained_method() == 

[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-04-03 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov updated this revision to Diff 510634.
alexander-shaposhnikov added a comment.

Address comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

Files:
  clang/lib/Sema/SemaConcept.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/SemaTemplateInstantiate.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/SemaTemplate/concepts-out-of-line-def.cpp

Index: clang/test/SemaTemplate/concepts-out-of-line-def.cpp
===
--- clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -127,3 +127,153 @@
 static_assert(S::specialization("str") == SPECIALIZATION_REQUIRES);
 
 } // namespace multiple_template_parameter_lists
+
+static constexpr int CONSTRAINED_METHOD_1 = 1;
+static constexpr int CONSTRAINED_METHOD_2 = 2;
+
+namespace constrained_members {
+
+template 
+struct S {
+  template 
+  static constexpr int constrained_method();
+};
+
+template <>
+template 
+constexpr int S<1>::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  template T4>
+  static constexpr int constrained_method();
+};
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained members
+
+namespace constrained_members_of_nested_types {
+
+template 
+struct S {
+  struct Inner0 {
+struct Inner1 {
+  template 
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template <>
+template 
+constexpr int S<1>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  struct Inner0 {
+struct Inner1 {
+  template T4>
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained_members_of_nested_types
+
+namespace constrained_member_sfinae {
+
+template struct S {
+  template
+  static constexpr int constrained_method() requires (sizeof(int[N * 1073741824 + 4]) == 16) {
+return CONSTRAINED_METHOD_1;
+  }
+
+  template
+  static constexpr int constrained_method() requires (sizeof(int[N]) == 16);
+};
+
+template<>
+template
+constexpr int S<4>::constrained_method() requires (sizeof(int[4]) == 16) {
+  return CONSTRAINED_METHOD_2;
+}
+
+// Verify that there is no amiguity in this case.
+static_assert(S<4>::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained_member_sfinae
+
+namespace requires_expression_references_members {
+
+void accept1(int x);
+void accept2(XY xy);
+
+template  struct S {
+  T Field = T();
+
+  constexpr int constrained_method()
+  requires requires { accept1(Field); };
+
+  constexpr int constrained_method()
+  requires requires { accept2(Field); };
+};
+
+template 
+constexpr int S::constrained_method()
+  requires requires { accept1(Field); } {
+  return CONSTRAINED_METHOD_1;
+}
+
+template 
+constexpr int S::constrained_method()
+  requires requires { accept2(Field); } {
+  return CONSTRAINED_METHOD_2;
+}
+
+static_assert(S().constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S().constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace requires_expression_references_members
Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1653,33 +1653,12 @@
 << QualifierLoc.getSourceRange();
   return nullptr;
 }
-
-if (PrevClassTemplate) {
-  const ClassTemplateDecl *MostRecentPrevCT =
-  

[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-03-31 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added a comment.

@rsmith - thanks a lot for the review, is there anything you'd like me to do on 
this diff or we are good to go ?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-03-31 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov updated this revision to Diff 509910.
alexander-shaposhnikov added a comment.

Rebased + rerun all the tests + internal testing.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

Files:
  clang/lib/Sema/SemaConcept.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/SemaTemplate/concepts-out-of-line-def.cpp

Index: clang/test/SemaTemplate/concepts-out-of-line-def.cpp
===
--- clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -127,3 +127,153 @@
 static_assert(S::specialization("str") == SPECIALIZATION_REQUIRES);
 
 } // namespace multiple_template_parameter_lists
+
+static constexpr int CONSTRAINED_METHOD_1 = 1;
+static constexpr int CONSTRAINED_METHOD_2 = 2;
+
+namespace constrained_members {
+
+template 
+struct S {
+  template 
+  static constexpr int constrained_method();
+};
+
+template <>
+template 
+constexpr int S<1>::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  template T4>
+  static constexpr int constrained_method();
+};
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained members
+
+namespace constrained_members_of_nested_types {
+
+template 
+struct S {
+  struct Inner0 {
+struct Inner1 {
+  template 
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template <>
+template 
+constexpr int S<1>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  struct Inner0 {
+struct Inner1 {
+  template T4>
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained_members_of_nested_types
+
+namespace constrained_member_sfinae {
+
+template struct S {
+  template
+  static constexpr int constrained_method() requires (sizeof(int[N * 1073741824 + 4]) == 16) {
+return CONSTRAINED_METHOD_1;
+  }
+
+  template
+  static constexpr int constrained_method() requires (sizeof(int[N]) == 16);
+};
+
+template<>
+template
+constexpr int S<4>::constrained_method() requires (sizeof(int[4]) == 16) {
+  return CONSTRAINED_METHOD_2;
+}
+
+// Verify that there is no amiguity in this case.
+static_assert(S<4>::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained_member_sfinae
+
+namespace requires_expression_references_members {
+
+void accept1(int x);
+void accept2(XY xy);
+
+template  struct S {
+  T Field = T();
+
+  constexpr int constrained_method()
+  requires requires { accept1(Field); };
+
+  constexpr int constrained_method()
+  requires requires { accept2(Field); };
+};
+
+template 
+constexpr int S::constrained_method()
+  requires requires { accept1(Field); } {
+  return CONSTRAINED_METHOD_1;
+}
+
+template 
+constexpr int S::constrained_method()
+  requires requires { accept2(Field); } {
+  return CONSTRAINED_METHOD_2;
+}
+
+static_assert(S().constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S().constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace requires_expression_references_members
Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1653,33 +1653,12 @@
 << QualifierLoc.getSourceRange();
   return nullptr;
 }
-
-if (PrevClassTemplate) {
-  const ClassTemplateDecl *MostRecentPrevCT =
-  

[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-03-29 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov updated this revision to Diff 509546.
alexander-shaposhnikov added a comment.

Address comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

Files:
  clang/lib/Sema/SemaConcept.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/SemaTemplate/concepts-out-of-line-def.cpp

Index: clang/test/SemaTemplate/concepts-out-of-line-def.cpp
===
--- clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -127,3 +127,153 @@
 static_assert(S::specialization("str") == SPECIALIZATION_REQUIRES);
 
 } // namespace multiple_template_parameter_lists
+
+static constexpr int CONSTRAINED_METHOD_1 = 1;
+static constexpr int CONSTRAINED_METHOD_2 = 2;
+
+namespace constrained_members {
+
+template 
+struct S {
+  template 
+  static constexpr int constrained_method();
+};
+
+template <>
+template 
+constexpr int S<1>::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  template T4>
+  static constexpr int constrained_method();
+};
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained members
+
+namespace constrained_members_of_nested_types {
+
+template 
+struct S {
+  struct Inner0 {
+struct Inner1 {
+  template 
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template <>
+template 
+constexpr int S<1>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  struct Inner0 {
+struct Inner1 {
+  template T4>
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained_members_of_nested_types
+
+namespace constrained_member_sfinae {
+
+template struct S {
+  template
+  static constexpr int constrained_method() requires (sizeof(int[N * 1073741824 + 4]) == 16) {
+return CONSTRAINED_METHOD_1;
+  }
+
+  template
+  static constexpr int constrained_method() requires (sizeof(int[N]) == 16);
+};
+
+template<>
+template
+constexpr int S<4>::constrained_method() requires (sizeof(int[4]) == 16) {
+  return CONSTRAINED_METHOD_2;
+}
+
+// Verify that there is no amiguity in this case.
+static_assert(S<4>::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained_member_sfinae
+
+namespace requires_expression_references_members {
+
+void accept1(int x);
+void accept2(XY xy);
+
+template  struct S {
+  T Field = T();
+
+  constexpr int constrained_method()
+  requires requires { accept1(Field); };
+
+  constexpr int constrained_method()
+  requires requires { accept2(Field); };
+};
+
+template 
+constexpr int S::constrained_method()
+  requires requires { accept1(Field); } {
+  return CONSTRAINED_METHOD_1;
+}
+
+template 
+constexpr int S::constrained_method()
+  requires requires { accept2(Field); } {
+  return CONSTRAINED_METHOD_2;
+}
+
+static_assert(S().constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S().constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace requires_expression_references_members
Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1653,33 +1653,12 @@
 << QualifierLoc.getSourceRange();
   return nullptr;
 }
-
-if (PrevClassTemplate) {
-  const ClassTemplateDecl *MostRecentPrevCT =
-  PrevClassTemplate->getMostRecentDecl();
-  

[PATCH] D146882: [clang-tidy] Correct union & macros handling in modernize-use-equals-default

2023-03-25 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov accepted this revision.
alexander-shaposhnikov added a comment.
This revision is now accepted and ready to land.

LG


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146882

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-03-22 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov updated this revision to Diff 507560.
alexander-shaposhnikov added a comment.

Add more tests.
P.S. we already have tests with self-friends (in concepts.cpp), the test from 
Richard's comment is also included (struct S12) (in a slightly simplified form)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

Files:
  clang/lib/Sema/SemaConcept.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/SemaTemplate/concepts-out-of-line-def.cpp

Index: clang/test/SemaTemplate/concepts-out-of-line-def.cpp
===
--- clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -127,3 +127,153 @@
 static_assert(S::specialization("str") == SPECIALIZATION_REQUIRES);
 
 } // namespace multiple_template_parameter_lists
+
+static constexpr int CONSTRAINED_METHOD_1 = 1;
+static constexpr int CONSTRAINED_METHOD_2 = 2;
+
+namespace constrained_members {
+
+template 
+struct S {
+  template 
+  static constexpr int constrained_method();
+};
+
+template <>
+template 
+constexpr int S<1>::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  template T4>
+  static constexpr int constrained_method();
+};
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained members
+
+namespace constrained_members_of_nested_types {
+
+template 
+struct S {
+  struct Inner0 {
+struct Inner1 {
+  template 
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template <>
+template 
+constexpr int S<1>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  struct Inner0 {
+struct Inner1 {
+  template T4>
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained_members_of_nested_types
+
+namespace constrained_member_sfinae {
+
+template struct S {
+  template
+  static constexpr int constrained_method() requires (sizeof(int[N * 1073741824 + 4]) == 16) {
+return CONSTRAINED_METHOD_1;
+  }
+
+  template
+  static constexpr int constrained_method() requires (sizeof(int[N]) == 16);
+};
+
+template<>
+template
+constexpr int S<4>::constrained_method() requires (sizeof(int[4]) == 16) {
+  return CONSTRAINED_METHOD_2;
+}
+
+// Verify that there is no amiguity in this case.
+static_assert(S<4>::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained_member_sfinae
+
+namespace requires_expression_references_members {
+
+void accept1(int x);
+void accept2(XY xy);
+
+template  struct S {
+  T Field = T();
+
+  constexpr int constrained_method()
+  requires requires { accept1(Field); };
+
+  constexpr int constrained_method()
+  requires requires { accept2(Field); };
+};
+
+template 
+constexpr int S::constrained_method()
+  requires requires { accept1(Field); } {
+  return CONSTRAINED_METHOD_1;
+}
+
+template 
+constexpr int S::constrained_method()
+  requires requires { accept2(Field); } {
+  return CONSTRAINED_METHOD_2;
+}
+
+static_assert(S().constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S().constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace requires_expression_references_members
Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1653,33 +1653,12 @@
 << QualifierLoc.getSourceRange();
   

[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-03-22 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov planned changes to this revision.
alexander-shaposhnikov added a comment.

will add more tests


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-03-22 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added inline comments.



Comment at: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp:1676
+Inst->setLexicalDeclContext(Owner);
+RecordInst->setLexicalDeclContext(Owner);
+

this bit is important


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-03-22 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added a comment.

@erichkeane - thanks for the comments, the changes in 
SemaTemplateInstantiateDecl.cpp are necessary, in particular, they enable us to 
handle the case

  template 
  concept Constraint = true;
  
  template 
  struct Iterator {
template 
friend class Iterator;
  };
  
  Iterator I;

(and the negative one) 
with the same machinery.
Regarding SFINAE  - it's necessary as well, 
the failed substitution is considered as "not equal" (according to the standard 
(mentioned by Richard above)).


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-03-22 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov updated this revision to Diff 507432.
alexander-shaposhnikov edited the summary of this revision.
alexander-shaposhnikov added a comment.

New approach to constraints' comparison


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

Files:
  clang/lib/Sema/SemaConcept.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/SemaTemplate/concepts-out-of-line-def.cpp

Index: clang/test/SemaTemplate/concepts-out-of-line-def.cpp
===
--- clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -127,3 +127,121 @@
 static_assert(S::specialization("str") == SPECIALIZATION_REQUIRES);
 
 } // namespace multiple_template_parameter_lists
+
+static constexpr int CONSTRAINED_METHOD_1 = 1;
+static constexpr int CONSTRAINED_METHOD_2 = 2;
+
+namespace constrained_members {
+
+template 
+struct S {
+  template 
+  static constexpr int constrained_method();
+};
+
+template <>
+template 
+constexpr int S<1>::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  template T4>
+  static constexpr int constrained_method();
+};
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained members
+
+namespace constrained_members_of_nested_types {
+
+template 
+struct S {
+  struct Inner0 {
+struct Inner1 {
+  template 
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template <>
+template 
+constexpr int S<1>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+
+template 
+concept ConceptT1T2 = true;
+
+template
+struct S12 {
+  struct Inner0 {
+struct Inner1 {
+  template T4>
+  static constexpr int constrained_method();
+};
+  };
+};
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template<>
+template T5>
+constexpr int S12::Inner0::Inner1::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S12::Inner0::Inner1::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained_members_of_nested_types
+
+namespace constrained_member_sfinae {
+
+template struct S {
+  template
+  static constexpr int constrained_method() requires (sizeof(int[N * 1073741824 + 4]) == 16) {
+return CONSTRAINED_METHOD_1;
+  }
+
+  template
+  static constexpr int constrained_method() requires (sizeof(int[N]) == 16);
+};
+
+template<>
+template
+constexpr int S<4>::constrained_method() requires (sizeof(int[4]) == 16) {
+  return CONSTRAINED_METHOD_2;
+}
+
+// Verify that there is no amiguity in this case.
+static_assert(S<4>::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained_member_sfinae
Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1653,33 +1653,12 @@
 << QualifierLoc.getSourceRange();
   return nullptr;
 }
-
-if (PrevClassTemplate) {
-  const ClassTemplateDecl *MostRecentPrevCT =
-  PrevClassTemplate->getMostRecentDecl();
-  TemplateParameterList *PrevParams =
-  MostRecentPrevCT->getTemplateParameters();
-
-  // Make sure the parameter lists match.
-  if (!SemaRef.TemplateParameterListsAreEqual(
-  D->getTemplatedDecl(), InstParams,
-  MostRecentPrevCT->getTemplatedDecl(), PrevParams, true,
-  Sema::TPL_TemplateMatch))
-return nullptr;
-
-  // Do some additional validation, then merge default arguments
-  // from the existing declarations.
-  if (SemaRef.CheckTemplateParameterList(InstParams, PrevParams,
- Sema::TPC_ClassTemplate))
-return nullptr;
-}
   }
 
   

[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-03-22 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added a comment.

@erichkeane - yes, I'm working on it, I hope to have a new version ~soon 
(within a few days).


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-03-16 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added a comment.

@shafik - it's a bit early to review this patch, this was the first attempt to 
fix the issue related to the current behavior of  
clang::Sema::TemplateParameterListsAreEqual that causes Clang to mishandle 
out-of-line definitions involving constraints (and possibly is the root cause 
of a few other issues related to concepts).
It's still work-in-progress. What's happening is roughly the following: there 
is a mismatch of depths of types (TemplateTypeParmType) referenced by 
ConceptSpecializationExpr. 
E.g. for the code

  template 
  concept Concept = true;
  
  template
  struct a
  {
template
void c(T1&& t);
  };
  
  template<>
  template
  void a::c(T2&& t)
  {}



  lldb) p OldConstr->dump()
  ConceptSpecializationExpr 0x64bc4c50 '_Bool' Concept 0x64bc4608 
'Concept'
  |-ImplicitConceptSpecializationDecl 0x64bc4be0 
  | `-TemplateArgument type 'type-parameter-1-0'
  |   `-TemplateTypeParmType 0x64bc4b70 'type-parameter-1-0' dependent 
depth 1 index 0
  `-TemplateArgument type 'T1'
`-TemplateTypeParmType 0x64bc4ba0 'T1' dependent depth 1 index 0
  `-TemplateTypeParm 0x64bc4ac8 'T1'
  
  (lldb) p NewConstr->dump()
  ConceptSpecializationExpr 0x64bc5140 '_Bool' Concept 0x64bc4608 
'Concept'
  |-ImplicitConceptSpecializationDecl 0x64bc50d0 
  | `-TemplateArgument type 'type-parameter-0-0'
  |   `-TemplateTypeParmType 0x64bc4580 'type-parameter-0-0' dependent 
depth 0 index 0
  `-TemplateArgument type 'T2'
`-TemplateTypeParmType 0x64bc5090 'T2' dependent depth 0 index 0
  `-TemplateTypeParm 0x64bc4ff0 'T2'

Inside Sema::AreConstraintExpressionsEqual there is some logic do adjust the 
depths, but at the moment i can't claim that i fully understand it - still 
investigating.
I think @erichkeane has also looked into the issue / debugged what's going on 
here - if I'm missing something / or something is not right - any corrections 
would be appreciated.
My current plan is to try to adopt the suggestion from

In D146178#4199382 , @erichkeane 
wrote:

> In D146178#4199263 , @erichkeane 
> wrote:
>
>> After a night of sleeping on it, the use of a AdjustConstraintDepth::Diff 
>> and AdjustConstraintDepth::Value feels like a hacky solution to SOMETHING 
>> here, though I'm not sure what yet. The depth of a template shouldn't change 
>> between the equality and constraint checking, it is usually a property of 
>> the specialization level.  I could definitely believe that 
>> `getTemplateInstantiationArgs` needs some sort of change here to better 
>> detect its own state, but this solution doesn't seem right to me.
>
> I debugged a bit: It isn't correct I think that `FunctionTemplateDecl` 
> doesn't pick up its template arguments in `getTemplateInstantiationArgs`.  
> Additionally, instead of picking up its `DeclContext`, it probably needs its 
> `LexicalDeclContext` as the next step, which I believe fixes the problem 
> (plus your change in SemaOverload.cpp)
>
> EDIT: `FunctionTemplateDecl` doesn't pick up its template arguments on 
> purpose: there ARE no template arguments, so that is me being silly.  
> However, the difference here is that it isn't picking its lexical decl 
> context here.  There is likely a similar solution here for VarTemplateDecl.
>
> I'm leaning toward the solution here being in the CalculateTemplateDepth here 
> instead: Recognize those two types, and set the correct DeclContext to pass 
> to the getTemplateInstantiationArgs (that is, the lexical decl context).

and see if i can make it functional, this will take some time.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-03-16 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added a comment.

@erichkeane - ok, thanks a lot for the comments / help, I need a bit of time to 
play with the code.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-03-16 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added inline comments.



Comment at: clang/lib/Sema/SemaConcept.cpp:779
+// The depths calculated for the declarations can be equal but they still
+// may differ from the depths of types inside OldConstr and NewConstr.
+OldConstr =

erichkeane wrote:
> I don't believe they are supposed to, at least based on what you've said 
> here.  Can you clarify what you mean?
i think I need to better understand what's going on here, because this is the 
culprit:
the calculated Depth1 and Depth2 are equal to 1 on our reproducer, thus no 
adjustments happen (in the old code), yet in the OldConst and NewConstr the 
depths are different.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-03-16 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added a comment.

@erichkeane , ok, let me think a bit a more about it / investigate further. 
It's unclear why we use AdjustConstraintDepth here in the first place, i.e. why 
the depth is incorrect in the first place. Regarding Diff/Value - TemplateDepth 
(despite its name) currently (without this diff) is used as an addend (i.e. 
AdjustConstraintDepth doesn't set depths to a given value but replaces  Depth 
with Depth +  TemplateDepth)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D146178

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


[PATCH] D146178: [Clang][Sema] Fix comparison of constraint expressions

2023-03-15 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov created this revision.
alexander-shaposhnikov added reviewers: erichkeane, rsmith, aaron.ballman.
alexander-shaposhnikov created this object with visibility "All Users".
Herald added a project: All.
alexander-shaposhnikov requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

The associated github issue: https://github.com/llvm/llvm-project/issues/61414
It also fixes 
https://github.com/llvm/llvm-project/issues/49620#issuecomment-1387667143 and 
https://github.com/llvm/llvm-project/issues/60231

Test plan:
1/ ninja check-all
2/ Bootstrapped Clang passes all the tests


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D146178

Files:
  clang/lib/Sema/SemaConcept.cpp
  clang/lib/Sema/SemaOverload.cpp
  clang/test/SemaTemplate/concepts-out-of-line-def.cpp

Index: clang/test/SemaTemplate/concepts-out-of-line-def.cpp
===
--- clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -127,3 +127,27 @@
 static_assert(S::specialization("str") == SPECIALIZATION_REQUIRES);
 
 } // namespace multiple_template_parameter_lists
+
+namespace constrained_members {
+
+static constexpr int CONSTRAINED_METHOD_1 = 1;
+static constexpr int CONSTRAINED_METHOD_2 = 2;
+
+template 
+struct S {
+  template 
+  static constexpr int constrained_method();
+};
+
+template <>
+template 
+constexpr int S<1>::constrained_method() { return CONSTRAINED_METHOD_1; }
+
+template <>
+template 
+constexpr int S<2>::constrained_method() { return CONSTRAINED_METHOD_2; }
+
+static_assert(S<1>::constrained_method() == CONSTRAINED_METHOD_1);
+static_assert(S<2>::constrained_method() == CONSTRAINED_METHOD_2);
+
+} // namespace constrained members
Index: clang/lib/Sema/SemaOverload.cpp
===
--- clang/lib/Sema/SemaOverload.cpp
+++ clang/lib/Sema/SemaOverload.cpp
@@ -1296,9 +1296,11 @@
 //
 // We check the return type and template parameter lists for function
 // templates first; the remaining checks follow.
+
 bool SameTemplateParameterList = TemplateParameterListsAreEqual(
-NewTemplate->getTemplateParameters(),
-OldTemplate->getTemplateParameters(), false, TPL_TemplateMatch);
+NewTemplate, NewTemplate->getTemplateParameters(), OldTemplate,
+OldTemplate->getTemplateParameters(), false, TPL_TemplateMatch,
+SourceLocation(), false /* PartialOrdering */);
 bool SameReturnType = Context.hasSameType(Old->getDeclaredReturnType(),
   New->getDeclaredReturnType());
 // FIXME(GH58571): Match template parameter list even for non-constrained
Index: clang/lib/Sema/SemaConcept.cpp
===
--- clang/lib/Sema/SemaConcept.cpp
+++ clang/lib/Sema/SemaConcept.cpp
@@ -733,12 +733,19 @@
 }
 
 namespace {
-  class AdjustConstraintDepth : public TreeTransform {
+class AdjustConstraintDepth : public TreeTransform {
+public:
+  enum DepthAdjustmentKind { Diff, Value };
+
+private:
   unsigned TemplateDepth = 0;
-  public:
+  DepthAdjustmentKind Kind;
+
+public:
   using inherited = TreeTransform;
-  AdjustConstraintDepth(Sema , unsigned TemplateDepth)
-  : inherited(SemaRef), TemplateDepth(TemplateDepth) {}
+  AdjustConstraintDepth(Sema , unsigned TemplateDepth,
+DepthAdjustmentKind Kind)
+  : inherited(SemaRef), TemplateDepth(TemplateDepth), Kind(Kind) {}
 
   using inherited::TransformTemplateTypeParmType;
   QualType TransformTemplateTypeParmType(TypeLocBuilder ,
@@ -751,13 +758,13 @@
   TransformDecl(TL.getNameLoc(), OldTTPDecl));
 
 QualType Result = getSema().Context.getTemplateTypeParmType(
-T->getDepth() + TemplateDepth, T->getIndex(), T->isParameterPack(),
-NewTTPDecl);
+Kind == Diff ? T->getDepth() + TemplateDepth : TemplateDepth,
+T->getIndex(), T->isParameterPack(), NewTTPDecl);
 TemplateTypeParmTypeLoc NewTL = TLB.push(Result);
 NewTL.setNameLoc(TL.getNameLoc());
 return Result;
   }
-  };
+};
 } // namespace
 
 bool Sema::AreConstraintExpressionsEqual(const NamedDecl *Old,
@@ -765,22 +772,19 @@
  const NamedDecl *New,
  const Expr *NewConstr) {
   if (Old && New && Old != New) {
-unsigned Depth1 = CalculateTemplateDepthForConstraints(
-*this, Old);
-unsigned Depth2 = CalculateTemplateDepthForConstraints(
-*this, New);
-
-// Adjust the 'shallowest' verison of this to increase the depth to match
-// the 'other'.
-if (Depth2 > Depth1) {
-  OldConstr = AdjustConstraintDepth(*this, Depth2 - Depth1)
-  .TransformExpr(const_cast(OldConstr))
-  .get();
-} else if (Depth1 > Depth2) {
-  

[PATCH] D145859: [Clang][CodeGen] Fix linkage and visibility of template parameter objects

2023-03-14 Thread Alexander Shaposhnikov 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 rG8403ccdcd28c: [Clang][CodeGen] Fix linkage and visibility of 
template parameter objects (authored by alexander-shaposhnikov).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145859

Files:
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/test/CodeGenCXX/template-param-objects-linkage.cpp
  clang/test/CodeGenCXX/template-param-objects-visibility.cpp
  clang/test/CodeGenCXX/template-param-objects.cpp


Index: clang/test/CodeGenCXX/template-param-objects.cpp
===
--- clang/test/CodeGenCXX/template-param-objects.cpp
+++ clang/test/CodeGenCXX/template-param-objects.cpp
@@ -7,7 +7,9 @@
 
 // ITANIUM: 
[[HELLO:@_ZTAXtl1StlA32_cLc104ELc101ELc108ELc108ELc111ELc32ELc119ELc111ELc114ELc108ELc100]]
 // MSABI: 
[[HELLO:@"[?][?]__N2US@@3D0GI@@0GF@@0GM@@0GM@@0GP@@0CA@@0HH@@0GP@@0HC@@0GM@@0GE@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@"]]
-// CHECK-SAME: = linkonce_odr constant { <{ [11 x i8], [21 x i8] }> } { <{ [11 
x i8], [21 x i8] }> <{ [11 x i8] c"hello world", [21 x i8] zeroinitializer }> 
}, comdat
+// ITANIUM-SAME: = linkonce_odr constant { <{ [11 x i8], [21 x i8] }> } { <{ 
[11 x i8], [21 x i8] }> <{ [11 x i8] c"hello world", [21 x i8] zeroinitializer 
}> }, comdat
+// MSABI-SAME: = linkonce_odr dso_local constant { <{ [11 x i8], [21 x i8] }> 
} { <{ [11 x i8], [21 x i8] }> <{ [11 x i8] c"hello world", [21 x i8] 
zeroinitializer }> }, comdat
+
 
 // ITANIUM: @p
 // MSABI: @"?p@@3PEBDEB"
Index: clang/test/CodeGenCXX/template-param-objects-visibility.cpp
===
--- /dev/null
+++ clang/test/CodeGenCXX/template-param-objects-visibility.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++20 %s -emit-llvm -o - | 
FileCheck %s
+
+struct S { char buf[32]; };
+template constexpr const char* f() { return s.buf; }
+const char* fbuf = f();
+// CHECK: @_ZTAXtl1StlA32_cLc97 = linkonce_odr constant { <{ i8, [31 x i8] 
}> }
+
+struct __attribute__ ((visibility ("hidden"))) HN { char buf[64]; };
+template  constexpr const char* g() { return hn.buf; }
+const char* gbuf = g();
+// CHECK: @_ZTAXtl2HNtlA64_cLc98 = linkonce_odr hidden constant { <{ i8, 
[63 x i8] }> }
Index: clang/test/CodeGenCXX/template-param-objects-linkage.cpp
===
--- /dev/null
+++ clang/test/CodeGenCXX/template-param-objects-linkage.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++20 %s -emit-llvm -o - | 
FileCheck %s
+
+struct S { char buf[32]; };
+template constexpr const char* f() { return s.buf; }
+const char* fbuf = f();
+// CHECK: @_ZTAXtl1StlA32_cLc97 = linkonce_odr constant { <{ i8, [31 x i8] 
}> }
+
+namespace {
+  struct UN { char buf[64]; };
+}
+template  constexpr const char* g() { return un.buf; }
+const char* gbuf = g();
+// CHECK: @_ZTAXtlN12_GLOBAL__N_12UNEtlA64_cLc98 = internal constant { <{ 
i8, [63 x i8] }> }
+
+struct Foo { int *i; };
+int m = 0;
+namespace { int n; }
+
+template 
+const int* h() { return foo.i; }
+
+const int* hm = h();
+// CHECK: @_ZTAXtl3FooadL_Z1mEEE = linkonce_odr constant %struct.Foo { ptr @m }
+
+const int* hn = h();
+// CHECK: @_ZTAXtl3FooadL_ZN12_GLOBAL__N_11n = internal constant 
%struct.Foo { ptr @_ZN12_GLOBAL__N_11nE }
Index: clang/lib/CodeGen/CodeGenModule.cpp
===
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -3238,9 +3238,13 @@
 return ConstantAddress::invalid();
   }
 
-  auto *GV = new llvm::GlobalVariable(
-  getModule(), Init->getType(),
-  /*isConstant=*/true, llvm::GlobalValue::LinkOnceODRLinkage, Init, Name);
+  llvm::GlobalValue::LinkageTypes Linkage =
+  isExternallyVisible(TPO->getLinkageAndVisibility().getLinkage())
+  ? llvm::GlobalValue::LinkOnceODRLinkage
+  : llvm::GlobalValue::InternalLinkage;
+  auto *GV = new llvm::GlobalVariable(getModule(), Init->getType(),
+  /*isConstant=*/true, Linkage, Init, 
Name);
+  setGVProperties(GV, TPO);
   if (supportsCOMDAT())
 GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
   Emitter.finalize(GV);


Index: clang/test/CodeGenCXX/template-param-objects.cpp
===
--- clang/test/CodeGenCXX/template-param-objects.cpp
+++ clang/test/CodeGenCXX/template-param-objects.cpp
@@ -7,7 +7,9 @@
 
 // ITANIUM: [[HELLO:@_ZTAXtl1StlA32_cLc104ELc101ELc108ELc108ELc111ELc32ELc119ELc111ELc114ELc108ELc100]]
 // MSABI: 

[PATCH] D145859: [Clang][CodeGen] Fix linkage and visibility of template parameter objects

2023-03-14 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov updated this revision to Diff 505175.
alexander-shaposhnikov retitled this revision from "[Clang][CodeGen] Fix 
linkage of template parameter objects" to "[Clang][CodeGen] Fix linkage and 
visibility of template parameter objects".
alexander-shaposhnikov edited the summary of this revision.

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145859

Files:
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/test/CodeGenCXX/template-param-objects-linkage.cpp
  clang/test/CodeGenCXX/template-param-objects-visibility.cpp
  clang/test/CodeGenCXX/template-param-objects.cpp


Index: clang/test/CodeGenCXX/template-param-objects.cpp
===
--- clang/test/CodeGenCXX/template-param-objects.cpp
+++ clang/test/CodeGenCXX/template-param-objects.cpp
@@ -7,7 +7,9 @@
 
 // ITANIUM: 
[[HELLO:@_ZTAXtl1StlA32_cLc104ELc101ELc108ELc108ELc111ELc32ELc119ELc111ELc114ELc108ELc100]]
 // MSABI: 
[[HELLO:@"[?][?]__N2US@@3D0GI@@0GF@@0GM@@0GM@@0GP@@0CA@@0HH@@0GP@@0HC@@0GM@@0GE@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@@0A@"]]
-// CHECK-SAME: = linkonce_odr constant { <{ [11 x i8], [21 x i8] }> } { <{ [11 
x i8], [21 x i8] }> <{ [11 x i8] c"hello world", [21 x i8] zeroinitializer }> 
}, comdat
+// ITANIUM-SAME: = linkonce_odr constant { <{ [11 x i8], [21 x i8] }> } { <{ 
[11 x i8], [21 x i8] }> <{ [11 x i8] c"hello world", [21 x i8] zeroinitializer 
}> }, comdat
+// MSABI-SAME: = linkonce_odr dso_local constant { <{ [11 x i8], [21 x i8] }> 
} { <{ [11 x i8], [21 x i8] }> <{ [11 x i8] c"hello world", [21 x i8] 
zeroinitializer }> }, comdat
+
 
 // ITANIUM: @p
 // MSABI: @"?p@@3PEBDEB"
Index: clang/test/CodeGenCXX/template-param-objects-visibility.cpp
===
--- /dev/null
+++ clang/test/CodeGenCXX/template-param-objects-visibility.cpp
@@ -0,0 +1,11 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++20 %s -emit-llvm -o - | 
FileCheck %s
+
+struct S { char buf[32]; };
+template constexpr const char* f() { return s.buf; }
+const char* fbuf = f();
+// CHECK: @_ZTAXtl1StlA32_cLc97 = linkonce_odr constant { <{ i8, [31 x i8] 
}> }
+
+struct __attribute__ ((visibility ("hidden"))) HN { char buf[64]; };
+template  constexpr const char* g() { return hn.buf; }
+const char* gbuf = g();
+// CHECK: @_ZTAXtl2HNtlA64_cLc98 = linkonce_odr hidden constant { <{ i8, 
[63 x i8] }> }
Index: clang/test/CodeGenCXX/template-param-objects-linkage.cpp
===
--- /dev/null
+++ clang/test/CodeGenCXX/template-param-objects-linkage.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++20 %s -emit-llvm -o - | 
FileCheck %s
+
+struct S { char buf[32]; };
+template constexpr const char* f() { return s.buf; }
+const char* fbuf = f();
+// CHECK: @_ZTAXtl1StlA32_cLc97 = linkonce_odr constant { <{ i8, [31 x i8] 
}> }
+
+namespace {
+  struct UN { char buf[64]; };
+}
+template  constexpr const char* g() { return un.buf; }
+const char* gbuf = g();
+// CHECK: @_ZTAXtlN12_GLOBAL__N_12UNEtlA64_cLc98 = internal constant { <{ 
i8, [63 x i8] }> }
+
+struct Foo { int *i; };
+int m = 0;
+namespace { int n; }
+
+template 
+const int* h() { return foo.i; }
+
+const int* hm = h();
+// CHECK: @_ZTAXtl3FooadL_Z1mEEE = linkonce_odr constant %struct.Foo { ptr @m }
+
+const int* hn = h();
+// CHECK: @_ZTAXtl3FooadL_ZN12_GLOBAL__N_11n = internal constant 
%struct.Foo { ptr @_ZN12_GLOBAL__N_11nE }
Index: clang/lib/CodeGen/CodeGenModule.cpp
===
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -3238,9 +3238,13 @@
 return ConstantAddress::invalid();
   }
 
-  auto *GV = new llvm::GlobalVariable(
-  getModule(), Init->getType(),
-  /*isConstant=*/true, llvm::GlobalValue::LinkOnceODRLinkage, Init, Name);
+  llvm::GlobalValue::LinkageTypes Linkage =
+  isExternallyVisible(TPO->getLinkageAndVisibility().getLinkage())
+  ? llvm::GlobalValue::LinkOnceODRLinkage
+  : llvm::GlobalValue::InternalLinkage;
+  auto *GV = new llvm::GlobalVariable(getModule(), Init->getType(),
+  /*isConstant=*/true, Linkage, Init, 
Name);
+  setGVProperties(GV, TPO);
   if (supportsCOMDAT())
 GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
   Emitter.finalize(GV);


Index: clang/test/CodeGenCXX/template-param-objects.cpp
===
--- clang/test/CodeGenCXX/template-param-objects.cpp
+++ clang/test/CodeGenCXX/template-param-objects.cpp
@@ -7,7 +7,9 @@
 
 // ITANIUM: [[HELLO:@_ZTAXtl1StlA32_cLc104ELc101ELc108ELc108ELc111ELc32ELc119ELc111ELc114ELc108ELc100]]
 // MSABI: 

[PATCH] D145859: [Clang][CodeGen] Fix linkage of template parameter objects

2023-03-11 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov created this revision.
alexander-shaposhnikov added reviewers: rsmith, aaron.ballman.
alexander-shaposhnikov created this object with visibility "All Users".
Herald added a project: All.
alexander-shaposhnikov requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This diff fixes linkage of template parameter objects.
The associated GitHub issue: https://github.com/llvm/llvm-project/issues/51571#

Test plan:
1/ ninja check-all
2/ bootstrapped Clang passes tests


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D145859

Files:
  clang/lib/CodeGen/CodeGenModule.cpp
  clang/test/CodeGenCXX/template-param-objects-linkage.cpp


Index: clang/test/CodeGenCXX/template-param-objects-linkage.cpp
===
--- /dev/null
+++ clang/test/CodeGenCXX/template-param-objects-linkage.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++20 %s -emit-llvm -o - | 
FileCheck %s
+
+struct S { char buf[32]; };
+template constexpr const char* f() { return s.buf; }
+const char* fbuf = f();
+// CHECK: @_ZTAXtl1StlA32_cLc97 = linkonce_odr constant { <{ i8, [31 x i8] 
}> }
+
+namespace {
+  struct UN { char buf[64]; };
+}
+template  constexpr const char* g() { return un.buf; }
+const char* gbuf = g();
+// CHECK: @_ZTAXtlN12_GLOBAL__N_12UNEtlA64_cLc98 = internal constant { <{ 
i8, [63 x i8] }> }
+
+struct Foo { int *i; };
+int m = 0;
+namespace { int n; }
+
+template 
+const int* h() { return foo.i; }
+
+const int* hm = h();
+// CHECK: @_ZTAXtl3FooadL_Z1mEEE = linkonce_odr constant %struct.Foo { ptr @m }
+
+const int* hn = h();
+// CHECK: @_ZTAXtl3FooadL_ZN12_GLOBAL__N_11n = internal constant 
%struct.Foo { ptr @_ZN12_GLOBAL__N_11nE }
Index: clang/lib/CodeGen/CodeGenModule.cpp
===
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -3238,9 +3238,12 @@
 return ConstantAddress::invalid();
   }
 
-  auto *GV = new llvm::GlobalVariable(
-  getModule(), Init->getType(),
-  /*isConstant=*/true, llvm::GlobalValue::LinkOnceODRLinkage, Init, Name);
+  llvm::GlobalValue::LinkageTypes Linkage =
+  isExternallyVisible(TPO->getLinkageAndVisibility().getLinkage())
+  ? llvm::GlobalValue::LinkOnceODRLinkage
+  : llvm::GlobalValue::InternalLinkage;
+  auto *GV = new llvm::GlobalVariable(getModule(), Init->getType(),
+  /*isConstant=*/true, Linkage, Init, 
Name);
   if (supportsCOMDAT())
 GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
   Emitter.finalize(GV);


Index: clang/test/CodeGenCXX/template-param-objects-linkage.cpp
===
--- /dev/null
+++ clang/test/CodeGenCXX/template-param-objects-linkage.cpp
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -std=c++20 %s -emit-llvm -o - | FileCheck %s
+
+struct S { char buf[32]; };
+template constexpr const char* f() { return s.buf; }
+const char* fbuf = f();
+// CHECK: @_ZTAXtl1StlA32_cLc97 = linkonce_odr constant { <{ i8, [31 x i8] }> }
+
+namespace {
+  struct UN { char buf[64]; };
+}
+template  constexpr const char* g() { return un.buf; }
+const char* gbuf = g();
+// CHECK: @_ZTAXtlN12_GLOBAL__N_12UNEtlA64_cLc98 = internal constant { <{ i8, [63 x i8] }> }
+
+struct Foo { int *i; };
+int m = 0;
+namespace { int n; }
+
+template 
+const int* h() { return foo.i; }
+
+const int* hm = h();
+// CHECK: @_ZTAXtl3FooadL_Z1mEEE = linkonce_odr constant %struct.Foo { ptr @m }
+
+const int* hn = h();
+// CHECK: @_ZTAXtl3FooadL_ZN12_GLOBAL__N_11n = internal constant %struct.Foo { ptr @_ZN12_GLOBAL__N_11nE }
Index: clang/lib/CodeGen/CodeGenModule.cpp
===
--- clang/lib/CodeGen/CodeGenModule.cpp
+++ clang/lib/CodeGen/CodeGenModule.cpp
@@ -3238,9 +3238,12 @@
 return ConstantAddress::invalid();
   }
 
-  auto *GV = new llvm::GlobalVariable(
-  getModule(), Init->getType(),
-  /*isConstant=*/true, llvm::GlobalValue::LinkOnceODRLinkage, Init, Name);
+  llvm::GlobalValue::LinkageTypes Linkage =
+  isExternallyVisible(TPO->getLinkageAndVisibility().getLinkage())
+  ? llvm::GlobalValue::LinkOnceODRLinkage
+  : llvm::GlobalValue::InternalLinkage;
+  auto *GV = new llvm::GlobalVariable(getModule(), Init->getType(),
+  /*isConstant=*/true, Linkage, Init, Name);
   if (supportsCOMDAT())
 GV->setComdat(TheModule.getOrInsertComdat(GV->getName()));
   Emitter.finalize(GV);
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D145034: [Clang][Sema] Start fixing handling of out-of-line definitions of constrained templates

2023-03-10 Thread Alexander Shaposhnikov 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 rG421c098b32bd: [Clang][Sema] Start fixing handling of 
out-of-line definitions of constrained… (authored by alexander-shaposhnikov).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145034

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/DeclSpec.h
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Sema/SemaCXXScopeSpec.cpp
  
clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp
  clang/test/SemaTemplate/concepts-out-of-line-def.cpp

Index: clang/test/SemaTemplate/concepts-out-of-line-def.cpp
===
--- /dev/null
+++ clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -0,0 +1,129 @@
+// RUN: %clang_cc1 -std=c++20 -verify %s
+// expected-no-diagnostics
+
+static constexpr int PRIMARY = 0;
+static constexpr int SPECIALIZATION_CONCEPT = 1;
+static constexpr int SPECIALIZATION_REQUIRES = 2;
+
+template 
+concept Concept = (sizeof(T) >= 2 * sizeof(int));
+
+struct XY {
+  int x;
+  int y;
+};
+
+namespace members {
+
+template  struct S {
+  static constexpr int primary();
+};
+
+template  constexpr int S::primary() {
+  return PRIMARY;
+};
+
+template  struct S {
+  static constexpr int specialization();
+};
+
+template 
+  requires(sizeof(T) == sizeof(int))
+struct S {
+  static constexpr int specialization();
+};
+
+template  constexpr int S::specialization() {
+  return SPECIALIZATION_CONCEPT;
+}
+
+template 
+  requires(sizeof(T) == sizeof(int))
+constexpr int S::specialization() {
+  return SPECIALIZATION_REQUIRES;
+}
+
+static_assert(S::primary() == PRIMARY);
+static_assert(S::specialization() == SPECIALIZATION_CONCEPT);
+static_assert(S::specialization() == SPECIALIZATION_REQUIRES);
+
+} // namespace members
+
+namespace enumerations {
+
+template  struct S {
+  enum class E : int;
+};
+
+template  enum class S::E { Value = PRIMARY };
+
+template  struct S {
+  enum class E : int;
+};
+
+template 
+enum class S::E {
+  Value = SPECIALIZATION_CONCEPT
+};
+
+template 
+  requires(sizeof(T) == sizeof(int))
+struct S {
+  enum class E : int;
+};
+
+template 
+  requires(sizeof(T) == sizeof(int))
+enum class S::E {
+  Value = SPECIALIZATION_REQUIRES
+};
+
+static_assert(static_cast(S::E::Value) == PRIMARY);
+static_assert(static_cast(S::E::Value) ==
+  SPECIALIZATION_CONCEPT);
+static_assert(static_cast(S::E::Value) ==
+  SPECIALIZATION_REQUIRES);
+
+} // namespace  enumerations
+
+namespace multiple_template_parameter_lists {
+
+template 
+struct S {
+  template 
+  static constexpr int primary(Inner);
+};
+
+template 
+template 
+constexpr int S::primary(Inner) {
+  return PRIMARY;
+};
+
+template 
+struct S {
+  template 
+  static constexpr int specialization(Inner);
+};
+
+template 
+template 
+constexpr int S::specialization(Inner) { return SPECIALIZATION_CONCEPT; }
+
+template 
+  requires(sizeof(Outer) == sizeof(int))
+struct S {
+  template 
+  static constexpr int specialization(Inner);
+};
+
+template 
+  requires(sizeof(Outer) == sizeof(int))
+template 
+constexpr int S::specialization(Inner) { return SPECIALIZATION_REQUIRES; }
+
+static_assert(S::primary("str") == PRIMARY);
+static_assert(S::specialization("str") == SPECIALIZATION_CONCEPT);
+static_assert(S::specialization("str") == SPECIALIZATION_REQUIRES);
+
+} // namespace multiple_template_parameter_lists
Index: clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp
===
--- clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp
+++ clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp
@@ -3,7 +3,7 @@
 template
 struct A;
 
-template // expected-note{{previous template declaration}}
+template
 struct A {
   void f0();
   void f1();
@@ -15,11 +15,10 @@
   void g0();
 };
 
-// FIXME: We should probably give more precise diagnostics here, but the
-// diagnostics we give aren't terrible.
-// FIXME: why not point to the first parameter that's "too many"?
-template // expected-error{{too many template parameters}}
-void A::f0() { }
+// FIXME: We should produce diagnostics pointing out the
+// non-matching candidates.
+template
+void A::f0() { } // expected-error{{does not refer into a class, class template or class template partial specialization}}
 
 template
 void A::f1() { } // expected-error{{out-of-line definition}}
Index: clang/lib/Sema/SemaCXXScopeSpec.cpp
===
--- clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -99,34 +99,52 @@
 if (ClassTemplateDecl *ClassTemplate
   = 

[PATCH] D145034: [Clang][Sema] Start fixing handling of out-of-line definitions of constrained templates

2023-03-09 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov updated this revision to Diff 504025.
alexander-shaposhnikov added a comment.

Release notes.

P.S. To the best of my knowledge the current status is the following: with this 
patch the examples reported in the comments on 
https://github.com/llvm/llvm-project/issues/49620 start to compile with the 
exception of 
https://github.com/llvm/llvm-project/issues/49620#issuecomment-1387667143 . 
This also might be related to 
the issues reported on https://github.com/llvm/llvm-project/issues/60231  but I 
haven't investigated it yet.

P.P.S. I'm planning to repeat all the testing and try to land this diff.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145034

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/DeclSpec.h
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Sema/SemaCXXScopeSpec.cpp
  
clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp
  clang/test/SemaTemplate/concepts-out-of-line-def.cpp

Index: clang/test/SemaTemplate/concepts-out-of-line-def.cpp
===
--- /dev/null
+++ clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -0,0 +1,129 @@
+// RUN: %clang_cc1 -std=c++20 -verify %s
+// expected-no-diagnostics
+
+static constexpr int PRIMARY = 0;
+static constexpr int SPECIALIZATION_CONCEPT = 1;
+static constexpr int SPECIALIZATION_REQUIRES = 2;
+
+template 
+concept Concept = (sizeof(T) >= 2 * sizeof(int));
+
+struct XY {
+  int x;
+  int y;
+};
+
+namespace members {
+
+template  struct S {
+  static constexpr int primary();
+};
+
+template  constexpr int S::primary() {
+  return PRIMARY;
+};
+
+template  struct S {
+  static constexpr int specialization();
+};
+
+template 
+  requires(sizeof(T) == sizeof(int))
+struct S {
+  static constexpr int specialization();
+};
+
+template  constexpr int S::specialization() {
+  return SPECIALIZATION_CONCEPT;
+}
+
+template 
+  requires(sizeof(T) == sizeof(int))
+constexpr int S::specialization() {
+  return SPECIALIZATION_REQUIRES;
+}
+
+static_assert(S::primary() == PRIMARY);
+static_assert(S::specialization() == SPECIALIZATION_CONCEPT);
+static_assert(S::specialization() == SPECIALIZATION_REQUIRES);
+
+} // namespace members
+
+namespace enumerations {
+
+template  struct S {
+  enum class E : int;
+};
+
+template  enum class S::E { Value = PRIMARY };
+
+template  struct S {
+  enum class E : int;
+};
+
+template 
+enum class S::E {
+  Value = SPECIALIZATION_CONCEPT
+};
+
+template 
+  requires(sizeof(T) == sizeof(int))
+struct S {
+  enum class E : int;
+};
+
+template 
+  requires(sizeof(T) == sizeof(int))
+enum class S::E {
+  Value = SPECIALIZATION_REQUIRES
+};
+
+static_assert(static_cast(S::E::Value) == PRIMARY);
+static_assert(static_cast(S::E::Value) ==
+  SPECIALIZATION_CONCEPT);
+static_assert(static_cast(S::E::Value) ==
+  SPECIALIZATION_REQUIRES);
+
+} // namespace  enumerations
+
+namespace multiple_template_parameter_lists {
+
+template 
+struct S {
+  template 
+  static constexpr int primary(Inner);
+};
+
+template 
+template 
+constexpr int S::primary(Inner) {
+  return PRIMARY;
+};
+
+template 
+struct S {
+  template 
+  static constexpr int specialization(Inner);
+};
+
+template 
+template 
+constexpr int S::specialization(Inner) { return SPECIALIZATION_CONCEPT; }
+
+template 
+  requires(sizeof(Outer) == sizeof(int))
+struct S {
+  template 
+  static constexpr int specialization(Inner);
+};
+
+template 
+  requires(sizeof(Outer) == sizeof(int))
+template 
+constexpr int S::specialization(Inner) { return SPECIALIZATION_REQUIRES; }
+
+static_assert(S::primary("str") == PRIMARY);
+static_assert(S::specialization("str") == SPECIALIZATION_CONCEPT);
+static_assert(S::specialization("str") == SPECIALIZATION_REQUIRES);
+
+} // namespace multiple_template_parameter_lists
Index: clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp
===
--- clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp
+++ clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp
@@ -3,7 +3,7 @@
 template
 struct A;
 
-template // expected-note{{previous template declaration}}
+template
 struct A {
   void f0();
   void f1();
@@ -15,11 +15,10 @@
   void g0();
 };
 
-// FIXME: We should probably give more precise diagnostics here, but the
-// diagnostics we give aren't terrible.
-// FIXME: why not point to the first parameter that's "too many"?
-template // expected-error{{too many template parameters}}
-void A::f0() { }
+// FIXME: We should produce diagnostics pointing out the
+// non-matching candidates.
+template
+void A::f0() { } // expected-error{{does not refer into a class, class template or class template partial 

[PATCH] D145034: [Clang][Sema] Start fixing handling of out-of-line definitions of constrained templates

2023-03-09 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added inline comments.



Comment at: clang/lib/Sema/SemaCXXScopeSpec.cpp:141
+  ClassTemplate->getInjectedClassNameSpecialization();
+  if (Context.hasSameType(Injected, ContextType))
+return ClassTemplate->getTemplatedDecl();

rsmith wrote:
> alexander-shaposhnikov wrote:
> > rsmith wrote:
> > > This should also be guarded by a check that 
> > > `TemplateParameterListsAreEqual` between 
> > > `ClassTemplate->getTemplateParameters()` and the template parameter list 
> > > we picked out of the given array of template parameter lists.
> > > 
> > > (With that check in place, we can move this back before the search for 
> > > partial specializations.)
> > The problem is that currently the template parameter list (the one which we 
> > are supposed to pick above) is not always present,
> > thus the fallback and this check are both still necessary. It happens e.g. 
> > for invalid code and if i remove the fallback it triggers more changes to 
> > the diagnostic output, other than that there might be more cases where we 
> > currently don't set TemplateParamLists for CXXScopeSpec, i kinda wanted to 
> > move incrementally.
> OK. Can we do the check in the case where we do have a list of template 
> parameter lists, at least, or does that also cause more diagnostic disruption 
> than you'd like to deal with in this change?
heh, unfortunately it does, in particular, the examples in the namespace "bad" 
in CXX/drs/dr5xx.cpp would be disrupted


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145034

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


[PATCH] D145034: [Clang][Sema] Start fixing handling of out-of-line definitions of constrained templates

2023-03-09 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added inline comments.



Comment at: clang/lib/Sema/SemaCXXScopeSpec.cpp:141
+  ClassTemplate->getInjectedClassNameSpecialization();
+  if (Context.hasSameType(Injected, ContextType))
+return ClassTemplate->getTemplatedDecl();

rsmith wrote:
> This should also be guarded by a check that `TemplateParameterListsAreEqual` 
> between `ClassTemplate->getTemplateParameters()` and the template parameter 
> list we picked out of the given array of template parameter lists.
> 
> (With that check in place, we can move this back before the search for 
> partial specializations.)
The problem is that currently the template parameter list (the one which we are 
supposed to pick above) is not always present,
thus the fallback and this check are both still necessary. It happens e.g. for 
invalid code and if i remove the fallback it triggers more changes to the 
diagnostic output, other than that there might be more cases where we currently 
don't set TemplateParamLists for CXXScopeSpec, i kinda wanted to move 
incrementally.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145034

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


[PATCH] D145034: [Clang][Sema] Preparations to fix handling of out-of-line definitions of constrained templates

2023-03-09 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov updated this revision to Diff 503750.
alexander-shaposhnikov added a comment.

Address comments


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145034

Files:
  clang/include/clang/Parse/Parser.h
  clang/include/clang/Sema/DeclSpec.h
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Sema/SemaCXXScopeSpec.cpp
  
clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp
  clang/test/SemaTemplate/concepts-out-of-line-def.cpp

Index: clang/test/SemaTemplate/concepts-out-of-line-def.cpp
===
--- /dev/null
+++ clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -0,0 +1,129 @@
+// RUN: %clang_cc1 -std=c++20 -verify %s
+// expected-no-diagnostics
+
+static constexpr int PRIMARY = 0;
+static constexpr int SPECIALIZATION_CONCEPT = 1;
+static constexpr int SPECIALIZATION_REQUIRES = 2;
+
+template 
+concept Concept = (sizeof(T) >= 2 * sizeof(int));
+
+struct XY {
+  int x;
+  int y;
+};
+
+namespace members {
+
+template  struct S {
+  static constexpr int primary();
+};
+
+template  constexpr int S::primary() {
+  return PRIMARY;
+};
+
+template  struct S {
+  static constexpr int specialization();
+};
+
+template 
+  requires(sizeof(T) == sizeof(int))
+struct S {
+  static constexpr int specialization();
+};
+
+template  constexpr int S::specialization() {
+  return SPECIALIZATION_CONCEPT;
+}
+
+template 
+  requires(sizeof(T) == sizeof(int))
+constexpr int S::specialization() {
+  return SPECIALIZATION_REQUIRES;
+}
+
+static_assert(S::primary() == PRIMARY);
+static_assert(S::specialization() == SPECIALIZATION_CONCEPT);
+static_assert(S::specialization() == SPECIALIZATION_REQUIRES);
+
+} // namespace members
+
+namespace enumerations {
+
+template  struct S {
+  enum class E : int;
+};
+
+template  enum class S::E { Value = PRIMARY };
+
+template  struct S {
+  enum class E : int;
+};
+
+template 
+enum class S::E {
+  Value = SPECIALIZATION_CONCEPT
+};
+
+template 
+  requires(sizeof(T) == sizeof(int))
+struct S {
+  enum class E : int;
+};
+
+template 
+  requires(sizeof(T) == sizeof(int))
+enum class S::E {
+  Value = SPECIALIZATION_REQUIRES
+};
+
+static_assert(static_cast(S::E::Value) == PRIMARY);
+static_assert(static_cast(S::E::Value) ==
+  SPECIALIZATION_CONCEPT);
+static_assert(static_cast(S::E::Value) ==
+  SPECIALIZATION_REQUIRES);
+
+} // namespace  enumerations
+
+namespace multiple_template_parameter_lists {
+
+template 
+struct S {
+  template 
+  static constexpr int primary(Inner);
+};
+
+template 
+template 
+constexpr int S::primary(Inner) {
+  return PRIMARY;
+};
+
+template 
+struct S {
+  template 
+  static constexpr int specialization(Inner);
+};
+
+template 
+template 
+constexpr int S::specialization(Inner) { return SPECIALIZATION_CONCEPT; }
+
+template 
+  requires(sizeof(Outer) == sizeof(int))
+struct S {
+  template 
+  static constexpr int specialization(Inner);
+};
+
+template 
+  requires(sizeof(Outer) == sizeof(int))
+template 
+constexpr int S::specialization(Inner) { return SPECIALIZATION_REQUIRES; }
+
+static_assert(S::primary("str") == PRIMARY);
+static_assert(S::specialization("str") == SPECIALIZATION_CONCEPT);
+static_assert(S::specialization("str") == SPECIALIZATION_REQUIRES);
+
+} // namespace multiple_template_parameter_lists
Index: clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp
===
--- clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp
+++ clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp
@@ -3,7 +3,7 @@
 template
 struct A;
 
-template // expected-note{{previous template declaration}}
+template
 struct A {
   void f0();
   void f1();
@@ -15,11 +15,10 @@
   void g0();
 };
 
-// FIXME: We should probably give more precise diagnostics here, but the
-// diagnostics we give aren't terrible.
-// FIXME: why not point to the first parameter that's "too many"?
-template // expected-error{{too many template parameters}}
-void A::f0() { }
+// FIXME: We should produce diagnostics pointing out the
+// non-matching candidates.
+template
+void A::f0() { } // expected-error{{does not refer into a class, class template or class template partial specialization}}
 
 template
 void A::f1() { } // expected-error{{out-of-line definition}}
Index: clang/lib/Sema/SemaCXXScopeSpec.cpp
===
--- clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -99,34 +99,52 @@
 if (ClassTemplateDecl *ClassTemplate
   = dyn_cast_or_null(
 SpecType->getTemplateName().getAsTemplateDecl())) {
-  QualType ContextType
-= Context.getCanonicalType(QualType(SpecType, 

[PATCH] D145034: [Clang][Sema] Preparations to fix handling of out-of-line definitions of constrained templates

2023-03-03 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added inline comments.



Comment at: clang/lib/Parse/ParseDeclCXX.cpp:1677-1678
 CXXScopeSpec Spec;
+if (TemplateInfo.TemplateParams)
+  Spec.setTemplateParamLists(*TemplateInfo.TemplateParams);
+

rsmith wrote:
> I think we'll need some similar logic for out-of-line definitions of member 
> enums too:
> ```
> template struct X;
> template concept bool Small = sizeof(T) == 1;
> template struct X {
>   enum class E;
> };
> template enum class X::E { e };
> ```
> 
> More generally, anywhere we might pass `EnteringContext = true`, we probably 
> ought to think about whether we have template parameters to pass in.
Added missing bits for enums,
regarding EnteringContext = true - yeah, I agree, I haven't done it on this 
diff  cause I'm kind of worried to do it without test cases and extracting test 
cases requires some efforts.




Comment at: 
clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp:2-4
+// XFAIL: *
+// NOTE: This test is marked XFAIL until the diagnostics of
+// too many template parameters is fixed.

rsmith wrote:
> What is the new diagnostic output? (Presumably we no longer match the partial 
> specialization when trying to match the declaration on line 25, because the 
> template parameter list doesn't match.)
the new diagnostic output:
  error: nested name specifier 'A::' for declaration does not refer 
into a class, class template or class template partial specialization 

```
template
void A::f0() { }
```




Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145034

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


[PATCH] D145034: [Clang][Sema] Preparations to fix handling of out-of-line definitions of constrained templates

2023-03-03 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov updated this revision to Diff 502067.
alexander-shaposhnikov added a comment.

1/ Add support for out-of-line definitions of member enums + add tests
2/ Updated comments DeclSpec.h


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D145034

Files:
  clang/include/clang/Sema/DeclSpec.h
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Sema/SemaCXXScopeSpec.cpp
  
clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp
  clang/test/SemaTemplate/concepts-out-of-line-def.cpp

Index: clang/test/SemaTemplate/concepts-out-of-line-def.cpp
===
--- /dev/null
+++ clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -0,0 +1,87 @@
+// RUN: %clang_cc1 -std=c++20 -verify %s
+// expected-no-diagnostics
+
+static constexpr int PRIMARY = 0;
+static constexpr int SPECIALIZATION_CONCEPT = 1;
+static constexpr int SPECIALIZATION_REQUIRES = 2;
+
+template 
+concept Concept = (sizeof(T) >= 2 * sizeof(int));
+
+struct XY {
+  int x;
+  int y;
+};
+
+namespace members {
+
+template  struct S {
+  constexpr int primary();
+};
+
+template  constexpr int S::primary() {
+  return PRIMARY;
+};
+
+template  struct S {
+  constexpr int specialization();
+};
+
+template 
+  requires(sizeof(T) == sizeof(int))
+struct S {
+  constexpr int specialization();
+};
+
+template  constexpr int S::specialization() {
+  return SPECIALIZATION_CONCEPT;
+}
+
+template 
+  requires(sizeof(T) == sizeof(int))
+constexpr int S::specialization() {
+  return SPECIALIZATION_REQUIRES;
+}
+
+static_assert(S().primary() == PRIMARY);
+static_assert(S().specialization() == SPECIALIZATION_CONCEPT);
+static_assert(S().specialization() == SPECIALIZATION_REQUIRES);
+
+} // namespace members
+
+namespace enumerations {
+
+template  struct S {
+  enum class E : int;
+};
+
+template  enum class S::E { Value = PRIMARY };
+
+template  struct S {
+  enum class E : int;
+};
+
+template 
+enum class S::E {
+  Value = SPECIALIZATION_CONCEPT
+};
+
+template 
+  requires(sizeof(T) == sizeof(int))
+struct S {
+  enum class E : int;
+};
+
+template 
+  requires(sizeof(T) == sizeof(int))
+enum class S::E {
+  Value = SPECIALIZATION_REQUIRES
+};
+
+static_assert(static_cast(S::E::Value) == PRIMARY);
+static_assert(static_cast(S::E::Value) ==
+  SPECIALIZATION_CONCEPT);
+static_assert(static_cast(S::E::Value) ==
+  SPECIALIZATION_REQUIRES);
+
+} // namespace  enumerations
Index: clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp
===
--- clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp
+++ clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp
@@ -1,4 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
+// XFAIL: *
+// NOTE: This test is marked XFAIL until the diagnostics of
+// too many template parameters is fixed.
 
 template
 struct A;
Index: clang/lib/Sema/SemaCXXScopeSpec.cpp
===
--- clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -102,31 +102,44 @@
   QualType ContextType
 = Context.getCanonicalType(QualType(SpecType, 0));
 
-  // If the type of the nested name specifier is the same as the
-  // injected class name of the named class template, we're entering
-  // into that class template definition.
-  QualType Injected
-= ClassTemplate->getInjectedClassNameSpecialization();
-  if (Context.hasSameType(Injected, ContextType))
-return ClassTemplate->getTemplatedDecl();
+  // FIXME: currently only the case of ParamLists containing a single
+  // element is supported. The fallback on the search of partial
+  // specialization using ContextType should be eventually removed since
+  // it doesn't handle the case of constrained template parameters
+  // correctly.
+  ClassTemplatePartialSpecializationDecl *PartialSpec = nullptr;
+  ArrayRef TemplateParamLists = SS.getTemplateParamLists();
+  if (TemplateParamLists.size() == 1) {
+// FIXME: pick the correct template parameter list based on NNS, SS
+// and getCurScope().
+TemplateParameterList *L = TemplateParamLists[0];
+void *Pos = nullptr;
+PartialSpec = ClassTemplate->findPartialSpecialization(
+SpecType->template_arguments(), L, Pos);
+  } else {
+PartialSpec = ClassTemplate->findPartialSpecialization(ContextType);
+  }
 
-  // If the type of the nested name specifier is the same as the
-  // type of one of the class template's class template partial
-  // specializations, 

[PATCH] D145034: [Clang][Sema] Preparations to fix handling of out-of-line definitions of constrained templates

2023-02-28 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov created this revision.
alexander-shaposhnikov added reviewers: rsmith, aaron.ballman.
alexander-shaposhnikov created this object with visibility "All Users".
Herald added a project: All.
alexander-shaposhnikov requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This diff starts fixing our handling of out-of-line definitions of constrained 
templates.
Initially it was motivated by https://github.com/llvm/llvm-project/issues/49620 
.
The current diff doesn't fully address those issues, more changes are required 
to make things work for the case where
multiple template parameter lists are attached to the declaration, this will be 
done in a follow-up diff.

Test plan:
1/ ninja check-all 
2/ Bootstrapped Clang passes all the tests
3/ Internal testing (built a few large projects (that use templates 
extensively) with the bootstrapped version of Clang)


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D145034

Files:
  clang/include/clang/Sema/DeclSpec.h
  clang/lib/Parse/ParseDecl.cpp
  clang/lib/Parse/ParseDeclCXX.cpp
  clang/lib/Sema/SemaCXXScopeSpec.cpp
  
clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp
  clang/test/SemaTemplate/concepts-out-of-line-def.cpp

Index: clang/test/SemaTemplate/concepts-out-of-line-def.cpp
===
--- /dev/null
+++ clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -0,0 +1,47 @@
+// RUN: %clang_cc1 -std=c++20 -verify %s
+// expected-no-diagnostics
+
+static constexpr int PRIMARY = 0;
+static constexpr int SPECIALIZATION_CONCEPT = 1;
+static constexpr int SPECIALIZATION_REQUIRES = 2;
+
+template 
+struct S {
+  constexpr int primary();
+};
+
+template 
+constexpr int S::primary() { return PRIMARY; };
+
+template 
+concept Concept = (sizeof(T) >= 2 * sizeof(int));
+
+template 
+struct S {
+constexpr int specialization();
+};
+
+template 
+requires (sizeof(T) == sizeof(int))
+struct S {
+constexpr int specialization();
+};
+
+
+template 
+constexpr int S::specialization() { return SPECIALIZATION_CONCEPT; }
+
+
+template 
+requires (sizeof(T) == sizeof(int))
+constexpr int S::specialization() { return SPECIALIZATION_REQUIRES; }
+
+struct XY {
+  int x;
+  int y;
+};
+
+static_assert (S().primary() == PRIMARY);
+static_assert (S().specialization() == SPECIALIZATION_CONCEPT);
+static_assert (S().specialization() == SPECIALIZATION_REQUIRES);
+
Index: clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp
===
--- clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp
+++ clang/test/CXX/temp/temp.decls/temp.class.spec/temp.class.spec.mfunc/p1-neg.cpp
@@ -1,4 +1,7 @@
 // RUN: %clang_cc1 -fsyntax-only -verify %s
+// XFAIL: *
+// NOTE: This test is marked XFAIL until the diagnostics of
+// too many template parameters is fixed.
 
 template
 struct A;
Index: clang/lib/Sema/SemaCXXScopeSpec.cpp
===
--- clang/lib/Sema/SemaCXXScopeSpec.cpp
+++ clang/lib/Sema/SemaCXXScopeSpec.cpp
@@ -102,31 +102,44 @@
   QualType ContextType
 = Context.getCanonicalType(QualType(SpecType, 0));
 
-  // If the type of the nested name specifier is the same as the
-  // injected class name of the named class template, we're entering
-  // into that class template definition.
-  QualType Injected
-= ClassTemplate->getInjectedClassNameSpecialization();
-  if (Context.hasSameType(Injected, ContextType))
-return ClassTemplate->getTemplatedDecl();
+  // FIXME: currently only the case of ParamLists containing a single
+  // element is supported. The fallback on the search of partial
+  // specialization using ContextType should be eventually removed since
+  // it doesn't handle the case of constrained template parameters
+  // correctly.
+  ClassTemplatePartialSpecializationDecl *PartialSpec = nullptr;
+  ArrayRef TemplateParamLists = SS.getTemplateParamLists();
+  if (TemplateParamLists.size() == 1) {
+// FIXME: pick the correct template parameter list based on NNS, SS
+// and getCurScope().
+TemplateParameterList *L = TemplateParamLists[0];
+void *Pos = nullptr;
+PartialSpec = ClassTemplate->findPartialSpecialization(
+SpecType->template_arguments(), L, Pos);
+  } else {
+PartialSpec = ClassTemplate->findPartialSpecialization(ContextType);
+  }
 
-  // If the type of the nested name specifier is the same as the
-  // type of one of the class template's class template partial
-  // specializations, we're entering into the definition of that
-  // class template partial 

[PATCH] D143781: [Clang][LLVM] Enable __arithmetic_fence and fprotect-parens on AArch64

2023-02-13 Thread Alexander Shaposhnikov 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 rG8f5d81585aa9: [Clang][LLVM] Enable __arithmetic_fence and 
fprotect-parens on AArch64 (authored by alexander-shaposhnikov).

Changed prior to commit:
  https://reviews.llvm.org/D143781?vs=496606=497055#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D143781

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Basic/Targets/AArch64.h
  clang/test/AST/arithmetic-fence-builtin.c
  clang/test/CodeGen/arithmetic-fence-builtin.c
  llvm/test/CodeGen/AArch64/arithmetic_fence.ll

Index: llvm/test/CodeGen/AArch64/arithmetic_fence.ll
===
--- /dev/null
+++ llvm/test/CodeGen/AArch64/arithmetic_fence.ll
@@ -0,0 +1,129 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=aarch64-none-linux-gnu -mattr=-neon -fp-contract=fast | FileCheck %s --check-prefix=Aarch64
+; RUN: llc < %s -mtriple=aarch64-none-linux-gnu -mattr=+neon -fp-contract=fast | FileCheck %s --check-prefix=Aarch64-Neon
+
+define float @f1(float %a, float %b, float %c) {
+; Aarch64-LABEL: f1:
+; Aarch64:   // %bb.0:
+; Aarch64-NEXT:fmadd s0, s1, s0, s2
+; Aarch64-NEXT:ret
+;
+; Aarch64-Neon-LABEL: f1:
+; Aarch64-Neon:   // %bb.0:
+; Aarch64-Neon-NEXT:fmadd s0, s1, s0, s2
+; Aarch64-Neon-NEXT:ret
+  %mul = fmul fast float %b, %a
+  %add = fadd fast float %mul, %c
+  ret float %add
+}
+
+define float @f2(float %a, float %b, float %c) {
+; Aarch64-LABEL: f2:
+; Aarch64:   // %bb.0:
+; Aarch64-NEXT:fmul s0, s1, s0
+; Aarch64-NEXT://ARITH_FENCE
+; Aarch64-NEXT:fadd s0, s0, s2
+; Aarch64-NEXT:ret
+;
+; Aarch64-Neon-LABEL: f2:
+; Aarch64-Neon:   // %bb.0:
+; Aarch64-Neon-NEXT:fmul s0, s1, s0
+; Aarch64-Neon-NEXT://ARITH_FENCE
+; Aarch64-Neon-NEXT:fadd s0, s0, s2
+; Aarch64-Neon-NEXT:ret
+  %mul = fmul fast float %b, %a
+  %tmp = call float @llvm.arithmetic.fence.f32(float %mul)
+  %add = fadd fast float %tmp, %c
+  ret float %add
+}
+
+define double @f3(double %a) {
+; Aarch64-LABEL: f3:
+; Aarch64:   // %bb.0:
+; Aarch64-NEXT:fmov d1, #4.
+; Aarch64-NEXT:fmul d0, d0, d1
+; Aarch64-NEXT:ret
+;
+; Aarch64-Neon-LABEL: f3:
+; Aarch64-Neon:   // %bb.0:
+; Aarch64-Neon-NEXT:fmov d1, #4.
+; Aarch64-Neon-NEXT:fmul d0, d0, d1
+; Aarch64-Neon-NEXT:ret
+  %1 = fadd fast double %a, %a
+  %2 = fadd fast double %a, %a
+  %3 = fadd fast double %1, %2
+  ret double %3
+}
+
+define double @f4(double %a) {
+; Aarch64-LABEL: f4:
+; Aarch64:   // %bb.0:
+; Aarch64-NEXT:fadd d0, d0, d0
+; Aarch64-NEXT:fmov d1, d0
+; Aarch64-NEXT://ARITH_FENCE
+; Aarch64-NEXT:fadd d0, d1, d0
+; Aarch64-NEXT:ret
+;
+; Aarch64-Neon-LABEL: f4:
+; Aarch64-Neon:   // %bb.0:
+; Aarch64-Neon-NEXT:fadd d0, d0, d0
+; Aarch64-Neon-NEXT:fmov d1, d0
+; Aarch64-Neon-NEXT://ARITH_FENCE
+; Aarch64-Neon-NEXT:fadd d0, d1, d0
+; Aarch64-Neon-NEXT:ret
+  %1 = fadd fast double %a, %a
+  %t = call double @llvm.arithmetic.fence.f64(double %1)
+  %2 = fadd fast double %a, %a
+  %3 = fadd fast double %t, %2
+  ret double %3
+}
+
+define <2 x float> @f5(<2 x float> %a) {
+; Aarch64-LABEL: f5:
+; Aarch64:   // %bb.0:
+; Aarch64-NEXT:fmov s2, #4.
+; Aarch64-NEXT:fmul s0, s0, s2
+; Aarch64-NEXT:fmul s1, s1, s2
+; Aarch64-NEXT:ret
+;
+; Aarch64-Neon-LABEL: f5:
+; Aarch64-Neon:   // %bb.0:
+; Aarch64-Neon-NEXT:fmov v1.2s, #4.
+; Aarch64-Neon-NEXT:fmul v0.2s, v0.2s, v1.2s
+; Aarch64-Neon-NEXT:ret
+  %1 = fadd fast <2 x float> %a, %a
+  %2 = fadd fast <2 x float> %a, %a
+  %3 = fadd fast <2 x float> %1, %2
+  ret <2 x float> %3
+}
+
+define <2 x float> @f6(<2 x float> %a) {
+; Aarch64-LABEL: f6:
+; Aarch64:   // %bb.0:
+; Aarch64-NEXT:fadd s0, s0, s0
+; Aarch64-NEXT:fadd s1, s1, s1
+; Aarch64-NEXT:fmov s2, s1
+; Aarch64-NEXT:fmov s3, s0
+; Aarch64-NEXT://ARITH_FENCE
+; Aarch64-NEXT://ARITH_FENCE
+; Aarch64-NEXT:fadd s0, s3, s0
+; Aarch64-NEXT:fadd s1, s2, s1
+; Aarch64-NEXT:ret
+;
+; Aarch64-Neon-LABEL: f6:
+; Aarch64-Neon:   // %bb.0:
+; Aarch64-Neon-NEXT:fadd v0.2s, v0.2s, v0.2s
+; Aarch64-Neon-NEXT:fmov d1, d0
+; Aarch64-Neon-NEXT://ARITH_FENCE
+; Aarch64-Neon-NEXT:fadd v0.2s, v1.2s, v0.2s
+; Aarch64-Neon-NEXT:ret
+  %1 = fadd fast <2 x float> %a, %a
+  %t = call <2 x float> @llvm.arithmetic.fence.v2f32(<2 x float> %1)
+  %2 = fadd fast <2 x float> %a, %a
+  %3 = fadd fast <2 x float> %t, %2
+  ret <2 x float> %3
+}
+
+declare float @llvm.arithmetic.fence.f32(float)
+declare double @llvm.arithmetic.fence.f64(double)
+declare <2 x float> @llvm.arithmetic.fence.v2f32(<2 x float>)
Index: 

[PATCH] D143781: [Clang][LLVM] Enable __arithmetic_fence and fprotect-parens on AArch64

2023-02-13 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added a comment.

sure, will do! thanks for the review


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D143781

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


[PATCH] D143781: [Clang][LLVM] Enable __arithmetic_fence and fprotect-parens on AArch64

2023-02-10 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov created this revision.
alexander-shaposhnikov added reviewers: efriedma, aaron.ballman, mibintc.
alexander-shaposhnikov created this object with visibility "All Users".
Herald added a subscriber: kristof.beyls.
Herald added a project: All.
alexander-shaposhnikov requested review of this revision.
Herald added projects: clang, LLVM.
Herald added a subscriber: cfe-commits.

Enable __arithmetic_fence and fprotect-parens on AArch64  (introduced in 
https://reviews.llvm.org/D100118)

Test plan: ninja check-all


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D143781

Files:
  clang/lib/Basic/Targets/AArch64.h
  clang/test/AST/arithmetic-fence-builtin.c
  clang/test/CodeGen/arithmetic-fence-builtin.c
  llvm/test/CodeGen/AArch64/arithmetic_fence.ll

Index: llvm/test/CodeGen/AArch64/arithmetic_fence.ll
===
--- /dev/null
+++ llvm/test/CodeGen/AArch64/arithmetic_fence.ll
@@ -0,0 +1,129 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=aarch64-none-linux-gnu -mattr=-neon -fp-contract=fast | FileCheck %s --check-prefix=Aarch64
+; RUN: llc < %s -mtriple=aarch64-none-linux-gnu -mattr=+neon -fp-contract=fast | FileCheck %s --check-prefix=Aarch64-Neon
+
+define float @f1(float %a, float %b, float %c) {
+; Aarch64-LABEL: f1:
+; Aarch64:   // %bb.0:
+; Aarch64-NEXT:fmadd s0, s1, s0, s2
+; Aarch64-NEXT:ret
+;
+; Aarch64-Neon-LABEL: f1:
+; Aarch64-Neon:   // %bb.0:
+; Aarch64-Neon-NEXT:fmadd s0, s1, s0, s2
+; Aarch64-Neon-NEXT:ret
+  %mul = fmul fast float %b, %a
+  %add = fadd fast float %mul, %c
+  ret float %add
+}
+
+define float @f2(float %a, float %b, float %c) {
+; Aarch64-LABEL: f2:
+; Aarch64:   // %bb.0:
+; Aarch64-NEXT:fmul s0, s1, s0
+; Aarch64-NEXT://ARITH_FENCE
+; Aarch64-NEXT:fadd s0, s0, s2
+; Aarch64-NEXT:ret
+;
+; Aarch64-Neon-LABEL: f2:
+; Aarch64-Neon:   // %bb.0:
+; Aarch64-Neon-NEXT:fmul s0, s1, s0
+; Aarch64-Neon-NEXT://ARITH_FENCE
+; Aarch64-Neon-NEXT:fadd s0, s0, s2
+; Aarch64-Neon-NEXT:ret
+  %mul = fmul fast float %b, %a
+  %tmp = call float @llvm.arithmetic.fence.f32(float %mul)
+  %add = fadd fast float %tmp, %c
+  ret float %add
+}
+
+define double @f3(double %a) {
+; Aarch64-LABEL: f3:
+; Aarch64:   // %bb.0:
+; Aarch64-NEXT:fmov d1, #4.
+; Aarch64-NEXT:fmul d0, d0, d1
+; Aarch64-NEXT:ret
+;
+; Aarch64-Neon-LABEL: f3:
+; Aarch64-Neon:   // %bb.0:
+; Aarch64-Neon-NEXT:fmov d1, #4.
+; Aarch64-Neon-NEXT:fmul d0, d0, d1
+; Aarch64-Neon-NEXT:ret
+  %1 = fadd fast double %a, %a
+  %2 = fadd fast double %a, %a
+  %3 = fadd fast double %1, %2
+  ret double %3
+}
+
+define double @f4(double %a) {
+; Aarch64-LABEL: f4:
+; Aarch64:   // %bb.0:
+; Aarch64-NEXT:fadd d0, d0, d0
+; Aarch64-NEXT:fmov d1, d0
+; Aarch64-NEXT://ARITH_FENCE
+; Aarch64-NEXT:fadd d0, d1, d0
+; Aarch64-NEXT:ret
+;
+; Aarch64-Neon-LABEL: f4:
+; Aarch64-Neon:   // %bb.0:
+; Aarch64-Neon-NEXT:fadd d0, d0, d0
+; Aarch64-Neon-NEXT:fmov d1, d0
+; Aarch64-Neon-NEXT://ARITH_FENCE
+; Aarch64-Neon-NEXT:fadd d0, d1, d0
+; Aarch64-Neon-NEXT:ret
+  %1 = fadd fast double %a, %a
+  %t = call double @llvm.arithmetic.fence.f64(double %1)
+  %2 = fadd fast double %a, %a
+  %3 = fadd fast double %t, %2
+  ret double %3
+}
+
+define <2 x float> @f5(<2 x float> %a) {
+; Aarch64-LABEL: f5:
+; Aarch64:   // %bb.0:
+; Aarch64-NEXT:fmov s2, #4.
+; Aarch64-NEXT:fmul s0, s0, s2
+; Aarch64-NEXT:fmul s1, s1, s2
+; Aarch64-NEXT:ret
+;
+; Aarch64-Neon-LABEL: f5:
+; Aarch64-Neon:   // %bb.0:
+; Aarch64-Neon-NEXT:fmov v1.2s, #4.
+; Aarch64-Neon-NEXT:fmul v0.2s, v0.2s, v1.2s
+; Aarch64-Neon-NEXT:ret
+  %1 = fadd fast <2 x float> %a, %a
+  %2 = fadd fast <2 x float> %a, %a
+  %3 = fadd fast <2 x float> %1, %2
+  ret <2 x float> %3
+}
+
+define <2 x float> @f6(<2 x float> %a) {
+; Aarch64-LABEL: f6:
+; Aarch64:   // %bb.0:
+; Aarch64-NEXT:fadd s0, s0, s0
+; Aarch64-NEXT:fadd s1, s1, s1
+; Aarch64-NEXT:fmov s2, s1
+; Aarch64-NEXT:fmov s3, s0
+; Aarch64-NEXT://ARITH_FENCE
+; Aarch64-NEXT://ARITH_FENCE
+; Aarch64-NEXT:fadd s0, s3, s0
+; Aarch64-NEXT:fadd s1, s2, s1
+; Aarch64-NEXT:ret
+;
+; Aarch64-Neon-LABEL: f6:
+; Aarch64-Neon:   // %bb.0:
+; Aarch64-Neon-NEXT:fadd v0.2s, v0.2s, v0.2s
+; Aarch64-Neon-NEXT:fmov d1, d0
+; Aarch64-Neon-NEXT://ARITH_FENCE
+; Aarch64-Neon-NEXT:fadd v0.2s, v1.2s, v0.2s
+; Aarch64-Neon-NEXT:ret
+  %1 = fadd fast <2 x float> %a, %a
+  %t = call <2 x float> @llvm.arithmetic.fence.v2f32(<2 x float> %1)
+  %2 = fadd fast <2 x float> %a, %a
+  %3 = fadd fast <2 x float> %t, %2
+  ret <2 x float> %3
+}
+
+declare float @llvm.arithmetic.fence.f32(float)
+declare double @llvm.arithmetic.fence.f64(double)
+declare <2 x 

[PATCH] D142430: [Clang] Treat `std::forward_like` as builtin

2023-01-28 Thread Alexander Shaposhnikov 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 rG0fd9c37d8cf2: [Clang] Treat `std::forward_like` as builtin 
(authored by alexander-shaposhnikov).

Changed prior to commit:
  https://reviews.llvm.org/D142430?vs=491598=493042#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D142430

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/Builtins.def
  clang/lib/AST/ExprConstant.cpp
  clang/lib/Analysis/BodyFarm.cpp
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/CodeGenCXX/builtin-std-move.cpp
  clang/test/SemaCXX/attr-lifetimebound.cpp
  clang/test/SemaCXX/builtin-std-move-nobuiltin.cpp
  clang/test/SemaCXX/builtin-std-move.cpp

Index: clang/test/SemaCXX/builtin-std-move.cpp
===
--- clang/test/SemaCXX/builtin-std-move.cpp
+++ clang/test/SemaCXX/builtin-std-move.cpp
@@ -43,6 +43,33 @@
 return static_cast(x);
   }
 
+  template  struct is_const { static constexpr bool value = false; };
+  template  struct is_const { static constexpr bool value = true; };
+
+  template  struct conditional { using type = T; };
+  template  struct conditional { using type = F; };
+
+  template 
+  using CopyConst = typename conditional<
+  is_const>::value,
+  const T, T>::type;
+
+  template 
+  using OverrideRef = typename conditional<
+  is_lvalue_reference::value,
+  typename remove_reference::type &,
+  typename remove_reference::type &&>::type;
+
+  template 
+  using ForwardLikeRetType = OverrideRef>;
+
+  template 
+  CONSTEXPR auto forward_like(T &) -> ForwardLikeRetType {
+using TT = typename remove_reference::type;
+static_assert(TT::moveable, "instantiated as_const"); // expected-error {{no member named 'moveable' in 'B'}}
+return static_cast>(t);
+  }
+
   template CONSTEXPR const T _const(T ) {
 static_assert(T::moveable, "instantiated as_const"); // expected-error {{no member named 'moveable' in 'B'}}
 return x;
@@ -92,14 +119,15 @@
 B &&(*pMove)(B&) = std::move; // #1 expected-note {{instantiation of}}
 B &&(*pMoveIfNoexcept)(B&) = ::move_if_noexcept; // #2 expected-note {{instantiation of}}
 B &&(*pForward)(B&) = ::forward; // #3 expected-note {{instantiation of}}
-const B &(*pAsConst)(B&) = ::as_const; // #4 expected-note {{instantiation of}}
-B *(*pAddressof)(B&) = ::addressof; // #5 expected-note {{instantiation of}}
-B *(*pUnderUnderAddressof)(B&) = ::__addressof; // #6 expected-note {{instantiation of}}
+B &&(*pForwardLike)(B&) = ::forward_like; // #4 expected-note {{instantiation of}}
+const B &(*pAsConst)(B&) = ::as_const; // #5 expected-note {{instantiation of}}
+B *(*pAddressof)(B&) = ::addressof; // #6 expected-note {{instantiation of}}
+B *(*pUnderUnderAddressof)(B&) = ::__addressof; // #7 expected-note {{instantiation of}}
 int (*pUnrelatedMove)(B, B) = std::move;
 
 struct C {};
-C &&()(C&) = std::move; // #7 expected-note {{instantiation of}}
-C &&()(C&) = std::forward; // #8 expected-note {{instantiation of}}
+C &&()(C&) = std::move; // #8 expected-note {{instantiation of}}
+C &&()(C&) = std::forward; // #9 expected-note {{instantiation of}}
 int ()(B, B) = std::move;
 
 #if __cplusplus <= 201703L
@@ -111,6 +139,7 @@
 // expected-warning@#6 {{non-addressable}}
 // expected-warning@#7 {{non-addressable}}
 // expected-warning@#8 {{non-addressable}}
+// expected-warning@#9 {{non-addressable}}
 #else
 // expected-error@#1 {{non-addressable}}
 // expected-error@#2 {{non-addressable}}
@@ -120,6 +149,7 @@
 // expected-error@#6 {{non-addressable}}
 // expected-error@#7 {{non-addressable}}
 // expected-error@#8 {{non-addressable}}
+// expected-error@#9 {{non-addressable}}
 #endif
 
 void attribute_const() {
@@ -127,6 +157,7 @@
   std::move(n); // expected-warning {{ignoring return value}}
   std::move_if_noexcept(n); // expected-warning {{ignoring return value}}
   std::forward(n); // expected-warning {{ignoring return value}}
+  std::forward_like(n); // expected-warning {{ignoring return value}}
   std::addressof(n); // expected-warning {{ignoring return value}}
   std::__addressof(n); // expected-warning {{ignoring return value}}
   std::as_const(n); // expected-warning {{ignoring return value}}
Index: clang/test/SemaCXX/builtin-std-move-nobuiltin.cpp
===
--- clang/test/SemaCXX/builtin-std-move-nobuiltin.cpp
+++ clang/test/SemaCXX/builtin-std-move-nobuiltin.cpp
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 -std=c++20 -verify %s -DBUILTIN=builtin
 // RUN: %clang_cc1 -std=c++20 -verify %s -DBUILTIN=nobuiltin -fno-builtin
-// RUN: %clang_cc1 -std=c++20 -verify %s -DBUILTIN=nobuiltin -fno-builtin-std-move -fno-builtin-std-move_if_noexcept -fno-builtin-std-forward
+// RUN: 

[PATCH] D142430: [Clang] Treat `std::forward_like` as builtin

2023-01-27 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov added a comment.

gentle ping )


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D142430

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


[PATCH] D142430: [Clang] Treat `std::forward_like` as builtin

2023-01-23 Thread Alexander Shaposhnikov via Phabricator via cfe-commits
alexander-shaposhnikov created this revision.
alexander-shaposhnikov added reviewers: rsmith, aaron.ballman.
alexander-shaposhnikov created this object with visibility "All Users".
Herald added a reviewer: NoQ.
Herald added a project: All.
alexander-shaposhnikov requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

This diff extends D123345  by adding support 
for std::forward_like.

Test plan: ninja check-clang check-clang-tools check-llvm


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D142430

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/Builtins.def
  clang/lib/AST/ExprConstant.cpp
  clang/lib/Analysis/BodyFarm.cpp
  clang/lib/CodeGen/CGBuiltin.cpp
  clang/lib/Sema/SemaChecking.cpp
  clang/lib/Sema/SemaDecl.cpp
  clang/test/CodeGenCXX/builtin-std-move.cpp
  clang/test/SemaCXX/attr-lifetimebound.cpp
  clang/test/SemaCXX/builtin-std-move-nobuiltin.cpp
  clang/test/SemaCXX/builtin-std-move.cpp

Index: clang/test/SemaCXX/builtin-std-move.cpp
===
--- clang/test/SemaCXX/builtin-std-move.cpp
+++ clang/test/SemaCXX/builtin-std-move.cpp
@@ -43,6 +43,33 @@
 return static_cast(x);
   }
 
+  template  struct is_const { static constexpr bool value = false; };
+  template  struct is_const { static constexpr bool value = true; };
+
+  template  struct conditional { using type = T; };
+  template  struct conditional { using type = F; };
+
+  template 
+  using CopyConst = typename conditional<
+  is_const>::value,
+  const T, T>::type;
+
+  template 
+  using OverrideRef = typename conditional<
+  is_lvalue_reference::value,
+  typename remove_reference::type &,
+  typename remove_reference::type &&>::type;
+
+  template 
+  using ForwardLikeRetType = OverrideRef>;
+
+  template 
+  CONSTEXPR auto forward_like(T &) -> ForwardLikeRetType {
+using TT = typename remove_reference::type;
+static_assert(TT::moveable, "instantiated as_const"); // expected-error {{no member named 'moveable' in 'B'}}
+return static_cast>(t);
+  }
+
   template CONSTEXPR const T _const(T ) {
 static_assert(T::moveable, "instantiated as_const"); // expected-error {{no member named 'moveable' in 'B'}}
 return x;
@@ -92,14 +119,15 @@
 B &&(*pMove)(B&) = std::move; // #1 expected-note {{instantiation of}}
 B &&(*pMoveIfNoexcept)(B&) = ::move_if_noexcept; // #2 expected-note {{instantiation of}}
 B &&(*pForward)(B&) = ::forward; // #3 expected-note {{instantiation of}}
-const B &(*pAsConst)(B&) = ::as_const; // #4 expected-note {{instantiation of}}
-B *(*pAddressof)(B&) = ::addressof; // #5 expected-note {{instantiation of}}
-B *(*pUnderUnderAddressof)(B&) = ::__addressof; // #6 expected-note {{instantiation of}}
+B &&(*pForwardLike)(B&) = ::forward_like; // #4 expected-note {{instantiation of}}
+const B &(*pAsConst)(B&) = ::as_const; // #5 expected-note {{instantiation of}}
+B *(*pAddressof)(B&) = ::addressof; // #6 expected-note {{instantiation of}}
+B *(*pUnderUnderAddressof)(B&) = ::__addressof; // #7 expected-note {{instantiation of}}
 int (*pUnrelatedMove)(B, B) = std::move;
 
 struct C {};
-C &&()(C&) = std::move; // #7 expected-note {{instantiation of}}
-C &&()(C&) = std::forward; // #8 expected-note {{instantiation of}}
+C &&()(C&) = std::move; // #8 expected-note {{instantiation of}}
+C &&()(C&) = std::forward; // #9 expected-note {{instantiation of}}
 int ()(B, B) = std::move;
 
 #if __cplusplus <= 201703L
@@ -111,6 +139,7 @@
 // expected-warning@#6 {{non-addressable}}
 // expected-warning@#7 {{non-addressable}}
 // expected-warning@#8 {{non-addressable}}
+// expected-warning@#9 {{non-addressable}}
 #else
 // expected-error@#1 {{non-addressable}}
 // expected-error@#2 {{non-addressable}}
@@ -120,6 +149,7 @@
 // expected-error@#6 {{non-addressable}}
 // expected-error@#7 {{non-addressable}}
 // expected-error@#8 {{non-addressable}}
+// expected-error@#9 {{non-addressable}}
 #endif
 
 void attribute_const() {
@@ -127,6 +157,7 @@
   std::move(n); // expected-warning {{ignoring return value}}
   std::move_if_noexcept(n); // expected-warning {{ignoring return value}}
   std::forward(n); // expected-warning {{ignoring return value}}
+  std::forward_like(n); // expected-warning {{ignoring return value}}
   std::addressof(n); // expected-warning {{ignoring return value}}
   std::__addressof(n); // expected-warning {{ignoring return value}}
   std::as_const(n); // expected-warning {{ignoring return value}}
Index: clang/test/SemaCXX/builtin-std-move-nobuiltin.cpp
===
--- clang/test/SemaCXX/builtin-std-move-nobuiltin.cpp
+++ clang/test/SemaCXX/builtin-std-move-nobuiltin.cpp
@@ -1,6 +1,6 @@
 // RUN: %clang_cc1 -std=c++20 -verify %s -DBUILTIN=builtin
 // RUN: %clang_cc1 -std=c++20 -verify %s -DBUILTIN=nobuiltin -fno-builtin
-// RUN: 

[PATCH] D141744: [Clang] Add lifetimebound attribute to std::move/std::forward

2023-01-19 Thread Alexander Shaposhnikov 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 rG31b0be4eba9e: [Clang] Add lifetimebound attribute to 
std::move/std::forward (authored by alexander-shaposhnikov).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D141744

Files:
  clang/docs/LanguageExtensions.rst
  clang/docs/ReleaseNotes.rst
  clang/lib/Sema/SemaDecl.cpp
  clang/test/SemaCXX/attr-lifetimebound.cpp
  clang/test/SemaCXX/builtin-std-move.cpp
  clang/test/SemaCXX/builtins.cpp

Index: clang/test/SemaCXX/builtins.cpp
===
--- clang/test/SemaCXX/builtins.cpp
+++ clang/test/SemaCXX/builtins.cpp
@@ -40,7 +40,7 @@
   struct U { int n : 5; } u;
   int *pbf = __builtin_addressof(u.n); // expected-error {{address of bit-field requested}}
 
-  S *ptmp = __builtin_addressof(S{}); // expected-error {{taking the address of a temporary}}
+  S *ptmp = __builtin_addressof(S{}); // expected-error {{taking the address of a temporary}} expected-warning {{temporary whose address is used as value of local variable 'ptmp' will be destroyed at the end of the full-expression}}
 }
 
 namespace function_start {
Index: clang/test/SemaCXX/builtin-std-move.cpp
===
--- clang/test/SemaCXX/builtin-std-move.cpp
+++ clang/test/SemaCXX/builtin-std-move.cpp
@@ -85,7 +85,7 @@
 
 A _rval_as_lval() {
   std::forward(A()); // expected-warning {{const attribute}}
-  return std::forward(A()); // expected-note {{instantiation of}}
+  return std::forward(A()); // expected-note {{instantiation of}} expected-warning {{returning reference}}
 }
 
 struct B {};
Index: clang/test/SemaCXX/attr-lifetimebound.cpp
===
--- clang/test/SemaCXX/attr-lifetimebound.cpp
+++ clang/test/SemaCXX/attr-lifetimebound.cpp
@@ -113,3 +113,77 @@
   std::map m;
   const std::string  = findOrDefault(m, "foo"s, "bar"s); // expected-warning {{temporary bound to local reference 'v'}}
 }
+
+// definitions for std::move, std::forward et al.
+namespace std {
+inline namespace foo {
+
+template  struct remove_reference {
+typedef T type;
+};
+template  struct remove_reference {
+typedef T type;
+};
+template  struct remove_reference {
+typedef T type;
+};
+
+template  constexpr typename remove_reference::type &(T &) {
+return static_cast::type>(t);
+}
+
+template 
+constexpr T &(typename remove_reference::type ) {
+return static_cast(t);
+}
+
+template 
+constexpr T &(typename remove_reference::type &) {
+return static_cast(t);
+}
+
+template  constexpr const T _const(T ) { return x; }
+
+template  struct PickRef {
+using type = typename remove_reference::type &;
+};
+template  struct PickRef {
+using type = typename remove_reference::type &&;
+};
+
+template 
+auto move_if_noexcept(T ) ->
+typename PickRef(t)))>::type {
+return static_cast<
+typename PickRef(t)))>::type>(t);
+}
+
+template  T *addressof(T ) {
+return reinterpret_cast(
+_cast(reinterpret_cast(arg)));
+}
+
+} // namespace foo
+} // namespace std
+
+namespace move_forward_et_al_examples {
+  struct S {
+S () [[clang::lifetimebound]] { return *this; }
+  };
+
+  S & = std::move(S{}); // expected-warning {{temporary bound to local reference 'Move' will be destroyed at the end of the full-expression}}
+  S MoveOk = std::move(S{});
+
+  S & = std::forward(S{}); // expected-warning {{temporary bound to local reference 'Forward' will be destroyed at the end of the full-expression}}
+  S ForwardOk = std::forward(S{});
+
+  const S  = std::as_const(S{}.self()); // expected-warning {{temporary bound to local reference 'Const' will be destroyed at the end of the full-expression}}
+  const S ConstOk = std::as_const(S{}.self());
+
+  S & = std::move_if_noexcept(S{}.self()); // expected-warning {{temporary bound to local reference 'MoveIfNoExcept' will be destroyed at the end of the full-expression}}
+  S MoveIfNoExceptOk = std::move_if_noexcept(S{}.self());
+
+  S *AddressOf = std::addressof(S{}.self()); // expected-warning {{temporary whose address is used as value of local variable 'AddressOf' will be destroyed at the end of the full-expression}}
+  S X;
+  S *AddressOfOk = std::addressof(X);
+} // namespace move_forward_et_al_examples
Index: clang/lib/Sema/SemaDecl.cpp
===
--- clang/lib/Sema/SemaDecl.cpp
+++ clang/lib/Sema/SemaDecl.cpp
@@ -16182,6 +16182,24 @@
 default:
   break;
 }
+
+// Add lifetime attribute to std::move, std::fowrard et al.
+switch (BuiltinID) {
+case Builtin::BIaddressof:
+case Builtin::BI__addressof:
+case Builtin::BI__builtin_addressof:
+case Builtin::BIas_const:
+case Builtin::BIforward:
+case 

  1   2   3   4   >