[PATCH] D122808: [clang] Fix warnings with `-Wdeprecated-enum-enum-conversion` is enabled

2022-03-31 Thread Antonio Frighetto via Phabricator via cfe-commits
antoniofrighetto created this revision.
antoniofrighetto added reviewers: aaron.ballman, dblaikie.
antoniofrighetto added a project: clang.
Herald added a project: All.
antoniofrighetto requested review of this revision.
Herald added a subscriber: cfe-commits.

clang may throw the following warning: 
`include/clang/AST/DeclarationName.h:210:52: error: arithmetic between 
different enumeration types ('clang::DeclarationName::StoredNameKind' and 
'clang::detail::DeclarationNameExtra::ExtraKind') is deprecated` when flags 
`-Werror,-Wdeprecated-enum-enum-conversion` are on.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D122808

Files:
  clang/include/clang/AST/DeclarationName.h


Index: clang/include/clang/AST/DeclarationName.h
===
--- clang/include/clang/AST/DeclarationName.h
+++ clang/include/clang/AST/DeclarationName.h
@@ -27,6 +27,7 @@
 #include 
 #include 
 #include 
+#include 
 
 namespace clang {
 
@@ -192,6 +193,13 @@
 "The various classes that DeclarationName::Ptr can point to"
 " must be at least aligned to 8 bytes!");
 
+  static_assert(
+  std::is_same,
+   std::underlying_type_t<
+   detail::DeclarationNameExtra::ExtraKind>>::value,
+  "The various enums used to compute values for NameKind should all have "
+  "the same underlying type");
+
 public:
   /// The kind of the name stored in this DeclarationName.
   /// The first 7 enumeration values are stored inline and correspond
@@ -205,15 +213,30 @@
 CXXDestructorName = StoredCXXDestructorName,
 CXXConversionFunctionName = StoredCXXConversionFunctionName,
 CXXOperatorName = StoredCXXOperatorName,
-CXXDeductionGuideName = UncommonNameKindOffset +
-
detail::DeclarationNameExtra::CXXDeductionGuideName,
+CXXDeductionGuideName =
+static_cast>(
+UncommonNameKindOffset) +
+static_cast<
+std::underlying_type_t>(
+detail::DeclarationNameExtra::CXXDeductionGuideName),
 CXXLiteralOperatorName =
-UncommonNameKindOffset +
-detail::DeclarationNameExtra::CXXLiteralOperatorName,
-CXXUsingDirective = UncommonNameKindOffset +
-detail::DeclarationNameExtra::CXXUsingDirective,
-ObjCMultiArgSelector = UncommonNameKindOffset +
-   detail::DeclarationNameExtra::ObjCMultiArgSelector
+static_cast>(
+UncommonNameKindOffset) +
+static_cast<
+std::underlying_type_t>(
+detail::DeclarationNameExtra::CXXLiteralOperatorName),
+CXXUsingDirective =
+static_cast>(
+UncommonNameKindOffset) +
+static_cast<
+std::underlying_type_t>(
+detail::DeclarationNameExtra::CXXUsingDirective),
+ObjCMultiArgSelector =
+static_cast>(
+UncommonNameKindOffset) +
+static_cast<
+std::underlying_type_t>(
+detail::DeclarationNameExtra::ObjCMultiArgSelector),
   };
 
 private:


Index: clang/include/clang/AST/DeclarationName.h
===
--- clang/include/clang/AST/DeclarationName.h
+++ clang/include/clang/AST/DeclarationName.h
@@ -27,6 +27,7 @@
 #include 
 #include 
 #include 
+#include 
 
 namespace clang {
 
@@ -192,6 +193,13 @@
 "The various classes that DeclarationName::Ptr can point to"
 " must be at least aligned to 8 bytes!");
 
+  static_assert(
+  std::is_same,
+   std::underlying_type_t<
+   detail::DeclarationNameExtra::ExtraKind>>::value,
+  "The various enums used to compute values for NameKind should all have "
+  "the same underlying type");
+
 public:
   /// The kind of the name stored in this DeclarationName.
   /// The first 7 enumeration values are stored inline and correspond
@@ -205,15 +213,30 @@
 CXXDestructorName = StoredCXXDestructorName,
 CXXConversionFunctionName = StoredCXXConversionFunctionName,
 CXXOperatorName = StoredCXXOperatorName,
-CXXDeductionGuideName = UncommonNameKindOffset +
-detail::DeclarationNameExtra::CXXDeductionGuideName,
+CXXDeductionGuideName =
+static_cast>(
+UncommonNameKindOffset) +
+static_cast<
+std::underlying_type_t>(
+detail::DeclarationNameExtra::CXXDeductionGuideName),
 CXXLiteralOperatorName =
-UncommonNameKindOffset +
-detail::DeclarationNameExtra::CXXLiteralOperatorName,
-CXXUsingDirective = UncommonNameKindOffset +
-detail::DeclarationNameExtra::CXXUsingDirective,
-ObjCMultiArgSelector = UncommonNameKindOffset +
-   detail::DeclarationNameExtra::ObjCMultiArgSelector
+static_cast>(
+UncommonNameKindOffset) +
+stati

[PATCH] D122808: [clang] Fix warnings when `-Wdeprecated-enum-enum-conversion` is enabled

2022-04-04 Thread Antonio Frighetto via Phabricator via cfe-commits
antoniofrighetto added a comment.

Looks definitely better! How about this slightly changed version protecting the 
interface?

  /// Helper which adds two underlying types of enumeration type.
  template , 
std::underlying_type_t>,
typename UT2 = std::enable_if_t, 
std::underlying_type_t>>
  constexpr auto addEnumValues(EnumTy1 LHS, EnumTy2 RHS) {
return static_cast(LHS) + static_cast(RHS);
  }

I feel like this is something we may wish to readopt in the future for other 
similar cases as well  (e.g., `-Wdeprecated-anon-enum-enum-conversion` in 
`Comment.h`).


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D122808

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


[PATCH] D122808: [clang] Fix warnings when `-Wdeprecated-enum-enum-conversion` is enabled

2022-04-05 Thread Antonio Frighetto via Phabricator via cfe-commits
antoniofrighetto updated this revision to Diff 420458.
Herald added subscribers: llvm-commits, dexonsmith.
Herald added a project: LLVM.

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

https://reviews.llvm.org/D122808

Files:
  clang/include/clang/AST/DeclarationName.h
  llvm/include/llvm/ADT/STLExtras.h


Index: llvm/include/llvm/ADT/STLExtras.h
===
--- llvm/include/llvm/ADT/STLExtras.h
+++ llvm/include/llvm/ADT/STLExtras.h
@@ -203,6 +203,16 @@
 template 
 using TypeAtIndex = std::tuple_element_t>;
 
+/// Helper which adds two underlying types of enumeration type.
+template ,
+  std::underlying_type_t>,
+  typename UT2 = std::enable_if_t,
+  std::underlying_type_t>>
+constexpr auto addEnumValues(EnumTy1 LHS, EnumTy2 RHS) {
+  return static_cast(LHS) + static_cast(RHS);
+}
+
 
//===--===//
 // Extra additions to 
 
//===--===//
Index: clang/include/clang/AST/DeclarationName.h
===
--- clang/include/clang/AST/DeclarationName.h
+++ clang/include/clang/AST/DeclarationName.h
@@ -21,6 +21,7 @@
 #include "clang/Basic/SourceLocation.h"
 #include "llvm/ADT/DenseMapInfo.h"
 #include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/type_traits.h"
 #include 
@@ -192,6 +193,13 @@
 "The various classes that DeclarationName::Ptr can point to"
 " must be at least aligned to 8 bytes!");
 
+  static_assert(
+  std::is_same,
+   std::underlying_type_t<
+   detail::DeclarationNameExtra::ExtraKind>>::value,
+  "The various enums used to compute values for NameKind should "
+  "all have the same underlying type");
+
 public:
   /// The kind of the name stored in this DeclarationName.
   /// The first 7 enumeration values are stored inline and correspond
@@ -205,15 +213,18 @@
 CXXDestructorName = StoredCXXDestructorName,
 CXXConversionFunctionName = StoredCXXConversionFunctionName,
 CXXOperatorName = StoredCXXOperatorName,
-CXXDeductionGuideName = UncommonNameKindOffset +
-
detail::DeclarationNameExtra::CXXDeductionGuideName,
-CXXLiteralOperatorName =
-UncommonNameKindOffset +
-detail::DeclarationNameExtra::CXXLiteralOperatorName,
-CXXUsingDirective = UncommonNameKindOffset +
-detail::DeclarationNameExtra::CXXUsingDirective,
-ObjCMultiArgSelector = UncommonNameKindOffset +
-   detail::DeclarationNameExtra::ObjCMultiArgSelector
+CXXDeductionGuideName = llvm::addEnumValues(
+UncommonNameKindOffset,
+detail::DeclarationNameExtra::CXXDeductionGuideName),
+CXXLiteralOperatorName = llvm::addEnumValues(
+UncommonNameKindOffset,
+detail::DeclarationNameExtra::CXXLiteralOperatorName),
+CXXUsingDirective =
+llvm::addEnumValues(UncommonNameKindOffset,
+detail::DeclarationNameExtra::CXXUsingDirective),
+ObjCMultiArgSelector =
+llvm::addEnumValues(UncommonNameKindOffset,
+
detail::DeclarationNameExtra::ObjCMultiArgSelector),
   };
 
 private:


Index: llvm/include/llvm/ADT/STLExtras.h
===
--- llvm/include/llvm/ADT/STLExtras.h
+++ llvm/include/llvm/ADT/STLExtras.h
@@ -203,6 +203,16 @@
 template 
 using TypeAtIndex = std::tuple_element_t>;
 
+/// Helper which adds two underlying types of enumeration type.
+template ,
+  std::underlying_type_t>,
+  typename UT2 = std::enable_if_t,
+  std::underlying_type_t>>
+constexpr auto addEnumValues(EnumTy1 LHS, EnumTy2 RHS) {
+  return static_cast(LHS) + static_cast(RHS);
+}
+
 //===--===//
 // Extra additions to 
 //===--===//
Index: clang/include/clang/AST/DeclarationName.h
===
--- clang/include/clang/AST/DeclarationName.h
+++ clang/include/clang/AST/DeclarationName.h
@@ -21,6 +21,7 @@
 #include "clang/Basic/SourceLocation.h"
 #include "llvm/ADT/DenseMapInfo.h"
 #include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/type_traits.h"
 #include 
@@ -192,6 +193,13 @@
 "The various classes that DeclarationName::Ptr can point to"
 " must be at least aligned to 8 bytes!");
 
+  static_assert(
+  std::is_same

[PATCH] D122808: [clang] Fix warnings when `-Wdeprecated-enum-enum-conversion` is enabled

2022-04-06 Thread Antonio Frighetto via Phabricator via cfe-commits
antoniofrighetto updated this revision to Diff 420894.

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

https://reviews.llvm.org/D122808

Files:
  clang/include/clang/AST/DeclarationName.h
  llvm/include/llvm/ADT/STLExtras.h
  llvm/unittests/ADT/STLExtrasTest.cpp

Index: llvm/unittests/ADT/STLExtrasTest.cpp
===
--- llvm/unittests/ADT/STLExtrasTest.cpp
+++ llvm/unittests/ADT/STLExtrasTest.cpp
@@ -989,4 +989,26 @@
   static_assert(!is_contained({1, 2, 3, 4}, 5), "It's not there :(");
 }
 
+TEST(STLExtrasTest, addEnumValues) {
+  enum A { Zero = 0, One = 1 };
+  enum B { IntMax = INT_MAX, ULongLongMax = ULLONG_MAX };
+  enum class C : unsigned { Two = 2 };
+
+  // Non-fixed underlying types, with same underlying types
+  static_assert(addEnumValues(Zero, One) == 1);
+  static_assert(addEnumValues(IntMax, ULongLongMax) ==
+INT_MAX + static_cast(ULLONG_MAX));
+  // Non-fixed underlying types, with different underlying types
+  static_assert(addEnumValues(Zero, IntMax) == INT_MAX);
+  static_assert(addEnumValues(One, ULongLongMax) ==
+1 + static_cast(ULLONG_MAX));
+  // Non-fixed underlying type enum and fixed underlying type enum, with same
+  // underlying types
+  static_assert(addEnumValues(One, C::Two) == 3);
+  // Non-fixed underlying type enum and fixed underlying type enum, with
+  // different underlying types
+  static_assert(addEnumValues(ULongLongMax, C::Two) ==
+static_cast(ULLONG_MAX) + 2);
+}
+
 } // namespace
Index: llvm/include/llvm/ADT/STLExtras.h
===
--- llvm/include/llvm/ADT/STLExtras.h
+++ llvm/include/llvm/ADT/STLExtras.h
@@ -203,6 +203,17 @@
 template 
 using TypeAtIndex = std::tuple_element_t>;
 
+/// Helper which adds two underlying types of enumeration type.
+/// Implicit conversion to a common type is accepted.
+template ::value,
+  std::underlying_type_t>,
+  typename UT2 = std::enable_if_t::value,
+  std::underlying_type_t>>
+constexpr auto addEnumValues(EnumTy1 LHS, EnumTy2 RHS) {
+  return static_cast(LHS) + static_cast(RHS);
+}
+
 //===--===//
 // Extra additions to 
 //===--===//
Index: clang/include/clang/AST/DeclarationName.h
===
--- clang/include/clang/AST/DeclarationName.h
+++ clang/include/clang/AST/DeclarationName.h
@@ -21,6 +21,7 @@
 #include "clang/Basic/SourceLocation.h"
 #include "llvm/ADT/DenseMapInfo.h"
 #include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/type_traits.h"
 #include 
@@ -192,6 +193,13 @@
 "The various classes that DeclarationName::Ptr can point to"
 " must be at least aligned to 8 bytes!");
 
+  static_assert(
+  std::is_same,
+   std::underlying_type_t<
+   detail::DeclarationNameExtra::ExtraKind>>::value,
+  "The various enums used to compute values for NameKind should "
+  "all have the same underlying type");
+
 public:
   /// The kind of the name stored in this DeclarationName.
   /// The first 7 enumeration values are stored inline and correspond
@@ -205,15 +213,18 @@
 CXXDestructorName = StoredCXXDestructorName,
 CXXConversionFunctionName = StoredCXXConversionFunctionName,
 CXXOperatorName = StoredCXXOperatorName,
-CXXDeductionGuideName = UncommonNameKindOffset +
-detail::DeclarationNameExtra::CXXDeductionGuideName,
-CXXLiteralOperatorName =
-UncommonNameKindOffset +
-detail::DeclarationNameExtra::CXXLiteralOperatorName,
-CXXUsingDirective = UncommonNameKindOffset +
-detail::DeclarationNameExtra::CXXUsingDirective,
-ObjCMultiArgSelector = UncommonNameKindOffset +
-   detail::DeclarationNameExtra::ObjCMultiArgSelector
+CXXDeductionGuideName = llvm::addEnumValues(
+UncommonNameKindOffset,
+detail::DeclarationNameExtra::CXXDeductionGuideName),
+CXXLiteralOperatorName = llvm::addEnumValues(
+UncommonNameKindOffset,
+detail::DeclarationNameExtra::CXXLiteralOperatorName),
+CXXUsingDirective =
+llvm::addEnumValues(UncommonNameKindOffset,
+detail::DeclarationNameExtra::CXXUsingDirective),
+ObjCMultiArgSelector =
+llvm::addEnumValues(UncommonNameKindOffset,
+detail::DeclarationNameExtra::ObjCMultiArgSelector),
   };
 
 private:
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D122808: [clang] Fix warnings when `-Wdeprecated-enum-enum-conversion` is enabled

2022-04-06 Thread Antonio Frighetto via Phabricator via cfe-commits
antoniofrighetto added a comment.

Fixed the change, and added a new test. Hope the coverage is at a fairly good 
level now!


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

https://reviews.llvm.org/D122808

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


[PATCH] D122808: [clang] Fix warnings when `-Wdeprecated-enum-enum-conversion` is enabled

2022-04-06 Thread Antonio Frighetto via Phabricator via cfe-commits
antoniofrighetto updated this revision to Diff 420957.

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

https://reviews.llvm.org/D122808

Files:
  clang/include/clang/AST/DeclarationName.h
  llvm/include/llvm/ADT/STLExtras.h
  llvm/unittests/ADT/STLExtrasTest.cpp

Index: llvm/unittests/ADT/STLExtrasTest.cpp
===
--- llvm/unittests/ADT/STLExtrasTest.cpp
+++ llvm/unittests/ADT/STLExtrasTest.cpp
@@ -989,4 +989,32 @@
   static_assert(!is_contained({1, 2, 3, 4}, 5), "It's not there :(");
 }
 
+TEST(STLExtrasTest, addEnumValues) {
+  enum A { Zero = 0, One = 1 };
+  enum B { IntMax = INT_MAX, ULongLongMax = ULLONG_MAX };
+  enum class C : unsigned { Two = 2 };
+
+  // Non-fixed underlying types, with same underlying types
+  static_assert(addEnumValues(Zero, One) == 1,
+"addEnumValues(Zero, One) failed.");
+  static_assert(addEnumValues(IntMax, ULongLongMax) ==
+INT_MAX + static_cast(ULLONG_MAX),
+"addEnumValues(IntMax, ULongLongMax) failed.");
+  // Non-fixed underlying types, with different underlying types
+  static_assert(addEnumValues(Zero, IntMax) == INT_MAX,
+"addEnumValues(Zero, IntMax) failed.");
+  static_assert(addEnumValues(One, ULongLongMax) ==
+1 + static_cast(ULLONG_MAX),
+"addEnumValues(One, ULongLongMax) failed.");
+  // Non-fixed underlying type enum and fixed underlying type enum, with same
+  // underlying types
+  static_assert(addEnumValues(One, C::Two) == 3,
+"addEnumValues(One, C::Two) failed.");
+  // Non-fixed underlying type enum and fixed underlying type enum, with
+  // different underlying types
+  static_assert(addEnumValues(ULongLongMax, C::Two) ==
+static_cast(ULLONG_MAX) + 2,
+"addEnumValues(ULongLongMax, C::Two) failed.");
+}
+
 } // namespace
Index: llvm/include/llvm/ADT/STLExtras.h
===
--- llvm/include/llvm/ADT/STLExtras.h
+++ llvm/include/llvm/ADT/STLExtras.h
@@ -203,6 +203,17 @@
 template 
 using TypeAtIndex = std::tuple_element_t>;
 
+/// Helper which adds two underlying types of enumeration type.
+/// Implicit conversion to a common type is accepted.
+template ::value,
+  std::underlying_type_t>,
+  typename UT2 = std::enable_if_t::value,
+  std::underlying_type_t>>
+constexpr auto addEnumValues(EnumTy1 LHS, EnumTy2 RHS) {
+  return static_cast(LHS) + static_cast(RHS);
+}
+
 //===--===//
 // Extra additions to 
 //===--===//
Index: clang/include/clang/AST/DeclarationName.h
===
--- clang/include/clang/AST/DeclarationName.h
+++ clang/include/clang/AST/DeclarationName.h
@@ -21,6 +21,7 @@
 #include "clang/Basic/SourceLocation.h"
 #include "llvm/ADT/DenseMapInfo.h"
 #include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/type_traits.h"
 #include 
@@ -192,6 +193,13 @@
 "The various classes that DeclarationName::Ptr can point to"
 " must be at least aligned to 8 bytes!");
 
+  static_assert(
+  std::is_same,
+   std::underlying_type_t<
+   detail::DeclarationNameExtra::ExtraKind>>::value,
+  "The various enums used to compute values for NameKind should "
+  "all have the same underlying type");
+
 public:
   /// The kind of the name stored in this DeclarationName.
   /// The first 7 enumeration values are stored inline and correspond
@@ -205,15 +213,18 @@
 CXXDestructorName = StoredCXXDestructorName,
 CXXConversionFunctionName = StoredCXXConversionFunctionName,
 CXXOperatorName = StoredCXXOperatorName,
-CXXDeductionGuideName = UncommonNameKindOffset +
-detail::DeclarationNameExtra::CXXDeductionGuideName,
-CXXLiteralOperatorName =
-UncommonNameKindOffset +
-detail::DeclarationNameExtra::CXXLiteralOperatorName,
-CXXUsingDirective = UncommonNameKindOffset +
-detail::DeclarationNameExtra::CXXUsingDirective,
-ObjCMultiArgSelector = UncommonNameKindOffset +
-   detail::DeclarationNameExtra::ObjCMultiArgSelector
+CXXDeductionGuideName = llvm::addEnumValues(
+UncommonNameKindOffset,
+detail::DeclarationNameExtra::CXXDeductionGuideName),
+CXXLiteralOperatorName = llvm::addEnumValues(
+UncommonNameKindOffset,
+detail::DeclarationNameExtra::CXXLiteralOperatorName),
+CXXUsingDirective =
+llvm::addEnumValues(UncommonNameKindOffset,
+detail::DeclarationNameExtra::CXX

[PATCH] D122808: [clang] Fix warnings when `-Wdeprecated-enum-enum-conversion` is enabled

2022-04-07 Thread Antonio Frighetto via Phabricator via cfe-commits
antoniofrighetto updated this revision to Diff 42.

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

https://reviews.llvm.org/D122808

Files:
  clang/include/clang/AST/DeclarationName.h
  llvm/include/llvm/ADT/STLExtras.h
  llvm/unittests/ADT/STLExtrasTest.cpp

Index: llvm/unittests/ADT/STLExtrasTest.cpp
===
--- llvm/unittests/ADT/STLExtrasTest.cpp
+++ llvm/unittests/ADT/STLExtrasTest.cpp
@@ -9,6 +9,7 @@
 #include "llvm/ADT/STLExtras.h"
 #include "gtest/gtest.h"
 
+#include 
 #include 
 #include 
 
@@ -989,4 +990,32 @@
   static_assert(!is_contained({1, 2, 3, 4}, 5), "It's not there :(");
 }
 
+TEST(STLExtrasTest, addEnumValues) {
+  enum A { Zero = 0, One = 1 };
+  enum B { IntMax = INT_MAX, ULongLongMax = ULLONG_MAX };
+  enum class C : unsigned { Two = 2 };
+
+  // Non-fixed underlying types, with same underlying types
+  static_assert(addEnumValues(Zero, One) == 1,
+"addEnumValues(Zero, One) failed.");
+  static_assert(addEnumValues(IntMax, ULongLongMax) ==
+INT_MAX + static_cast(ULLONG_MAX),
+"addEnumValues(IntMax, ULongLongMax) failed.");
+  // Non-fixed underlying types, with different underlying types
+  static_assert(addEnumValues(Zero, IntMax) == INT_MAX,
+"addEnumValues(Zero, IntMax) failed.");
+  static_assert(addEnumValues(One, ULongLongMax) ==
+1 + static_cast(ULLONG_MAX),
+"addEnumValues(One, ULongLongMax) failed.");
+  // Non-fixed underlying type enum and fixed underlying type enum, with same
+  // underlying types
+  static_assert(addEnumValues(One, C::Two) == 3,
+"addEnumValues(One, C::Two) failed.");
+  // Non-fixed underlying type enum and fixed underlying type enum, with
+  // different underlying types
+  static_assert(addEnumValues(ULongLongMax, C::Two) ==
+static_cast(ULLONG_MAX) + 2,
+"addEnumValues(ULongLongMax, C::Two) failed.");
+}
+
 } // namespace
Index: llvm/include/llvm/ADT/STLExtras.h
===
--- llvm/include/llvm/ADT/STLExtras.h
+++ llvm/include/llvm/ADT/STLExtras.h
@@ -203,6 +203,17 @@
 template 
 using TypeAtIndex = std::tuple_element_t>;
 
+/// Helper which adds two underlying types of enumeration type.
+/// Implicit conversion to a common type is accepted.
+template ::value,
+  std::underlying_type_t>,
+  typename UT2 = std::enable_if_t::value,
+  std::underlying_type_t>>
+constexpr auto addEnumValues(EnumTy1 LHS, EnumTy2 RHS) {
+  return static_cast(LHS) + static_cast(RHS);
+}
+
 //===--===//
 // Extra additions to 
 //===--===//
Index: clang/include/clang/AST/DeclarationName.h
===
--- clang/include/clang/AST/DeclarationName.h
+++ clang/include/clang/AST/DeclarationName.h
@@ -21,6 +21,7 @@
 #include "clang/Basic/SourceLocation.h"
 #include "llvm/ADT/DenseMapInfo.h"
 #include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/type_traits.h"
 #include 
@@ -192,6 +193,13 @@
 "The various classes that DeclarationName::Ptr can point to"
 " must be at least aligned to 8 bytes!");
 
+  static_assert(
+  std::is_same,
+   std::underlying_type_t<
+   detail::DeclarationNameExtra::ExtraKind>>::value,
+  "The various enums used to compute values for NameKind should "
+  "all have the same underlying type");
+
 public:
   /// The kind of the name stored in this DeclarationName.
   /// The first 7 enumeration values are stored inline and correspond
@@ -205,15 +213,18 @@
 CXXDestructorName = StoredCXXDestructorName,
 CXXConversionFunctionName = StoredCXXConversionFunctionName,
 CXXOperatorName = StoredCXXOperatorName,
-CXXDeductionGuideName = UncommonNameKindOffset +
-detail::DeclarationNameExtra::CXXDeductionGuideName,
-CXXLiteralOperatorName =
-UncommonNameKindOffset +
-detail::DeclarationNameExtra::CXXLiteralOperatorName,
-CXXUsingDirective = UncommonNameKindOffset +
-detail::DeclarationNameExtra::CXXUsingDirective,
-ObjCMultiArgSelector = UncommonNameKindOffset +
-   detail::DeclarationNameExtra::ObjCMultiArgSelector
+CXXDeductionGuideName = llvm::addEnumValues(
+UncommonNameKindOffset,
+detail::DeclarationNameExtra::CXXDeductionGuideName),
+CXXLiteralOperatorName = llvm::addEnumValues(
+UncommonNameKindOffset,
+detail::DeclarationNameExtra::CXXLiteralOperatorName),
+CXXUsingDirective =
+  

[PATCH] D122808: [clang] Fix warnings when `-Wdeprecated-enum-enum-conversion` is enabled

2022-04-07 Thread Antonio Frighetto via Phabricator via cfe-commits
antoniofrighetto added inline comments.



Comment at: llvm/unittests/ADT/STLExtrasTest.cpp:994
+  enum A { Zero = 0, One = 1 };
+  enum B { IntMax = INT_MAX, ULongLongMax = ULLONG_MAX };
+  enum class C : unsigned { Two = 2 };

aaron.ballman wrote:
> It looks like you need to include `` for the macros.
Right, saw the CI, fixed, thanks! :)


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

https://reviews.llvm.org/D122808

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


[PATCH] D122808: [clang] Fix warnings when `-Wdeprecated-enum-enum-conversion` is enabled

2022-04-07 Thread Antonio Frighetto via Phabricator via cfe-commits
antoniofrighetto added a comment.

Awesome, thank you for reviewing this! PS: I do not have commit access, feel 
free to close it, if you say.


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

https://reviews.llvm.org/D122808

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


[PATCH] D155716: [clang][CodeGen] Introduce `-frecord-command-line` for MachO

2023-07-19 Thread Antonio Frighetto via Phabricator via cfe-commits
antoniofrighetto created this revision.
antoniofrighetto added reviewers: davide, ab, scott.linder.
Herald added a subscriber: hiraditya.
Herald added a project: All.
antoniofrighetto requested review of this revision.
Herald added subscribers: llvm-commits, cfe-commits, MaskRay.
Herald added projects: clang, LLVM.

Allow clang driver command-line recording when targeting MachO object files as 
well.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D155716

Files:
  clang/lib/Driver/ToolChains/Clang.cpp
  llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
  llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
  llvm/test/CodeGen/AArch64/arm64-command-line-metadata.ll


Index: llvm/test/CodeGen/AArch64/arm64-command-line-metadata.ll
===
--- /dev/null
+++ llvm/test/CodeGen/AArch64/arm64-command-line-metadata.ll
@@ -0,0 +1,15 @@
+; RUN: llc -mtriple=aarch64-apple-darwin < %s | FileCheck %s
+; Verify that llvm.commandline metadata is emitted to a
+; MachO section named __command_line within __TEXT segment.
+
+; CHECK:.section   __TEXT,__text,regular,pure_instructions
+; CHECK-NEXT:   .section   __TEXT,__command_line
+; CHECK-NEXT:   .space 1
+; CHECK-NEXT:   .ascii "clang -command1"
+; CHECK-NEXT:   .space 1
+; CHECK-NEXT:   .ascii "clang -command2"
+; CHECK-NEXT:   .space 1
+
+!llvm.commandline = !{!0, !1}
+!0 = !{!"clang -command1"}
+!1 = !{!"clang -command2"}
Index: llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
===
--- llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -1420,6 +1420,11 @@
   return ReadOnlySection;  // .const
 }
 
+MCSection *TargetLoweringObjectFileMachO::getSectionForCommandLines() const {
+  return getContext().getMachOSection("__TEXT", "__command_line", 0,
+  SectionKind::getReadOnly());
+}
+
 const MCExpr *TargetLoweringObjectFileMachO::getTTypeGlobalReference(
 const GlobalValue *GV, unsigned Encoding, const TargetMachine &TM,
 MachineModuleInfo *MMI, MCStreamer &Streamer) const {
Index: llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
===
--- llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
+++ llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
@@ -156,6 +156,8 @@
 
   void getNameWithPrefix(SmallVectorImpl &OutName, const GlobalValue *GV,
  const TargetMachine &TM) const override;
+
+  MCSection *getSectionForCommandLines() const override;
 };
 
 class TargetLoweringObjectFileCOFF : public TargetLoweringObjectFile {
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -7179,7 +7179,7 @@
   Args.hasFlag(options::OPT_frecord_command_line,
options::OPT_fno_record_command_line, false);
   if (FRecordSwitches && !Triple.isOSBinFormatELF() &&
-  !Triple.isOSBinFormatXCOFF())
+  !Triple.isOSBinFormatXCOFF() && !Triple.isOSBinFormatMachO())
 D.Diag(diag::err_drv_unsupported_opt_for_target)
 << 
Args.getLastArg(options::OPT_frecord_command_line)->getAsString(Args)
 << TripleStr;


Index: llvm/test/CodeGen/AArch64/arm64-command-line-metadata.ll
===
--- /dev/null
+++ llvm/test/CodeGen/AArch64/arm64-command-line-metadata.ll
@@ -0,0 +1,15 @@
+; RUN: llc -mtriple=aarch64-apple-darwin < %s | FileCheck %s
+; Verify that llvm.commandline metadata is emitted to a
+; MachO section named __command_line within __TEXT segment.
+
+; CHECK:.section	__TEXT,__text,regular,pure_instructions
+; CHECK-NEXT:   .section	__TEXT,__command_line
+; CHECK-NEXT:   .space	1
+; CHECK-NEXT:   .ascii	"clang -command1"
+; CHECK-NEXT:   .space	1
+; CHECK-NEXT:   .ascii	"clang -command2"
+; CHECK-NEXT:   .space	1
+
+!llvm.commandline = !{!0, !1}
+!0 = !{!"clang -command1"}
+!1 = !{!"clang -command2"}
Index: llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
===
--- llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -1420,6 +1420,11 @@
   return ReadOnlySection;  // .const
 }
 
+MCSection *TargetLoweringObjectFileMachO::getSectionForCommandLines() const {
+  return getContext().getMachOSection("__TEXT", "__command_line", 0,
+  SectionKind::getReadOnly());
+}
+
 const MCExpr *TargetLoweringObjectFileMachO::getTTypeGlobalReference(
 const GlobalValue *GV, unsigned Encoding, const TargetMachine &TM,
 MachineModuleInfo *MMI, MCStreamer &Streamer) const {
Index: llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
=

[PATCH] D155716: [clang][CodeGen] Introduce `-frecord-command-line` for MachO

2023-07-20 Thread Antonio Frighetto via Phabricator via cfe-commits
antoniofrighetto updated this revision to Diff 542483.

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

https://reviews.llvm.org/D155716

Files:
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/Driver/clang_f_opts.c
  llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
  llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
  llvm/test/CodeGen/AArch64/commandline-metadata.ll


Index: llvm/test/CodeGen/AArch64/commandline-metadata.ll
===
--- /dev/null
+++ llvm/test/CodeGen/AArch64/commandline-metadata.ll
@@ -0,0 +1,24 @@
+; RUN: llc -mtriple=arm64-linux-gnu < %s | FileCheck %s
+; RUN: llc -mtriple=arm64-apple-darwin < %s | FileCheck %s 
--check-prefix=CHECK-MACHO
+
+; Verify that llvm.commandline metadata is emitted to the corresponding 
command line section.
+
+; CHECK:  .text
+; CHECK:  .section .GCC.command.line,"MS",@progbits,1
+; CHECK-NEXT: .zero 1
+; CHECK-NEXT: .ascii "clang -command1"
+; CHECK-NEXT: .zero 1
+; CHECK-NEXT: .ascii "clang -command2"
+; CHECK-NEXT: .zero 1
+
+; CHECK-MACHO:.section __TEXT,__text,regular,pure_instructions
+; CHECK-MACHO-NEXT:   .section __TEXT,__command_line
+; CHECK-MACHO-NEXT:   .space   1
+; CHECK-MACHO-NEXT:   .ascii   "clang -command1"
+; CHECK-MACHO-NEXT:   .space   1
+; CHECK-MACHO-NEXT:   .ascii   "clang -command2"
+; CHECK-MACHO-NEXT:   .space   1
+
+!llvm.commandline = !{!0, !1}
+!0 = !{!"clang -command1"}
+!1 = !{!"clang -command2"}
Index: llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
===
--- llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -1420,6 +1420,11 @@
   return ReadOnlySection;  // .const
 }
 
+MCSection *TargetLoweringObjectFileMachO::getSectionForCommandLines() const {
+  return getContext().getMachOSection("__TEXT", "__command_line", 0,
+  SectionKind::getReadOnly());
+}
+
 const MCExpr *TargetLoweringObjectFileMachO::getTTypeGlobalReference(
 const GlobalValue *GV, unsigned Encoding, const TargetMachine &TM,
 MachineModuleInfo *MMI, MCStreamer &Streamer) const {
Index: llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
===
--- llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
+++ llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
@@ -156,6 +156,8 @@
 
   void getNameWithPrefix(SmallVectorImpl &OutName, const GlobalValue *GV,
  const TargetMachine &TM) const override;
+
+  MCSection *getSectionForCommandLines() const override;
 };
 
 class TargetLoweringObjectFileCOFF : public TargetLoweringObjectFile {
Index: clang/test/Driver/clang_f_opts.c
===
--- clang/test/Driver/clang_f_opts.c
+++ clang/test/Driver/clang_f_opts.c
@@ -541,7 +541,7 @@
 // RUN: %clang -### -S -target x86_64-unknown-linux -fno-record-command-line 
-frecord-command-line %s 2>&1 | FileCheck 
-check-prefix=CHECK-RECORD-GCC-SWITCHES %s
 // RUN: %clang -### -S -target x86_64-unknown-linux -frecord-command-line 
-fno-record-command-line %s 2>&1 | FileCheck 
-check-prefix=CHECK-NO-RECORD-GCC-SWITCHES %s
 // Test with a couple examples of non-ELF object file formats
-// RUN: %clang -### -S -target x86_64-unknown-macosx -frecord-command-line %s 
2>&1 | FileCheck -check-prefix=CHECK-RECORD-GCC-SWITCHES-ERROR %s
+// RUN: %clang -### -S -target x86_64-unknown-macosx -frecord-command-line %s 
2>&1 | FileCheck -check-prefix=CHECK-RECORD-GCC-SWITCHES %s
 // RUN: %clang -### -S -target x86_64-unknown-windows -frecord-command-line %s 
2>&1 | FileCheck -check-prefix=CHECK-RECORD-GCC-SWITCHES-ERROR %s
 // CHECK-RECORD-GCC-SWITCHES: "-record-command-line"
 // CHECK-NO-RECORD-GCC-SWITCHES-NOT: "-record-command-line"
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -7179,7 +7179,7 @@
   Args.hasFlag(options::OPT_frecord_command_line,
options::OPT_fno_record_command_line, false);
   if (FRecordSwitches && !Triple.isOSBinFormatELF() &&
-  !Triple.isOSBinFormatXCOFF())
+  !Triple.isOSBinFormatXCOFF() && !Triple.isOSBinFormatMachO())
 D.Diag(diag::err_drv_unsupported_opt_for_target)
 << 
Args.getLastArg(options::OPT_frecord_command_line)->getAsString(Args)
 << TripleStr;


Index: llvm/test/CodeGen/AArch64/commandline-metadata.ll
===
--- /dev/null
+++ llvm/test/CodeGen/AArch64/commandline-metadata.ll
@@ -0,0 +1,24 @@
+; RUN: llc -mtriple=arm64-linux-gnu < %s | FileCheck %s
+; RUN: llc -mtriple=arm64-apple-darwin < %s | FileCheck %s --check-prefix=CHECK

[PATCH] D155716: [clang][CodeGen] Introduce `-frecord-command-line` for MachO

2023-07-20 Thread Antonio Frighetto via Phabricator via cfe-commits
antoniofrighetto added a comment.

Thanks a lot for the reviews and for pointing out clang tests as well, there 
was a minor update to do there too!




Comment at: llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp:1424
+MCSection *TargetLoweringObjectFileMachO::getSectionForCommandLines() const {
+  return getContext().getMachOSection("__TEXT", "__command_line", 0,
+  SectionKind::getReadOnly());

sgraenitz wrote:
> Can we put it in `__DATA`?
> 
> Also the [[ 
> https://github.com/llvm/llvm-project/blob/release/16.x/llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp#L1160
>  | ELF implementation notes ]] that it "attempts to mimic GCC's switch of the 
> same name" and thus calls the section `.GCC.command.line`. I guess we cannot 
> use the dots in MachO, but should we add a `gcc` prefix?
Whilst I agree it should be better to distinguish this from executable data, I 
think this should live as read-only data, which `__TEXT` is traditionally for.

Following MachO conventions, I first tried `__gcc_command_line`, but the [[ 
https://github.com/llvm/llvm-project/blob/main/llvm/include/llvm/BinaryFormat/MachO.h#L587
 | section name ]] is restricted to 16 chars, and I'm not sure adding more 
bytes for the name is worth the change (thus I thought we'd prefer 
`__command_line` over `__gcc_cmd_line`).


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

https://reviews.llvm.org/D155716

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


[PATCH] D155716: [clang][CodeGen] Introduce `-frecord-command-line` for MachO

2023-07-24 Thread Antonio Frighetto 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 rG2dea969d8337: [clang][CodeGen] Introduce 
`-frecord-command-line` for MachO (authored by antoniofrighetto).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D155716

Files:
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/Driver/clang_f_opts.c
  llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
  llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
  llvm/test/CodeGen/AArch64/commandline-metadata.ll


Index: llvm/test/CodeGen/AArch64/commandline-metadata.ll
===
--- /dev/null
+++ llvm/test/CodeGen/AArch64/commandline-metadata.ll
@@ -0,0 +1,24 @@
+; RUN: llc -mtriple=arm64-linux-gnu < %s | FileCheck %s
+; RUN: llc -mtriple=arm64-apple-darwin < %s | FileCheck %s 
--check-prefix=CHECK-MACHO
+
+; Verify that llvm.commandline metadata is emitted to the corresponding 
command line section.
+
+; CHECK:  .text
+; CHECK:  .section .GCC.command.line,"MS",@progbits,1
+; CHECK-NEXT: .zero 1
+; CHECK-NEXT: .ascii "clang -command1"
+; CHECK-NEXT: .zero 1
+; CHECK-NEXT: .ascii "clang -command2"
+; CHECK-NEXT: .zero 1
+
+; CHECK-MACHO:.section __TEXT,__text,regular,pure_instructions
+; CHECK-MACHO-NEXT:   .section __TEXT,__command_line
+; CHECK-MACHO-NEXT:   .space   1
+; CHECK-MACHO-NEXT:   .ascii   "clang -command1"
+; CHECK-MACHO-NEXT:   .space   1
+; CHECK-MACHO-NEXT:   .ascii   "clang -command2"
+; CHECK-MACHO-NEXT:   .space   1
+
+!llvm.commandline = !{!0, !1}
+!0 = !{!"clang -command1"}
+!1 = !{!"clang -command2"}
Index: llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
===
--- llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
+++ llvm/lib/CodeGen/TargetLoweringObjectFileImpl.cpp
@@ -1420,6 +1420,11 @@
   return ReadOnlySection;  // .const
 }
 
+MCSection *TargetLoweringObjectFileMachO::getSectionForCommandLines() const {
+  return getContext().getMachOSection("__TEXT", "__command_line", 0,
+  SectionKind::getReadOnly());
+}
+
 const MCExpr *TargetLoweringObjectFileMachO::getTTypeGlobalReference(
 const GlobalValue *GV, unsigned Encoding, const TargetMachine &TM,
 MachineModuleInfo *MMI, MCStreamer &Streamer) const {
Index: llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
===
--- llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
+++ llvm/include/llvm/CodeGen/TargetLoweringObjectFileImpl.h
@@ -156,6 +156,8 @@
 
   void getNameWithPrefix(SmallVectorImpl &OutName, const GlobalValue *GV,
  const TargetMachine &TM) const override;
+
+  MCSection *getSectionForCommandLines() const override;
 };
 
 class TargetLoweringObjectFileCOFF : public TargetLoweringObjectFile {
Index: clang/test/Driver/clang_f_opts.c
===
--- clang/test/Driver/clang_f_opts.c
+++ clang/test/Driver/clang_f_opts.c
@@ -541,7 +541,7 @@
 // RUN: %clang -### -S -target x86_64-unknown-linux -fno-record-command-line 
-frecord-command-line %s 2>&1 | FileCheck 
-check-prefix=CHECK-RECORD-GCC-SWITCHES %s
 // RUN: %clang -### -S -target x86_64-unknown-linux -frecord-command-line 
-fno-record-command-line %s 2>&1 | FileCheck 
-check-prefix=CHECK-NO-RECORD-GCC-SWITCHES %s
 // Test with a couple examples of non-ELF object file formats
-// RUN: %clang -### -S -target x86_64-unknown-macosx -frecord-command-line %s 
2>&1 | FileCheck -check-prefix=CHECK-RECORD-GCC-SWITCHES-ERROR %s
+// RUN: %clang -### -S -target x86_64-unknown-macosx -frecord-command-line %s 
2>&1 | FileCheck -check-prefix=CHECK-RECORD-GCC-SWITCHES %s
 // RUN: %clang -### -S -target x86_64-unknown-windows -frecord-command-line %s 
2>&1 | FileCheck -check-prefix=CHECK-RECORD-GCC-SWITCHES-ERROR %s
 // CHECK-RECORD-GCC-SWITCHES: "-record-command-line"
 // CHECK-NO-RECORD-GCC-SWITCHES-NOT: "-record-command-line"
Index: clang/lib/Driver/ToolChains/Clang.cpp
===
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -7183,7 +7183,7 @@
   Args.hasFlag(options::OPT_frecord_command_line,
options::OPT_fno_record_command_line, false);
   if (FRecordSwitches && !Triple.isOSBinFormatELF() &&
-  !Triple.isOSBinFormatXCOFF())
+  !Triple.isOSBinFormatXCOFF() && !Triple.isOSBinFormatMachO())
 D.Diag(diag::err_drv_unsupported_opt_for_target)
 << 
Args.getLastArg(options::OPT_frecord_command_line)->getAsString(Args)
 << TripleStr;


Index: llvm/test/CodeGen/AArch64/commandline-metadata.ll
=