[clang-tools-extra] [clang-tidy] Fix handling --driver-mode= (PR #66553)

2024-03-30 Thread Piotr Zegar via cfe-commits

https://github.com/PiotrZSL updated 
https://github.com/llvm/llvm-project/pull/66553

>From f4f9c996171892813dc11eb5bcb29e0616475f40 Mon Sep 17 00:00:00 2001
From: Piotr Zegar 
Date: Fri, 15 Sep 2023 21:39:17 +
Subject: [PATCH 1/3] [clang-tidy] Fix handling --driver-mode=

Driver mode passed as an extra argument (command line or config)
were not utilized for removing invalid arguments in
stripPositionalArgs function, and even if passed as config
driver mode were not used for dependency file striping
leading to invalid handling of -MD. Additionally driver mode
were needed even if user already added cl.exe after --.
---
 .../clang-tidy/tool/ClangTidyMain.cpp | 96 ++-
 clang-tools-extra/docs/ReleaseNotes.rst   |  5 +
 .../clang-tidy/infrastructure/driver-mode.cpp | 57 +++
 3 files changed, 157 insertions(+), 1 deletion(-)
 create mode 100644 
clang-tools-extra/test/clang-tidy/infrastructure/driver-mode.cpp

diff --git a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp 
b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
index 9f3d6b6db6cbca1..b594319187dbcc8 100644
--- a/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
+++ b/clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp
@@ -19,6 +19,7 @@
 #include "../ClangTidyForceLinker.h"
 #include "../GlobList.h"
 #include "clang/Tooling/CommonOptionsParser.h"
+#include "clang/Tooling/Tooling.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/Support/InitLLVM.h"
 #include "llvm/Support/PluginLoader.h"
@@ -26,7 +27,11 @@
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/TargetSelect.h"
 #include "llvm/Support/WithColor.h"
+#include 
+#include 
 #include 
+#include 
+#include 
 
 using namespace clang::tooling;
 using namespace llvm;
@@ -450,7 +455,7 @@ static StringRef closest(StringRef Value, const StringSet<> 
&Allowed) {
   return Closest;
 }
 
-static constexpr StringLiteral VerifyConfigWarningEnd = " [-verify-config]\n";
+static constexpr StringRef VerifyConfigWarningEnd = " [-verify-config]\n";
 
 static bool verifyChecks(const StringSet<> &AllChecks, StringRef CheckGlob,
  StringRef Source) {
@@ -550,9 +555,91 @@ static llvm::IntrusiveRefCntPtr 
createBaseFS() {
   return BaseFS;
 }
 
+static llvm::Expected
+recreateOptionsParserIfNeeded(llvm::ArrayRef Args,
+  llvm::Expected 
OptionsParser,
+  const ClangTidyOptions &EffectiveOptions) {
+
+  auto DoubleDashIt = std::find(Args.begin(), Args.end(), StringRef("--"));
+
+  // Exit if we don't have any compiler arguments
+  if (DoubleDashIt == Args.end() || Args.empty() ||
+  Args.back() == StringRef("--"))
+return OptionsParser;
+
+  auto IsDriverMode = [](StringRef Argument) {
+return Argument.startswith("--driver-mode=");
+  };
+
+  // Exit if --driver-mode= is explicitly passed in compiler arguments
+  if (Args.end() !=
+  std::find_if(std::next(DoubleDashIt), Args.end(), IsDriverMode))
+return OptionsParser;
+
+  std::vector CommandArguments(std::next(DoubleDashIt),
+Args.end());
+
+  // Add clang-tool as program name if not added
+  if (CommandArguments.empty() ||
+  llvm::StringRef(CommandArguments.front()).startswith("-"))
+CommandArguments.insert(CommandArguments.begin(), "clang-tool");
+
+  // Apply --extra-arg and --extra-arg-before to compiler arguments
+  CommandArguments =
+  OptionsParser->getArgumentsAdjuster()(CommandArguments, "");
+
+  // Apply ExtraArgsBefore from clang-tidy config to compiler arguments
+  if (EffectiveOptions.ExtraArgsBefore)
+CommandArguments = tooling::getInsertArgumentAdjuster(
+*EffectiveOptions.ExtraArgsBefore,
+tooling::ArgumentInsertPosition::BEGIN)(CommandArguments, "");
+
+  // Apply ExtraArgs from clang-tidy config to compiler arguments
+  if (EffectiveOptions.ExtraArgs)
+CommandArguments = tooling::getInsertArgumentAdjuster(
+*EffectiveOptions.ExtraArgs,
+tooling::ArgumentInsertPosition::END)(CommandArguments, "");
+
+  // Check if now we have --driver-mode=
+  auto DriverModeIt = std::find_if(CommandArguments.begin(),
+   CommandArguments.end(), IsDriverMode);
+  if (DriverModeIt == CommandArguments.end()) {
+// Try to detect and add --driver-mode=
+std::string ExeName = CommandArguments.front();
+tooling::addTargetAndModeForProgramName(CommandArguments, ExeName);
+DriverModeIt = std::find_if(CommandArguments.begin(),
+CommandArguments.end(), IsDriverMode);
+  }
+
+  // Exit if there is no --driver-mode= at this stage
+  if (DriverModeIt == CommandArguments.end())
+return OptionsParser;
+
+  std::vector NewArgs(Args.begin(), Args.end());
+
+  // Find place to insert --driver-mode= into new args, best after program 
name.
+  auto InsertIt =
+  NewArgs.begin() + std::distance(Args.begin(), DoubleDashIt) + 1U;
+  if (!StringRef(*In

[clang-tools-extra] [clang-tidy] add new check readability-enum-initial-value (PR #86129)

2024-03-30 Thread Piotr Zegar via cfe-commits

https://github.com/PiotrZSL edited 
https://github.com/llvm/llvm-project/pull/86129
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] add new check readability-enum-initial-value (PR #86129)

2024-03-30 Thread Piotr Zegar via cfe-commits


@@ -0,0 +1,200 @@
+//===--- EnumInitialValueCheck.cpp - clang-tidy 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "EnumInitialValueCheck.h"
+#include "../utils/LexerUtils.h"
+#include "clang/AST/Decl.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::readability {
+
+static bool isNoneEnumeratorsInitialized(const EnumDecl &Node) {
+  return llvm::all_of(Node.enumerators(), [](const EnumConstantDecl *ECD) {
+return ECD->getInitExpr() == nullptr;
+  });
+}
+
+static bool isOnlyFirstEnumeratorInitialized(const EnumDecl &Node) {
+  bool IsFirst = true;
+  for (const EnumConstantDecl *ECD : Node.enumerators()) {
+if ((IsFirst && ECD->getInitExpr() == nullptr) ||
+(!IsFirst && ECD->getInitExpr() != nullptr))
+  return false;
+IsFirst = false;
+  }
+  return !IsFirst;
+}
+
+static bool areAllEnumeratorsInitialized(const EnumDecl &Node) {
+  return llvm::all_of(Node.enumerators(), [](const EnumConstantDecl *ECD) {
+return ECD->getInitExpr() != nullptr;
+  });
+}
+
+/// Check if \p Enumerator is initialized with a (potentially negated) \c
+/// IntegerLiteral.
+static bool isInitializedByLiteral(const EnumConstantDecl *Enumerator) {
+  const Expr *const Init = Enumerator->getInitExpr();
+  if (!Init)
+return false;
+  return Init->isIntegerConstantExpr(Enumerator->getASTContext());
+}
+
+static void cleanInitialValue(DiagnosticBuilder &Diag,
+  const EnumConstantDecl *ECD,
+  const SourceManager &SM,
+  const LangOptions &LangOpts) {
+  const SourceRange InitExprRange = ECD->getInitExpr()->getSourceRange();
+  if (InitExprRange.isInvalid() || InitExprRange.getBegin().isMacroID() ||
+  InitExprRange.getEnd().isMacroID())
+return;
+  std::optional EqualToken = 
utils::lexer::findNextTokenSkippingComments(
+  ECD->getLocation(), SM, LangOpts);
+  if (!EqualToken.has_value() ||
+  EqualToken.value().getKind() != tok::TokenKind::equal)
+return;
+  const SourceLocation EqualLoc{EqualToken->getLocation()};
+  if (EqualLoc.isInvalid() || EqualLoc.isMacroID())
+return;
+  Diag << FixItHint::CreateRemoval(EqualLoc)
+   << FixItHint::CreateRemoval(InitExprRange);
+  return;
+}
+
+namespace {
+
+AST_MATCHER(EnumDecl, isMacro) {
+  SourceLocation Loc = Node.getBeginLoc();
+  return Loc.isMacroID();
+}
+
+AST_MATCHER(EnumDecl, hasConsistentInitialValues) {
+  return isNoneEnumeratorsInitialized(Node) ||
+ isOnlyFirstEnumeratorInitialized(Node) ||
+ areAllEnumeratorsInitialized(Node);
+}
+
+AST_MATCHER(EnumDecl, hasZeroInitialValueForFirstEnumerator) {
+  const EnumDecl::enumerator_range Enumerators = Node.enumerators();
+  if (Enumerators.empty())
+return false;
+  const EnumConstantDecl *ECD = *Enumerators.begin();
+  return isOnlyFirstEnumeratorInitialized(Node) &&
+ isInitializedByLiteral(ECD) && ECD->getInitVal().isZero();
+}
+
+/// Excludes bitfields because enumerators initialized with the result of a
+/// bitwise operator on enumeration values or any other expr that is not a
+/// potentially negative integer literal.
+/// Enumerations where it is not directly clear if they are used with
+/// bitmask, evident when enumerators are only initialized with (potentially
+/// negative) integer literals, are ignored. This is also the case when all
+/// enumerators are powers of two (e.g., 0, 1, 2).
+AST_MATCHER(EnumDecl, hasSequentialInitialValues) {
+  const EnumDecl::enumerator_range Enumerators = Node.enumerators();
+  if (Enumerators.empty())
+return false;
+  const EnumConstantDecl *const FirstEnumerator = *Node.enumerator_begin();
+  llvm::APSInt PrevValue = FirstEnumerator->getInitVal();
+  if (!isInitializedByLiteral(FirstEnumerator))
+return false;
+  bool AllEnumeratorsArePowersOfTwo = true;
+  for (const EnumConstantDecl *Enumerator : llvm::drop_begin(Enumerators)) {
+const llvm::APSInt NewValue = Enumerator->getInitVal();
+if (NewValue != ++PrevValue)
+  return false;
+if (!isInitializedByLiteral(Enumerator))
+  return false;
+PrevValue = NewValue;
+AllEnumeratorsArePowersOfTwo &= NewValue.isPowerOf2();
+  }
+  return !AllEnumeratorsArePowersOfTwo;
+}
+
+} // namespace
+
+EnumInitialValueCheck::EnumInitialValueCheck(StringRef Name,
+ ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  AllowExplici

[clang-tools-extra] [clang-tidy] add new check readability-enum-initial-value (PR #86129)

2024-03-30 Thread Piotr Zegar via cfe-commits

https://github.com/PiotrZSL approved this pull request.

For me looks fine (had to check how it behave when coma is in next line).
Some ideas for separate check or future options:
- enforce that enums are sorted by value
- enforce that enums are sorted by name
- enforce that there is no duplicated values (bugprone), not there is warning 
for implicit duplicate, but not explicit.

https://github.com/llvm/llvm-project/pull/86129
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] add new check readability-enum-initial-value (PR #86129)

2024-03-30 Thread Piotr Zegar via cfe-commits

https://github.com/PiotrZSL edited 
https://github.com/llvm/llvm-project/pull/86129
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Add clang-tidy check readability-math-missing-parentheses (PR #84481)

2024-03-30 Thread Piotr Zegar via cfe-commits

https://github.com/PiotrZSL edited 
https://github.com/llvm/llvm-project/pull/84481
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Add clang-tidy check readability-math-missing-parentheses (PR #84481)

2024-03-30 Thread Piotr Zegar via cfe-commits


@@ -0,0 +1,112 @@
+//===--- MathMissingParenthesesCheck.cpp - clang-tidy 
-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "MathMissingParenthesesCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::readability {
+
+void MathMissingParenthesesCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(binaryOperator(unless(hasParent(binaryOperator())),

PiotrZSL wrote:

```
unless(isAssignmentOperator()),
unless(isComparisonOperator()),
unless(hasAnyOperatorName("&&", "||"))
--





```




()),

https://github.com/llvm/llvm-project/pull/84481
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Add clang-tidy check readability-math-missing-parentheses (PR #84481)

2024-03-30 Thread Piotr Zegar via cfe-commits


@@ -0,0 +1,112 @@
+//===--- MathMissingParenthesesCheck.cpp - clang-tidy 
-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "MathMissingParenthesesCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::readability {
+
+void MathMissingParenthesesCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(binaryOperator(unless(hasParent(binaryOperator())),
+unless(allOf(hasOperatorName("&&"),
+ hasOperatorName("||"))),
+hasDescendant(binaryOperator()))
+ .bind("binOp"),
+ this);
+}
+
+static int getPrecedence(const BinaryOperator *BinOp) {
+  if (!BinOp)
+return 0;
+  switch (BinOp->getOpcode()) {
+  case BO_Mul:
+  case BO_Div:
+  case BO_Rem:
+return 5;
+  case BO_Add:
+  case BO_Sub:
+return 4;
+  case BO_And:
+return 3;
+  case BO_Xor:
+return 2;
+  case BO_Or:
+return 1;
+  default:
+return 0;
+  }
+}
+static bool addParantheses(
+const BinaryOperator *BinOp, const BinaryOperator *ParentBinOp,
+std::vector<
+std::pair>>
+&Insertions,
+const clang::SourceManager &SM, const clang::LangOptions &LangOpts) {
+  bool NeedToDiagnose = false;
+  if (!BinOp)
+return NeedToDiagnose;
+
+  if (ParentBinOp != nullptr &&
+  getPrecedence(BinOp) != getPrecedence(ParentBinOp)) {
+NeedToDiagnose = true;
+const clang::SourceLocation StartLoc = BinOp->getBeginLoc();
+clang::SourceLocation EndLoc =
+clang::Lexer::getLocForEndOfToken(BinOp->getEndLoc(), 0, SM, LangOpts);
+Insertions.push_back(
+{clang::SourceRange(StartLoc, EndLoc), {BinOp, ParentBinOp}});
+  }
+
+  NeedToDiagnose |= addParantheses(
+  dyn_cast(BinOp->getLHS()->IgnoreImpCasts()), BinOp,
+  Insertions, SM, LangOpts);
+  NeedToDiagnose |= addParantheses(
+  dyn_cast(BinOp->getRHS()->IgnoreImpCasts()), BinOp,
+  Insertions, SM, LangOpts);
+  return NeedToDiagnose;
+}
+
+void MathMissingParenthesesCheck::check(
+const MatchFinder::MatchResult &Result) {
+  const auto *BinOp = Result.Nodes.getNodeAs("binOp");
+  std::vector<
+  std::pair>>
+  Insertions;
+  const clang::SourceLocation StartLoc = BinOp->getBeginLoc();
+  const SourceManager &SM = *Result.SourceManager;
+  const clang::LangOptions &LO = Result.Context->getLangOpts();
+
+  if (addParantheses(BinOp, nullptr, Insertions, SM, LO)) {
+for (const auto &Insertion : Insertions) {
+  const clang::BinaryOperator *BinOp1 = Insertion.second.first;
+  const clang::BinaryOperator *BinOp2 = Insertion.second.second;
+
+  int Precedence1 = getPrecedence(BinOp1);
+  int Precedence2 = getPrecedence(BinOp2);
+
+  auto Diag = diag(Insertion.first.getBegin(),
+   "'%0' has higher precedence than '%1'; add parentheses "
+   "to make the precedence of operations explicit")

PiotrZSL wrote:

were thinking about this, I thing this will be better:
`'%0' has higher precedence than '%1'; add parentheses to explicitly specify 
the order of operations`

https://github.com/llvm/llvm-project/pull/84481
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Add clang-tidy check readability-math-missing-parentheses (PR #84481)

2024-03-30 Thread Piotr Zegar via cfe-commits

https://github.com/PiotrZSL commented:

Overall, I like what I see.
Just few nits.

https://github.com/llvm/llvm-project/pull/84481
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Add clang-tidy check readability-math-missing-parentheses (PR #84481)

2024-03-30 Thread Piotr Zegar via cfe-commits


@@ -129,6 +129,12 @@ New checks
   Replaces certain conditional statements with equivalent calls to
   ``std::min`` or ``std::max``.
 
+- New :doc:`readability-math-missing-parentheses

PiotrZSL wrote:

put this before readability-use-std-min-max

https://github.com/llvm/llvm-project/pull/84481
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Add clang-tidy check readability-math-missing-parentheses (PR #84481)

2024-03-30 Thread Piotr Zegar via cfe-commits


@@ -0,0 +1,81 @@
+// RUN: %check_clang_tidy %s readability-math-missing-parentheses %t
+
+int foo(){
+return 5;
+}
+
+int bar(){
+return 4;
+}
+
+class fun{
+public:  
+int A;
+double B;
+fun(){
+A = 5;
+B = 5.4;
+}
+};
+
+void f(){
+//CHECK-MESSAGES: :[[@LINE+2]]:17: warning: '*' has higher precedence than 
'+'; add parentheses to make the precedence of operations explicit 
[readability-math-missing-parentheses]
+//CHECK-FIXES: int a = 1 + (2 * 3);
+int a = 1 + 2 * 3; 
+
+int b = 1 + 2 + 3; // No warning
+
+int c = 1 * 2 * 3; // No warning
+
+//CHECK-MESSAGES: :[[@LINE+3]]:17: warning: '*' has higher precedence than 
'+'; add parentheses to make the precedence of operations explicit 
[readability-math-missing-parentheses]
+//CHECK-MESSAGES: :[[@LINE+2]]:25: warning: '/' has higher precedence than 
'-'; add parentheses to make the precedence of operations explicit 
[readability-math-missing-parentheses]
+//CHECK-FIXES: int d = 1 + (2 * 3) - (4 / 5);
+int d = 1 + 2 * 3 - 4 / 5;

PiotrZSL wrote:

Add more negative tests, like this:
`int d_negative = 1 + (2 * 3) - (4 / 5);`
Just to check that `()` won't be added if they already exists.

https://github.com/llvm/llvm-project/pull/84481
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Add clang-tidy check readability-math-missing-parentheses (PR #84481)

2024-03-30 Thread Piotr Zegar via cfe-commits


@@ -0,0 +1,25 @@
+.. title:: clang-tidy - readability-math-missing-parentheses
+
+readability-math-missing-parentheses
+
+
+Check for missing parentheses in mathematical expressions that involve 
operators
+of different priorities. Parentheses in mathematical expressions clarify the 
order

PiotrZSL wrote:

add empty line after "priorities."

https://github.com/llvm/llvm-project/pull/84481
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Add clang-tidy check readability-math-missing-parentheses (PR #84481)

2024-03-30 Thread Piotr Zegar via cfe-commits

https://github.com/PiotrZSL edited 
https://github.com/llvm/llvm-project/pull/84481
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] add check to suggest replacement of nested std::min or std::max with initializer lists (PR #85572)

2024-03-30 Thread Piotr Zegar via cfe-commits


@@ -0,0 +1,337 @@
+//===--- MinMaxUseInitializerListCheck.cpp - clang-tidy 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "MinMaxUseInitializerListCheck.h"
+#include "../utils/ASTUtils.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+struct FindArgsResult {
+  const Expr *First;
+  const Expr *Last;
+  const Expr *Compare;
+  std::vector Args;
+};

PiotrZSL wrote:

Put into anonymous namespace to avoid ODR issues.

https://github.com/llvm/llvm-project/pull/85572
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] add check to suggest replacement of nested std::min or std::max with initializer lists (PR #85572)

2024-03-30 Thread Piotr Zegar via cfe-commits


@@ -0,0 +1,337 @@
+//===--- MinMaxUseInitializerListCheck.cpp - clang-tidy 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "MinMaxUseInitializerListCheck.h"
+#include "../utils/ASTUtils.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+struct FindArgsResult {
+  const Expr *First;
+  const Expr *Last;
+  const Expr *Compare;
+  std::vector Args;
+};
+
+static const FindArgsResult findArgs(const CallExpr *Call);
+static std::vector>
+getCommentRanges(const std::string &source);
+static bool
+isPositionInComment(int position,
+const std::vector> &commentRanges);
+static void
+removeCharacterFromSource(std::string &FunctionCallSource,
+  const std::vector> 
&CommentRanges,
+  char Character, const CallExpr *InnerCall,
+  std::vector &Result, bool ReverseSearch);
+static SourceLocation
+getLocForEndOfToken(const Expr *expr, const MatchFinder::MatchResult &Match);
+static const std::vector
+generateReplacement(const MatchFinder::MatchResult &Match,
+const CallExpr *TopCall, const FindArgsResult &Result);
+
+MinMaxUseInitializerListCheck::MinMaxUseInitializerListCheck(
+StringRef Name, ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  Inserter(Options.getLocalOrGlobal("IncludeStyle",
+utils::IncludeSorter::IS_LLVM),
+   areDiagsSelfContained()) {}
+
+void MinMaxUseInitializerListCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IncludeStyle", Inserter.getStyle());
+}
+
+void MinMaxUseInitializerListCheck::registerMatchers(MatchFinder *Finder) {
+  auto CreateMatcher = [](const std::string &FunctionName) {

PiotrZSL wrote:

use `llvm::StringRef instead` of `const std::string&`

https://github.com/llvm/llvm-project/pull/85572
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] add check to suggest replacement of nested std::min or std::max with initializer lists (PR #85572)

2024-03-30 Thread Piotr Zegar via cfe-commits


@@ -0,0 +1,337 @@
+//===--- MinMaxUseInitializerListCheck.cpp - clang-tidy 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "MinMaxUseInitializerListCheck.h"
+#include "../utils/ASTUtils.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+struct FindArgsResult {
+  const Expr *First;
+  const Expr *Last;
+  const Expr *Compare;
+  std::vector Args;
+};
+
+static const FindArgsResult findArgs(const CallExpr *Call);
+static std::vector>
+getCommentRanges(const std::string &source);
+static bool
+isPositionInComment(int position,
+const std::vector> &commentRanges);
+static void
+removeCharacterFromSource(std::string &FunctionCallSource,
+  const std::vector> 
&CommentRanges,
+  char Character, const CallExpr *InnerCall,
+  std::vector &Result, bool ReverseSearch);
+static SourceLocation
+getLocForEndOfToken(const Expr *expr, const MatchFinder::MatchResult &Match);
+static const std::vector
+generateReplacement(const MatchFinder::MatchResult &Match,
+const CallExpr *TopCall, const FindArgsResult &Result);
+
+MinMaxUseInitializerListCheck::MinMaxUseInitializerListCheck(
+StringRef Name, ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  Inserter(Options.getLocalOrGlobal("IncludeStyle",
+utils::IncludeSorter::IS_LLVM),
+   areDiagsSelfContained()) {}
+
+void MinMaxUseInitializerListCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IncludeStyle", Inserter.getStyle());
+}
+
+void MinMaxUseInitializerListCheck::registerMatchers(MatchFinder *Finder) {
+  auto CreateMatcher = [](const std::string &FunctionName) {
+auto FuncDecl = functionDecl(hasName(FunctionName));
+auto Expression = callExpr(callee(FuncDecl));
+
+return callExpr(callee(FuncDecl),
+anyOf(hasArgument(0, Expression),
+  hasArgument(1, Expression),
+  hasArgument(0, cxxStdInitializerListExpr())),
+unless(hasParent(Expression)))
+.bind("topCall");
+  };
+
+  Finder->addMatcher(CreateMatcher("::std::max"), this);
+  Finder->addMatcher(CreateMatcher("::std::min"), this);
+}
+
+void MinMaxUseInitializerListCheck::registerPPCallbacks(
+const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) 
{
+  Inserter.registerPreprocessor(PP);
+}
+
+void MinMaxUseInitializerListCheck::check(
+const MatchFinder::MatchResult &Match) {
+
+  const auto *TopCall = Match.Nodes.getNodeAs("topCall");
+
+  FindArgsResult Result = findArgs(TopCall);
+  const std::vector Replacement =
+  generateReplacement(Match, TopCall, Result);
+
+  // if only changes are inserting '{' and '}' then ignore
+  if (Replacement.size() <= 2) {
+return;
+  }
+
+  const DiagnosticBuilder Diagnostic =
+  diag(TopCall->getBeginLoc(),
+   "do not use nested 'std::%0' calls, use initializer lists instead")
+  << TopCall->getDirectCallee()->getName()
+  << Inserter.createIncludeInsertion(
+ Match.SourceManager->getFileID(TopCall->getBeginLoc()),
+ "");
+
+  for (const auto &FixIt : Replacement) {
+Diagnostic << FixIt;
+  }
+}
+
+static const FindArgsResult findArgs(const CallExpr *Call) {
+  FindArgsResult Result;
+  Result.First = nullptr;
+  Result.Last = nullptr;
+  Result.Compare = nullptr;
+
+  if (Call->getNumArgs() == 3) {
+auto ArgIterator = Call->arguments().begin();
+std::advance(ArgIterator, 2);
+Result.Compare = *ArgIterator;
+  } else {
+auto ArgIterator = Call->arguments().begin();
+
+if (const auto *InitListExpr =
+dyn_cast(*ArgIterator)) {
+  if (const auto *TempExpr =
+  dyn_cast(InitListExpr->getSubExpr())) {
+if (const auto *InitList =
+dyn_cast(TempExpr->getSubExpr())) {
+  for (const Expr *Init : InitList->inits()) {
+Result.Args.push_back(Init);
+  }
+  Result.First = *ArgIterator;
+  Result.Last = *ArgIterator;
+
+  std::advance(ArgIterator, 1);
+  if (ArgIterator != Call->arguments().end()) {
+Result.Compare = *ArgIterator;
+  }
+  return Result;
+}
+  }
+}
+  }
+
+  for (const Expr *Arg : Call->arguments()) {
+if (!Result.First)
+  Result.First = Arg;
+
+if (Arg == Result.Compare)
+  continue;
+
+Result.Args.push_back(Arg);
+R

[clang-tools-extra] [clang-tidy] add check to suggest replacement of nested std::min or std::max with initializer lists (PR #85572)

2024-03-30 Thread Piotr Zegar via cfe-commits


@@ -0,0 +1,337 @@
+//===--- MinMaxUseInitializerListCheck.cpp - clang-tidy 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "MinMaxUseInitializerListCheck.h"
+#include "../utils/ASTUtils.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+struct FindArgsResult {
+  const Expr *First;
+  const Expr *Last;
+  const Expr *Compare;
+  std::vector Args;
+};
+
+static const FindArgsResult findArgs(const CallExpr *Call);
+static std::vector>
+getCommentRanges(const std::string &source);
+static bool
+isPositionInComment(int position,
+const std::vector> &commentRanges);
+static void
+removeCharacterFromSource(std::string &FunctionCallSource,
+  const std::vector> 
&CommentRanges,
+  char Character, const CallExpr *InnerCall,
+  std::vector &Result, bool ReverseSearch);
+static SourceLocation
+getLocForEndOfToken(const Expr *expr, const MatchFinder::MatchResult &Match);
+static const std::vector
+generateReplacement(const MatchFinder::MatchResult &Match,
+const CallExpr *TopCall, const FindArgsResult &Result);
+
+MinMaxUseInitializerListCheck::MinMaxUseInitializerListCheck(
+StringRef Name, ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  Inserter(Options.getLocalOrGlobal("IncludeStyle",
+utils::IncludeSorter::IS_LLVM),
+   areDiagsSelfContained()) {}
+
+void MinMaxUseInitializerListCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IncludeStyle", Inserter.getStyle());
+}
+
+void MinMaxUseInitializerListCheck::registerMatchers(MatchFinder *Finder) {
+  auto CreateMatcher = [](const std::string &FunctionName) {
+auto FuncDecl = functionDecl(hasName(FunctionName));
+auto Expression = callExpr(callee(FuncDecl));
+
+return callExpr(callee(FuncDecl),
+anyOf(hasArgument(0, Expression),
+  hasArgument(1, Expression),
+  hasArgument(0, cxxStdInitializerListExpr())),
+unless(hasParent(Expression)))
+.bind("topCall");
+  };
+
+  Finder->addMatcher(CreateMatcher("::std::max"), this);
+  Finder->addMatcher(CreateMatcher("::std::min"), this);
+}
+
+void MinMaxUseInitializerListCheck::registerPPCallbacks(
+const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) 
{
+  Inserter.registerPreprocessor(PP);
+}
+
+void MinMaxUseInitializerListCheck::check(
+const MatchFinder::MatchResult &Match) {
+
+  const auto *TopCall = Match.Nodes.getNodeAs("topCall");
+
+  FindArgsResult Result = findArgs(TopCall);
+  const std::vector Replacement =
+  generateReplacement(Match, TopCall, Result);
+
+  // if only changes are inserting '{' and '}' then ignore
+  if (Replacement.size() <= 2) {
+return;
+  }
+
+  const DiagnosticBuilder Diagnostic =
+  diag(TopCall->getBeginLoc(),
+   "do not use nested 'std::%0' calls, use initializer lists instead")
+  << TopCall->getDirectCallee()->getName()
+  << Inserter.createIncludeInsertion(
+ Match.SourceManager->getFileID(TopCall->getBeginLoc()),
+ "");
+
+  for (const auto &FixIt : Replacement) {
+Diagnostic << FixIt;
+  }
+}
+
+static const FindArgsResult findArgs(const CallExpr *Call) {
+  FindArgsResult Result;
+  Result.First = nullptr;
+  Result.Last = nullptr;
+  Result.Compare = nullptr;
+
+  if (Call->getNumArgs() == 3) {
+auto ArgIterator = Call->arguments().begin();
+std::advance(ArgIterator, 2);
+Result.Compare = *ArgIterator;
+  } else {
+auto ArgIterator = Call->arguments().begin();
+
+if (const auto *InitListExpr =
+dyn_cast(*ArgIterator)) {
+  if (const auto *TempExpr =

PiotrZSL wrote:

Remove TempExpr , use `InitListExpr->getSubExpr()->IgnoreImplicit()`

https://github.com/llvm/llvm-project/pull/85572
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] add check to suggest replacement of nested std::min or std::max with initializer lists (PR #85572)

2024-03-30 Thread Piotr Zegar via cfe-commits


@@ -0,0 +1,337 @@
+//===--- MinMaxUseInitializerListCheck.cpp - clang-tidy 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "MinMaxUseInitializerListCheck.h"
+#include "../utils/ASTUtils.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+struct FindArgsResult {
+  const Expr *First;
+  const Expr *Last;
+  const Expr *Compare;
+  std::vector Args;
+};
+
+static const FindArgsResult findArgs(const CallExpr *Call);
+static std::vector>
+getCommentRanges(const std::string &source);
+static bool
+isPositionInComment(int position,
+const std::vector> &commentRanges);
+static void
+removeCharacterFromSource(std::string &FunctionCallSource,
+  const std::vector> 
&CommentRanges,
+  char Character, const CallExpr *InnerCall,
+  std::vector &Result, bool ReverseSearch);
+static SourceLocation
+getLocForEndOfToken(const Expr *expr, const MatchFinder::MatchResult &Match);
+static const std::vector
+generateReplacement(const MatchFinder::MatchResult &Match,
+const CallExpr *TopCall, const FindArgsResult &Result);
+
+MinMaxUseInitializerListCheck::MinMaxUseInitializerListCheck(
+StringRef Name, ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  Inserter(Options.getLocalOrGlobal("IncludeStyle",
+utils::IncludeSorter::IS_LLVM),
+   areDiagsSelfContained()) {}
+
+void MinMaxUseInitializerListCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IncludeStyle", Inserter.getStyle());
+}
+
+void MinMaxUseInitializerListCheck::registerMatchers(MatchFinder *Finder) {
+  auto CreateMatcher = [](const std::string &FunctionName) {
+auto FuncDecl = functionDecl(hasName(FunctionName));
+auto Expression = callExpr(callee(FuncDecl));
+
+return callExpr(callee(FuncDecl),
+anyOf(hasArgument(0, Expression),
+  hasArgument(1, Expression),
+  hasArgument(0, cxxStdInitializerListExpr())),
+unless(hasParent(Expression)))
+.bind("topCall");
+  };
+
+  Finder->addMatcher(CreateMatcher("::std::max"), this);
+  Finder->addMatcher(CreateMatcher("::std::min"), this);
+}
+
+void MinMaxUseInitializerListCheck::registerPPCallbacks(
+const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) 
{
+  Inserter.registerPreprocessor(PP);
+}
+
+void MinMaxUseInitializerListCheck::check(
+const MatchFinder::MatchResult &Match) {
+
+  const auto *TopCall = Match.Nodes.getNodeAs("topCall");
+
+  FindArgsResult Result = findArgs(TopCall);
+  const std::vector Replacement =
+  generateReplacement(Match, TopCall, Result);
+
+  // if only changes are inserting '{' and '}' then ignore
+  if (Replacement.size() <= 2) {
+return;
+  }
+
+  const DiagnosticBuilder Diagnostic =
+  diag(TopCall->getBeginLoc(),
+   "do not use nested 'std::%0' calls, use initializer lists instead")
+  << TopCall->getDirectCallee()->getName()
+  << Inserter.createIncludeInsertion(
+ Match.SourceManager->getFileID(TopCall->getBeginLoc()),
+ "");
+
+  for (const auto &FixIt : Replacement) {
+Diagnostic << FixIt;
+  }
+}
+
+static const FindArgsResult findArgs(const CallExpr *Call) {
+  FindArgsResult Result;
+  Result.First = nullptr;
+  Result.Last = nullptr;
+  Result.Compare = nullptr;
+
+  if (Call->getNumArgs() == 3) {
+auto ArgIterator = Call->arguments().begin();
+std::advance(ArgIterator, 2);
+Result.Compare = *ArgIterator;
+  } else {
+auto ArgIterator = Call->arguments().begin();
+
+if (const auto *InitListExpr =
+dyn_cast(*ArgIterator)) {
+  if (const auto *TempExpr =
+  dyn_cast(InitListExpr->getSubExpr())) {
+if (const auto *InitList =
+dyn_cast(TempExpr->getSubExpr())) {
+  for (const Expr *Init : InitList->inits()) {
+Result.Args.push_back(Init);
+  }
+  Result.First = *ArgIterator;
+  Result.Last = *ArgIterator;
+
+  std::advance(ArgIterator, 1);
+  if (ArgIterator != Call->arguments().end()) {
+Result.Compare = *ArgIterator;
+  }
+  return Result;
+}
+  }
+}
+  }
+
+  for (const Expr *Arg : Call->arguments()) {
+if (!Result.First)
+  Result.First = Arg;
+
+if (Arg == Result.Compare)
+  continue;
+
+Result.Args.push_back(Arg);
+R

[clang-tools-extra] [clang-tidy] add check to suggest replacement of nested std::min or std::max with initializer lists (PR #85572)

2024-03-30 Thread Piotr Zegar via cfe-commits


@@ -0,0 +1,337 @@
+//===--- MinMaxUseInitializerListCheck.cpp - clang-tidy 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "MinMaxUseInitializerListCheck.h"
+#include "../utils/ASTUtils.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+struct FindArgsResult {
+  const Expr *First;
+  const Expr *Last;
+  const Expr *Compare;
+  std::vector Args;
+};
+
+static const FindArgsResult findArgs(const CallExpr *Call);
+static std::vector>
+getCommentRanges(const std::string &source);
+static bool
+isPositionInComment(int position,
+const std::vector> &commentRanges);
+static void
+removeCharacterFromSource(std::string &FunctionCallSource,
+  const std::vector> 
&CommentRanges,
+  char Character, const CallExpr *InnerCall,
+  std::vector &Result, bool ReverseSearch);
+static SourceLocation
+getLocForEndOfToken(const Expr *expr, const MatchFinder::MatchResult &Match);
+static const std::vector
+generateReplacement(const MatchFinder::MatchResult &Match,
+const CallExpr *TopCall, const FindArgsResult &Result);

PiotrZSL wrote:

You shoudn't need to do forward declarations. Just move those functions to the 
begining of file.

https://github.com/llvm/llvm-project/pull/85572
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] add check to suggest replacement of nested std::min or std::max with initializer lists (PR #85572)

2024-03-30 Thread Piotr Zegar via cfe-commits

https://github.com/PiotrZSL edited 
https://github.com/llvm/llvm-project/pull/85572
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] add check to suggest replacement of nested std::min or std::max with initializer lists (PR #85572)

2024-03-30 Thread Piotr Zegar via cfe-commits

https://github.com/PiotrZSL commented:

In short, avoid any string parsing/manipulation.

https://github.com/llvm/llvm-project/pull/85572
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Improved --verify-config when using literal style in config file (PR #85591)

2024-03-30 Thread Piotr Zegar via cfe-commits
=?utf-8?q?F=C3=A9lix-Antoine?= Constantin,
=?utf-8?q?F=C3=A9lix-Antoine?= Constantin,
=?utf-8?q?F=C3=A9lix-Antoine?= Constantin,
=?utf-8?q?F=C3=A9lix-Antoine?= Constantin
Message-ID:
In-Reply-To: 


https://github.com/PiotrZSL approved this pull request.

LGTM

https://github.com/llvm/llvm-project/pull/85591
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Support renaming designated initializers (PR #86976)

2024-03-30 Thread Piotr Zegar via cfe-commits

https://github.com/PiotrZSL edited 
https://github.com/llvm/llvm-project/pull/86976
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Support renaming designated initializers (PR #86976)

2024-03-30 Thread Piotr Zegar via cfe-commits


@@ -367,6 +367,25 @@ class RenamerClangTidyVisitor
 return true;
   }
 
+  bool VisitDesignatedInitExpr(DesignatedInitExpr *Expr) {
+for (const auto &Designator : Expr->designators()) {
+  if (!Designator.isFieldDesignator())
+continue;
+  auto *FieldDecl = Designator.getFieldDecl();
+  if (!FieldDecl)
+continue;
+  auto *II = FieldDecl->getIdentifier();
+  if (!II)
+continue;
+  SourceRange FixLocation{
+  Designator.getFieldLoc(),
+  Designator.getFieldLoc().getLocWithOffset(II->getLength())};

PiotrZSL wrote:

won't this getLocWithOffset point pass the end ?, usually end should point to 
last token, this will point to last token +1 character. In theory: `SourceRange 
FixLocation{Designator.getFieldLoc(), Designator.getFieldLoc());` should work 
in same way. 


https://github.com/llvm/llvm-project/pull/86976
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Support renaming designated initializers (PR #86976)

2024-03-30 Thread Piotr Zegar via cfe-commits

https://github.com/PiotrZSL commented:

Release notes entry is missing. Should be:

"Improved 
[readability-identifier-naming](https://clang.llvm.org/extra/clang-tidy/checks/readability/identifier-naming.html)
 check in GetConfigPerFile mode by resolving symbolic links to header files. 
Fixed handling of Hungarian Prefix when configured to LowerCase. Added support 
for renaming designated initializers."

in clang-tools-extra/docs/ReleaseNotes.rst


Fix pointed out issues, and could land.

https://github.com/llvm/llvm-project/pull/86976
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Support renaming designated initializers (PR #86976)

2024-03-30 Thread Piotr Zegar via cfe-commits


@@ -755,3 +755,11 @@ STATIC_MACRO void someFunc(MyFunPtr, const MyFunPtr) {}
 // CHECK-FIXES: {{^}}STATIC_MACRO void someFunc(my_fun_ptr_t, const 
my_fun_ptr_t) {}
 #undef STATIC_MACRO
 }
+
+struct Some_struct {
+  int SomeMember;
+// CHECK-MESSAGES: :[[@LINE-1]]:7: warning: invalid case style for public 
member 'SomeMember' [readability-identifier-naming]
+// CHECK-FIXES: {{^}}  int some_member;
+};
+Some_struct g_s{ .SomeMember = 1 };
+// CHECK-FIXES: {{^}}Some_struct g_s{ .some_member = 1 };

PiotrZSL wrote:

Add test (without whitespaces):
`Some_struct g_s{.SomeMember=1};`

https://github.com/llvm/llvm-project/pull/86976
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [HLSL][DXIL][SPIRV] Intrinsic unification PR (PR #87171)

2024-03-30 Thread Farzon Lotfi via cfe-commits

https://github.com/farzonl updated 
https://github.com/llvm/llvm-project/pull/87171

>From dcf4896ca4d86a34a731f31e7dc42e271a62a02f Mon Sep 17 00:00:00 2001
From: Farzon Lotfi 
Date: Thu, 28 Mar 2024 21:05:36 -0400
Subject: [PATCH] [HLSL][DXIL][SPIRV] Intrinsic unification PR

---
 clang/include/clang/Basic/Builtins.td |   6 +
 clang/lib/CodeGen/CGBuiltin.cpp   |  19 ++
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  | 112 +++
 clang/lib/Sema/SemaChecking.cpp   |   1 +
 clang/test/CodeGenHLSL/builtins/all.hlsl  | 277 ++
 llvm/include/llvm/IR/Intrinsics.td|  12 +
 llvm/include/llvm/IR/IntrinsicsDirectX.td |   4 +-
 llvm/include/llvm/IR/IntrinsicsSPIRV.td   |   3 +-
 .../Target/SPIRV/SPIRVInstructionSelector.cpp |  19 ++
 .../test/CodeGen/SPIRV/hlsl-intrinsics/all.ll |  95 ++
 10 files changed, 545 insertions(+), 3 deletions(-)
 create mode 100644 clang/test/CodeGenHLSL/builtins/all.hlsl
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/all.ll

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index f421223ff087de..d6ceb450bd106b 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4587,6 +4587,12 @@ def GetDeviceSideMangledName : LangBuiltin<"CUDA_LANG"> {
 }
 
 // HLSL
+def HLSLAll : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_elementwise_all"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "bool(...)";
+}
+
 def HLSLAny : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_elementwise_any"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index bb007231c0b783..add7ec1fa0eb45 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -51,6 +51,7 @@
 #include "llvm/IR/IntrinsicsR600.h"
 #include "llvm/IR/IntrinsicsRISCV.h"
 #include "llvm/IR/IntrinsicsS390.h"
+#include "llvm/IR/IntrinsicsSPIRV.h"
 #include "llvm/IR/IntrinsicsVE.h"
 #include "llvm/IR/IntrinsicsWebAssembly.h"
 #include "llvm/IR/IntrinsicsX86.h"
@@ -18176,12 +18177,30 @@ Intrinsic::ID getDotProductIntrinsic(QualType QT, int 
elementCount) {
   return Intrinsic::dx_udot;
 }
 
+Intrinsic::ID getAllIntrinsic(const llvm::Triple::ArchType Arch) {
+  switch (Arch) {
+  case llvm::Triple::dxil:
+return Intrinsic::dx_all;
+  case llvm::Triple::spirv:
+return Intrinsic::spv_all;
+  default:
+llvm_unreachable("Input semantic not supported by target");
+  }
+}
+
 Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
 const CallExpr *E) {
   if (!getLangOpts().HLSL)
 return nullptr;
 
   switch (BuiltinID) {
+  case Builtin::BI__builtin_hlsl_elementwise_all: {
+Value *Op0 = EmitScalarExpr(E->getArg(0));
+return Builder.CreateIntrinsic(
+/*ReturnType=*/llvm::Type::getInt1Ty(getLLVMContext()),
+getAllIntrinsic(CGM.getTarget().getTriple().getArch()),
+ArrayRef{Op0}, nullptr, "hlsl.all");
+  }
   case Builtin::BI__builtin_hlsl_elementwise_any: {
 Value *Op0 = EmitScalarExpr(E->getArg(0));
 return Builder.CreateIntrinsic(
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 9fb6204f90c9a8..06409c6fc77417 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -100,6 +100,118 @@ double3 abs(double3);
 _HLSL_BUILTIN_ALIAS(__builtin_elementwise_abs)
 double4 abs(double4);
 
+//===--===//
+// all builtins
+//===--===//
+
+/// \fn bool all(T x)
+/// \brief Returns True if all components of the \a x parameter are non-zero;
+/// otherwise, false. \param x The input value.
+
+#ifdef __HLSL_ENABLE_16_BIT
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(int16_t);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(int16_t2);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(int16_t3);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(int16_t4);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(uint16_t);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(uint16_t2);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(uint16_t3);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(uint16_t4);
+#endif
+
+_HLSL_16BIT_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(half);
+_HLSL_16BIT_AV

[clang] [Clang][Sema] set declaration invalid earlier to prevent crash in calculating record layout (PR #87173)

2024-03-30 Thread Qizhi Hu via cfe-commits

https://github.com/jcsxky updated 
https://github.com/llvm/llvm-project/pull/87173

>From 710a72c43ae9612e577172a978bfafe6553a6f9e Mon Sep 17 00:00:00 2001
From: huqizhi 
Date: Sun, 31 Mar 2024 09:38:05 +0800
Subject: [PATCH] [Clang][Sema] set declaration invalid earlier to prevent
 crash in calculating record layout

---
 clang/docs/ReleaseNotes.rst| 2 ++
 clang/lib/Sema/SemaType.cpp| 3 +++
 clang/test/SemaCXX/PR75221.cpp | 6 ++
 3 files changed, 11 insertions(+)
 create mode 100644 clang/test/SemaCXX/PR75221.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 37b843915a0dee..20578c9b60e33c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -465,6 +465,8 @@ Bug Fixes to C++ Support
   following the first `::` were ignored).
 - Fix an out-of-bounds crash when checking the validity of template partial 
specializations. (part of #GH86757).
 - Fix an issue caused by not handling invalid cases when substituting into the 
parameter mapping of a constraint. Fixes (#GH86757).
+- Fix a crash caused by defined struct in a type alias template when the 
structure
+  has fields with dependent type. Fixes (#GH75221).
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index fd94caa4e1d449..973ad20c943bde 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -3899,6 +3899,9 @@ static QualType 
GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
   SemaRef.Diag(OwnedTagDecl->getLocation(), DiagID)
   << SemaRef.Context.getTypeDeclType(OwnedTagDecl);
   D.setInvalidType(true);
+  OwnedTagDecl->setCompleteDefinition(false);
+  OwnedTagDecl->setInvalidDecl();
+  OwnedTagDecl->setCompleteDefinition();
 }
   }
 
diff --git a/clang/test/SemaCXX/PR75221.cpp b/clang/test/SemaCXX/PR75221.cpp
new file mode 100644
index 00..b342e347c5606a
--- /dev/null
+++ b/clang/test/SemaCXX/PR75221.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -verify -std=c++11 -fsyntax-only %s
+
+template  using foo = struct foo { // expected-error {{'foo' cannot 
be defined in a type alias template}}
+  T size = 0;
+};
+foo a;

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


[clang] [Clang][Sema] set declaration invalid earlier to prevent crash in calculating record layout (PR #87173)

2024-03-30 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Qizhi Hu (jcsxky)


Changes

Try to fix https://github.com/llvm/llvm-project/issues/75221
This crash caused by calculating record layout which contains a field 
declaration with dependent type. Make it invalid when report diagnose to 
prevent this crash. Set the record declaration incomplete bypass the assertion 
and restore the status when finish setting it invalid.

---
Full diff: https://github.com/llvm/llvm-project/pull/87173.diff


3 Files Affected:

- (modified) clang/docs/ReleaseNotes.rst (+2) 
- (modified) clang/lib/Sema/SemaType.cpp (+3) 
- (added) clang/test/SemaCXX/PR75221.cpp (+7) 


``diff
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 37b843915a0dee..20578c9b60e33c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -465,6 +465,8 @@ Bug Fixes to C++ Support
   following the first `::` were ignored).
 - Fix an out-of-bounds crash when checking the validity of template partial 
specializations. (part of #GH86757).
 - Fix an issue caused by not handling invalid cases when substituting into the 
parameter mapping of a constraint. Fixes (#GH86757).
+- Fix a crash caused by defined struct in a type alias template when the 
structure
+  has fields with dependent type. Fixes (#GH75221).
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index fd94caa4e1d449..973ad20c943bde 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -3899,6 +3899,9 @@ static QualType 
GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
   SemaRef.Diag(OwnedTagDecl->getLocation(), DiagID)
   << SemaRef.Context.getTypeDeclType(OwnedTagDecl);
   D.setInvalidType(true);
+  OwnedTagDecl->setCompleteDefinition(false);
+  OwnedTagDecl->setInvalidDecl();
+  OwnedTagDecl->setCompleteDefinition();
 }
   }
 
diff --git a/clang/test/SemaCXX/PR75221.cpp b/clang/test/SemaCXX/PR75221.cpp
new file mode 100644
index 00..08b7a06676a8a5
--- /dev/null
+++ b/clang/test/SemaCXX/PR75221.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -verify -std=c++11 -fsyntax-only %s
+// expected-no-diagnostics
+
+template  using foo = struct foo {
+  T size = 0;
+};
+foo a;

``




https://github.com/llvm/llvm-project/pull/87173
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang][Sema] set declaration invalid earlier to prevent crash in calculating record layout (PR #87173)

2024-03-30 Thread Qizhi Hu via cfe-commits

https://github.com/jcsxky created 
https://github.com/llvm/llvm-project/pull/87173

Try to fix https://github.com/llvm/llvm-project/issues/75221
This crash caused by calculating record layout which contains a field 
declaration with dependent type. Make it invalid when report diagnose to 
prevent this crash. Set the record declaration incomplete bypass the assertion 
and restore the status when finish setting it invalid.

>From 98c7c28b2e3484d599847f4a4046fc4ebef5a1e0 Mon Sep 17 00:00:00 2001
From: huqizhi 
Date: Sun, 31 Mar 2024 09:38:05 +0800
Subject: [PATCH] [Clang][Sema] set declaration invalid earlier to prevent
 crash in calculating record layout

---
 clang/docs/ReleaseNotes.rst| 2 ++
 clang/lib/Sema/SemaType.cpp| 3 +++
 clang/test/SemaCXX/PR75221.cpp | 7 +++
 3 files changed, 12 insertions(+)
 create mode 100644 clang/test/SemaCXX/PR75221.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 37b843915a0dee..20578c9b60e33c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -465,6 +465,8 @@ Bug Fixes to C++ Support
   following the first `::` were ignored).
 - Fix an out-of-bounds crash when checking the validity of template partial 
specializations. (part of #GH86757).
 - Fix an issue caused by not handling invalid cases when substituting into the 
parameter mapping of a constraint. Fixes (#GH86757).
+- Fix a crash caused by defined struct in a type alias template when the 
structure
+  has fields with dependent type. Fixes (#GH75221).
 
 Bug Fixes to AST Handling
 ^
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index fd94caa4e1d449..973ad20c943bde 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -3899,6 +3899,9 @@ static QualType 
GetDeclSpecTypeForDeclarator(TypeProcessingState &state,
   SemaRef.Diag(OwnedTagDecl->getLocation(), DiagID)
   << SemaRef.Context.getTypeDeclType(OwnedTagDecl);
   D.setInvalidType(true);
+  OwnedTagDecl->setCompleteDefinition(false);
+  OwnedTagDecl->setInvalidDecl();
+  OwnedTagDecl->setCompleteDefinition();
 }
   }
 
diff --git a/clang/test/SemaCXX/PR75221.cpp b/clang/test/SemaCXX/PR75221.cpp
new file mode 100644
index 00..08b7a06676a8a5
--- /dev/null
+++ b/clang/test/SemaCXX/PR75221.cpp
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -verify -std=c++11 -fsyntax-only %s
+// expected-no-diagnostics
+
+template  using foo = struct foo {
+  T size = 0;
+};
+foo a;

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


[clang] [analyzer][docs] Document the `optin.performance.Padding` checker (PR #86411)

2024-03-30 Thread via cfe-commits

https://github.com/komalverma04 commented:

Great learning!

https://github.com/llvm/llvm-project/pull/86411
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] add new check readability-enum-initial-value (PR #86129)

2024-03-30 Thread Congcong Cai via cfe-commits

https://github.com/HerrCai0907 updated 
https://github.com/llvm/llvm-project/pull/86129

>From 4e0845a143a820d4a68ffbdced206654c7593359 Mon Sep 17 00:00:00 2001
From: Congcong Cai 
Date: Fri, 15 Mar 2024 08:07:47 +0800
Subject: [PATCH 1/8] [clang-tidy] add new check readability-enum-initial-value

Fixes: #85243.
---
 .../clang-tidy/readability/CMakeLists.txt |  1 +
 .../readability/EnumInitialValueCheck.cpp | 82 +++
 .../readability/EnumInitialValueCheck.h   | 31 +++
 .../readability/ReadabilityTidyModule.cpp |  3 +
 clang-tools-extra/docs/ReleaseNotes.rst   |  6 ++
 .../docs/clang-tidy/checks/list.rst   |  1 +
 .../checks/readability/enum-initial-value.rst | 45 ++
 .../checkers/readability/enum-initial-value.c | 27 ++
 .../readability/enum-initial-value.cpp| 27 ++
 9 files changed, 223 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/readability/enum-initial-value.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value.c
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value.cpp

diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
index 5728c9970fb65d..dd772d69202548 100644
--- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
@@ -17,6 +17,7 @@ add_clang_library(clangTidyReadabilityModule
   DeleteNullPointerCheck.cpp
   DuplicateIncludeCheck.cpp
   ElseAfterReturnCheck.cpp
+  EnumInitialValueCheck.cpp
   FunctionCognitiveComplexityCheck.cpp
   FunctionSizeCheck.cpp
   IdentifierLengthCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp
new file mode 100644
index 00..78d5101d439dde
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp
@@ -0,0 +1,82 @@
+//===--- EnumInitialValueCheck.cpp - clang-tidy 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "EnumInitialValueCheck.h"
+#include "../utils/LexerUtils.h"
+#include "clang/AST/Decl.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::readability {
+
+namespace {
+
+AST_MATCHER(EnumDecl, isNoneEnumeratorsInitialized) {
+  return llvm::all_of(Node.enumerators(), [](EnumConstantDecl const *ECD) {
+return ECD->getInitExpr() == nullptr;
+  });
+}
+
+AST_MATCHER(EnumDecl, isOnlyFirstEnumeratorsInitialized) {
+  for (EnumConstantDecl const *ECD : Node.enumerators())
+if (ECD == *Node.enumerator_begin()) {
+  if (ECD->getInitExpr() == nullptr)
+return false;
+} else {
+  if (ECD->getInitExpr() != nullptr)
+return false;
+}
+  return true;
+}
+
+AST_MATCHER(EnumDecl, isAllEnumeratorsInitialized) {
+  return llvm::all_of(Node.enumerators(), [](EnumConstantDecl const *ECD) {
+return ECD->getInitExpr() != nullptr;
+  });
+}
+
+} // namespace
+
+void EnumInitialValueCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(enumDecl(unless(anyOf(isNoneEnumeratorsInitialized(),
+   isOnlyFirstEnumeratorsInitialized(),
+   isAllEnumeratorsInitialized(
+ .bind("enum"),
+ this);
+}
+
+void EnumInitialValueCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Enum = Result.Nodes.getNodeAs("enum");
+  assert(Enum != nullptr);
+  SourceLocation Loc = Enum->getBeginLoc();
+  if (Loc.isInvalid() || Loc.isMacroID())
+return;
+  DiagnosticBuilder Diag =
+  diag(Loc, "inital value in enum %0 has readability issue, "
+"explicit initialization of all of enumerators")
+  << Enum->getName();
+  for (EnumConstantDecl const *ECD : Enum->enumerators())
+if (ECD->getInitExpr() == nullptr) {
+  SourceLocation ECDLoc = ECD->getEndLoc();
+  if (ECDLoc.isInvalid() || ECDLoc.isMacroID())
+continue;
+  std::optional Next = utils::lexer::findNextTokenSkippingComments(
+  ECDLoc, *Result.SourceManager, getLangOpts());
+  if (!Next.has_value() || Next->getLocation().isMacroID())
+continue;
+  llvm::SmallString<8> Str{" = "}

[clang] [llvm] [HLSL][DXIL][SPIRV] Intrinsic unification PR (PR #87171)

2024-03-30 Thread Farzon Lotfi via cfe-commits

https://github.com/farzonl edited 
https://github.com/llvm/llvm-project/pull/87171
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] add new check readability-enum-initial-value (PR #86129)

2024-03-30 Thread Julian Schmidt via cfe-commits


@@ -0,0 +1,199 @@
+//===--- EnumInitialValueCheck.cpp - clang-tidy 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "EnumInitialValueCheck.h"
+#include "../utils/LexerUtils.h"
+#include "clang/AST/Decl.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::readability {
+
+static bool isNoneEnumeratorsInitialized(const EnumDecl &Node) {
+  return llvm::all_of(Node.enumerators(), [](const EnumConstantDecl *ECD) {
+return ECD->getInitExpr() == nullptr;
+  });
+}
+
+static bool isOnlyFirstEnumeratorInitialized(const EnumDecl &Node) {
+  bool IsFirst = true;
+  for (const EnumConstantDecl *ECD : Node.enumerators()) {
+if ((IsFirst && ECD->getInitExpr() == nullptr) ||
+(!IsFirst && ECD->getInitExpr() != nullptr))
+  return false;
+IsFirst = false;
+  }
+  return !IsFirst;
+}
+
+static bool areAllEnumeratorsInitialized(const EnumDecl &Node) {
+  return llvm::all_of(Node.enumerators(), [](const EnumConstantDecl *ECD) {
+return ECD->getInitExpr() != nullptr;
+  });
+}
+
+/// Check if \p Enumerator is initialized with a (potentially negated) \c
+/// IntegerLiteral.
+static bool isInitializedByLiteral(const EnumConstantDecl *Enumerator) {
+  const Expr *const Init = Enumerator->getInitExpr();
+  if (!Init)
+return false;
+  return Init->isIntegerConstantExpr(Enumerator->getASTContext());
+}
+
+static void cleanInitialValue(DiagnosticBuilder &Diag,
+  const EnumConstantDecl *ECD,
+  const SourceManager &SM,
+  const LangOptions &LangOpts) {
+  std::optional EqualToken = 
utils::lexer::findNextTokenSkippingComments(
+  ECD->getLocation(), SM, LangOpts);
+  if (!EqualToken.has_value())
+return;
+  SourceLocation EqualLoc{EqualToken->getLocation()};
+  if (EqualLoc.isInvalid() || EqualLoc.isMacroID())
+return;
+  SourceRange InitExprRange = ECD->getInitExpr()->getSourceRange();
+  if (InitExprRange.isInvalid() || InitExprRange.getBegin().isMacroID() ||
+  InitExprRange.getEnd().isMacroID())
+return;
+  Diag << FixItHint::CreateRemoval(EqualLoc)
+   << FixItHint::CreateRemoval(InitExprRange);
+  return;
+}
+
+namespace {
+
+AST_MATCHER(EnumDecl, isMacro) {
+  SourceLocation Loc = Node.getBeginLoc();
+  return Loc.isMacroID();
+}
+
+AST_MATCHER(EnumDecl, hasConsistentInitialValues) {
+  return isNoneEnumeratorsInitialized(Node) ||
+ isOnlyFirstEnumeratorInitialized(Node) ||
+ areAllEnumeratorsInitialized(Node);
+}
+
+AST_MATCHER(EnumDecl, hasZeroInitialValueForFirstEnumerator) {
+  EnumDecl::enumerator_range Enumerators = Node.enumerators();
+  if (Enumerators.empty())
+return false;
+  const EnumConstantDecl *ECD = *Enumerators.begin();
+  return isOnlyFirstEnumeratorInitialized(Node) &&
+ isInitializedByLiteral(ECD) && ECD->getInitVal().isZero();
+}
+
+/// Excludes bitfields because enumerators initialized with the result of a
+/// bitwise operator on enumeration values or any other expr that is not a
+/// potentially negative integer literal.
+/// Enumerations where it is not directly clear if they are used with
+/// bitmask, evident when enumerators are only initialized with (potentially
+/// negative) integer literals, are ignored. This is also the case when all
+/// enumerators are powers of two (e.g., 0, 1, 2).
+AST_MATCHER(EnumDecl, hasSequentialInitialValues) {
+  EnumDecl::enumerator_range Enumerators = Node.enumerators();
+  if (Enumerators.empty())
+return false;
+  const EnumConstantDecl *const FirstEnumerator = *Node.enumerator_begin();
+  llvm::APSInt PrevValue = FirstEnumerator->getInitVal();
+  if (!isInitializedByLiteral(FirstEnumerator))
+return false;
+  bool AllEnumeratorsArePowersOfTwo = true;
+  for (const EnumConstantDecl *Enumerator : llvm::drop_begin(Enumerators)) {
+const llvm::APSInt NewValue = Enumerator->getInitVal();
+if (NewValue != ++PrevValue)
+  return false;
+if (!isInitializedByLiteral(Enumerator))
+  return false;
+PrevValue = NewValue;
+AllEnumeratorsArePowersOfTwo &= NewValue.isPowerOf2();
+  }
+  return !AllEnumeratorsArePowersOfTwo;
+}
+
+} // namespace
+
+EnumInitialValueCheck::EnumInitialValueCheck(StringRef Name,
+ ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  AllowExplicitZeroFirstInitialValue(
+  Options.get("AllowExplicitZeroFirstInitialValue", tru

[clang-tools-extra] [clang-tidy] add new check readability-enum-initial-value (PR #86129)

2024-03-30 Thread Congcong Cai via cfe-commits

https://github.com/HerrCai0907 updated 
https://github.com/llvm/llvm-project/pull/86129

>From 4e0845a143a820d4a68ffbdced206654c7593359 Mon Sep 17 00:00:00 2001
From: Congcong Cai 
Date: Fri, 15 Mar 2024 08:07:47 +0800
Subject: [PATCH 1/7] [clang-tidy] add new check readability-enum-initial-value

Fixes: #85243.
---
 .../clang-tidy/readability/CMakeLists.txt |  1 +
 .../readability/EnumInitialValueCheck.cpp | 82 +++
 .../readability/EnumInitialValueCheck.h   | 31 +++
 .../readability/ReadabilityTidyModule.cpp |  3 +
 clang-tools-extra/docs/ReleaseNotes.rst   |  6 ++
 .../docs/clang-tidy/checks/list.rst   |  1 +
 .../checks/readability/enum-initial-value.rst | 45 ++
 .../checkers/readability/enum-initial-value.c | 27 ++
 .../readability/enum-initial-value.cpp| 27 ++
 9 files changed, 223 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.h
 create mode 100644 
clang-tools-extra/docs/clang-tidy/checks/readability/enum-initial-value.rst
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value.c
 create mode 100644 
clang-tools-extra/test/clang-tidy/checkers/readability/enum-initial-value.cpp

diff --git a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
index 5728c9970fb65d..dd772d69202548 100644
--- a/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/readability/CMakeLists.txt
@@ -17,6 +17,7 @@ add_clang_library(clangTidyReadabilityModule
   DeleteNullPointerCheck.cpp
   DuplicateIncludeCheck.cpp
   ElseAfterReturnCheck.cpp
+  EnumInitialValueCheck.cpp
   FunctionCognitiveComplexityCheck.cpp
   FunctionSizeCheck.cpp
   IdentifierLengthCheck.cpp
diff --git a/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp
new file mode 100644
index 00..78d5101d439dde
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/readability/EnumInitialValueCheck.cpp
@@ -0,0 +1,82 @@
+//===--- EnumInitialValueCheck.cpp - clang-tidy 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "EnumInitialValueCheck.h"
+#include "../utils/LexerUtils.h"
+#include "clang/AST/Decl.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/Diagnostic.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::readability {
+
+namespace {
+
+AST_MATCHER(EnumDecl, isNoneEnumeratorsInitialized) {
+  return llvm::all_of(Node.enumerators(), [](EnumConstantDecl const *ECD) {
+return ECD->getInitExpr() == nullptr;
+  });
+}
+
+AST_MATCHER(EnumDecl, isOnlyFirstEnumeratorsInitialized) {
+  for (EnumConstantDecl const *ECD : Node.enumerators())
+if (ECD == *Node.enumerator_begin()) {
+  if (ECD->getInitExpr() == nullptr)
+return false;
+} else {
+  if (ECD->getInitExpr() != nullptr)
+return false;
+}
+  return true;
+}
+
+AST_MATCHER(EnumDecl, isAllEnumeratorsInitialized) {
+  return llvm::all_of(Node.enumerators(), [](EnumConstantDecl const *ECD) {
+return ECD->getInitExpr() != nullptr;
+  });
+}
+
+} // namespace
+
+void EnumInitialValueCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(enumDecl(unless(anyOf(isNoneEnumeratorsInitialized(),
+   isOnlyFirstEnumeratorsInitialized(),
+   isAllEnumeratorsInitialized(
+ .bind("enum"),
+ this);
+}
+
+void EnumInitialValueCheck::check(const MatchFinder::MatchResult &Result) {
+  const auto *Enum = Result.Nodes.getNodeAs("enum");
+  assert(Enum != nullptr);
+  SourceLocation Loc = Enum->getBeginLoc();
+  if (Loc.isInvalid() || Loc.isMacroID())
+return;
+  DiagnosticBuilder Diag =
+  diag(Loc, "inital value in enum %0 has readability issue, "
+"explicit initialization of all of enumerators")
+  << Enum->getName();
+  for (EnumConstantDecl const *ECD : Enum->enumerators())
+if (ECD->getInitExpr() == nullptr) {
+  SourceLocation ECDLoc = ECD->getEndLoc();
+  if (ECDLoc.isInvalid() || ECDLoc.isMacroID())
+continue;
+  std::optional Next = utils::lexer::findNextTokenSkippingComments(
+  ECDLoc, *Result.SourceManager, getLangOpts());
+  if (!Next.has_value() || Next->getLocation().isMacroID())
+continue;
+  llvm::SmallString<8> Str{" = "}

[clang-tools-extra] [clang-tidy] add new check readability-enum-initial-value (PR #86129)

2024-03-30 Thread Congcong Cai via cfe-commits


@@ -0,0 +1,199 @@
+//===--- EnumInitialValueCheck.cpp - clang-tidy 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "EnumInitialValueCheck.h"
+#include "../utils/LexerUtils.h"
+#include "clang/AST/Decl.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::readability {
+
+static bool isNoneEnumeratorsInitialized(const EnumDecl &Node) {
+  return llvm::all_of(Node.enumerators(), [](const EnumConstantDecl *ECD) {
+return ECD->getInitExpr() == nullptr;
+  });
+}
+
+static bool isOnlyFirstEnumeratorInitialized(const EnumDecl &Node) {
+  bool IsFirst = true;
+  for (const EnumConstantDecl *ECD : Node.enumerators()) {
+if ((IsFirst && ECD->getInitExpr() == nullptr) ||
+(!IsFirst && ECD->getInitExpr() != nullptr))
+  return false;
+IsFirst = false;
+  }
+  return !IsFirst;
+}
+
+static bool areAllEnumeratorsInitialized(const EnumDecl &Node) {
+  return llvm::all_of(Node.enumerators(), [](const EnumConstantDecl *ECD) {
+return ECD->getInitExpr() != nullptr;
+  });
+}
+
+/// Check if \p Enumerator is initialized with a (potentially negated) \c
+/// IntegerLiteral.
+static bool isInitializedByLiteral(const EnumConstantDecl *Enumerator) {
+  const Expr *const Init = Enumerator->getInitExpr();
+  if (!Init)
+return false;
+  return Init->isIntegerConstantExpr(Enumerator->getASTContext());
+}
+
+static void cleanInitialValue(DiagnosticBuilder &Diag,
+  const EnumConstantDecl *ECD,
+  const SourceManager &SM,
+  const LangOptions &LangOpts) {
+  std::optional EqualToken = 
utils::lexer::findNextTokenSkippingComments(
+  ECD->getLocation(), SM, LangOpts);
+  if (!EqualToken.has_value())
+return;
+  SourceLocation EqualLoc{EqualToken->getLocation()};
+  if (EqualLoc.isInvalid() || EqualLoc.isMacroID())
+return;
+  SourceRange InitExprRange = ECD->getInitExpr()->getSourceRange();
+  if (InitExprRange.isInvalid() || InitExprRange.getBegin().isMacroID() ||
+  InitExprRange.getEnd().isMacroID())
+return;
+  Diag << FixItHint::CreateRemoval(EqualLoc)
+   << FixItHint::CreateRemoval(InitExprRange);
+  return;
+}
+
+namespace {
+
+AST_MATCHER(EnumDecl, isMacro) {
+  SourceLocation Loc = Node.getBeginLoc();
+  return Loc.isMacroID();
+}
+
+AST_MATCHER(EnumDecl, hasConsistentInitialValues) {
+  return isNoneEnumeratorsInitialized(Node) ||
+ isOnlyFirstEnumeratorInitialized(Node) ||
+ areAllEnumeratorsInitialized(Node);
+}
+
+AST_MATCHER(EnumDecl, hasZeroInitialValueForFirstEnumerator) {
+  EnumDecl::enumerator_range Enumerators = Node.enumerators();
+  if (Enumerators.empty())
+return false;
+  const EnumConstantDecl *ECD = *Enumerators.begin();
+  return isOnlyFirstEnumeratorInitialized(Node) &&
+ isInitializedByLiteral(ECD) && ECD->getInitVal().isZero();
+}
+
+/// Excludes bitfields because enumerators initialized with the result of a
+/// bitwise operator on enumeration values or any other expr that is not a
+/// potentially negative integer literal.
+/// Enumerations where it is not directly clear if they are used with
+/// bitmask, evident when enumerators are only initialized with (potentially
+/// negative) integer literals, are ignored. This is also the case when all
+/// enumerators are powers of two (e.g., 0, 1, 2).
+AST_MATCHER(EnumDecl, hasSequentialInitialValues) {
+  EnumDecl::enumerator_range Enumerators = Node.enumerators();
+  if (Enumerators.empty())
+return false;
+  const EnumConstantDecl *const FirstEnumerator = *Node.enumerator_begin();
+  llvm::APSInt PrevValue = FirstEnumerator->getInitVal();
+  if (!isInitializedByLiteral(FirstEnumerator))
+return false;
+  bool AllEnumeratorsArePowersOfTwo = true;
+  for (const EnumConstantDecl *Enumerator : llvm::drop_begin(Enumerators)) {
+const llvm::APSInt NewValue = Enumerator->getInitVal();
+if (NewValue != ++PrevValue)
+  return false;
+if (!isInitializedByLiteral(Enumerator))
+  return false;
+PrevValue = NewValue;
+AllEnumeratorsArePowersOfTwo &= NewValue.isPowerOf2();
+  }
+  return !AllEnumeratorsArePowersOfTwo;
+}
+
+} // namespace
+
+EnumInitialValueCheck::EnumInitialValueCheck(StringRef Name,
+ ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  AllowExplicitZeroFirstInitialValue(
+  Options.get("AllowExplicitZeroFirstInitialValue", tru

[clang] [Clang] [Sema] Improve support for `__restrict`-qualified member functions (PR #83855)

2024-03-30 Thread via cfe-commits

Sirraide wrote:

Update: it seems that the GCC behaviour is intended, and it actually makes a 
lot of sense now imo at least (see the initial pr comment for more info about 
this).

https://github.com/llvm/llvm-project/pull/83855
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [Clang] [Sema] Improve support for `__restrict`-qualified member functions (PR #83855)

2024-03-30 Thread via cfe-commits

https://github.com/Sirraide edited 
https://github.com/llvm/llvm-project/pull/83855
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [HLSL][DXIL][SPIRV] Intrinsic unification PR (PR #87171)

2024-03-30 Thread Farzon Lotfi via cfe-commits

https://github.com/farzonl edited 
https://github.com/llvm/llvm-project/pull/87171
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [HLSL][DXIL][SPIRV] Intrinsic unification PR (PR #87171)

2024-03-30 Thread Farzon Lotfi via cfe-commits

https://github.com/farzonl edited 
https://github.com/llvm/llvm-project/pull/87171
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [HLSL][DXIL][SPIRV] Intrinsic unification PR (PR #87171)

2024-03-30 Thread Farzon Lotfi via cfe-commits


@@ -18176,12 +18177,30 @@ Intrinsic::ID getDotProductIntrinsic(QualType QT, int 
elementCount) {
   return Intrinsic::dx_udot;
 }
 
+Intrinsic::ID getAllIntrinsic(const llvm::Triple::ArchType Arch) {

farzonl wrote:

this is a simple memchanism since we are only doing one intrinsic. 
Long term EmitHLSLBuiltinExpr may need to invoke a map using 
`llvm::Triple::ArchType Arch`  ie a arch map of  intrinsic maps. righting the 
same switch statement over and over again to pick the right intrinsics could 
become tedious.

```
spv_intrinsic = 
archMap[llvm::Triple::spirv][Builtin::BI__builtin_hlsl_elementwise_all] -->  
Intrinsic::spv_all;
dx_intrinsic  = 
archMap[llvm::Triple::dxil][Builtin::BI__builtin_hlsl_elementwise_all] -->  
Intrinsic::dx_all;
```

https://github.com/llvm/llvm-project/pull/87171
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [HLSL][DXIL][SPIRV] Intrinsic unification PR (PR #87171)

2024-03-30 Thread Farzon Lotfi via cfe-commits

https://github.com/farzonl created 
https://github.com/llvm/llvm-project/pull/87171

 DO NOT MERGE 
This is part of a proposal for how to unify spir-v and DirectX intrinsics. 
The issue tracking this work is: #83882


>From 02a78955fc1ccb78690b0cd87de51f73cf8785de Mon Sep 17 00:00:00 2001
From: Farzon Lotfi 
Date: Thu, 28 Mar 2024 21:05:36 -0400
Subject: [PATCH] [HLSL][DXIL][SPIRV] Intrinsic unification PR

---
 clang/include/clang/Basic/Builtins.td |   6 +
 clang/lib/CodeGen/CGBuiltin.cpp   |  19 ++
 clang/lib/Headers/hlsl/hlsl_intrinsics.h  | 112 +++
 clang/lib/Sema/SemaChecking.cpp   |   1 +
 clang/test/CodeGenHLSL/builtins/all.hlsl  | 277 ++
 llvm/include/llvm/IR/Intrinsics.td|  12 +
 llvm/include/llvm/IR/IntrinsicsDirectX.td |   4 +-
 llvm/include/llvm/IR/IntrinsicsSPIRV.td   |   3 +-
 .../Target/SPIRV/SPIRVInstructionSelector.cpp |  19 ++
 .../test/CodeGen/SPIRV/hlsl-intrinsics/all.ll |  95 ++
 10 files changed, 545 insertions(+), 3 deletions(-)
 create mode 100644 clang/test/CodeGenHLSL/builtins/all.hlsl
 create mode 100644 llvm/test/CodeGen/SPIRV/hlsl-intrinsics/all.ll

diff --git a/clang/include/clang/Basic/Builtins.td 
b/clang/include/clang/Basic/Builtins.td
index f421223ff087de..d6ceb450bd106b 100644
--- a/clang/include/clang/Basic/Builtins.td
+++ b/clang/include/clang/Basic/Builtins.td
@@ -4587,6 +4587,12 @@ def GetDeviceSideMangledName : LangBuiltin<"CUDA_LANG"> {
 }
 
 // HLSL
+def HLSLAll : LangBuiltin<"HLSL_LANG"> {
+  let Spellings = ["__builtin_hlsl_elementwise_all"];
+  let Attributes = [NoThrow, Const];
+  let Prototype = "bool(...)";
+}
+
 def HLSLAny : LangBuiltin<"HLSL_LANG"> {
   let Spellings = ["__builtin_hlsl_elementwise_any"];
   let Attributes = [NoThrow, Const];
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index bb007231c0b783..add7ec1fa0eb45 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -51,6 +51,7 @@
 #include "llvm/IR/IntrinsicsR600.h"
 #include "llvm/IR/IntrinsicsRISCV.h"
 #include "llvm/IR/IntrinsicsS390.h"
+#include "llvm/IR/IntrinsicsSPIRV.h"
 #include "llvm/IR/IntrinsicsVE.h"
 #include "llvm/IR/IntrinsicsWebAssembly.h"
 #include "llvm/IR/IntrinsicsX86.h"
@@ -18176,12 +18177,30 @@ Intrinsic::ID getDotProductIntrinsic(QualType QT, int 
elementCount) {
   return Intrinsic::dx_udot;
 }
 
+Intrinsic::ID getAllIntrinsic(const llvm::Triple::ArchType Arch) {
+  switch (Arch) {
+  case llvm::Triple::dxil:
+return Intrinsic::dx_all;
+  case llvm::Triple::spirv:
+return Intrinsic::spv_all;
+  default:
+llvm_unreachable("Input semantic not supported by target");
+  }
+}
+
 Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned BuiltinID,
 const CallExpr *E) {
   if (!getLangOpts().HLSL)
 return nullptr;
 
   switch (BuiltinID) {
+  case Builtin::BI__builtin_hlsl_elementwise_all: {
+Value *Op0 = EmitScalarExpr(E->getArg(0));
+return Builder.CreateIntrinsic(
+/*ReturnType=*/llvm::Type::getInt1Ty(getLLVMContext()),
+getAllIntrinsic(CGM.getTarget().getTriple().getArch()),
+ArrayRef{Op0}, nullptr, "hlsl.all");
+  }
   case Builtin::BI__builtin_hlsl_elementwise_any: {
 Value *Op0 = EmitScalarExpr(E->getArg(0));
 return Builder.CreateIntrinsic(
diff --git a/clang/lib/Headers/hlsl/hlsl_intrinsics.h 
b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
index 9fb6204f90c9a8..06409c6fc77417 100644
--- a/clang/lib/Headers/hlsl/hlsl_intrinsics.h
+++ b/clang/lib/Headers/hlsl/hlsl_intrinsics.h
@@ -100,6 +100,118 @@ double3 abs(double3);
 _HLSL_BUILTIN_ALIAS(__builtin_elementwise_abs)
 double4 abs(double4);
 
+//===--===//
+// all builtins
+//===--===//
+
+/// \fn bool all(T x)
+/// \brief Returns True if all components of the \a x parameter are non-zero;
+/// otherwise, false. \param x The input value.
+
+#ifdef __HLSL_ENABLE_16_BIT
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(int16_t);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(int16_t2);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(int16_t3);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(int16_t4);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(uint16_t);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(uint16_t2);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(uint16_t3);
+_HLSL_AVAILABILITY(shadermodel, 6.2)
+_HLSL_BUILTIN_ALIAS(__builtin_hlsl_elementwise_all)
+bool all(uint16_t4)

[clang] [HLSL][clang] Move hlsl_wave_get_lane_index to EmitHLSLBuiltinExpr (PR #87131)

2024-03-30 Thread Marc Auberer via cfe-commits

marcauberer wrote:

Workflow run also succeeded: 
https://github.com/llvm/llvm-project/actions/runs/8493247308

https://github.com/llvm/llvm-project/pull/87131
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] add new check readability-enum-initial-value (PR #86129)

2024-03-30 Thread Julian Schmidt via cfe-commits


@@ -0,0 +1,199 @@
+//===--- EnumInitialValueCheck.cpp - clang-tidy 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "EnumInitialValueCheck.h"
+#include "../utils/LexerUtils.h"
+#include "clang/AST/Decl.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::readability {
+
+static bool isNoneEnumeratorsInitialized(const EnumDecl &Node) {
+  return llvm::all_of(Node.enumerators(), [](const EnumConstantDecl *ECD) {
+return ECD->getInitExpr() == nullptr;
+  });
+}
+
+static bool isOnlyFirstEnumeratorInitialized(const EnumDecl &Node) {
+  bool IsFirst = true;
+  for (const EnumConstantDecl *ECD : Node.enumerators()) {
+if ((IsFirst && ECD->getInitExpr() == nullptr) ||
+(!IsFirst && ECD->getInitExpr() != nullptr))
+  return false;
+IsFirst = false;
+  }
+  return !IsFirst;
+}
+
+static bool areAllEnumeratorsInitialized(const EnumDecl &Node) {
+  return llvm::all_of(Node.enumerators(), [](const EnumConstantDecl *ECD) {
+return ECD->getInitExpr() != nullptr;
+  });
+}
+
+/// Check if \p Enumerator is initialized with a (potentially negated) \c
+/// IntegerLiteral.
+static bool isInitializedByLiteral(const EnumConstantDecl *Enumerator) {
+  const Expr *const Init = Enumerator->getInitExpr();
+  if (!Init)
+return false;
+  return Init->isIntegerConstantExpr(Enumerator->getASTContext());
+}
+
+static void cleanInitialValue(DiagnosticBuilder &Diag,
+  const EnumConstantDecl *ECD,
+  const SourceManager &SM,
+  const LangOptions &LangOpts) {
+  std::optional EqualToken = 
utils::lexer::findNextTokenSkippingComments(
+  ECD->getLocation(), SM, LangOpts);
+  if (!EqualToken.has_value())
+return;
+  SourceLocation EqualLoc{EqualToken->getLocation()};
+  if (EqualLoc.isInvalid() || EqualLoc.isMacroID())
+return;
+  SourceRange InitExprRange = ECD->getInitExpr()->getSourceRange();
+  if (InitExprRange.isInvalid() || InitExprRange.getBegin().isMacroID() ||
+  InitExprRange.getEnd().isMacroID())
+return;
+  Diag << FixItHint::CreateRemoval(EqualLoc)
+   << FixItHint::CreateRemoval(InitExprRange);
+  return;
+}
+
+namespace {
+
+AST_MATCHER(EnumDecl, isMacro) {
+  SourceLocation Loc = Node.getBeginLoc();
+  return Loc.isMacroID();
+}
+
+AST_MATCHER(EnumDecl, hasConsistentInitialValues) {
+  return isNoneEnumeratorsInitialized(Node) ||
+ isOnlyFirstEnumeratorInitialized(Node) ||
+ areAllEnumeratorsInitialized(Node);
+}
+
+AST_MATCHER(EnumDecl, hasZeroInitialValueForFirstEnumerator) {
+  EnumDecl::enumerator_range Enumerators = Node.enumerators();
+  if (Enumerators.empty())
+return false;
+  const EnumConstantDecl *ECD = *Enumerators.begin();
+  return isOnlyFirstEnumeratorInitialized(Node) &&
+ isInitializedByLiteral(ECD) && ECD->getInitVal().isZero();
+}
+
+/// Excludes bitfields because enumerators initialized with the result of a
+/// bitwise operator on enumeration values or any other expr that is not a
+/// potentially negative integer literal.
+/// Enumerations where it is not directly clear if they are used with
+/// bitmask, evident when enumerators are only initialized with (potentially
+/// negative) integer literals, are ignored. This is also the case when all
+/// enumerators are powers of two (e.g., 0, 1, 2).
+AST_MATCHER(EnumDecl, hasSequentialInitialValues) {
+  EnumDecl::enumerator_range Enumerators = Node.enumerators();
+  if (Enumerators.empty())
+return false;
+  const EnumConstantDecl *const FirstEnumerator = *Node.enumerator_begin();
+  llvm::APSInt PrevValue = FirstEnumerator->getInitVal();
+  if (!isInitializedByLiteral(FirstEnumerator))
+return false;
+  bool AllEnumeratorsArePowersOfTwo = true;
+  for (const EnumConstantDecl *Enumerator : llvm::drop_begin(Enumerators)) {
+const llvm::APSInt NewValue = Enumerator->getInitVal();
+if (NewValue != ++PrevValue)
+  return false;
+if (!isInitializedByLiteral(Enumerator))
+  return false;
+PrevValue = NewValue;
+AllEnumeratorsArePowersOfTwo &= NewValue.isPowerOf2();
+  }
+  return !AllEnumeratorsArePowersOfTwo;
+}
+
+} // namespace
+
+EnumInitialValueCheck::EnumInitialValueCheck(StringRef Name,
+ ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  AllowExplicitZeroFirstInitialValue(
+  Options.get("AllowExplicitZeroFirstInitialValue", tru

[clang-tools-extra] [clang-tidy] add new check readability-enum-initial-value (PR #86129)

2024-03-30 Thread Julian Schmidt via cfe-commits


@@ -0,0 +1,199 @@
+//===--- EnumInitialValueCheck.cpp - clang-tidy 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "EnumInitialValueCheck.h"
+#include "../utils/LexerUtils.h"
+#include "clang/AST/Decl.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::readability {
+
+static bool isNoneEnumeratorsInitialized(const EnumDecl &Node) {
+  return llvm::all_of(Node.enumerators(), [](const EnumConstantDecl *ECD) {
+return ECD->getInitExpr() == nullptr;
+  });
+}
+
+static bool isOnlyFirstEnumeratorInitialized(const EnumDecl &Node) {
+  bool IsFirst = true;
+  for (const EnumConstantDecl *ECD : Node.enumerators()) {
+if ((IsFirst && ECD->getInitExpr() == nullptr) ||
+(!IsFirst && ECD->getInitExpr() != nullptr))
+  return false;
+IsFirst = false;
+  }
+  return !IsFirst;
+}
+
+static bool areAllEnumeratorsInitialized(const EnumDecl &Node) {
+  return llvm::all_of(Node.enumerators(), [](const EnumConstantDecl *ECD) {
+return ECD->getInitExpr() != nullptr;
+  });
+}
+
+/// Check if \p Enumerator is initialized with a (potentially negated) \c
+/// IntegerLiteral.
+static bool isInitializedByLiteral(const EnumConstantDecl *Enumerator) {
+  const Expr *const Init = Enumerator->getInitExpr();
+  if (!Init)
+return false;
+  return Init->isIntegerConstantExpr(Enumerator->getASTContext());
+}
+
+static void cleanInitialValue(DiagnosticBuilder &Diag,
+  const EnumConstantDecl *ECD,
+  const SourceManager &SM,
+  const LangOptions &LangOpts) {
+  std::optional EqualToken = 
utils::lexer::findNextTokenSkippingComments(
+  ECD->getLocation(), SM, LangOpts);
+  if (!EqualToken.has_value())
+return;
+  SourceLocation EqualLoc{EqualToken->getLocation()};
+  if (EqualLoc.isInvalid() || EqualLoc.isMacroID())
+return;
+  SourceRange InitExprRange = ECD->getInitExpr()->getSourceRange();
+  if (InitExprRange.isInvalid() || InitExprRange.getBegin().isMacroID() ||
+  InitExprRange.getEnd().isMacroID())
+return;
+  Diag << FixItHint::CreateRemoval(EqualLoc)
+   << FixItHint::CreateRemoval(InitExprRange);
+  return;
+}
+
+namespace {
+
+AST_MATCHER(EnumDecl, isMacro) {
+  SourceLocation Loc = Node.getBeginLoc();
+  return Loc.isMacroID();
+}
+
+AST_MATCHER(EnumDecl, hasConsistentInitialValues) {
+  return isNoneEnumeratorsInitialized(Node) ||
+ isOnlyFirstEnumeratorInitialized(Node) ||
+ areAllEnumeratorsInitialized(Node);
+}
+
+AST_MATCHER(EnumDecl, hasZeroInitialValueForFirstEnumerator) {
+  EnumDecl::enumerator_range Enumerators = Node.enumerators();
+  if (Enumerators.empty())
+return false;
+  const EnumConstantDecl *ECD = *Enumerators.begin();
+  return isOnlyFirstEnumeratorInitialized(Node) &&
+ isInitializedByLiteral(ECD) && ECD->getInitVal().isZero();
+}
+
+/// Excludes bitfields because enumerators initialized with the result of a
+/// bitwise operator on enumeration values or any other expr that is not a
+/// potentially negative integer literal.
+/// Enumerations where it is not directly clear if they are used with
+/// bitmask, evident when enumerators are only initialized with (potentially
+/// negative) integer literals, are ignored. This is also the case when all
+/// enumerators are powers of two (e.g., 0, 1, 2).
+AST_MATCHER(EnumDecl, hasSequentialInitialValues) {
+  EnumDecl::enumerator_range Enumerators = Node.enumerators();
+  if (Enumerators.empty())
+return false;
+  const EnumConstantDecl *const FirstEnumerator = *Node.enumerator_begin();
+  llvm::APSInt PrevValue = FirstEnumerator->getInitVal();
+  if (!isInitializedByLiteral(FirstEnumerator))
+return false;
+  bool AllEnumeratorsArePowersOfTwo = true;
+  for (const EnumConstantDecl *Enumerator : llvm::drop_begin(Enumerators)) {
+const llvm::APSInt NewValue = Enumerator->getInitVal();
+if (NewValue != ++PrevValue)
+  return false;
+if (!isInitializedByLiteral(Enumerator))
+  return false;
+PrevValue = NewValue;
+AllEnumeratorsArePowersOfTwo &= NewValue.isPowerOf2();
+  }
+  return !AllEnumeratorsArePowersOfTwo;
+}
+
+} // namespace
+
+EnumInitialValueCheck::EnumInitialValueCheck(StringRef Name,
+ ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  AllowExplicitZeroFirstInitialValue(
+  Options.get("AllowExplicitZeroFirstInitialValue", tru

[clang-tools-extra] [clang-tidy] add new check readability-enum-initial-value (PR #86129)

2024-03-30 Thread Julian Schmidt via cfe-commits


@@ -0,0 +1,199 @@
+//===--- EnumInitialValueCheck.cpp - clang-tidy 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "EnumInitialValueCheck.h"
+#include "../utils/LexerUtils.h"
+#include "clang/AST/Decl.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::readability {
+
+static bool isNoneEnumeratorsInitialized(const EnumDecl &Node) {
+  return llvm::all_of(Node.enumerators(), [](const EnumConstantDecl *ECD) {
+return ECD->getInitExpr() == nullptr;
+  });
+}
+
+static bool isOnlyFirstEnumeratorInitialized(const EnumDecl &Node) {
+  bool IsFirst = true;
+  for (const EnumConstantDecl *ECD : Node.enumerators()) {
+if ((IsFirst && ECD->getInitExpr() == nullptr) ||
+(!IsFirst && ECD->getInitExpr() != nullptr))
+  return false;
+IsFirst = false;
+  }
+  return !IsFirst;
+}
+
+static bool areAllEnumeratorsInitialized(const EnumDecl &Node) {
+  return llvm::all_of(Node.enumerators(), [](const EnumConstantDecl *ECD) {
+return ECD->getInitExpr() != nullptr;
+  });
+}
+
+/// Check if \p Enumerator is initialized with a (potentially negated) \c
+/// IntegerLiteral.
+static bool isInitializedByLiteral(const EnumConstantDecl *Enumerator) {
+  const Expr *const Init = Enumerator->getInitExpr();
+  if (!Init)
+return false;
+  return Init->isIntegerConstantExpr(Enumerator->getASTContext());
+}
+
+static void cleanInitialValue(DiagnosticBuilder &Diag,
+  const EnumConstantDecl *ECD,
+  const SourceManager &SM,
+  const LangOptions &LangOpts) {
+  std::optional EqualToken = 
utils::lexer::findNextTokenSkippingComments(
+  ECD->getLocation(), SM, LangOpts);
+  if (!EqualToken.has_value())
+return;
+  SourceLocation EqualLoc{EqualToken->getLocation()};
+  if (EqualLoc.isInvalid() || EqualLoc.isMacroID())
+return;
+  SourceRange InitExprRange = ECD->getInitExpr()->getSourceRange();
+  if (InitExprRange.isInvalid() || InitExprRange.getBegin().isMacroID() ||
+  InitExprRange.getEnd().isMacroID())
+return;

5chmidti wrote:

This check can be done before the call to `findNextTokenSkippingComments`, 
which is cheaper than going through the lexer first.

https://github.com/llvm/llvm-project/pull/86129
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] add new check readability-enum-initial-value (PR #86129)

2024-03-30 Thread Julian Schmidt via cfe-commits


@@ -0,0 +1,199 @@
+//===--- EnumInitialValueCheck.cpp - clang-tidy 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "EnumInitialValueCheck.h"
+#include "../utils/LexerUtils.h"
+#include "clang/AST/Decl.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::readability {
+
+static bool isNoneEnumeratorsInitialized(const EnumDecl &Node) {
+  return llvm::all_of(Node.enumerators(), [](const EnumConstantDecl *ECD) {
+return ECD->getInitExpr() == nullptr;
+  });
+}
+
+static bool isOnlyFirstEnumeratorInitialized(const EnumDecl &Node) {
+  bool IsFirst = true;
+  for (const EnumConstantDecl *ECD : Node.enumerators()) {
+if ((IsFirst && ECD->getInitExpr() == nullptr) ||
+(!IsFirst && ECD->getInitExpr() != nullptr))
+  return false;
+IsFirst = false;
+  }
+  return !IsFirst;
+}
+
+static bool areAllEnumeratorsInitialized(const EnumDecl &Node) {
+  return llvm::all_of(Node.enumerators(), [](const EnumConstantDecl *ECD) {
+return ECD->getInitExpr() != nullptr;
+  });
+}
+
+/// Check if \p Enumerator is initialized with a (potentially negated) \c
+/// IntegerLiteral.
+static bool isInitializedByLiteral(const EnumConstantDecl *Enumerator) {
+  const Expr *const Init = Enumerator->getInitExpr();
+  if (!Init)
+return false;
+  return Init->isIntegerConstantExpr(Enumerator->getASTContext());
+}
+
+static void cleanInitialValue(DiagnosticBuilder &Diag,
+  const EnumConstantDecl *ECD,
+  const SourceManager &SM,
+  const LangOptions &LangOpts) {
+  std::optional EqualToken = 
utils::lexer::findNextTokenSkippingComments(
+  ECD->getLocation(), SM, LangOpts);
+  if (!EqualToken.has_value())
+return;
+  SourceLocation EqualLoc{EqualToken->getLocation()};
+  if (EqualLoc.isInvalid() || EqualLoc.isMacroID())
+return;
+  SourceRange InitExprRange = ECD->getInitExpr()->getSourceRange();

5chmidti wrote:

2x `const SourceRange`

https://github.com/llvm/llvm-project/pull/86129
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] add new check readability-enum-initial-value (PR #86129)

2024-03-30 Thread Julian Schmidt via cfe-commits


@@ -0,0 +1,199 @@
+//===--- EnumInitialValueCheck.cpp - clang-tidy 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "EnumInitialValueCheck.h"
+#include "../utils/LexerUtils.h"
+#include "clang/AST/Decl.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::readability {
+
+static bool isNoneEnumeratorsInitialized(const EnumDecl &Node) {
+  return llvm::all_of(Node.enumerators(), [](const EnumConstantDecl *ECD) {
+return ECD->getInitExpr() == nullptr;
+  });
+}
+
+static bool isOnlyFirstEnumeratorInitialized(const EnumDecl &Node) {
+  bool IsFirst = true;
+  for (const EnumConstantDecl *ECD : Node.enumerators()) {
+if ((IsFirst && ECD->getInitExpr() == nullptr) ||
+(!IsFirst && ECD->getInitExpr() != nullptr))
+  return false;
+IsFirst = false;
+  }
+  return !IsFirst;
+}
+
+static bool areAllEnumeratorsInitialized(const EnumDecl &Node) {
+  return llvm::all_of(Node.enumerators(), [](const EnumConstantDecl *ECD) {
+return ECD->getInitExpr() != nullptr;
+  });
+}
+
+/// Check if \p Enumerator is initialized with a (potentially negated) \c
+/// IntegerLiteral.
+static bool isInitializedByLiteral(const EnumConstantDecl *Enumerator) {
+  const Expr *const Init = Enumerator->getInitExpr();
+  if (!Init)
+return false;
+  return Init->isIntegerConstantExpr(Enumerator->getASTContext());
+}
+
+static void cleanInitialValue(DiagnosticBuilder &Diag,
+  const EnumConstantDecl *ECD,
+  const SourceManager &SM,
+  const LangOptions &LangOpts) {
+  std::optional EqualToken = 
utils::lexer::findNextTokenSkippingComments(
+  ECD->getLocation(), SM, LangOpts);
+  if (!EqualToken.has_value())
+return;
+  SourceLocation EqualLoc{EqualToken->getLocation()};
+  if (EqualLoc.isInvalid() || EqualLoc.isMacroID())
+return;
+  SourceRange InitExprRange = ECD->getInitExpr()->getSourceRange();
+  if (InitExprRange.isInvalid() || InitExprRange.getBegin().isMacroID() ||
+  InitExprRange.getEnd().isMacroID())
+return;
+  Diag << FixItHint::CreateRemoval(EqualLoc)
+   << FixItHint::CreateRemoval(InitExprRange);
+  return;
+}
+
+namespace {
+
+AST_MATCHER(EnumDecl, isMacro) {
+  SourceLocation Loc = Node.getBeginLoc();
+  return Loc.isMacroID();
+}
+
+AST_MATCHER(EnumDecl, hasConsistentInitialValues) {
+  return isNoneEnumeratorsInitialized(Node) ||
+ isOnlyFirstEnumeratorInitialized(Node) ||
+ areAllEnumeratorsInitialized(Node);
+}
+
+AST_MATCHER(EnumDecl, hasZeroInitialValueForFirstEnumerator) {
+  EnumDecl::enumerator_range Enumerators = Node.enumerators();

5chmidti wrote:

Please add `const`

https://github.com/llvm/llvm-project/pull/86129
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] add new check readability-enum-initial-value (PR #86129)

2024-03-30 Thread Julian Schmidt via cfe-commits

https://github.com/5chmidti commented:

I only have some minor comments, otherwise looks good to me

https://github.com/llvm/llvm-project/pull/86129
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] add new check readability-enum-initial-value (PR #86129)

2024-03-30 Thread Julian Schmidt via cfe-commits

https://github.com/5chmidti edited 
https://github.com/llvm/llvm-project/pull/86129
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] add new check readability-enum-initial-value (PR #86129)

2024-03-30 Thread Julian Schmidt via cfe-commits


@@ -0,0 +1,199 @@
+//===--- EnumInitialValueCheck.cpp - clang-tidy 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "EnumInitialValueCheck.h"
+#include "../utils/LexerUtils.h"
+#include "clang/AST/Decl.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Basic/SourceLocation.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::readability {
+
+static bool isNoneEnumeratorsInitialized(const EnumDecl &Node) {
+  return llvm::all_of(Node.enumerators(), [](const EnumConstantDecl *ECD) {
+return ECD->getInitExpr() == nullptr;
+  });
+}
+
+static bool isOnlyFirstEnumeratorInitialized(const EnumDecl &Node) {
+  bool IsFirst = true;
+  for (const EnumConstantDecl *ECD : Node.enumerators()) {
+if ((IsFirst && ECD->getInitExpr() == nullptr) ||
+(!IsFirst && ECD->getInitExpr() != nullptr))
+  return false;
+IsFirst = false;
+  }
+  return !IsFirst;
+}
+
+static bool areAllEnumeratorsInitialized(const EnumDecl &Node) {
+  return llvm::all_of(Node.enumerators(), [](const EnumConstantDecl *ECD) {
+return ECD->getInitExpr() != nullptr;
+  });
+}
+
+/// Check if \p Enumerator is initialized with a (potentially negated) \c
+/// IntegerLiteral.
+static bool isInitializedByLiteral(const EnumConstantDecl *Enumerator) {
+  const Expr *const Init = Enumerator->getInitExpr();
+  if (!Init)
+return false;
+  return Init->isIntegerConstantExpr(Enumerator->getASTContext());
+}
+
+static void cleanInitialValue(DiagnosticBuilder &Diag,
+  const EnumConstantDecl *ECD,
+  const SourceManager &SM,
+  const LangOptions &LangOpts) {
+  std::optional EqualToken = 
utils::lexer::findNextTokenSkippingComments(
+  ECD->getLocation(), SM, LangOpts);
+  if (!EqualToken.has_value())
+return;
+  SourceLocation EqualLoc{EqualToken->getLocation()};
+  if (EqualLoc.isInvalid() || EqualLoc.isMacroID())
+return;
+  SourceRange InitExprRange = ECD->getInitExpr()->getSourceRange();
+  if (InitExprRange.isInvalid() || InitExprRange.getBegin().isMacroID() ||
+  InitExprRange.getEnd().isMacroID())
+return;
+  Diag << FixItHint::CreateRemoval(EqualLoc)
+   << FixItHint::CreateRemoval(InitExprRange);
+  return;
+}
+
+namespace {
+
+AST_MATCHER(EnumDecl, isMacro) {
+  SourceLocation Loc = Node.getBeginLoc();
+  return Loc.isMacroID();
+}
+
+AST_MATCHER(EnumDecl, hasConsistentInitialValues) {
+  return isNoneEnumeratorsInitialized(Node) ||
+ isOnlyFirstEnumeratorInitialized(Node) ||
+ areAllEnumeratorsInitialized(Node);
+}
+
+AST_MATCHER(EnumDecl, hasZeroInitialValueForFirstEnumerator) {
+  EnumDecl::enumerator_range Enumerators = Node.enumerators();
+  if (Enumerators.empty())
+return false;
+  const EnumConstantDecl *ECD = *Enumerators.begin();
+  return isOnlyFirstEnumeratorInitialized(Node) &&
+ isInitializedByLiteral(ECD) && ECD->getInitVal().isZero();
+}
+
+/// Excludes bitfields because enumerators initialized with the result of a
+/// bitwise operator on enumeration values or any other expr that is not a
+/// potentially negative integer literal.
+/// Enumerations where it is not directly clear if they are used with
+/// bitmask, evident when enumerators are only initialized with (potentially
+/// negative) integer literals, are ignored. This is also the case when all
+/// enumerators are powers of two (e.g., 0, 1, 2).
+AST_MATCHER(EnumDecl, hasSequentialInitialValues) {
+  EnumDecl::enumerator_range Enumerators = Node.enumerators();
+  if (Enumerators.empty())
+return false;
+  const EnumConstantDecl *const FirstEnumerator = *Node.enumerator_begin();
+  llvm::APSInt PrevValue = FirstEnumerator->getInitVal();
+  if (!isInitializedByLiteral(FirstEnumerator))
+return false;
+  bool AllEnumeratorsArePowersOfTwo = true;
+  for (const EnumConstantDecl *Enumerator : llvm::drop_begin(Enumerators)) {
+const llvm::APSInt NewValue = Enumerator->getInitVal();
+if (NewValue != ++PrevValue)
+  return false;
+if (!isInitializedByLiteral(Enumerator))
+  return false;
+PrevValue = NewValue;
+AllEnumeratorsArePowersOfTwo &= NewValue.isPowerOf2();
+  }
+  return !AllEnumeratorsArePowersOfTwo;
+}
+
+} // namespace
+
+EnumInitialValueCheck::EnumInitialValueCheck(StringRef Name,
+ ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  AllowExplicitZeroFirstInitialValue(
+  Options.get("AllowExplicitZeroFirstInitialValue", tru

[clang] [HLSL][clang] Move hlsl_wave_get_lane_index to EmitHLSLBuiltinExpr (PR #87131)

2024-03-30 Thread Marc Auberer via cfe-commits

https://github.com/marcauberer closed 
https://github.com/llvm/llvm-project/pull/87131
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 3c8ede9 - [HLSL][clang] Move hlsl_wave_get_lane_index to EmitHLSLBuiltinExpr (#87131)

2024-03-30 Thread via cfe-commits

Author: Marc Auberer
Date: 2024-03-30T21:33:56+01:00
New Revision: 3c8ede9f4524fd8defbbf41788003a6d4b0afb04

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

LOG: [HLSL][clang] Move hlsl_wave_get_lane_index to EmitHLSLBuiltinExpr (#87131)

Resolves #87109

Added: 


Modified: 
clang/lib/CodeGen/CGBuiltin.cpp

Removed: 




diff  --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 287e763bad82dd..bb007231c0b783 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -5892,16 +5892,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
 Name),
 {NDRange, Kernel, Block}));
   }
-
-  case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
-auto *CI = EmitRuntimeCall(CGM.CreateRuntimeFunction(
-llvm::FunctionType::get(IntTy, {}, false), 
"__hlsl_wave_get_lane_index",
-{}, false, true));
-if (getTarget().getTriple().isSPIRVLogical())
-  CI = dyn_cast(addControlledConvergenceToken(CI));
-return RValue::get(CI);
-  }
-
   case Builtin::BI__builtin_store_half:
   case Builtin::BI__builtin_store_halff: {
 Value *Val = EmitScalarExpr(E->getArg(0));
@@ -18317,6 +18307,14 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned 
BuiltinID,
 /*ReturnType=*/Op0->getType(), Intrinsic::dx_rsqrt,
 ArrayRef{Op0}, nullptr, "dx.rsqrt");
   }
+  case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
+auto *CI = EmitRuntimeCall(CGM.CreateRuntimeFunction(
+llvm::FunctionType::get(IntTy, {}, false), 
"__hlsl_wave_get_lane_index",
+{}, false, true));
+if (getTarget().getTriple().isSPIRVLogical())
+  CI = dyn_cast(addControlledConvergenceToken(CI));
+return CI;
+  }
   }
   return nullptr;
 }



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


[clang] [HLSL][clang] Move hlsl_wave_get_lane_index to EmitHLSLBuiltinExpr (PR #87131)

2024-03-30 Thread Marc Auberer via cfe-commits

marcauberer wrote:

@farzonl All three tests pass 👍🏽 

```sh
$ ./bin/llvm-lit ../llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveGetLaneIndex.ll 
../llvm/test/CodeGen/SPIRV/scfg-add-pre-headers.ll 
../llvm/test/CodeGen/SPIRV/transcoding/spirv-private-array-initialization.ll
-- Testing: 3 tests, 3 workers --
PASS: LLVM :: CodeGen/SPIRV/scfg-add-pre-headers.ll (1 of 3)
PASS: LLVM :: CodeGen/SPIRV/transcoding/spirv-private-array-initialization.ll 
(2 of 3)
PASS: LLVM :: CodeGen/SPIRV/hlsl-intrinsics/WaveGetLaneIndex.ll (3 of 3)

Testing Time: 0.04s

Total Discovered Tests: 3
  Passed: 3 (100.00%)
```

https://github.com/llvm/llvm-project/pull/87131
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [HLSL][clang] Move hlsl_wave_get_lane_index to EmitHLSLBuiltinExpr (PR #87131)

2024-03-30 Thread Marc Auberer via cfe-commits

https://github.com/marcauberer edited 
https://github.com/llvm/llvm-project/pull/87131
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][HLSL] Move hlsl_wave_get_lane_index to EmitHLSLBuiltinExpr (PR #87131)

2024-03-30 Thread Farzon Lotfi via cfe-commits

farzonl wrote:

minor nit pick, you don't have to do this one: could you make the HLSL prefix 
first. It helps with some bookeeping we are doing.

https://github.com/llvm/llvm-project/pull/87131
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][HLSL] Move hlsl_wave_get_lane_index to EmitHLSLBuiltinExpr (PR #87131)

2024-03-30 Thread Farzon Lotfi via cfe-commits

https://github.com/farzonl approved this pull request.


https://github.com/llvm/llvm-project/pull/87131
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][HLSL] Move hlsl_wave_get_lane_index to EmitHLSLBuiltinExpr (PR #87131)

2024-03-30 Thread Farzon Lotfi via cfe-commits

farzonl wrote:

Hi @marcauberer  The change looks good. I'm 99% sure this won't have an effect 
on the SPIRV backend, however there is still that 1% chance it does.

The tests I want to check landed in this PR
https://github.com/llvm/llvm-project/pull/85979/files 

For convenience this is what you can pass to `llvm-lit`:
- llvm/test/CodeGen/SPIRV/hlsl-intrinsics/WaveGetLaneIndex.ll  (really this one 
is the one im concerned about)
- llvm/test/CodeGen/SPIRV/scfg-add-pre-headers.ll 
- llvm/test/CodeGen/SPIRV/transcoding/spirv-private-array-initialization.ll


Since you aren't changing anything in the SPIRV backend the github action 
didn't trigger. So if you could do one of two things   after I approve, I would 
appreciate it,

Option 1: build spirv backend and test the above test cases
Should be a straight forward build
```
cmake -B  -G Ninja -S llvm 
-DLLVM_ENABLE_PROJECTS="llvm;clang" -DCMAKE_C_COMPILER=clang 
-DCMAKE_CXX_COMPILER=clang++ -DCMAKE_BUILD_TYPE=Debug 
-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=SPIRV -DLLVM_INCLUDE_SPIRV_TOOLS_TESTS=ON
```
Option 2: watch or trigger the SPIR_V Test github actions
https://github.com/llvm/llvm-project/actions/workflows/spirv-tests.yml
make sure the tests pass if they don't and it is one of the tests listed above 
you might have to revert your change.


https://github.com/llvm/llvm-project/pull/87131
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-format] Add SpacesInParensOption for attributes and filtering for repeated parens (PR #77522)

2024-03-30 Thread Gedare Bloom via cfe-commits

gedare wrote:

I saw some comments on this. Looks like some were deleted maybe. This is still 
in my queue, but unclear when I'll get back to it.

https://github.com/llvm/llvm-project/pull/77522
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] Add fix-its to `avoid-return-with-void-value` check (PR #81420)

2024-03-30 Thread Danny Mösch via cfe-commits

https://github.com/SimplyDanny updated 
https://github.com/llvm/llvm-project/pull/81420

From 30213a8dd24e77aa7189bc6db0a7484138a7dc52 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Danny=20M=C3=B6sch?= 
Date: Sun, 11 Feb 2024 17:04:12 +0100
Subject: [PATCH 1/5] [clang-tidy] Add fix-its to
 `avoid-return-with-void-value` check

---
 .../AvoidReturnWithVoidValueCheck.cpp | 41 +++
 clang-tools-extra/docs/ReleaseNotes.rst   |  4 ++
 .../avoid-return-with-void-value.cpp  | 14 ++-
 3 files changed, 49 insertions(+), 10 deletions(-)

diff --git 
a/clang-tools-extra/clang-tidy/readability/AvoidReturnWithVoidValueCheck.cpp 
b/clang-tools-extra/clang-tidy/readability/AvoidReturnWithVoidValueCheck.cpp
index e3400f614fa564..1202eeebd06674 100644
--- a/clang-tools-extra/clang-tidy/readability/AvoidReturnWithVoidValueCheck.cpp
+++ b/clang-tools-extra/clang-tidy/readability/AvoidReturnWithVoidValueCheck.cpp
@@ -10,16 +10,18 @@
 #include "clang/AST/Stmt.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
 #include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Lex/Lexer.h"
 
 using namespace clang::ast_matchers;
 
 namespace clang::tidy::readability {
 
-static constexpr auto IgnoreMacrosName = "IgnoreMacros";
-static constexpr auto IgnoreMacrosDefault = true;
+static constexpr char IgnoreMacrosName[] = "IgnoreMacros";
+static const bool IgnoreMacrosDefault = true;
 
-static constexpr auto StrictModeName = "StrictMode";
-static constexpr auto StrictModeDefault = true;
+static constexpr char StrictModeName[] = "StrictMode";
+static const bool StrictModeDefault = true;
 
 AvoidReturnWithVoidValueCheck::AvoidReturnWithVoidValueCheck(
 StringRef Name, ClangTidyContext *Context)
@@ -40,12 +42,35 @@ void 
AvoidReturnWithVoidValueCheck::registerMatchers(MatchFinder *Finder) {
 void AvoidReturnWithVoidValueCheck::check(
 const MatchFinder::MatchResult &Result) {
   const auto *VoidReturn = Result.Nodes.getNodeAs("void_return");
-  if (IgnoreMacros && VoidReturn->getBeginLoc().isMacroID())
+  if (IgnoreMacros && VoidReturn->getBeginLoc().isMacroID()) {
 return;
-  if (!StrictMode && !Result.Nodes.getNodeAs("compound_parent"))
+  }
+  const auto *SurroundingBlock =
+  Result.Nodes.getNodeAs("compound_parent");
+  if (!StrictMode && !SurroundingBlock) {
 return;
-  diag(VoidReturn->getBeginLoc(), "return statement within a void function "
-  "should not have a specified return value");
+  }
+  DiagnosticBuilder Diag = diag(VoidReturn->getBeginLoc(),
+"return statement within a void function "
+"should not have a specified return value");
+  std::optional SemicolonPos =
+  Lexer::findNextToken(VoidReturn->getRetValue()->getEndLoc(),
+   *Result.SourceManager, getLangOpts());
+  if (!SemicolonPos) {
+return;
+  }
+  const StringRef ReturnExpr =
+  Lexer::getSourceText(CharSourceRange::getTokenRange(
+   VoidReturn->getRetValue()->getSourceRange()),
+   *Result.SourceManager, getLangOpts());
+  std::string Replacement = (ReturnExpr + "; return;").str();
+  if (!SurroundingBlock) {
+Replacement = "{" + Replacement + "}";
+  }
+  Diag << FixItHint::CreateReplacement(
+  CharSourceRange::getTokenRange(VoidReturn->getBeginLoc(),
+ SemicolonPos->getEndLoc()),
+  Replacement);
 }
 
 void AvoidReturnWithVoidValueCheck::storeOptions(
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst 
b/clang-tools-extra/docs/ReleaseNotes.rst
index 78b09d23d4427f..977a20d67a9ed5 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -245,6 +245,10 @@ Changes in existing checks
   analyzed, se the check now handles the common patterns
   `const auto e = (*vector_ptr)[i]` and `const auto e = vector_ptr->at(i);`.
 
+- Improved :doc:`readability-avoid-return-with-void-value
+  ` check by adding
+  fix-its.
+
 - Improved :doc:`readability-identifier-naming
   ` check in 
`GetConfigPerFile`
   mode by resolving symbolic links to header files. Fixed handling of Hungarian
diff --git 
a/clang-tools-extra/test/clang-tidy/checkers/readability/avoid-return-with-void-value.cpp
 
b/clang-tools-extra/test/clang-tidy/checkers/readability/avoid-return-with-void-value.cpp
index f00407c99ce570..0d269ceee82bc9 100644
--- 
a/clang-tools-extra/test/clang-tidy/checkers/readability/avoid-return-with-void-value.cpp
+++ 
b/clang-tools-extra/test/clang-tidy/checkers/readability/avoid-return-with-void-value.cpp
@@ -12,14 +12,18 @@ void f2() {
 return f1();
 // CHECK-MESSAGES: :[[@LINE-1]]:5: warning: return statement within a void 
function should not have a specified return value 
[readability-avoid-return-with-void-value]
 // CHECK-MESSAGES-LENIENT: :[[@LINE-2]]:5: warning: return statement 
within a void

[clang-tools-extra] Add clang-tidy check readability-math-missing-parentheses (PR #84481)

2024-03-30 Thread Julian Schmidt via cfe-commits

https://github.com/5chmidti edited 
https://github.com/llvm/llvm-project/pull/84481
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Add clang-tidy check readability-math-missing-parentheses (PR #84481)

2024-03-30 Thread Julian Schmidt via cfe-commits

https://github.com/5chmidti commented:

I had an idea to simplify `addParantheses` and `check` a bit, otherwise this 
looks good.

https://github.com/llvm/llvm-project/pull/84481
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] Add clang-tidy check readability-math-missing-parentheses (PR #84481)

2024-03-30 Thread Julian Schmidt via cfe-commits


@@ -0,0 +1,112 @@
+//===--- MathMissingParenthesesCheck.cpp - clang-tidy 
-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "MathMissingParenthesesCheck.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::readability {
+
+void MathMissingParenthesesCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(binaryOperator(unless(hasParent(binaryOperator())),
+unless(allOf(hasOperatorName("&&"),
+ hasOperatorName("||"))),
+hasDescendant(binaryOperator()))
+ .bind("binOp"),
+ this);
+}
+
+static int getPrecedence(const BinaryOperator *BinOp) {
+  if (!BinOp)
+return 0;
+  switch (BinOp->getOpcode()) {
+  case BO_Mul:
+  case BO_Div:
+  case BO_Rem:
+return 5;
+  case BO_Add:
+  case BO_Sub:
+return 4;
+  case BO_And:
+return 3;
+  case BO_Xor:
+return 2;
+  case BO_Or:
+return 1;
+  default:
+return 0;
+  }
+}
+static bool addParantheses(
+const BinaryOperator *BinOp, const BinaryOperator *ParentBinOp,
+std::vector<
+std::pair>>
+&Insertions,
+const clang::SourceManager &SM, const clang::LangOptions &LangOpts) {
+  bool NeedToDiagnose = false;
+  if (!BinOp)
+return NeedToDiagnose;
+
+  if (ParentBinOp != nullptr &&
+  getPrecedence(BinOp) != getPrecedence(ParentBinOp)) {
+NeedToDiagnose = true;
+const clang::SourceLocation StartLoc = BinOp->getBeginLoc();
+clang::SourceLocation EndLoc =
+clang::Lexer::getLocForEndOfToken(BinOp->getEndLoc(), 0, SM, LangOpts);
+Insertions.push_back(
+{clang::SourceRange(StartLoc, EndLoc), {BinOp, ParentBinOp}});

5chmidti wrote:

Instead of filling this vector, you could move emitting the diagnostic itself 
into this function by passing it the check itself like in
https://github.com/llvm/llvm-project/blob/6aa53888a8e8a6e3f0bd279539703f4d4701b4e7/clang-tools-extra/clang-tidy/bugprone/UseAfterMoveCheck.cpp#L377-L379

Because whatever you push into the vector will be diagnosed. This would remove 
the need for the vector and the bool return type.

https://github.com/llvm/llvm-project/pull/84481
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] add check to suggest replacement of nested std::min or std::max with initializer lists (PR #85572)

2024-03-30 Thread Julian Schmidt via cfe-commits

https://github.com/5chmidti edited 
https://github.com/llvm/llvm-project/pull/85572
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] add check to suggest replacement of nested std::min or std::max with initializer lists (PR #85572)

2024-03-30 Thread Julian Schmidt via cfe-commits

https://github.com/5chmidti edited 
https://github.com/llvm/llvm-project/pull/85572
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] add check to suggest replacement of nested std::min or std::max with initializer lists (PR #85572)

2024-03-30 Thread Julian Schmidt via cfe-commits


@@ -0,0 +1,342 @@
+//===--- MinMaxUseInitializerListCheck.cpp - clang-tidy 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "MinMaxUseInitializerListCheck.h"
+#include "../utils/ASTUtils.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+struct FindArgsResult {
+  const Expr *First;
+  const Expr *Last;
+  const Expr *Compare;
+  std::vector Args;
+};
+
+static const FindArgsResult findArgs(const CallExpr *Call);
+static std::vector>
+getCommentRanges(const std::string &source);
+static bool
+isPositionInComment(int position,
+const std::vector> &commentRanges);
+static void
+removeCharacterFromSource(std::string &FunctionCallSource,
+  const std::vector> 
&CommentRanges,
+  char Character, const CallExpr *InnerCall,
+  std::vector &Result, bool ReverseSearch);
+static SourceLocation
+getLocForEndOfToken(const Expr *expr, const MatchFinder::MatchResult &Match);
+static const std::vector
+generateReplacement(const MatchFinder::MatchResult &Match,
+const CallExpr *TopCall, const FindArgsResult &Result);
+
+MinMaxUseInitializerListCheck::MinMaxUseInitializerListCheck(
+StringRef Name, ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  Inserter(Options.getLocalOrGlobal("IncludeStyle",
+utils::IncludeSorter::IS_LLVM),
+   areDiagsSelfContained()) {}
+
+void MinMaxUseInitializerListCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IncludeStyle", Inserter.getStyle());
+}
+
+void MinMaxUseInitializerListCheck::registerMatchers(MatchFinder *Finder) {
+  auto CreateMatcher = [](const std::string &FunctionName) {
+auto FuncDecl = functionDecl(hasName(FunctionName));
+auto Expression = callExpr(callee(FuncDecl));
+
+return callExpr(callee(FuncDecl),
+anyOf(hasArgument(0, Expression),
+  hasArgument(1, Expression),
+  hasArgument(0, cxxStdInitializerListExpr())),
+unless(hasParent(Expression)))
+.bind("topCall");
+  };
+
+  Finder->addMatcher(CreateMatcher("::std::max"), this);
+  Finder->addMatcher(CreateMatcher("::std::min"), this);
+}
+
+void MinMaxUseInitializerListCheck::registerPPCallbacks(
+const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) 
{
+  Inserter.registerPreprocessor(PP);
+}
+
+void MinMaxUseInitializerListCheck::check(
+const MatchFinder::MatchResult &Match) {
+
+  const auto *TopCall = Match.Nodes.getNodeAs("topCall");
+
+  // if topcall in macro ignore
+  if (TopCall->getBeginLoc().isMacroID()) {
+return;
+  }
+
+  FindArgsResult Result = findArgs(TopCall);
+  const std::vector Replacement =
+  generateReplacement(Match, TopCall, Result);
+
+  // if only changes are inserting '{' and '}' then ignore
+  if (Replacement.size() <= 2) {
+return;
+  }
+
+  const DiagnosticBuilder Diagnostic =
+  diag(TopCall->getBeginLoc(),
+   "do not use nested 'std::%0' calls, use initializer lists instead")
+  << TopCall->getDirectCallee()->getName()
+  << Inserter.createIncludeInsertion(
+ Match.SourceManager->getFileID(TopCall->getBeginLoc()),
+ "");
+
+  for (const auto &FixIt : Replacement) {
+Diagnostic << FixIt;
+  }
+}
+
+static const FindArgsResult findArgs(const CallExpr *Call) {
+  FindArgsResult Result;
+  Result.First = nullptr;
+  Result.Last = nullptr;
+  Result.Compare = nullptr;
+
+  if (Call->getNumArgs() == 3) {
+auto ArgIterator = Call->arguments().begin();
+std::advance(ArgIterator, 2);
+Result.Compare = *ArgIterator;
+  } else {
+auto ArgIterator = Call->arguments().begin();
+
+if (const auto *InitListExpr =
+dyn_cast(*ArgIterator)) {
+  if (const auto *TempExpr =
+  dyn_cast(InitListExpr->getSubExpr())) {
+if (const auto *InitList =
+dyn_cast(TempExpr->getSubExpr())) {
+  for (const Expr *Init : InitList->inits()) {
+Result.Args.push_back(Init);
+  }
+  Result.First = *ArgIterator;
+  Result.Last = *ArgIterator;
+
+  std::advance(ArgIterator, 1);
+  if (ArgIterator != Call->arguments().end()) {
+Result.Compare = *ArgIterator;
+  }
+  return Result;
+}
+  }
+}
+  }
+
+  for (const Expr *Arg : Call->arguments()) {
+if (!Result.First)
+  Result.First =

[clang-tools-extra] [clang-tidy] add check to suggest replacement of nested std::min or std::max with initializer lists (PR #85572)

2024-03-30 Thread Julian Schmidt via cfe-commits


@@ -0,0 +1,342 @@
+//===--- MinMaxUseInitializerListCheck.cpp - clang-tidy 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "MinMaxUseInitializerListCheck.h"
+#include "../utils/ASTUtils.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+struct FindArgsResult {
+  const Expr *First;
+  const Expr *Last;
+  const Expr *Compare;
+  std::vector Args;
+};
+
+static const FindArgsResult findArgs(const CallExpr *Call);
+static std::vector>
+getCommentRanges(const std::string &source);
+static bool
+isPositionInComment(int position,
+const std::vector> &commentRanges);
+static void
+removeCharacterFromSource(std::string &FunctionCallSource,
+  const std::vector> 
&CommentRanges,
+  char Character, const CallExpr *InnerCall,
+  std::vector &Result, bool ReverseSearch);
+static SourceLocation
+getLocForEndOfToken(const Expr *expr, const MatchFinder::MatchResult &Match);
+static const std::vector
+generateReplacement(const MatchFinder::MatchResult &Match,
+const CallExpr *TopCall, const FindArgsResult &Result);
+
+MinMaxUseInitializerListCheck::MinMaxUseInitializerListCheck(
+StringRef Name, ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  Inserter(Options.getLocalOrGlobal("IncludeStyle",
+utils::IncludeSorter::IS_LLVM),
+   areDiagsSelfContained()) {}
+
+void MinMaxUseInitializerListCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IncludeStyle", Inserter.getStyle());
+}
+
+void MinMaxUseInitializerListCheck::registerMatchers(MatchFinder *Finder) {
+  auto CreateMatcher = [](const std::string &FunctionName) {
+auto FuncDecl = functionDecl(hasName(FunctionName));
+auto Expression = callExpr(callee(FuncDecl));
+
+return callExpr(callee(FuncDecl),
+anyOf(hasArgument(0, Expression),
+  hasArgument(1, Expression),
+  hasArgument(0, cxxStdInitializerListExpr())),
+unless(hasParent(Expression)))
+.bind("topCall");
+  };
+
+  Finder->addMatcher(CreateMatcher("::std::max"), this);
+  Finder->addMatcher(CreateMatcher("::std::min"), this);
+}
+
+void MinMaxUseInitializerListCheck::registerPPCallbacks(
+const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) 
{
+  Inserter.registerPreprocessor(PP);
+}
+
+void MinMaxUseInitializerListCheck::check(
+const MatchFinder::MatchResult &Match) {
+
+  const auto *TopCall = Match.Nodes.getNodeAs("topCall");
+
+  // if topcall in macro ignore
+  if (TopCall->getBeginLoc().isMacroID()) {
+return;
+  }
+
+  FindArgsResult Result = findArgs(TopCall);
+  const std::vector Replacement =
+  generateReplacement(Match, TopCall, Result);
+
+  // if only changes are inserting '{' and '}' then ignore
+  if (Replacement.size() <= 2) {
+return;
+  }
+
+  const DiagnosticBuilder Diagnostic =
+  diag(TopCall->getBeginLoc(),
+   "do not use nested 'std::%0' calls, use initializer lists instead")
+  << TopCall->getDirectCallee()->getName()
+  << Inserter.createIncludeInsertion(
+ Match.SourceManager->getFileID(TopCall->getBeginLoc()),
+ "");
+
+  for (const auto &FixIt : Replacement) {
+Diagnostic << FixIt;
+  }
+}
+
+static const FindArgsResult findArgs(const CallExpr *Call) {
+  FindArgsResult Result;
+  Result.First = nullptr;
+  Result.Last = nullptr;
+  Result.Compare = nullptr;
+
+  if (Call->getNumArgs() == 3) {
+auto ArgIterator = Call->arguments().begin();
+std::advance(ArgIterator, 2);
+Result.Compare = *ArgIterator;
+  } else {
+auto ArgIterator = Call->arguments().begin();
+
+if (const auto *InitListExpr =
+dyn_cast(*ArgIterator)) {
+  if (const auto *TempExpr =
+  dyn_cast(InitListExpr->getSubExpr())) {
+if (const auto *InitList =
+dyn_cast(TempExpr->getSubExpr())) {
+  for (const Expr *Init : InitList->inits()) {
+Result.Args.push_back(Init);
+  }
+  Result.First = *ArgIterator;
+  Result.Last = *ArgIterator;
+
+  std::advance(ArgIterator, 1);
+  if (ArgIterator != Call->arguments().end()) {
+Result.Compare = *ArgIterator;
+  }
+  return Result;
+}
+  }
+}
+  }
+
+  for (const Expr *Arg : Call->arguments()) {
+if (!Result.First)
+  Result.First =

[clang-tools-extra] [clang-tidy] add check to suggest replacement of nested std::min or std::max with initializer lists (PR #85572)

2024-03-30 Thread Julian Schmidt via cfe-commits


@@ -0,0 +1,337 @@
+//===--- MinMaxUseInitializerListCheck.cpp - clang-tidy 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "MinMaxUseInitializerListCheck.h"
+#include "../utils/ASTUtils.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+struct FindArgsResult {
+  const Expr *First;
+  const Expr *Last;
+  const Expr *Compare;
+  std::vector Args;
+};
+
+static const FindArgsResult findArgs(const CallExpr *Call);
+static std::vector>
+getCommentRanges(const std::string &source);
+static bool
+isPositionInComment(int position,
+const std::vector> &commentRanges);
+static void
+removeCharacterFromSource(std::string &FunctionCallSource,
+  const std::vector> 
&CommentRanges,
+  char Character, const CallExpr *InnerCall,
+  std::vector &Result, bool ReverseSearch);
+static SourceLocation
+getLocForEndOfToken(const Expr *expr, const MatchFinder::MatchResult &Match);
+static const std::vector
+generateReplacement(const MatchFinder::MatchResult &Match,
+const CallExpr *TopCall, const FindArgsResult &Result);
+
+MinMaxUseInitializerListCheck::MinMaxUseInitializerListCheck(
+StringRef Name, ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  Inserter(Options.getLocalOrGlobal("IncludeStyle",
+utils::IncludeSorter::IS_LLVM),
+   areDiagsSelfContained()) {}
+
+void MinMaxUseInitializerListCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IncludeStyle", Inserter.getStyle());
+}
+
+void MinMaxUseInitializerListCheck::registerMatchers(MatchFinder *Finder) {
+  auto CreateMatcher = [](const std::string &FunctionName) {
+auto FuncDecl = functionDecl(hasName(FunctionName));
+auto Expression = callExpr(callee(FuncDecl));
+
+return callExpr(callee(FuncDecl),
+anyOf(hasArgument(0, Expression),
+  hasArgument(1, Expression),
+  hasArgument(0, cxxStdInitializerListExpr())),
+unless(hasParent(Expression)))
+.bind("topCall");
+  };
+
+  Finder->addMatcher(CreateMatcher("::std::max"), this);
+  Finder->addMatcher(CreateMatcher("::std::min"), this);
+}
+
+void MinMaxUseInitializerListCheck::registerPPCallbacks(
+const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) 
{
+  Inserter.registerPreprocessor(PP);
+}
+
+void MinMaxUseInitializerListCheck::check(
+const MatchFinder::MatchResult &Match) {
+
+  const auto *TopCall = Match.Nodes.getNodeAs("topCall");
+
+  FindArgsResult Result = findArgs(TopCall);

5chmidti wrote:

`const FindArgsResult`

https://github.com/llvm/llvm-project/pull/85572
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] add check to suggest replacement of nested std::min or std::max with initializer lists (PR #85572)

2024-03-30 Thread Julian Schmidt via cfe-commits


@@ -0,0 +1,342 @@
+//===--- MinMaxUseInitializerListCheck.cpp - clang-tidy 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "MinMaxUseInitializerListCheck.h"
+#include "../utils/ASTUtils.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+struct FindArgsResult {
+  const Expr *First;
+  const Expr *Last;
+  const Expr *Compare;
+  std::vector Args;
+};
+
+static const FindArgsResult findArgs(const CallExpr *Call);
+static std::vector>
+getCommentRanges(const std::string &source);
+static bool
+isPositionInComment(int position,
+const std::vector> &commentRanges);
+static void
+removeCharacterFromSource(std::string &FunctionCallSource,
+  const std::vector> 
&CommentRanges,
+  char Character, const CallExpr *InnerCall,
+  std::vector &Result, bool ReverseSearch);
+static SourceLocation
+getLocForEndOfToken(const Expr *expr, const MatchFinder::MatchResult &Match);
+static const std::vector
+generateReplacement(const MatchFinder::MatchResult &Match,
+const CallExpr *TopCall, const FindArgsResult &Result);

5chmidti wrote:

Don't return values (not references) by const, same goes for the definition of 
these functions.

You comment handling functions are also not needed, see comments on 
`generateReplacement`

https://github.com/llvm/llvm-project/pull/85572
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] add check to suggest replacement of nested std::min or std::max with initializer lists (PR #85572)

2024-03-30 Thread Julian Schmidt via cfe-commits


@@ -0,0 +1,268 @@
+//===--- MinMaxUseInitializerListCheck.cpp - clang-tidy 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "MinMaxUseInitializerListCheck.h"
+#include "../utils/ASTUtils.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+struct FindArgsResult {
+  const Expr *First;
+  const Expr *Last;
+  const Expr *Compare;
+  std::vector Args;
+};
+
+static const FindArgsResult findArgs(const CallExpr *Call);
+static const std::vector
+generateReplacement(const MatchFinder::MatchResult &Match,
+const CallExpr *TopCall, const FindArgsResult &Result);
+
+MinMaxUseInitializerListCheck::MinMaxUseInitializerListCheck(
+StringRef Name, ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  Inserter(Options.getLocalOrGlobal("IncludeStyle",
+utils::IncludeSorter::IS_LLVM),
+   areDiagsSelfContained()) {}
+
+void MinMaxUseInitializerListCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IncludeStyle", Inserter.getStyle());
+}
+
+void MinMaxUseInitializerListCheck::registerMatchers(MatchFinder *Finder) {
+  auto CreateMatcher = [](const std::string &FunctionName) {
+auto FuncDecl = functionDecl(hasName(FunctionName));
+auto Expression = callExpr(callee(FuncDecl));
+
+return callExpr(callee(FuncDecl),
+anyOf(hasArgument(0, Expression),
+  hasArgument(1, Expression),
+  hasArgument(0, cxxStdInitializerListExpr())),
+unless(hasParent(Expression)))
+.bind("topCall");
+  };
+
+  Finder->addMatcher(CreateMatcher("::std::max"), this);
+  Finder->addMatcher(CreateMatcher("::std::min"), this);
+}
+
+void MinMaxUseInitializerListCheck::registerPPCallbacks(
+const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) 
{
+  Inserter.registerPreprocessor(PP);
+}
+
+void MinMaxUseInitializerListCheck::check(
+const MatchFinder::MatchResult &Match) {
+
+  const auto *TopCall = Match.Nodes.getNodeAs("topCall");
+
+  FindArgsResult Result = findArgs(TopCall);
+  const std::vector Replacement =
+  generateReplacement(Match, TopCall, Result);
+
+  if (Replacement.size() <= 2) {
+return;
+  }
+
+  const DiagnosticBuilder Diagnostic =
+  diag(TopCall->getBeginLoc(),
+   "do not use nested 'std::%0' calls, use initializer lists instead")
+  << TopCall->getDirectCallee()->getName()
+  << Inserter.createIncludeInsertion(
+ Match.SourceManager->getFileID(TopCall->getBeginLoc()),
+ "");
+
+  for (const auto &FixIt : Replacement) {
+Diagnostic << FixIt;
+  }
+}
+
+static const FindArgsResult findArgs(const CallExpr *Call) {
+  FindArgsResult Result;
+  Result.First = nullptr;
+  Result.Last = nullptr;
+  Result.Compare = nullptr;
+
+  if (Call->getNumArgs() == 3) {
+auto ArgIterator = Call->arguments().begin();
+std::advance(ArgIterator, 2);
+Result.Compare = *ArgIterator;
+  } else {
+auto ArgIterator = Call->arguments().begin();
+
+if (const auto *InitListExpr =
+dyn_cast(*ArgIterator)) {
+  if (const auto *TempExpr =
+  dyn_cast(InitListExpr->getSubExpr())) {
+if (const auto *InitList =
+dyn_cast(TempExpr->getSubExpr())) {
+  for (const Expr *Init : InitList->inits()) {
+Result.Args.push_back(Init);
+  }
+  Result.First = *ArgIterator;
+  Result.Last = *ArgIterator;
+
+  std::advance(ArgIterator, 1);
+  if (ArgIterator != Call->arguments().end()) {
+Result.Compare = *ArgIterator;
+  }
+  return Result;
+}
+  }
+}
+  }

5chmidti wrote:

You can skip the cast (and the associated if-stmt) to 
`MaterializeTemporaryExpr` by writing 
`dyn_cast(TempExpr->getSubExpr()->IgnoreImplicit())` in 
the if statement of `InitList`.

https://github.com/llvm/llvm-project/pull/85572
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] add check to suggest replacement of nested std::min or std::max with initializer lists (PR #85572)

2024-03-30 Thread Julian Schmidt via cfe-commits

https://github.com/5chmidti requested changes to this pull request.

I've added a comment about the string parsing and comments in 
`generateReplacement` on how to do this in a better way, which should help you.
Also, if-statements with a single statement branches should not have braces.

https://github.com/llvm/llvm-project/pull/85572
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] add check to suggest replacement of nested std::min or std::max with initializer lists (PR #85572)

2024-03-30 Thread Julian Schmidt via cfe-commits


@@ -0,0 +1,342 @@
+//===--- MinMaxUseInitializerListCheck.cpp - clang-tidy 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "MinMaxUseInitializerListCheck.h"
+#include "../utils/ASTUtils.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+struct FindArgsResult {
+  const Expr *First;
+  const Expr *Last;
+  const Expr *Compare;
+  std::vector Args;
+};
+
+static const FindArgsResult findArgs(const CallExpr *Call);
+static std::vector>
+getCommentRanges(const std::string &source);
+static bool
+isPositionInComment(int position,
+const std::vector> &commentRanges);
+static void
+removeCharacterFromSource(std::string &FunctionCallSource,
+  const std::vector> 
&CommentRanges,
+  char Character, const CallExpr *InnerCall,
+  std::vector &Result, bool ReverseSearch);
+static SourceLocation
+getLocForEndOfToken(const Expr *expr, const MatchFinder::MatchResult &Match);
+static const std::vector
+generateReplacement(const MatchFinder::MatchResult &Match,
+const CallExpr *TopCall, const FindArgsResult &Result);
+
+MinMaxUseInitializerListCheck::MinMaxUseInitializerListCheck(
+StringRef Name, ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  Inserter(Options.getLocalOrGlobal("IncludeStyle",
+utils::IncludeSorter::IS_LLVM),
+   areDiagsSelfContained()) {}
+
+void MinMaxUseInitializerListCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IncludeStyle", Inserter.getStyle());
+}
+
+void MinMaxUseInitializerListCheck::registerMatchers(MatchFinder *Finder) {
+  auto CreateMatcher = [](const std::string &FunctionName) {
+auto FuncDecl = functionDecl(hasName(FunctionName));
+auto Expression = callExpr(callee(FuncDecl));
+
+return callExpr(callee(FuncDecl),
+anyOf(hasArgument(0, Expression),
+  hasArgument(1, Expression),
+  hasArgument(0, cxxStdInitializerListExpr())),
+unless(hasParent(Expression)))
+.bind("topCall");
+  };
+
+  Finder->addMatcher(CreateMatcher("::std::max"), this);
+  Finder->addMatcher(CreateMatcher("::std::min"), this);
+}
+
+void MinMaxUseInitializerListCheck::registerPPCallbacks(
+const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) 
{
+  Inserter.registerPreprocessor(PP);
+}
+
+void MinMaxUseInitializerListCheck::check(
+const MatchFinder::MatchResult &Match) {
+
+  const auto *TopCall = Match.Nodes.getNodeAs("topCall");
+
+  // if topcall in macro ignore
+  if (TopCall->getBeginLoc().isMacroID()) {
+return;
+  }
+
+  FindArgsResult Result = findArgs(TopCall);
+  const std::vector Replacement =
+  generateReplacement(Match, TopCall, Result);
+
+  // if only changes are inserting '{' and '}' then ignore
+  if (Replacement.size() <= 2) {
+return;
+  }
+
+  const DiagnosticBuilder Diagnostic =
+  diag(TopCall->getBeginLoc(),
+   "do not use nested 'std::%0' calls, use initializer lists instead")

5chmidti wrote:

This should spell `"do not use nested 'std::%0' calls, use an initializer list 
instead"` instead, because the replacement code only uses one initializer list, 
not multiple.

https://github.com/llvm/llvm-project/pull/85572
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] add check to suggest replacement of nested std::min or std::max with initializer lists (PR #85572)

2024-03-30 Thread Julian Schmidt via cfe-commits


@@ -0,0 +1,342 @@
+//===--- MinMaxUseInitializerListCheck.cpp - clang-tidy 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "MinMaxUseInitializerListCheck.h"
+#include "../utils/ASTUtils.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+struct FindArgsResult {
+  const Expr *First;
+  const Expr *Last;
+  const Expr *Compare;
+  std::vector Args;
+};
+
+static const FindArgsResult findArgs(const CallExpr *Call);
+static std::vector>
+getCommentRanges(const std::string &source);
+static bool
+isPositionInComment(int position,
+const std::vector> &commentRanges);
+static void
+removeCharacterFromSource(std::string &FunctionCallSource,
+  const std::vector> 
&CommentRanges,
+  char Character, const CallExpr *InnerCall,
+  std::vector &Result, bool ReverseSearch);
+static SourceLocation
+getLocForEndOfToken(const Expr *expr, const MatchFinder::MatchResult &Match);
+static const std::vector
+generateReplacement(const MatchFinder::MatchResult &Match,
+const CallExpr *TopCall, const FindArgsResult &Result);
+
+MinMaxUseInitializerListCheck::MinMaxUseInitializerListCheck(
+StringRef Name, ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  Inserter(Options.getLocalOrGlobal("IncludeStyle",
+utils::IncludeSorter::IS_LLVM),
+   areDiagsSelfContained()) {}
+
+void MinMaxUseInitializerListCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IncludeStyle", Inserter.getStyle());
+}
+
+void MinMaxUseInitializerListCheck::registerMatchers(MatchFinder *Finder) {
+  auto CreateMatcher = [](const std::string &FunctionName) {
+auto FuncDecl = functionDecl(hasName(FunctionName));
+auto Expression = callExpr(callee(FuncDecl));
+
+return callExpr(callee(FuncDecl),
+anyOf(hasArgument(0, Expression),
+  hasArgument(1, Expression),
+  hasArgument(0, cxxStdInitializerListExpr())),
+unless(hasParent(Expression)))
+.bind("topCall");
+  };
+
+  Finder->addMatcher(CreateMatcher("::std::max"), this);
+  Finder->addMatcher(CreateMatcher("::std::min"), this);
+}
+
+void MinMaxUseInitializerListCheck::registerPPCallbacks(
+const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) 
{
+  Inserter.registerPreprocessor(PP);
+}
+
+void MinMaxUseInitializerListCheck::check(
+const MatchFinder::MatchResult &Match) {
+
+  const auto *TopCall = Match.Nodes.getNodeAs("topCall");
+
+  // if topcall in macro ignore
+  if (TopCall->getBeginLoc().isMacroID()) {
+return;
+  }
+
+  FindArgsResult Result = findArgs(TopCall);
+  const std::vector Replacement =
+  generateReplacement(Match, TopCall, Result);
+
+  // if only changes are inserting '{' and '}' then ignore
+  if (Replacement.size() <= 2) {
+return;
+  }
+
+  const DiagnosticBuilder Diagnostic =
+  diag(TopCall->getBeginLoc(),
+   "do not use nested 'std::%0' calls, use initializer lists instead")
+  << TopCall->getDirectCallee()->getName()
+  << Inserter.createIncludeInsertion(
+ Match.SourceManager->getFileID(TopCall->getBeginLoc()),
+ "");
+
+  for (const auto &FixIt : Replacement) {
+Diagnostic << FixIt;
+  }
+}
+
+static const FindArgsResult findArgs(const CallExpr *Call) {
+  FindArgsResult Result;
+  Result.First = nullptr;
+  Result.Last = nullptr;
+  Result.Compare = nullptr;
+
+  if (Call->getNumArgs() == 3) {
+auto ArgIterator = Call->arguments().begin();
+std::advance(ArgIterator, 2);
+Result.Compare = *ArgIterator;
+  } else {
+auto ArgIterator = Call->arguments().begin();
+
+if (const auto *InitListExpr =
+dyn_cast(*ArgIterator)) {
+  if (const auto *TempExpr =
+  dyn_cast(InitListExpr->getSubExpr())) {
+if (const auto *InitList =
+dyn_cast(TempExpr->getSubExpr())) {
+  for (const Expr *Init : InitList->inits()) {
+Result.Args.push_back(Init);
+  }
+  Result.First = *ArgIterator;
+  Result.Last = *ArgIterator;
+
+  std::advance(ArgIterator, 1);
+  if (ArgIterator != Call->arguments().end()) {
+Result.Compare = *ArgIterator;
+  }
+  return Result;
+}
+  }
+}
+  }
+
+  for (const Expr *Arg : Call->arguments()) {
+if (!Result.First)
+  Result.First =

[clang-tools-extra] [clang-tidy] add check to suggest replacement of nested std::min or std::max with initializer lists (PR #85572)

2024-03-30 Thread Julian Schmidt via cfe-commits


@@ -0,0 +1,337 @@
+//===--- MinMaxUseInitializerListCheck.cpp - clang-tidy 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "MinMaxUseInitializerListCheck.h"
+#include "../utils/ASTUtils.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+struct FindArgsResult {
+  const Expr *First;
+  const Expr *Last;
+  const Expr *Compare;
+  std::vector Args;
+};
+
+static const FindArgsResult findArgs(const CallExpr *Call);
+static std::vector>
+getCommentRanges(const std::string &source);
+static bool
+isPositionInComment(int position,
+const std::vector> &commentRanges);
+static void
+removeCharacterFromSource(std::string &FunctionCallSource,
+  const std::vector> 
&CommentRanges,
+  char Character, const CallExpr *InnerCall,
+  std::vector &Result, bool ReverseSearch);
+static SourceLocation
+getLocForEndOfToken(const Expr *expr, const MatchFinder::MatchResult &Match);
+static const std::vector
+generateReplacement(const MatchFinder::MatchResult &Match,
+const CallExpr *TopCall, const FindArgsResult &Result);
+
+MinMaxUseInitializerListCheck::MinMaxUseInitializerListCheck(
+StringRef Name, ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  Inserter(Options.getLocalOrGlobal("IncludeStyle",
+utils::IncludeSorter::IS_LLVM),
+   areDiagsSelfContained()) {}
+
+void MinMaxUseInitializerListCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IncludeStyle", Inserter.getStyle());
+}
+
+void MinMaxUseInitializerListCheck::registerMatchers(MatchFinder *Finder) {
+  auto CreateMatcher = [](const std::string &FunctionName) {
+auto FuncDecl = functionDecl(hasName(FunctionName));
+auto Expression = callExpr(callee(FuncDecl));
+
+return callExpr(callee(FuncDecl),
+anyOf(hasArgument(0, Expression),
+  hasArgument(1, Expression),
+  hasArgument(0, cxxStdInitializerListExpr())),
+unless(hasParent(Expression)))
+.bind("topCall");
+  };
+
+  Finder->addMatcher(CreateMatcher("::std::max"), this);
+  Finder->addMatcher(CreateMatcher("::std::min"), this);
+}
+
+void MinMaxUseInitializerListCheck::registerPPCallbacks(
+const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) 
{
+  Inserter.registerPreprocessor(PP);
+}
+
+void MinMaxUseInitializerListCheck::check(
+const MatchFinder::MatchResult &Match) {
+
+  const auto *TopCall = Match.Nodes.getNodeAs("topCall");
+
+  FindArgsResult Result = findArgs(TopCall);
+  const std::vector Replacement =
+  generateReplacement(Match, TopCall, Result);
+
+  // if only changes are inserting '{' and '}' then ignore
+  if (Replacement.size() <= 2) {
+return;
+  }
+
+  const DiagnosticBuilder Diagnostic =
+  diag(TopCall->getBeginLoc(),
+   "do not use nested 'std::%0' calls, use initializer lists instead")
+  << TopCall->getDirectCallee()->getName()
+  << Inserter.createIncludeInsertion(
+ Match.SourceManager->getFileID(TopCall->getBeginLoc()),
+ "");
+
+  for (const auto &FixIt : Replacement) {
+Diagnostic << FixIt;
+  }
+}
+
+static const FindArgsResult findArgs(const CallExpr *Call) {
+  FindArgsResult Result;
+  Result.First = nullptr;
+  Result.Last = nullptr;
+  Result.Compare = nullptr;
+
+  if (Call->getNumArgs() == 3) {
+auto ArgIterator = Call->arguments().begin();
+std::advance(ArgIterator, 2);
+Result.Compare = *ArgIterator;
+  } else {
+auto ArgIterator = Call->arguments().begin();
+
+if (const auto *InitListExpr =
+dyn_cast(*ArgIterator)) {
+  if (const auto *TempExpr =
+  dyn_cast(InitListExpr->getSubExpr())) {
+if (const auto *InitList =
+dyn_cast(TempExpr->getSubExpr())) {
+  for (const Expr *Init : InitList->inits()) {
+Result.Args.push_back(Init);
+  }
+  Result.First = *ArgIterator;
+  Result.Last = *ArgIterator;
+
+  std::advance(ArgIterator, 1);
+  if (ArgIterator != Call->arguments().end()) {
+Result.Compare = *ArgIterator;
+  }
+  return Result;
+}
+  }
+}
+  }
+
+  for (const Expr *Arg : Call->arguments()) {
+if (!Result.First)
+  Result.First = Arg;
+
+if (Arg == Result.Compare)
+  continue;
+
+Result.Args.push_back(Arg);
+R

[clang-tools-extra] [clang-tidy] add check to suggest replacement of nested std::min or std::max with initializer lists (PR #85572)

2024-03-30 Thread Julian Schmidt via cfe-commits

https://github.com/5chmidti edited 
https://github.com/llvm/llvm-project/pull/85572
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] add check to suggest replacement of nested std::min or std::max with initializer lists (PR #85572)

2024-03-30 Thread Julian Schmidt via cfe-commits


@@ -0,0 +1,26 @@
+.. title:: clang-tidy - modernize-min-max-use-initializer-list
+
+modernize-min-max-use-initializer-list
+==
+
+Replaces nested ``std::min`` and ``std::max`` calls with an initializer list 
where applicable.
+
+For instance, consider the following code:
+
+.. code-block:: cpp
+
+   int a = std::max(std::max(i, j), k);
+
+`modernize-min-max-use-initializer-list` check will transform the above code 
to:

5chmidti wrote:

Add `The` to the start of this sentence, maybe drop the check name.

https://github.com/llvm/llvm-project/pull/85572
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] add check to suggest replacement of nested std::min or std::max with initializer lists (PR #85572)

2024-03-30 Thread via cfe-commits

https://github.com/sopyb updated https://github.com/llvm/llvm-project/pull/85572

>From 17d6ad65216237f9a325d9b608c1372cbbf83ff0 Mon Sep 17 00:00:00 2001
From: sopy 
Date: Sun, 17 Mar 2024 17:30:27 +0200
Subject: [PATCH 1/6] [clang-tidy] add check to suggest replacement of nested
 std::min or std::max with initializer lists

---
 .../clang-tidy/modernize/CMakeLists.txt   |   1 +
 .../MinMaxUseInitializerListCheck.cpp | 138 ++
 .../modernize/MinMaxUseInitializerListCheck.h |  58 
 .../modernize/ModernizeTidyModule.cpp |   3 +
 clang-tools-extra/docs/ReleaseNotes.rst   |   6 +
 .../docs/clang-tidy/checks/list.rst   |   1 +
 6 files changed, 207 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/MinMaxUseInitializerListCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/MinMaxUseInitializerListCheck.h

diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
index 6852db6c2ee311..8005d6e91c060c 100644
--- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
@@ -16,6 +16,7 @@ add_clang_library(clangTidyModernizeModule
   MakeSharedCheck.cpp
   MakeSmartPtrCheck.cpp
   MakeUniqueCheck.cpp
+  MinMaxUseInitializerListCheck.cpp
   ModernizeTidyModule.cpp
   PassByValueCheck.cpp
   RawStringLiteralCheck.cpp
diff --git 
a/clang-tools-extra/clang-tidy/modernize/MinMaxUseInitializerListCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/MinMaxUseInitializerListCheck.cpp
new file mode 100644
index 00..b7dc3ff436f6e3
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/modernize/MinMaxUseInitializerListCheck.cpp
@@ -0,0 +1,138 @@
+//===--- MinMaxUseInitializerListCheck.cpp - clang-tidy 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "MinMaxUseInitializerListCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+MinMaxUseInitializerListCheck::MinMaxUseInitializerListCheck(
+StringRef Name, ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  Inserter(Options.getLocalOrGlobal("IncludeStyle",
+utils::IncludeSorter::IS_LLVM),
+   areDiagsSelfContained()) {}
+
+void MinMaxUseInitializerListCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IncludeStyle", Inserter.getStyle());
+}
+
+void MinMaxUseInitializerListCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+  callExpr(
+  callee(functionDecl(hasName("::std::max"))),
+  
hasAnyArgument(callExpr(callee(functionDecl(hasName("::std::max"),
+  unless(
+  
hasParent(callExpr(callee(functionDecl(hasName("::std::max")))
+  .bind("maxCall"),
+  this);
+
+  Finder->addMatcher(
+  callExpr(
+  callee(functionDecl(hasName("::std::min"))),
+  
hasAnyArgument(callExpr(callee(functionDecl(hasName("::std::min"),
+  unless(
+  
hasParent(callExpr(callee(functionDecl(hasName("::std::min")))
+  .bind("minCall"),
+  this);
+}
+
+void MinMaxUseInitializerListCheck::registerPPCallbacks(
+const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) 
{
+  Inserter.registerPreprocessor(PP);
+}
+
+void MinMaxUseInitializerListCheck::check(
+const MatchFinder::MatchResult &Result) {
+  const auto *MaxCall = Result.Nodes.getNodeAs("maxCall");
+  const auto *MinCall = Result.Nodes.getNodeAs("minCall");
+
+  const CallExpr *TopCall = MaxCall ? MaxCall : MinCall;
+  if (!TopCall) {
+return;
+  }
+  const QualType ResultType =
+  TopCall->getDirectCallee()->getReturnType().getNonReferenceType();
+
+  const Expr *FirstArg = nullptr;
+  const Expr *LastArg = nullptr;
+  std::vector Args;
+  findArgs(TopCall, &FirstArg, &LastArg, Args);
+
+  if (!FirstArg || !LastArg || Args.size() <= 2) {
+return;
+  }
+
+  std::string ReplacementText = "{";
+  for (const Expr *Arg : Args) {
+QualType ArgType = Arg->getType();
+bool CastNeeded =
+ArgType.getCanonicalType() != ResultType.getCanonicalType();
+
+if (CastNeeded)
+  ReplacementText += "static_cast<" + ResultType.getAsString() + ">(";
+
+ReplacementText += Lexer::getSourceText(
+CharSourceRange::getTokenRange(Arg->getSourceRange()),
+*Result.SourceManager, Result.Context->getLangOpts());
+
+if (CastNeeded)
+  ReplacementText += ")";
+ReplacementText += ", ";
+ 

[clang-tools-extra] [clang-tidy] add check to suggest replacement of nested std::min or std::max with initializer lists (PR #85572)

2024-03-30 Thread via cfe-commits

sopyb wrote:

I tried to figure it out today as well, but I couldn't. I just ended up going 
through the source code figuring out the comment ranges and checking if the 
characters are contained between those. Let me know if there was a better way 
to do it and I will go ahead and make more changes.

https://github.com/llvm/llvm-project/pull/85572
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang-tidy] add check to suggest replacement of nested std::min or std::max with initializer lists (PR #85572)

2024-03-30 Thread via cfe-commits

https://github.com/sopyb updated https://github.com/llvm/llvm-project/pull/85572

>From 17d6ad65216237f9a325d9b608c1372cbbf83ff0 Mon Sep 17 00:00:00 2001
From: sopy 
Date: Sun, 17 Mar 2024 17:30:27 +0200
Subject: [PATCH 1/5] [clang-tidy] add check to suggest replacement of nested
 std::min or std::max with initializer lists

---
 .../clang-tidy/modernize/CMakeLists.txt   |   1 +
 .../MinMaxUseInitializerListCheck.cpp | 138 ++
 .../modernize/MinMaxUseInitializerListCheck.h |  58 
 .../modernize/ModernizeTidyModule.cpp |   3 +
 clang-tools-extra/docs/ReleaseNotes.rst   |   6 +
 .../docs/clang-tidy/checks/list.rst   |   1 +
 6 files changed, 207 insertions(+)
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/MinMaxUseInitializerListCheck.cpp
 create mode 100644 
clang-tools-extra/clang-tidy/modernize/MinMaxUseInitializerListCheck.h

diff --git a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt 
b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
index 6852db6c2ee311..8005d6e91c060c 100644
--- a/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
+++ b/clang-tools-extra/clang-tidy/modernize/CMakeLists.txt
@@ -16,6 +16,7 @@ add_clang_library(clangTidyModernizeModule
   MakeSharedCheck.cpp
   MakeSmartPtrCheck.cpp
   MakeUniqueCheck.cpp
+  MinMaxUseInitializerListCheck.cpp
   ModernizeTidyModule.cpp
   PassByValueCheck.cpp
   RawStringLiteralCheck.cpp
diff --git 
a/clang-tools-extra/clang-tidy/modernize/MinMaxUseInitializerListCheck.cpp 
b/clang-tools-extra/clang-tidy/modernize/MinMaxUseInitializerListCheck.cpp
new file mode 100644
index 00..b7dc3ff436f6e3
--- /dev/null
+++ b/clang-tools-extra/clang-tidy/modernize/MinMaxUseInitializerListCheck.cpp
@@ -0,0 +1,138 @@
+//===--- MinMaxUseInitializerListCheck.cpp - clang-tidy 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "MinMaxUseInitializerListCheck.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Lex/Lexer.h"
+
+using namespace clang::ast_matchers;
+
+namespace clang::tidy::modernize {
+
+MinMaxUseInitializerListCheck::MinMaxUseInitializerListCheck(
+StringRef Name, ClangTidyContext *Context)
+: ClangTidyCheck(Name, Context),
+  Inserter(Options.getLocalOrGlobal("IncludeStyle",
+utils::IncludeSorter::IS_LLVM),
+   areDiagsSelfContained()) {}
+
+void MinMaxUseInitializerListCheck::storeOptions(
+ClangTidyOptions::OptionMap &Opts) {
+  Options.store(Opts, "IncludeStyle", Inserter.getStyle());
+}
+
+void MinMaxUseInitializerListCheck::registerMatchers(MatchFinder *Finder) {
+  Finder->addMatcher(
+  callExpr(
+  callee(functionDecl(hasName("::std::max"))),
+  
hasAnyArgument(callExpr(callee(functionDecl(hasName("::std::max"),
+  unless(
+  
hasParent(callExpr(callee(functionDecl(hasName("::std::max")))
+  .bind("maxCall"),
+  this);
+
+  Finder->addMatcher(
+  callExpr(
+  callee(functionDecl(hasName("::std::min"))),
+  
hasAnyArgument(callExpr(callee(functionDecl(hasName("::std::min"),
+  unless(
+  
hasParent(callExpr(callee(functionDecl(hasName("::std::min")))
+  .bind("minCall"),
+  this);
+}
+
+void MinMaxUseInitializerListCheck::registerPPCallbacks(
+const SourceManager &SM, Preprocessor *PP, Preprocessor *ModuleExpanderPP) 
{
+  Inserter.registerPreprocessor(PP);
+}
+
+void MinMaxUseInitializerListCheck::check(
+const MatchFinder::MatchResult &Result) {
+  const auto *MaxCall = Result.Nodes.getNodeAs("maxCall");
+  const auto *MinCall = Result.Nodes.getNodeAs("minCall");
+
+  const CallExpr *TopCall = MaxCall ? MaxCall : MinCall;
+  if (!TopCall) {
+return;
+  }
+  const QualType ResultType =
+  TopCall->getDirectCallee()->getReturnType().getNonReferenceType();
+
+  const Expr *FirstArg = nullptr;
+  const Expr *LastArg = nullptr;
+  std::vector Args;
+  findArgs(TopCall, &FirstArg, &LastArg, Args);
+
+  if (!FirstArg || !LastArg || Args.size() <= 2) {
+return;
+  }
+
+  std::string ReplacementText = "{";
+  for (const Expr *Arg : Args) {
+QualType ArgType = Arg->getType();
+bool CastNeeded =
+ArgType.getCanonicalType() != ResultType.getCanonicalType();
+
+if (CastNeeded)
+  ReplacementText += "static_cast<" + ResultType.getAsString() + ">(";
+
+ReplacementText += Lexer::getSourceText(
+CharSourceRange::getTokenRange(Arg->getSourceRange()),
+*Result.SourceManager, Result.Context->getLangOpts());
+
+if (CastNeeded)
+  ReplacementText += ")";
+ReplacementText += ", ";
+ 

[clang] 556bf03 - [clang][NFC] Fix ARM64EC clang-cl linker driver tests. (#87160)

2024-03-30 Thread via cfe-commits

Author: Jacek Caban
Date: 2024-03-30T17:18:12+01:00
New Revision: 556bf03a572fb8f6a91f1ad5227603b37717c55d

URL: 
https://github.com/llvm/llvm-project/commit/556bf03a572fb8f6a91f1ad5227603b37717c55d
DIFF: 
https://github.com/llvm/llvm-project/commit/556bf03a572fb8f6a91f1ad5227603b37717c55d.diff

LOG: [clang][NFC] Fix ARM64EC clang-cl linker driver tests. (#87160)

Add '--' argument to clang-cl to avoid interpreting input files with /U
option. Fix for llvm-clang-aarch64-darwin buildbot failure after #86835.

Added: 


Modified: 
clang/test/Driver/msvc-link.c

Removed: 




diff  --git a/clang/test/Driver/msvc-link.c b/clang/test/Driver/msvc-link.c
index f80b043c6cfce2..b5c32b17378522 100644
--- a/clang/test/Driver/msvc-link.c
+++ b/clang/test/Driver/msvc-link.c
@@ -38,16 +38,16 @@
 // VFSOVERLAY: "/vfsoverlay:{{.*}}" "{{.*}}.obj"
 
 // RUN: %clang -target arm64ec-pc-windows-msvc -fuse-ld=link -### %s 2>&1 | 
FileCheck --check-prefix=ARM64EC %s
-// RUN: %clang_cl -target arm64ec-pc-windows-msvc -fuse-ld=link -### %s 2>&1 | 
FileCheck --check-prefix=ARM64EC %s
-// RUN: %clang_cl -arm64EC -fuse-ld=link -### %s 2>&1 | FileCheck 
--check-prefix=ARM64EC %s
+// RUN: %clang_cl -target arm64ec-pc-windows-msvc -fuse-ld=link -### -- %s 
2>&1 | FileCheck --check-prefix=ARM64EC %s
+// RUN: %clang_cl -arm64EC -fuse-ld=link -### -- %s 2>&1 | FileCheck 
--check-prefix=ARM64EC %s
 // ARM64EC: "-machine:arm64ec"
 
 // RUN: %clang -target arm64ec-pc-windows-msvc -fuse-ld=link -marm64x -### %s 
2>&1 | \
 // RUN:FileCheck --check-prefix=ARM64X %s
 // RUN: %clang -target aarch64-pc-windows-msvc -fuse-ld=link -marm64x -### %s 
2>&1 | \
 // RUN:FileCheck --check-prefix=ARM64X %s
-// RUN: %clang_cl -marm64x -fuse-ld=link -### %s 2>&1 | FileCheck 
--check-prefix=ARM64X %s
-// RUN: %clang_cl -arm64EC -marm64x -fuse-ld=link -### %s 2>&1 | FileCheck 
--check-prefix=ARM64X %s
+// RUN: %clang_cl -marm64x -fuse-ld=link -### -- %s 2>&1 | FileCheck 
--check-prefix=ARM64X %s
+// RUN: %clang_cl -arm64EC -marm64x -fuse-ld=link -### -- %s 2>&1 | FileCheck 
--check-prefix=ARM64X %s
 // ARM64X: "-machine:arm64x"
 
 // RUN: not %clang -target x86_64-linux-gnu -marm64x -### %s 2>&1 | FileCheck 
--check-prefix=HYBRID-ERR %s



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


[clang] [clang][NFC] Fix ARM64EC clang-cl linker driver tests. (PR #87160)

2024-03-30 Thread Jacek Caban via cfe-commits

https://github.com/cjacek closed https://github.com/llvm/llvm-project/pull/87160
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][NFC] Fix ARM64EC clang-cl linker driver tests. (PR #87160)

2024-03-30 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang-driver

Author: Jacek Caban (cjacek)


Changes

Add '--' argument to clang-cl to avoid interpreting input files with /U option. 
Fix for llvm-clang-aarch64-darwin buildbot failure after #86835.

---
Full diff: https://github.com/llvm/llvm-project/pull/87160.diff


1 Files Affected:

- (modified) clang/test/Driver/msvc-link.c (+4-4) 


``diff
diff --git a/clang/test/Driver/msvc-link.c b/clang/test/Driver/msvc-link.c
index f80b043c6cfce2..b5c32b17378522 100644
--- a/clang/test/Driver/msvc-link.c
+++ b/clang/test/Driver/msvc-link.c
@@ -38,16 +38,16 @@
 // VFSOVERLAY: "/vfsoverlay:{{.*}}" "{{.*}}.obj"
 
 // RUN: %clang -target arm64ec-pc-windows-msvc -fuse-ld=link -### %s 2>&1 | 
FileCheck --check-prefix=ARM64EC %s
-// RUN: %clang_cl -target arm64ec-pc-windows-msvc -fuse-ld=link -### %s 2>&1 | 
FileCheck --check-prefix=ARM64EC %s
-// RUN: %clang_cl -arm64EC -fuse-ld=link -### %s 2>&1 | FileCheck 
--check-prefix=ARM64EC %s
+// RUN: %clang_cl -target arm64ec-pc-windows-msvc -fuse-ld=link -### -- %s 
2>&1 | FileCheck --check-prefix=ARM64EC %s
+// RUN: %clang_cl -arm64EC -fuse-ld=link -### -- %s 2>&1 | FileCheck 
--check-prefix=ARM64EC %s
 // ARM64EC: "-machine:arm64ec"
 
 // RUN: %clang -target arm64ec-pc-windows-msvc -fuse-ld=link -marm64x -### %s 
2>&1 | \
 // RUN:FileCheck --check-prefix=ARM64X %s
 // RUN: %clang -target aarch64-pc-windows-msvc -fuse-ld=link -marm64x -### %s 
2>&1 | \
 // RUN:FileCheck --check-prefix=ARM64X %s
-// RUN: %clang_cl -marm64x -fuse-ld=link -### %s 2>&1 | FileCheck 
--check-prefix=ARM64X %s
-// RUN: %clang_cl -arm64EC -marm64x -fuse-ld=link -### %s 2>&1 | FileCheck 
--check-prefix=ARM64X %s
+// RUN: %clang_cl -marm64x -fuse-ld=link -### -- %s 2>&1 | FileCheck 
--check-prefix=ARM64X %s
+// RUN: %clang_cl -arm64EC -marm64x -fuse-ld=link -### -- %s 2>&1 | FileCheck 
--check-prefix=ARM64X %s
 // ARM64X: "-machine:arm64x"
 
 // RUN: not %clang -target x86_64-linux-gnu -marm64x -### %s 2>&1 | FileCheck 
--check-prefix=HYBRID-ERR %s

``




https://github.com/llvm/llvm-project/pull/87160
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][NFC] Fix ARM64EC clang-cl linker driver tests. (PR #87160)

2024-03-30 Thread Jacek Caban via cfe-commits

https://github.com/cjacek created 
https://github.com/llvm/llvm-project/pull/87160

Add '--' argument to clang-cl to avoid interpreting input files with /U option. 
Fix for llvm-clang-aarch64-darwin buildbot failure after #86835.

>From 2808ce015e4d025164c635d75795c714babe4f05 Mon Sep 17 00:00:00 2001
From: Jacek Caban 
Date: Sat, 30 Mar 2024 17:11:45 +0100
Subject: [PATCH] [clang][NFC] Fix ARM64EC clang-cl linker driver tests.

Add '--' argument to clang-cl to avoid interpreting input files with /U option.
Fix for llvm-clang-aarch64-darwin buildbot failure after #86835.
---
 clang/test/Driver/msvc-link.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/clang/test/Driver/msvc-link.c b/clang/test/Driver/msvc-link.c
index f80b043c6cfce2..b5c32b17378522 100644
--- a/clang/test/Driver/msvc-link.c
+++ b/clang/test/Driver/msvc-link.c
@@ -38,16 +38,16 @@
 // VFSOVERLAY: "/vfsoverlay:{{.*}}" "{{.*}}.obj"
 
 // RUN: %clang -target arm64ec-pc-windows-msvc -fuse-ld=link -### %s 2>&1 | 
FileCheck --check-prefix=ARM64EC %s
-// RUN: %clang_cl -target arm64ec-pc-windows-msvc -fuse-ld=link -### %s 2>&1 | 
FileCheck --check-prefix=ARM64EC %s
-// RUN: %clang_cl -arm64EC -fuse-ld=link -### %s 2>&1 | FileCheck 
--check-prefix=ARM64EC %s
+// RUN: %clang_cl -target arm64ec-pc-windows-msvc -fuse-ld=link -### -- %s 
2>&1 | FileCheck --check-prefix=ARM64EC %s
+// RUN: %clang_cl -arm64EC -fuse-ld=link -### -- %s 2>&1 | FileCheck 
--check-prefix=ARM64EC %s
 // ARM64EC: "-machine:arm64ec"
 
 // RUN: %clang -target arm64ec-pc-windows-msvc -fuse-ld=link -marm64x -### %s 
2>&1 | \
 // RUN:FileCheck --check-prefix=ARM64X %s
 // RUN: %clang -target aarch64-pc-windows-msvc -fuse-ld=link -marm64x -### %s 
2>&1 | \
 // RUN:FileCheck --check-prefix=ARM64X %s
-// RUN: %clang_cl -marm64x -fuse-ld=link -### %s 2>&1 | FileCheck 
--check-prefix=ARM64X %s
-// RUN: %clang_cl -arm64EC -marm64x -fuse-ld=link -### %s 2>&1 | FileCheck 
--check-prefix=ARM64X %s
+// RUN: %clang_cl -marm64x -fuse-ld=link -### -- %s 2>&1 | FileCheck 
--check-prefix=ARM64X %s
+// RUN: %clang_cl -arm64EC -marm64x -fuse-ld=link -### -- %s 2>&1 | FileCheck 
--check-prefix=ARM64X %s
 // ARM64X: "-machine:arm64x"
 
 // RUN: not %clang -target x86_64-linux-gnu -marm64x -### %s 2>&1 | FileCheck 
--check-prefix=HYBRID-ERR %s

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


[clang] [clang][HLSL] Move hlsl_wave_get_lane_index to EmitHLSLBuiltinExpr (PR #87131)

2024-03-30 Thread Marc Auberer via cfe-commits

https://github.com/marcauberer ready_for_review 
https://github.com/llvm/llvm-project/pull/87131
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][HLSL] Move hlsl_wave_get_lane_index to EmitHLSLBuiltinExpr (PR #87131)

2024-03-30 Thread Marc Auberer via cfe-commits

https://github.com/marcauberer updated 
https://github.com/llvm/llvm-project/pull/87131

>From b275a7b3e79fdf316ac2d19b25b43e9298b3715a Mon Sep 17 00:00:00 2001
From: Marc Auberer 
Date: Sat, 30 Mar 2024 01:52:52 +0100
Subject: [PATCH] [Clang] Move hlsl_wave_get_lane_index to EmitHLSLBuiltinExpr

---
 clang/lib/CodeGen/CGBuiltin.cpp | 18 --
 1 file changed, 8 insertions(+), 10 deletions(-)

diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp
index 287e763bad82dd..bb007231c0b783 100644
--- a/clang/lib/CodeGen/CGBuiltin.cpp
+++ b/clang/lib/CodeGen/CGBuiltin.cpp
@@ -5892,16 +5892,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl 
GD, unsigned BuiltinID,
 Name),
 {NDRange, Kernel, Block}));
   }
-
-  case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
-auto *CI = EmitRuntimeCall(CGM.CreateRuntimeFunction(
-llvm::FunctionType::get(IntTy, {}, false), 
"__hlsl_wave_get_lane_index",
-{}, false, true));
-if (getTarget().getTriple().isSPIRVLogical())
-  CI = dyn_cast(addControlledConvergenceToken(CI));
-return RValue::get(CI);
-  }
-
   case Builtin::BI__builtin_store_half:
   case Builtin::BI__builtin_store_halff: {
 Value *Val = EmitScalarExpr(E->getArg(0));
@@ -18317,6 +18307,14 @@ Value *CodeGenFunction::EmitHLSLBuiltinExpr(unsigned 
BuiltinID,
 /*ReturnType=*/Op0->getType(), Intrinsic::dx_rsqrt,
 ArrayRef{Op0}, nullptr, "dx.rsqrt");
   }
+  case Builtin::BI__builtin_hlsl_wave_get_lane_index: {
+auto *CI = EmitRuntimeCall(CGM.CreateRuntimeFunction(
+llvm::FunctionType::get(IntTy, {}, false), 
"__hlsl_wave_get_lane_index",
+{}, false, true));
+if (getTarget().getTriple().isSPIRVLogical())
+  CI = dyn_cast(addControlledConvergenceToken(CI));
+return CI;
+  }
   }
   return nullptr;
 }

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


[clang] [clang][Driver] Pass -machine argument to the linker explicitly for ARM64EC targets. (PR #86835)

2024-03-30 Thread Jacek Caban via cfe-commits

https://github.com/cjacek closed https://github.com/llvm/llvm-project/pull/86835
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] 37c175a - [clang][Driver] Pass -machine argument to the linker explicitly for ARM64EC targets. (#86835)

2024-03-30 Thread via cfe-commits

Author: Jacek Caban
Date: 2024-03-30T16:43:33+01:00
New Revision: 37c175af955f0aeab67e8c553a0a47b2ed0fdba2

URL: 
https://github.com/llvm/llvm-project/commit/37c175af955f0aeab67e8c553a0a47b2ed0fdba2
DIFF: 
https://github.com/llvm/llvm-project/commit/37c175af955f0aeab67e8c553a0a47b2ed0fdba2.diff

LOG: [clang][Driver] Pass -machine argument to the linker explicitly for 
ARM64EC targets. (#86835)

This is required by the linker. Also add a new -marm64x command line argument 
to allow specifying -machine:arm64x.

Added: 


Modified: 
clang/include/clang/Driver/Options.td
clang/lib/Driver/ToolChains/MSVC.cpp
clang/test/Driver/msvc-link.c

Removed: 




diff  --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 8a3929eeb6692b..04eb87f0d5d1aa 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4510,6 +4510,9 @@ def mwindows : Joined<["-"], "mwindows">, Group;
 def mdll : Joined<["-"], "mdll">, Group;
 def municode : Joined<["-"], "municode">, Group;
 def mthreads : Joined<["-"], "mthreads">, Group;
+def marm64x : Joined<["-"], "marm64x">, Group,
+  Visibility<[ClangOption, CLOption]>,
+  HelpText<"Link as a hybrid ARM64X image">;
 def mguard_EQ : Joined<["-"], "mguard=">, Group,
   HelpText<"Enable or disable Control Flow Guard checks and guard tables 
emission">,
   Values<"none,cf,cf-nochecks">;

diff  --git a/clang/lib/Driver/ToolChains/MSVC.cpp 
b/clang/lib/Driver/ToolChains/MSVC.cpp
index dc534a33e6d0ef..fbf2f45b543844 100644
--- a/clang/lib/Driver/ToolChains/MSVC.cpp
+++ b/clang/lib/Driver/ToolChains/MSVC.cpp
@@ -79,6 +79,11 @@ void visualstudio::Linker::ConstructJob(Compilation &C, 
const JobAction &JA,
 CmdArgs.push_back(
 Args.MakeArgString(std::string("-out:") + Output.getFilename()));
 
+  if (Args.hasArg(options::OPT_marm64x))
+CmdArgs.push_back("-machine:arm64x");
+  else if (TC.getTriple().isWindowsArm64EC())
+CmdArgs.push_back("-machine:arm64ec");
+
   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) &&
   !C.getDriver().IsCLMode() && !C.getDriver().IsFlangMode()) {
 CmdArgs.push_back("-defaultlib:libcmt");
@@ -1017,4 +1022,7 @@ void MSVCToolChain::addClangTargetOptions(
   if (DriverArgs.hasFlag(options::OPT_fno_rtti, options::OPT_frtti,
  /*Default=*/false))
 CC1Args.push_back("-D_HAS_STATIC_RTTI=0");
+
+  if (Arg *A = DriverArgs.getLastArgNoClaim(options::OPT_marm64x))
+A->ignoreTargetSpecific();
 }

diff  --git a/clang/test/Driver/msvc-link.c b/clang/test/Driver/msvc-link.c
index 64e099ea63042f..f80b043c6cfce2 100644
--- a/clang/test/Driver/msvc-link.c
+++ b/clang/test/Driver/msvc-link.c
@@ -36,3 +36,23 @@
 // VFSOVERLAY: "--vfsoverlay"
 // VFSOVERLAY: lld-link
 // VFSOVERLAY: "/vfsoverlay:{{.*}}" "{{.*}}.obj"
+
+// RUN: %clang -target arm64ec-pc-windows-msvc -fuse-ld=link -### %s 2>&1 | 
FileCheck --check-prefix=ARM64EC %s
+// RUN: %clang_cl -target arm64ec-pc-windows-msvc -fuse-ld=link -### %s 2>&1 | 
FileCheck --check-prefix=ARM64EC %s
+// RUN: %clang_cl -arm64EC -fuse-ld=link -### %s 2>&1 | FileCheck 
--check-prefix=ARM64EC %s
+// ARM64EC: "-machine:arm64ec"
+
+// RUN: %clang -target arm64ec-pc-windows-msvc -fuse-ld=link -marm64x -### %s 
2>&1 | \
+// RUN:FileCheck --check-prefix=ARM64X %s
+// RUN: %clang -target aarch64-pc-windows-msvc -fuse-ld=link -marm64x -### %s 
2>&1 | \
+// RUN:FileCheck --check-prefix=ARM64X %s
+// RUN: %clang_cl -marm64x -fuse-ld=link -### %s 2>&1 | FileCheck 
--check-prefix=ARM64X %s
+// RUN: %clang_cl -arm64EC -marm64x -fuse-ld=link -### %s 2>&1 | FileCheck 
--check-prefix=ARM64X %s
+// ARM64X: "-machine:arm64x"
+
+// RUN: not %clang -target x86_64-linux-gnu -marm64x -### %s 2>&1 | FileCheck 
--check-prefix=HYBRID-ERR %s
+// HYBRID-ERR: error: unsupported option '-marm64x' for target 
'x86_64-linux-gnu'
+
+// RUN: %clang -c -marm64x  -target arm64ec-pc-windows-msvc -fuse-ld=link -### 
%s 2>&1 | \
+// RUN:FileCheck --check-prefix=HYBRID-WARN %s
+// HYBRID-WARN: warning: argument unused during compilation: '-marm64x' 
[-Wunused-command-line-argument]



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


[clang] [Doc][HLSL] Add documentation for root signature. (PR #83933)

2024-03-30 Thread Xiang Li via cfe-commits


@@ -0,0 +1,258 @@
+
+HLSL Root Signatures
+
+
+.. contents::
+   :local:
+
+Usage
+=
+
+In HLSL, the `root signature
+`_ 
+defines what types of resources are bound to the graphics pipeline. 
+
+A root signature can be specified in HLSL as a `string
+`_.
 
+The string contains a collection of comma-separated clauses that describe root 
+signature constituent components. 
+
+There are two mechanisms to compile an HLSL root signature. First, it is 
+possible to attach a root signature string to a particular shader via the 
+RootSignature attribute (in the following example, using the MyRS1 entry 

python3kgae wrote:

yes.

https://github.com/llvm/llvm-project/pull/83933
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [WIP][Clang] Extend lifetime of the temporary in default member init expression (PR #86960)

2024-03-30 Thread via cfe-commits

https://github.com/yronglin updated 
https://github.com/llvm/llvm-project/pull/86960

>From 107cf4fdda2680a3de4fd0cea6e9fc1eaaf5f8c7 Mon Sep 17 00:00:00 2001
From: yronglin 
Date: Thu, 28 Mar 2024 22:02:16 +0800
Subject: [PATCH] [WIP][Clang] Extend lifetime of the temporary in default
 member init expression

Signed-off-by: yronglin 
---
 clang/lib/Sema/SemaExpr.cpp |  9 ++---
 clang/lib/Sema/SemaInit.cpp | 27 ---
 2 files changed, 14 insertions(+), 22 deletions(-)

diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 5f03b981428251..3c923d7c002feb 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -6372,7 +6372,7 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation 
Loc, FieldDecl *Field) {
   Expr *Init = nullptr;
 
   bool NestedDefaultChecking = isCheckingDefaultArgumentOrInitializer();
-
+  bool InLifetimeExtendingContext = isInLifetimeExtendingContext();
   EnterExpressionEvaluationContext EvalContext(
   *this, ExpressionEvaluationContext::PotentiallyEvaluated, Field);
 
@@ -6407,12 +6407,15 @@ ExprResult Sema::BuildCXXDefaultInitExpr(SourceLocation 
Loc, FieldDecl *Field) {
   ImmediateCallVisitor V(getASTContext());
   if (!NestedDefaultChecking)
 V.TraverseDecl(Field);
-  if (V.HasImmediateCalls) {
+  if (V.HasImmediateCalls || InLifetimeExtendingContext) {
 ExprEvalContexts.back().DelayedDefaultInitializationContext = {Loc, Field,
CurContext};
 ExprEvalContexts.back().IsCurrentlyCheckingDefaultArgumentOrInitializer =
 NestedDefaultChecking;
-
+// Pass down lifetime extending flag, and collect temporaries in
+// CreateMaterializeTemporaryExpr when we rewrite the call argument.
+keepInLifetimeExtendingContext();
+keepInMaterializeTemporaryObjectContext();
 EnsureImmediateInvocationInDefaultArgs Immediate(*this);
 ExprResult Res;
 runWithSufficientStackSpace(Loc, [&] {
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index aa470adb30b47f..85baf52e1f074c 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -8052,11 +8052,7 @@ static void 
visitLocalsRetainedByInitializer(IndirectLocalPath &Path,
 enum PathLifetimeKind {
   /// Lifetime-extend along this path.
   Extend,
-  /// We should lifetime-extend, but we don't because (due to technical
-  /// limitations) we can't. This happens for default member initializers,
-  /// which we don't clone for every use, so we don't have a unique
-  /// MaterializeTemporaryExpr to update.
-  ShouldExtend,
+
   /// Do not lifetime extend along this path.
   NoExtend
 };
@@ -8067,9 +8063,7 @@ static PathLifetimeKind
 shouldLifetimeExtendThroughPath(const IndirectLocalPath &Path) {
   PathLifetimeKind Kind = PathLifetimeKind::Extend;
   for (auto Elem : Path) {
-if (Elem.Kind == IndirectLocalPathEntry::DefaultInit)
-  Kind = PathLifetimeKind::ShouldExtend;
-else if (Elem.Kind != IndirectLocalPathEntry::LambdaCaptureInit)
+if (Elem.Kind != IndirectLocalPathEntry::LambdaCaptureInit)
   return PathLifetimeKind::NoExtend;
   }
   return Kind;
@@ -8182,6 +8176,12 @@ void Sema::checkInitializerLifetime(const 
InitializedEntity &Entity,
 
   switch (shouldLifetimeExtendThroughPath(Path)) {
   case PathLifetimeKind::Extend:
+
+// If in a lifetime-extending context, delay extending action.
+// e.g. Delayed lifetime extending until building for-range-stmt. 
+if (isInLifetimeExtendingContext())
+  return true;
+
 // Update the storage duration of the materialized temporary.
 // FIXME: Rebuild the expression instead of mutating it.
 MTE->setExtendingDecl(ExtendingEntity->getDecl(),
@@ -8189,17 +8189,6 @@ void Sema::checkInitializerLifetime(const 
InitializedEntity &Entity,
 // Also visit the temporaries lifetime-extended by this initializer.
 return true;
 
-  case PathLifetimeKind::ShouldExtend:
-// We're supposed to lifetime-extend the temporary along this path (per
-// the resolution of DR1815), but we don't support that yet.
-//
-// FIXME: Properly handle this situation. Perhaps the easiest approach
-// would be to clone the initializer expression on each use that would
-// lifetime extend its temporaries.
-Diag(DiagLoc, diag::warn_unsupported_lifetime_extension)
-<< RK << DiagRange;
-break;
-
   case PathLifetimeKind::NoExtend:
 // If the path goes through the initialization of a variable or field,
 // it can't possibly reach a temporary created in this full-expression.

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


[clang] [RFC][Clang] Enable custom type checking for printf (PR #86801)

2024-03-30 Thread Vikram Hegde via cfe-commits

vikramRH wrote:

> I looked at the OpenCL spec for C standard library support and was surprised 
> that 1) it's only talking about C99 so it's unclear what happens for C11 
> (clause 6 says "This document describes the modifications and restrictions to 
> C99 and C11 in OpenCL C" but 6.11 only talks about C99 headers and leaves 
> `iso646.h`, `math.h`, `stdbool.h`, `stddef.h`, (all in C99) as well as 
> `stdalign.h`, `stdatomic.h`, `stdnoreturn.h`, `threads.h`, and `uchar.h` 
> available?), and 2) OpenCL's `printf` is not really the same function as C's 
> `printf` 
> (https://registry.khronos.org/OpenCL/specs/3.0-unified/html/OpenCL_C.html#differences-between-opencl-c-and-c99-printf).
> 
> #1 is probably more of an oversight than anything, at least with the C11 
> headers. So maybe this isn't a super slippery slope, but maybe C23 will 
> change that (I can imagine `stdbit.h` being of use in OpenCL for bit-bashing 
> operations). However, the fact that the builtin isn't really `printf` but is 
> `printf`-like makes me think we should make it a separate builtin to avoid 
> surprises (we do diagnostics based on builtin IDs and we have special 
> checking logic that we perhaps should be exempting in some cases).

Understood. Then I propose the following. 
1. Currently Builtin TableGen does not seem to support specifying lang address 
spaces in function prototypes. this needs to be implemented first if not 
already in development.
2. We could have two new macro variants probably named "OCL_BUILTIN" and 
"OCL_LIB_BUILTIN" which will take the ID's of the form 
"BI_OCL##". we would also need corresponding TableGen classes 
(probably named similar to the macros) which can expose such overloaded 
prototypes when required.

How does this sound ?


https://github.com/llvm/llvm-project/pull/86801
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [ClangFE] Improve handling of casting of atomic memory operations. (PR #86691)

2024-03-30 Thread Jonas Paulsson via cfe-commits

JonPsson1 wrote:

Updated per review.

https://github.com/llvm/llvm-project/pull/86691
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [ClangFE] Improve handling of casting of atomic memory operations. (PR #86691)

2024-03-30 Thread Jonas Paulsson via cfe-commits


@@ -134,14 +134,11 @@ static _Atomic float glob_flt = 0.0f;
 
 void force_global_uses(void) {
   (void)glob_pointer;
-  // CHECK: %[[LOCAL_INT:.+]] = load atomic i32, ptr @[[GLOB_POINTER]] seq_cst
-  // CHECK-NEXT: inttoptr i32 %[[LOCAL_INT]] to ptr
+  // CHECK: load atomic ptr, ptr @[[GLOB_POINTER]] seq_cst
   (void)glob_pointer_from_int;
-  // CHECK: %[[LOCAL_INT_2:.+]] = load atomic i32, ptr 
@[[GLOB_POINTER_FROM_INT]] seq_cst
-  // CHECK-NEXT: inttoptr i32 %[[LOCAL_INT_2]] to ptr
+  // CHECK-NEXT: load atomic ptr, ptr @[[GLOB_POINTER_FROM_INT]] seq_cst
   (void)nonstatic_glob_pointer_from_int;
-  // CHECK: %[[LOCAL_INT_3:.+]] = load atomic i32, ptr 
@[[NONSTATIC_GLOB_POINTER_FROM_INT]] seq_cst
-  // CHECK-NEXT: inttoptr i32 %[[LOCAL_INT_3]] to ptr
+  // CHECK-NEXT: load atomic ptr, ptr @[[NONSTATIC_GLOB_POINTER_FROM_INT]] 
seq_cst

JonPsson1 wrote:

Added tests for double and long double, and also a run for systemz as the long 
double type is fp80 on x86, evidently.

https://github.com/llvm/llvm-project/pull/86691
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [RISCV][FMV] Support target_clones (PR #85786)

2024-03-30 Thread Piyou Chen via cfe-commits

BeMg wrote:

1. Suppress the warning `warn_target_clone_mixed_values` for RISC-V
2. Update `__riscv_ifunc_select`. From `__riscv_ifunc_select(char *)` into 
`__riscv_ifunc_select(unsigned long long, unsigned long long )`. 
3. Add one more error messenge when there are +extension that hwprobe can't 
detect.

https://github.com/llvm/llvm-project/pull/85786
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [ClangFE] Improve handling of casting of atomic memory operations. (PR #86691)

2024-03-30 Thread Jonas Paulsson via cfe-commits


@@ -1399,13 +1401,22 @@ RValue AtomicInfo::convertAtomicTempToRValue(Address 
addr,
   LVal.getBaseInfo(), TBAAAccessInfo()));
 }
 
+static bool shouldCastToInt(llvm::Type *ValTy, bool CmpXchg) {

JonPsson1 wrote:

I thought it was a bit more clear than 'CastFP', as the reason for it now is 
the compare-and-exchange instruction only.
Also added comment.

https://github.com/llvm/llvm-project/pull/86691
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [ClangFE] Improve handling of casting of atomic memory operations. (PR #86691)

2024-03-30 Thread Jonas Paulsson via cfe-commits

https://github.com/JonPsson1 updated 
https://github.com/llvm/llvm-project/pull/86691

>From 0b4ee03b3e095d904c4ce37eee8dee0e5e055a4c Mon Sep 17 00:00:00 2001
From: Jonas Paulsson 
Date: Tue, 26 Mar 2024 01:16:25 +0100
Subject: [PATCH 1/3] Refactoring with shouldCastToInt(). Also include atomic
 pointers.

---
 clang/lib/CodeGen/CGAtomic.cpp | 80 +-
 clang/test/CodeGen/atomic.c|  9 ++--
 2 files changed, 44 insertions(+), 45 deletions(-)

diff --git a/clang/lib/CodeGen/CGAtomic.cpp b/clang/lib/CodeGen/CGAtomic.cpp
index 56198385de9dcb..74bc127d3d2445 100644
--- a/clang/lib/CodeGen/CGAtomic.cpp
+++ b/clang/lib/CodeGen/CGAtomic.cpp
@@ -197,11 +197,11 @@ namespace {
 llvm::Value *getScalarRValValueOrNull(RValue RVal) const;
 
 /// Converts an rvalue to integer value if needed.
-llvm::Value *convertRValueToInt(RValue RVal, bool CastFP = true) const;
+llvm::Value *convertRValueToInt(RValue RVal, bool CmpXchg = false) const;
 
 RValue ConvertToValueOrAtomic(llvm::Value *IntVal, AggValueSlot ResultSlot,
   SourceLocation Loc, bool AsValue,
-  bool CastFP = true) const;
+  bool CmpXchg = false) const;
 
 /// Copy an atomic r-value into atomic-layout memory.
 void emitCopyIntoMemory(RValue rvalue) const;
@@ -264,7 +264,7 @@ namespace {
llvm::AtomicOrdering AO, bool IsVolatile);
 /// Emits atomic load as LLVM instruction.
 llvm::Value *EmitAtomicLoadOp(llvm::AtomicOrdering AO, bool IsVolatile,
-  bool CastFP = true);
+  bool CmpXchg = false);
 /// Emits atomic compare-and-exchange op as a libcall.
 llvm::Value *EmitAtomicCompareExchangeLibcall(
 llvm::Value *ExpectedAddr, llvm::Value *DesiredAddr,
@@ -272,7 +272,9 @@ namespace {
 llvm::AtomicOrdering::SequentiallyConsistent,
 llvm::AtomicOrdering Failure =
 llvm::AtomicOrdering::SequentiallyConsistent);
-/// Emits atomic compare-and-exchange op as LLVM instruction.
+/// Emits atomic compare-and-exchange op as LLVM instruction. Operands
+/// must be of integer or pointer type, so float must be casted.
+/// TODO: this could change - see comment in AtomicExpandPass.cpp.
 std::pair EmitAtomicCompareExchangeOp(
 llvm::Value *ExpectedVal, llvm::Value *DesiredVal,
 llvm::AtomicOrdering Success =
@@ -1401,13 +1403,22 @@ RValue AtomicInfo::convertAtomicTempToRValue(Address 
addr,
   LVal.getBaseInfo(), TBAAAccessInfo()));
 }
 
+static bool shouldCastToInt(llvm::Type *ValTy, bool CmpXchg) {
+  // TODO: Also pass through non-ieee FP types.
+  bool KeepType = (ValTy->isIntegerTy() || ValTy->isPointerTy() ||
+   (ValTy->isIEEELikeFPTy() && !CmpXchg));
+  return !KeepType;
+}
+
 RValue AtomicInfo::ConvertToValueOrAtomic(llvm::Value *Val,
   AggValueSlot ResultSlot,
   SourceLocation Loc, bool AsValue,
-  bool CastFP) const {
+  bool CmpXchg) const {
   // Try not to in some easy cases.
-  assert((Val->getType()->isIntegerTy() || Val->getType()->isIEEELikeFPTy()) &&
- "Expected integer or floating point value");
+  assert((Val->getType()->isIntegerTy() || Val->getType()->isPointerTy() ||
+  Val->getType()->isIEEELikeFPTy()) &&
+ "Expected integer, pointer or floating point value when converting "
+ "result.");
   if (getEvaluationKind() == TEK_Scalar &&
   (((!LVal.isBitField() ||
  LVal.getBitFieldInfo().Size == ValueSizeInBits) &&
@@ -1416,13 +1427,11 @@ RValue AtomicInfo::ConvertToValueOrAtomic(llvm::Value 
*Val,
 auto *ValTy = AsValue
   ? CGF.ConvertTypeForMem(ValueTy)
   : getAtomicAddress().getElementType();
-if (ValTy->isIntegerTy() || (!CastFP && ValTy->isIEEELikeFPTy())) {
+if (!shouldCastToInt(ValTy, CmpXchg)) {
   assert((!ValTy->isIntegerTy() || Val->getType() == ValTy) &&
  "Different integer types.");
   return RValue::get(CGF.EmitFromMemory(Val, ValueTy));
-} else if (ValTy->isPointerTy())
-  return RValue::get(CGF.Builder.CreateIntToPtr(Val, ValTy));
-else if (llvm::CastInst::isBitCastable(Val->getType(), ValTy))
+} else if (llvm::CastInst::isBitCastable(Val->getType(), ValTy))
   return RValue::get(CGF.Builder.CreateBitCast(Val, ValTy));
   }
 
@@ -1459,10 +1468,10 @@ void AtomicInfo::EmitAtomicLoadLibcall(llvm::Value 
*AddForLoaded,
 }
 
 llvm::Value *AtomicInfo::EmitAtomicLoadOp(llvm::AtomicOrdering AO,
-  bool IsVolatile, bool CastFP) {
+  bool IsVolatile, bool CmpXchg) {
   // Okay, we're doing this natively.
   Address Addr = g

[clang] [llvm] [RISCV][FMV] Support target_clones (PR #85786)

2024-03-30 Thread Piyou Chen via cfe-commits

https://github.com/BeMg updated https://github.com/llvm/llvm-project/pull/85786

>From 239b404203c66ab5336ffdfb45969a50c439a1c0 Mon Sep 17 00:00:00 2001
From: Piyou Chen 
Date: Tue, 19 Mar 2024 06:22:17 -0700
Subject: [PATCH 1/4] [RISCV][FMV] Support target_clones

---
 clang/include/clang/Basic/TargetInfo.h|   3 +-
 clang/lib/AST/ASTContext.cpp  |   9 ++
 clang/lib/Basic/Targets/RISCV.cpp |  10 +-
 clang/lib/Basic/Targets/RISCV.h   |   2 +
 clang/lib/CodeGen/CodeGenFunction.cpp | 102 -
 clang/lib/CodeGen/CodeGenFunction.h   |   3 +
 clang/lib/CodeGen/CodeGenModule.cpp   |   2 +
 clang/lib/CodeGen/Targets/RISCV.cpp   |  23 +++
 clang/lib/Sema/SemaDeclAttr.cpp   |  22 +++
 clang/test/CodeGen/attr-target-clones-riscv.c | 135 +
 .../CodeGenCXX/attr-target-clones-riscv.cpp   | 136 ++
 .../test/SemaCXX/attr-target-clones-riscv.cpp |  19 +++
 12 files changed, 462 insertions(+), 4 deletions(-)
 create mode 100644 clang/test/CodeGen/attr-target-clones-riscv.c
 create mode 100644 clang/test/CodeGenCXX/attr-target-clones-riscv.cpp
 create mode 100644 clang/test/SemaCXX/attr-target-clones-riscv.cpp

diff --git a/clang/include/clang/Basic/TargetInfo.h 
b/clang/include/clang/Basic/TargetInfo.h
index 374595edd2ce4a..aa48596fbce07d 100644
--- a/clang/include/clang/Basic/TargetInfo.h
+++ b/clang/include/clang/Basic/TargetInfo.h
@@ -1445,7 +1445,8 @@ class TargetInfo : public TransferrableTargetInfo,
   /// Identify whether this target supports multiversioning of functions,
   /// which requires support for cpu_supports and cpu_is functionality.
   bool supportsMultiVersioning() const {
-return getTriple().isX86() || getTriple().isAArch64();
+return getTriple().isX86() || getTriple().isAArch64() ||
+   getTriple().isRISCV();
   }
 
   /// Identify whether this target supports IFuncs.
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 5a8fae76a43a4d..0fd75e0b36b123 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -13636,6 +13636,15 @@ void 
ASTContext::getFunctionFeatureMap(llvm::StringMap &FeatureMap,
   Features.insert(Features.begin(),
   Target->getTargetOpts().FeaturesAsWritten.begin(),
   Target->getTargetOpts().FeaturesAsWritten.end());
+} else if (Target->getTriple().isRISCV()) {
+  if (VersionStr != "default") {
+ParsedTargetAttr ParsedAttr = Target->parseTargetAttr(VersionStr);
+Features.insert(Features.begin(), ParsedAttr.Features.begin(),
+ParsedAttr.Features.end());
+  }
+  Features.insert(Features.begin(),
+  Target->getTargetOpts().FeaturesAsWritten.begin(),
+  Target->getTargetOpts().FeaturesAsWritten.end());
 } else {
   if (VersionStr.starts_with("arch="))
 TargetCPU = VersionStr.drop_front(sizeof("arch=") - 1);
diff --git a/clang/lib/Basic/Targets/RISCV.cpp 
b/clang/lib/Basic/Targets/RISCV.cpp
index a6d4af2b88111a..8e9132c9191a3c 100644
--- a/clang/lib/Basic/Targets/RISCV.cpp
+++ b/clang/lib/Basic/Targets/RISCV.cpp
@@ -257,7 +257,7 @@ bool RISCVTargetInfo::initFeatureMap(
 
   // If a target attribute specified a full arch string, override all the ISA
   // extension target features.
-  const auto I = llvm::find(FeaturesVec, "__RISCV_TargetAttrNeedOverride");
+  const auto I = llvm::find(FeaturesVec, "+__RISCV_TargetAttrNeedOverride");
   if (I != FeaturesVec.end()) {
 std::vector OverrideFeatures(std::next(I), FeaturesVec.end());
 
@@ -366,6 +366,12 @@ bool 
RISCVTargetInfo::handleTargetFeatures(std::vector &Features,
   return true;
 }
 
+bool RISCVTargetInfo::isValidFeatureName(StringRef Feature) const {
+  if (Feature.starts_with("__RISCV_TargetAttrNeedOverride"))
+return true;
+  return llvm::RISCVISAInfo::isSupportedExtensionFeature(Feature);
+}
+
 bool RISCVTargetInfo::isValidCPUName(StringRef Name) const {
   bool Is64Bit = getTriple().isArch64Bit();
   return llvm::RISCV::parseCPU(Name, Is64Bit);
@@ -390,7 +396,7 @@ void RISCVTargetInfo::fillValidTuneCPUList(
 
 static void handleFullArchString(StringRef FullArchStr,
  std::vector &Features) {
-  Features.push_back("__RISCV_TargetAttrNeedOverride");
+  Features.push_back("+__RISCV_TargetAttrNeedOverride");
   auto RII = llvm::RISCVISAInfo::parseArchString(
   FullArchStr, /* EnableExperimentalExtension */ true);
   if (llvm::errorToBool(RII.takeError())) {
diff --git a/clang/lib/Basic/Targets/RISCV.h b/clang/lib/Basic/Targets/RISCV.h
index bfbdafb682c851..ef8f59185d753c 100644
--- a/clang/lib/Basic/Targets/RISCV.h
+++ b/clang/lib/Basic/Targets/RISCV.h
@@ -106,6 +106,8 @@ class RISCVTargetInfo : public TargetInfo {
   bool handleTargetFeatures(std::vector &Features,
 DiagnosticsEngine &Diags) override;
 
+  bool is

[clang] [Win32][ELF] Make CodeView a DebugInfoFormat only for COFF format (PR #87149)

2024-03-30 Thread Phoebe Wang via cfe-commits

https://github.com/phoebewang updated 
https://github.com/llvm/llvm-project/pull/87149

>From 16fea4659909423319f0107b2a4d5bcc31185299 Mon Sep 17 00:00:00 2001
From: Phoebe Wang 
Date: Sat, 30 Mar 2024 17:29:06 +0800
Subject: [PATCH] [Win32][ELF] Make CodeView a DebugInfoFormat only for COFF
 format

We have many problems to use CodeView for a win32-elf target, e.g., #87140
and `error: .seh_* directives are not supported on this target`.

Fixes: #87140
---
 clang/lib/Driver/ToolChains/MSVC.h | 5 ++---
 clang/test/Misc/win32-elf.c| 5 +
 2 files changed, 7 insertions(+), 3 deletions(-)
 create mode 100644 clang/test/Misc/win32-elf.c

diff --git a/clang/lib/Driver/ToolChains/MSVC.h 
b/clang/lib/Driver/ToolChains/MSVC.h
index 48369e030aade2..3950a8ed38e8b4 100644
--- a/clang/lib/Driver/ToolChains/MSVC.h
+++ b/clang/lib/Driver/ToolChains/MSVC.h
@@ -61,9 +61,8 @@ class LLVM_LIBRARY_VISIBILITY MSVCToolChain : public 
ToolChain {
   /// formats, and to DWARF otherwise. Users can use -gcodeview and -gdwarf to
   /// override the default.
   llvm::codegenoptions::DebugInfoFormat getDefaultDebugFormat() const override 
{
-return getTriple().isOSBinFormatMachO()
-   ? llvm::codegenoptions::DIF_DWARF
-   : llvm::codegenoptions::DIF_CodeView;
+return getTriple().isOSBinFormatCOFF() ? llvm::codegenoptions::DIF_CodeView
+   : llvm::codegenoptions::DIF_DWARF;
   }
 
   /// Set the debugger tuning to "default", since we're definitely not tuning
diff --git a/clang/test/Misc/win32-elf.c b/clang/test/Misc/win32-elf.c
new file mode 100644
index 00..f75281dc418727
--- /dev/null
+++ b/clang/test/Misc/win32-elf.c
@@ -0,0 +1,5 @@
+// Check that basic use of win32-elf targets works.
+// RUN: %clang -fsyntax-only -target x86_64-pc-win32-elf %s
+
+// RUN: %clang -fsyntax-only -target x86_64-pc-win32-elf -g %s -### 2>&1 | 
FileCheck %s -check-prefix=DEBUG-INFO
+// DEBUG-INFO: -dwarf-version={{.*}}

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


[clang] [clang-repl] Expose markUserCodeStart() in extended Interpreter interface (PR #87064)

2024-03-30 Thread Vassil Vassilev via cfe-commits

vgvassilev wrote:

You are right. I guess I was a little worried that we are leaking "severe" 
implementation details to the interface.

https://github.com/llvm/llvm-project/pull/87064
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [X86_32] Teach X86_32 va_arg to ignore empty structs. (PR #86075)

2024-03-30 Thread via cfe-commits

github-actions[bot] wrote:




:warning: C/C++ code formatter, clang-format found issues in your code. 
:warning:



You can test this locally with the following command:


``bash
git-clang-format --diff 44a81af510801edce842e9574ec4d52cc7bd0ae9 
5178a001cc3ce765e3d29e91e24597fa1b0f42d6 -- 
clang/test/CodeGenCXX/x86_32-vaarg.cpp clang/lib/CodeGen/Targets/X86.cpp
``





View the diff from clang-format here.


``diff
diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 2cb880752d..38143d1eed 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -1069,7 +1069,7 @@ Address X86_32ABIInfo::EmitVAArg(CodeGenFunction &CGF,
 
   auto TypeInfo = getContext().getTypeInfoInChars(Ty);
 
-  CCState State(*const_cast(CGF.CurFnInfo));
+  CCState State(*const_cast(CGF.CurFnInfo));
   ABIArgInfo AI = classifyArgumentType(Ty, State, /*ArgIndex*/ 0);
   // Empty records are ignored for parameter passing purposes.
   if (AI.isIgnore())

``




https://github.com/llvm/llvm-project/pull/86075
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [X86_32] Teach X86_32 va_arg to ignore empty structs. (PR #86075)

2024-03-30 Thread Longsheng Mou via cfe-commits

https://github.com/CoTinker updated 
https://github.com/llvm/llvm-project/pull/86075

>From 5178a001cc3ce765e3d29e91e24597fa1b0f42d6 Mon Sep 17 00:00:00 2001
From: Longsheng Mou 
Date: Thu, 21 Mar 2024 11:23:56 +0800
Subject: [PATCH] [X86_32] Teach X86_32 va_arg to ignore empty structs.

Empty structs are ignored for parameter passing purposes, but va_arg was
incrementing the pointer anyway for that the size of empty struct in c++
is 1 byte, which could lead to va_list getting out of sync.
---
 clang/lib/CodeGen/Targets/X86.cpp  |  6 ++
 clang/test/CodeGenCXX/x86_32-vaarg.cpp | 20 
 2 files changed, 26 insertions(+)
 create mode 100644 clang/test/CodeGenCXX/x86_32-vaarg.cpp

diff --git a/clang/lib/CodeGen/Targets/X86.cpp 
b/clang/lib/CodeGen/Targets/X86.cpp
index 1ec0f159ebcb8a..2cb880752de3ea 100644
--- a/clang/lib/CodeGen/Targets/X86.cpp
+++ b/clang/lib/CodeGen/Targets/X86.cpp
@@ -1069,6 +1069,12 @@ Address X86_32ABIInfo::EmitVAArg(CodeGenFunction &CGF,
 
   auto TypeInfo = getContext().getTypeInfoInChars(Ty);
 
+  CCState State(*const_cast(CGF.CurFnInfo));
+  ABIArgInfo AI = classifyArgumentType(Ty, State, /*ArgIndex*/ 0);
+  // Empty records are ignored for parameter passing purposes.
+  if (AI.isIgnore())
+return CGF.CreateMemTemp(Ty);
+
   // x86-32 changes the alignment of certain arguments on the stack.
   //
   // Just messing with TypeInfo like this works because we never pass
diff --git a/clang/test/CodeGenCXX/x86_32-vaarg.cpp 
b/clang/test/CodeGenCXX/x86_32-vaarg.cpp
new file mode 100644
index 00..23eac1164118c6
--- /dev/null
+++ b/clang/test/CodeGenCXX/x86_32-vaarg.cpp
@@ -0,0 +1,20 @@
+// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py
+// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple i386-linux-gnu -emit-llvm -x c -o - %s | FileCheck 
%s
+
+typedef struct {} empty;
+
+// CHECK-LABEL: @{{.*}}empty_record_test
+// CHECK-NEXT:  entry:
+// CHECK-NEXT:[[RESULT_PTR:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:[[Z_ADDR:%.*]] = alloca i32, align 4
+// CHECK-NEXT:[[LIST:%.*]] = alloca ptr, align 4
+// CHECK-NEXT:[[TMP:%.*]] = alloca [[STRUCT_EMPTY:%.*]], align 1
+// CHECK-NEXT:store ptr [[AGG_RESULT:%.*]], ptr [[RESULT_PTR]], align 4
+// CHECK-NEXT:store i32 [[Z:%.*]], ptr [[Z_ADDR]], align 4
+// CHECK-NEXT:call void @llvm.va_start(ptr [[LIST]])
+empty empty_record_test(int z, ...) {
+  __builtin_va_list list;
+  __builtin_va_start(list, z);
+  return __builtin_va_arg(list, empty);
+}

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


  1   2   >