[clang] 3faf1f1 - [Clang] Implement static operator[]

Roy Jacobson via cfe-commits cfe-commits at lists.llvm.org
Tue Nov 29 02:39:59 PST 2022


Author: Roy Jacobson
Date: 2022-11-29T12:39:52+02:00
New Revision: 3faf1f17a5c30a3ff1181898f2d2c7649066323d

URL: https://github.com/llvm/llvm-project/commit/3faf1f17a5c30a3ff1181898f2d2c7649066323d
DIFF: https://github.com/llvm/llvm-project/commit/3faf1f17a5c30a3ff1181898f2d2c7649066323d.diff

LOG: [Clang] Implement static operator[]

After accepted in Kona, update the code to accept static operator[] as well.

No big code changes: accept this operator as static in SemaDeclCXX, update AST call generation in SemaOverload and update feature macros + tests accordingly.

Reviewed By: cor3ntin, erichkeane, #clang-language-wg

Differential Revision: https://reviews.llvm.org/D138387

Added: 
    clang/test/CodeGenCXX/cxx2b-static-subscript-operator.cpp

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Frontend/InitPreprocessor.cpp
    clang/lib/Sema/SemaDeclCXX.cpp
    clang/lib/Sema/SemaOverload.cpp
    clang/test/CXX/over/over.oper/p7.cpp
    clang/test/CodeGenCXX/cxx2b-static-call-operator.cpp
    clang/test/Lexer/cxx-features.cpp
    clang/www/cxx_status.html

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 86911bd3b1a1e..ffce71f8c38a2 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -661,7 +661,7 @@ C++2b Feature Support
 ^^^^^^^^^^^^^^^^^^^^^
 
 - Support label at end of compound statement (`P2324 <https://wg21.link/p2324r2>`_).
-- Implemented `P1169R4: static operator() <https://wg21.link/P1169R4>`_.
+- Implemented `P1169R4: static operator() <https://wg21.link/P1169R4>`_ and `P2589R1: static operator[] <https://wg21.link/P2589R1>`_.
 - Implemented "char8_t Compatibility and Portability Fix" (`P2513R3 <https://wg21.link/P2513R3>`_).
   This change was applied to C++20 as a Defect Report.
 - Implemented "Permitting static constexpr variables in constexpr functions" (`P2647R1 <https://wg21.link/P2647R1>_`).

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 71093da21b0d5..84ce58c69848c 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9110,10 +9110,10 @@ def err_operator_overload_needs_class_or_enum : Error<
   "or enumeration type">;
 
 def err_operator_overload_variadic : Error<"overloaded %0 cannot be variadic">;
+def warn_cxx20_compat_operator_overload_static : Warning<
+  "declaring overloaded %0 as 'static' is incompatible with C++ standards "
+  "before C++2b">, InGroup<CXXPre2bCompat>, DefaultIgnore;
 def ext_operator_overload_static : ExtWarn<
-  "declaring overloaded %0 as 'static' is a C++2b extension">,
-  InGroup<CXXPre2bCompat>, DefaultIgnore;
-def err_call_operator_overload_static : ExtWarn<
   "declaring overloaded %0 as 'static' is a C++2b extension">, InGroup<CXX2b>;
 def err_operator_overload_static : Error<
   "overloaded %0 cannot be a static member function">;

diff  --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp
index 53a5f13e24afe..69480c9469262 100644
--- a/clang/lib/Frontend/InitPreprocessor.cpp
+++ b/clang/lib/Frontend/InitPreprocessor.cpp
@@ -695,7 +695,7 @@ static void InitializeCPlusPlusFeatureTestMacros(const LangOptions &LangOpts,
     Builder.defineMacro("__cpp_implicit_move", "202011L");
     Builder.defineMacro("__cpp_size_t_suffix", "202011L");
     Builder.defineMacro("__cpp_if_consteval", "202106L");
-    Builder.defineMacro("__cpp_multidimensional_subscript", "202110L");
+    Builder.defineMacro("__cpp_multidimensional_subscript", "202211L");
   }
 
   // We provide those C++2b features as extensions in earlier language modes, so

diff  --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 174fe43a2cd51..194298ab5f7bf 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -16015,10 +16015,11 @@ bool Sema::CheckOverloadedOperatorDeclaration(FunctionDecl *FnDecl) {
   //       function allowed to be static is the call operator function.
   if (CXXMethodDecl *MethodDecl = dyn_cast<CXXMethodDecl>(FnDecl)) {
     if (MethodDecl->isStatic()) {
-      if (Op == OO_Call)
+      if (Op == OO_Call || Op == OO_Subscript)
         Diag(FnDecl->getLocation(),
-             (LangOpts.CPlusPlus2b ? diag::ext_operator_overload_static
-                                   : diag::err_call_operator_overload_static))
+             (LangOpts.CPlusPlus2b
+                  ? diag::warn_cxx20_compat_operator_overload_static
+                  : diag::ext_operator_overload_static))
             << FnDecl;
       else
         return Diag(FnDecl->getLocation(), diag::err_operator_overload_static)

diff  --git a/clang/lib/Sema/SemaOverload.cpp b/clang/lib/Sema/SemaOverload.cpp
index f2c897dbe882f..a20d7dda79300 100644
--- a/clang/lib/Sema/SemaOverload.cpp
+++ b/clang/lib/Sema/SemaOverload.cpp
@@ -14425,12 +14425,17 @@ ExprResult Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
         // Convert the arguments.
         CXXMethodDecl *Method = cast<CXXMethodDecl>(FnDecl);
         SmallVector<Expr *, 2> MethodArgs;
-        ExprResult Arg0 = PerformObjectArgumentInitialization(
-            Args[0], /*Qualifier=*/nullptr, Best->FoundDecl, Method);
-        if (Arg0.isInvalid())
-          return ExprError();
 
-        MethodArgs.push_back(Arg0.get());
+        // Handle 'this' parameter if the selected function is not static.
+        if (Method->isInstance()) {
+          ExprResult Arg0 = PerformObjectArgumentInitialization(
+              Args[0], /*Qualifier=*/nullptr, Best->FoundDecl, Method);
+          if (Arg0.isInvalid())
+            return ExprError();
+
+          MethodArgs.push_back(Arg0.get());
+        }
+
         bool IsError = PrepareArgumentsForCallToObjectOfClassType(
             *this, MethodArgs, Method, ArgExpr, LLoc);
         if (IsError)
@@ -14450,9 +14455,16 @@ ExprResult Sema::CreateOverloadedArraySubscriptExpr(SourceLocation LLoc,
         ExprValueKind VK = Expr::getValueKindForType(ResultTy);
         ResultTy = ResultTy.getNonLValueExprType(Context);
 
-        CXXOperatorCallExpr *TheCall = CXXOperatorCallExpr::Create(
-            Context, OO_Subscript, FnExpr.get(), MethodArgs, ResultTy, VK, RLoc,
-            CurFPFeatureOverrides());
+        CallExpr *TheCall;
+        if (Method->isInstance())
+          TheCall = CXXOperatorCallExpr::Create(
+              Context, OO_Subscript, FnExpr.get(), MethodArgs, ResultTy, VK,
+              RLoc, CurFPFeatureOverrides());
+        else
+          TheCall =
+              CallExpr::Create(Context, FnExpr.get(), MethodArgs, ResultTy, VK,
+                               RLoc, CurFPFeatureOverrides());
+
         if (CheckCallReturnType(FnDecl->getReturnType(), LLoc, TheCall, FnDecl))
           return ExprError();
 

diff  --git a/clang/test/CXX/over/over.oper/p7.cpp b/clang/test/CXX/over/over.oper/p7.cpp
index c7a169de26cd2..7d304762c57f8 100644
--- a/clang/test/CXX/over/over.oper/p7.cpp
+++ b/clang/test/CXX/over/over.oper/p7.cpp
@@ -5,14 +5,19 @@
 
 struct Functor {
   static int operator()(int a, int b);
-  // cxx11-warning at -1 {{is a C++2b extension}}
-  // precxx2b-warning at -2 {{declaring overloaded 'operator()' as 'static' is a C++2b extension}}
+  static int operator[](int a1);
+  // cxx11-warning at -2 {{declaring overloaded 'operator()' as 'static' is a C++2b extension}}
+  // cxx11-warning at -2 {{declaring overloaded 'operator[]' as 'static' is a C++2b extension}}
+  // precxx2b-warning at -4 {{incompatible with C++ standards before C++2b}}
+  // precxx2b-warning at -4 {{incompatible with C++ standards before C++2b}}
 };
 
 struct InvalidParsing1 {
   extern int operator()(int a, int b);  // expected-error {{storage class specified}}
+  extern int operator[](int a1);  // expected-error {{storage class specified}}
 };
 
 struct InvalidParsing2 {
   extern static int operator()(int a, int b);  // expected-error {{storage class specified}} // expected-error {{cannot combine with previous 'extern' declaration specifier}}
+  extern static int operator[](int a);  // expected-error {{storage class specified}} // expected-error {{cannot combine with previous 'extern' declaration specifier}}
 };

diff  --git a/clang/test/CodeGenCXX/cxx2b-static-call-operator.cpp b/clang/test/CodeGenCXX/cxx2b-static-call-operator.cpp
index e85974d911f7c..1d0b05ba10aa3 100644
--- a/clang/test/CodeGenCXX/cxx2b-static-call-operator.cpp
+++ b/clang/test/CodeGenCXX/cxx2b-static-call-operator.cpp
@@ -28,6 +28,7 @@ void call_static_call_operator() {
   f(101, 102);
   f.operator()(201, 202);
   Functor{}(301, 302);
+  Functor::operator()(401, 402);
 }
 
 // CHECK:      define {{.*}}call_static_call_operator{{.*}}
@@ -35,6 +36,7 @@ void call_static_call_operator() {
 // CHECK:        {{.*}} = call noundef i32 {{.*}}Functor{{.*}}(i32 noundef 101, i32 noundef 102)
 // CHECK-NEXT:   {{.*}} = call noundef i32 {{.*}}Functor{{.*}}(i32 noundef 201, i32 noundef 202)
 // CHECK-NEXT:   {{.*}} = call noundef i32 {{.*}}Functor{{.*}}(i32 noundef 301, i32 noundef 302)
+// CHECK-NEXT:   {{.*}} = call noundef i32 {{.*}}Functor{{.*}}(i32 noundef 401, i32 noundef 402)
 // CHECK-NEXT:   ret void
 // CHECK-NEXT: }
 

diff  --git a/clang/test/CodeGenCXX/cxx2b-static-subscript-operator.cpp b/clang/test/CodeGenCXX/cxx2b-static-subscript-operator.cpp
new file mode 100644
index 0000000000000..3d8957698f5a7
--- /dev/null
+++ b/clang/test/CodeGenCXX/cxx2b-static-subscript-operator.cpp
@@ -0,0 +1,66 @@
+// RUN: %clang_cc1 -std=c++2b %s -emit-llvm -triple x86_64-linux -o - | FileCheck %s
+// RUN: %clang_cc1 -std=c++2b %s -emit-llvm -triple x86_64-windows-msvc -o - | FileCheck %s
+
+struct Functor {
+  static int operator[](int x, int y) {
+    return x + y;
+  }
+};
+
+void call_static_subscript_operator() {
+  Functor f;
+  f[101, 102];
+  f.operator[](201, 202);
+  Functor{}[301, 302];
+  Functor::operator[](401, 402);
+}
+
+// CHECK:      define {{.*}}call_static_subscript_operator{{.*}}
+// CHECK-NEXT: entry:
+// CHECK:        {{.*}} = call noundef i32 {{.*}}Functor{{.*}}(i32 noundef 101, i32 noundef 102)
+// CHECK-NEXT:   {{.*}} = call noundef i32 {{.*}}Functor{{.*}}(i32 noundef 201, i32 noundef 202)
+// CHECK-NEXT:   {{.*}} = call noundef i32 {{.*}}Functor{{.*}}(i32 noundef 301, i32 noundef 302)
+// CHECK-NEXT:   {{.*}} = call noundef i32 {{.*}}Functor{{.*}}(i32 noundef 401, i32 noundef 402)
+// CHECK-NEXT:   ret void
+// CHECK-NEXT: }
+
+struct FunctorConsteval {
+  consteval static int operator[](int x, int y) {
+      return x + y;
+  }
+};
+
+struct FunctorConstexpr {
+  constexpr static int operator[](int x, int y) {
+      return x + y;
+  }
+};
+
+void test_consteval_constexpr() {
+  int x = 0;
+  int y = FunctorConstexpr{}[x, 2];
+  constexpr int z1 = FunctorConsteval{}[2, 2];
+  constexpr int z2 = FunctorConstexpr{}[2, 2];
+  
+  static_assert(z1 == 4);
+  static_assert(z2 == 4);
+}
+
+template <class T>
+struct DepFunctor {
+  static int operator[](T t) {
+    return int(t);
+  }
+};
+
+void test_dep_functors() {
+  int x = DepFunctor<float>{}[1.0f];
+  int y = DepFunctor<bool>{}[true];
+}
+
+// CHECK:      define {{.*}}test_dep_functors{{.*}}
+// CHECK-NEXT: entry:
+// CHECK:        %call = call noundef i32 {{.*}}DepFunctor{{.*}}(float noundef 1.000000e+00)
+// CHECK:        %call1 = call noundef i32 {{.*}}DepFunctor{{.*}}(i1 noundef zeroext true)
+// CHECK:        ret void
+// CHECK-NEXT: }

diff  --git a/clang/test/Lexer/cxx-features.cpp b/clang/test/Lexer/cxx-features.cpp
index e577801560292..67b5265d7daf0 100644
--- a/clang/test/Lexer/cxx-features.cpp
+++ b/clang/test/Lexer/cxx-features.cpp
@@ -43,7 +43,7 @@
 #error "wrong value for __cpp_if_consteval"
 #endif
 
-#if check(multidimensional_subscript, 0, 0, 0, 0, 0, 202110)
+#if check(multidimensional_subscript, 0, 0, 0, 0, 0, 202211)
 #error "wrong value for __cpp_multidimensional_subscript"
 #endif
 

diff  --git a/clang/www/cxx_status.html b/clang/www/cxx_status.html
index e296d5d3c597c..9559c562bdec0 100755
--- a/clang/www/cxx_status.html
+++ b/clang/www/cxx_status.html
@@ -1518,7 +1518,7 @@ <h2 id="cxx23">C++2b implementation status</h2>
     <tr>
       <td>static <code>operator[]</code></td>
       <td><a href="https://wg21.link/P2589R1">P2589R1</a></td>
-      <td class="none" align="center">No</td>
+      <td class="unreleased" align="center">16</td>
     </tr>
     <tr>
       <td>Permitting static constexpr variables in constexpr functions (DR)</td>


        


More information about the cfe-commits mailing list