[clang] [clang-format] Add --fail-on-incomplete-format. (PR #84346)

2024-03-18 Thread Roberto Bampi via cfe-commits

gigaroby wrote:

> Can you add lit test cases?

Done.

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


[clang] [clang-format] Add --fail-on-incomplete-format. (PR #84346)

2024-03-18 Thread Roberto Bampi via cfe-commits

https://github.com/gigaroby updated 
https://github.com/llvm/llvm-project/pull/84346

>From ee4f8f1c4abaa20d4eedd3451fd96f3306990d0e Mon Sep 17 00:00:00 2001
From: Roberto Bampi 
Date: Thu, 7 Mar 2024 18:10:56 +0100
Subject: [PATCH 1/2] [clang-format] Add --fail-on-incomplete-format.

At the moment clang-format will return exit code 0 on incomplete
results. In scripts it would sometimes be useful if clang-format would
instead fail in those cases, signalling that there was something wrong
with the code being formatted.
---
 clang/docs/ClangFormat.rst   |  1 +
 clang/test/Format/fail-on-incomplete.cpp |  5 +
 clang/tools/clang-format/ClangFormat.cpp | 14 +++---
 3 files changed, 17 insertions(+), 3 deletions(-)
 create mode 100644 clang/test/Format/fail-on-incomplete.cpp

diff --git a/clang/docs/ClangFormat.rst b/clang/docs/ClangFormat.rst
index 819d9ee9f9cde1..80dc38a075c8fc 100644
--- a/clang/docs/ClangFormat.rst
+++ b/clang/docs/ClangFormat.rst
@@ -61,6 +61,7 @@ to format C/C++/Java/JavaScript/JSON/Objective-C/Protobuf/C# 
code.
 --dry-run  - If set, do not actually make the 
formatting changes
 --dump-config  - Dump configuration options to stdout and 
exit.
  Can be used with -style option.
+--fail-on-incomplete-format- If set, fail with exit code 1 on 
incomplete format.
 --fallback-style=  - The name of the predefined style used as a
  fallback in case clang-format is invoked 
with
  -style=file, but can not find the 
.clang-format
diff --git a/clang/test/Format/fail-on-incomplete.cpp 
b/clang/test/Format/fail-on-incomplete.cpp
new file mode 100644
index 00..23220e654e4625
--- /dev/null
+++ b/clang/test/Format/fail-on-incomplete.cpp
@@ -0,0 +1,5 @@
+// RUN: cat %s | not clang-format --fail-on-incomplete-format | FileCheck %s
+// RUN: cat %s | clang-format | FileCheck %s
+int a([) {}
+
+// CHECK: int a([) {}
\ No newline at end of file
diff --git a/clang/tools/clang-format/ClangFormat.cpp 
b/clang/tools/clang-format/ClangFormat.cpp
index 60b0f5d1a0f414..e2600435b0a620 100644
--- a/clang/tools/clang-format/ClangFormat.cpp
+++ b/clang/tools/clang-format/ClangFormat.cpp
@@ -199,6 +199,11 @@ static cl::list FileNames(cl::Positional,
cl::desc("[@] [ ...]"),
cl::cat(ClangFormatCategory));
 
+static cl::opt FailOnIncompleteFormat(
+"fail-on-incomplete-format",
+cl::desc("If set, fail with exit code 1 on incomplete format."),
+cl::init(false), cl::cat(ClangFormatCategory));
+
 namespace clang {
 namespace format {
 
@@ -393,7 +398,7 @@ class ClangFormatDiagConsumer : public DiagnosticConsumer {
 };
 
 // Returns true on error.
-static bool format(StringRef FileName) {
+static bool format(StringRef FileName, bool ErrorOnIncompleteFormat = false) {
   const bool IsSTDIN = FileName == "-";
   if (!OutputXML && Inplace && IsSTDIN) {
 errs() << "error: cannot use -i when reading from stdin.\n";
@@ -529,6 +534,9 @@ static bool format(StringRef FileName) {
   Rewrite.getEditBuffer(ID).write(outs());
 }
   }
+  if (ErrorOnIncompleteFormat && !Status.FormatComplete)
+return true;
+
   return false;
 }
 
@@ -693,7 +701,7 @@ int main(int argc, const char **argv) {
   }
 
   if (FileNames.empty())
-return clang::format::format("-");
+return clang::format::format("-", FailOnIncompleteFormat);
 
   if (FileNames.size() > 1 &&
   (!Offsets.empty() || !Lengths.empty() || !LineRanges.empty())) {
@@ -711,7 +719,7 @@ int main(int argc, const char **argv) {
   errs() << "Formatting [" << FileNo++ << "/" << FileNames.size() << "] "
  << FileName << "\n";
 }
-Error |= clang::format::format(FileName);
+Error |= clang::format::format(FileName, FailOnIncompleteFormat);
   }
   return Error ? 1 : 0;
 }

>From 9763d8bb325cbaedf9af045e77d50f81c200a5f8 Mon Sep 17 00:00:00 2001
From: Roberto Bampi 
Date: Fri, 8 Mar 2024 14:51:49 +0100
Subject: [PATCH 2/2] Update clang/tools/clang-format/ClangFormat.cpp
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Co-authored-by: Björn Schäpers 
---
 clang/tools/clang-format/ClangFormat.cpp | 5 +
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/clang/tools/clang-format/ClangFormat.cpp 
b/clang/tools/clang-format/ClangFormat.cpp
index e2600435b0a620..0e54a478f94fd3 100644
--- a/clang/tools/clang-format/ClangFormat.cpp
+++ b/clang/tools/clang-format/ClangFormat.cpp
@@ -534,10 +534,7 @@ static bool format(StringRef FileName, bool 
ErrorOnIncompleteFormat = false) {
   Rewrite.getEditBuffer(ID).write(outs());
 }
   }
-  if (ErrorOnIncompleteFormat && !Status.FormatComplete)
-return true;
-
-  return false;
+  return ErrorOnIncompleteFormat && !Status.FormatComplete;
 }
 
 } // namespace 

[libclc] [libclc] Convert tabs to spaces in CMake (PR #85634)

2024-03-18 Thread Fraser Cormack via cfe-commits

frasercrmck wrote:

FWIW I don't think the build bots are actually building `libclc`.

Locally, at least, it's not sufficient to specify `LLVM_ENABLE_PROJECTS=libclc` 
- you _also_ need `LLVM_EXTERNAL_PROJECTS=libclc`. Even then, it doesn't build 
for me in-tree, because it assumes `CMAKE_SOURCE_DIR` is its own top-level 
directory, which it isn't as it's `llvm/`.

I had a patch locally to switch `CMAKE_SOURCE_DIR` to `PROJECT_SOURCE_DIR` 
which I think is sufficient to cover both build styles. Should I contribute 
this upstream?

Another problem is that all `libclc` targets are enabled by default, but the 
`spirv-mesa3d` and `spirv64-mesa3d` targets both need `llvm-spirv` which I 
doubt our buildbots have available. Should those be disabled by default, or 
should the buildbots disable them?

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


[clang] [clang][dataflow] Fix `getResultObjectLocation()` on `CXXDefaultArgExpr`. (PR #85072)

2024-03-18 Thread via cfe-commits

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


[clang] 27d5049 - [clang][dataflow] Fix `getResultObjectLocation()` on `CXXDefaultArgExpr`. (#85072)

2024-03-18 Thread via cfe-commits

Author: martinboehme
Date: 2024-03-18T13:36:20+01:00
New Revision: 27d504998ec7ec596bc9ff5d16333aea7a1bac18

URL: 
https://github.com/llvm/llvm-project/commit/27d504998ec7ec596bc9ff5d16333aea7a1bac18
DIFF: 
https://github.com/llvm/llvm-project/commit/27d504998ec7ec596bc9ff5d16333aea7a1bac18.diff

LOG: [clang][dataflow] Fix `getResultObjectLocation()` on `CXXDefaultArgExpr`. 
(#85072)

This patch includes a test that causes an assertion failure without the
other
changes in this patch.

Added: 


Modified: 
clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
clang/lib/Analysis/FlowSensitive/Transfer.cpp
clang/unittests/Analysis/FlowSensitive/TransferTest.cpp

Removed: 




diff  --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp 
b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
index 1d2bd9a9b08af3..cc1ebd511191a9 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -771,6 +771,7 @@ static bool isOriginalRecordConstructor(const Expr 
) {
 return !Init->isSemanticForm() || !Init->isTransparent();
   return isa(RecordPRValue) || isa(RecordPRValue) 
||
  isa(RecordPRValue) ||
+ isa(RecordPRValue) ||
  isa(RecordPRValue) ||
  // The framework currently does not propagate the objects created in
  // the two branches of a `ConditionalOperator` because there is no way

diff  --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp 
b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
index 04aa2831df0558..8b44bcb4e3caeb 100644
--- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -450,6 +450,25 @@ class TransferVisitor : public 
ConstStmtVisitor {
 Env.setStorageLocation(*S, *MemberLoc);
   }
 
+  void VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *S) {
+const Expr *ArgExpr = S->getExpr();
+assert(ArgExpr != nullptr);
+propagateValueOrStorageLocation(*ArgExpr, *S, Env);
+
+// If this is a prvalue of record type, we consider it to be an "original
+// record constructor", which we always require to have a `RecordValue`.
+// So make sure we have a value if we didn't propagate one above.
+if (S->isPRValue() && S->getType()->isRecordType()) {
+  if (Env.getValue(*S) == nullptr) {
+Value *Val = Env.createValue(S->getType());
+// We're guaranteed to always be able to create a value for record
+// types.
+assert(Val != nullptr);
+Env.setValue(*S, *Val);
+  }
+}
+  }
+
   void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *S) {
 const Expr *InitExpr = S->getExpr();
 assert(InitExpr != nullptr);

diff  --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp 
b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
index a8c282f140b4cd..86c7f32f0104be 100644
--- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -2924,6 +2924,36 @@ TEST(TransferTest, ResultObjectLocation) {
   });
 }
 
+TEST(TransferTest, ResultObjectLocationForDefaultArgExpr) {
+  std::string Code = R"(
+struct S {};
+void funcWithDefaultArg(S s = S());
+void target() {
+  funcWithDefaultArg();
+  // [[p]]
+}
+  )";
+
+  using ast_matchers::cxxDefaultArgExpr;
+  using ast_matchers::match;
+  using ast_matchers::selectFirst;
+  runDataflow(
+  Code,
+  [](const llvm::StringMap> ,
+ ASTContext ) {
+const Environment  = getEnvironmentAtAnnotation(Results, "p");
+
+auto *DefaultArg = selectFirst(
+"default_arg",
+match(cxxDefaultArgExpr().bind("default_arg"), ASTCtx));
+ASSERT_NE(DefaultArg, nullptr);
+
+// The values for default arguments aren't modeled; we merely verify
+// that we can get a result object location for a default arg.
+Env.getResultObjectLocation(*DefaultArg);
+  });
+}
+
 TEST(TransferTest, ResultObjectLocationForDefaultInitExpr) {
   std::string Code = R"(
 struct S {};



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


[clang] Reland Print library module manifest path again (PR #84881)

2024-03-18 Thread via cfe-commits

llvmbot wrote:

/pull-request llvm/llvm-project#85637

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


[clang] Reland Print library module manifest path again (PR #84881)

2024-03-18 Thread Arthur Laurent via cfe-commits

Arthapz wrote:

> The file we're looking for is `modules.json`; Renaming it 
> `libc++.modules.json` like `.so` / `.a` file might be a better idea which 
> could avoid name clashes when installed in `/usr/lib`.

but i didn't rename it, it was installed like this :/

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


[clang] Reland Print library module manifest path again (PR #84881)

2024-03-18 Thread Chuanqi Xu via cfe-commits

ChuanqiXu9 wrote:

/cherry-pick 0e1e1fc8f0e

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


[clang] [clang-tools-extra] [libcxx] [clang] Enable sized deallocation by default in C++14 onwards (PR #83774)

2024-03-18 Thread Wang Pengcheng via cfe-commits

wangpc-pp wrote:

There is a Windows failure that I can't reproduce: 
https://buildkite.com/llvm-project/github-pull-requests/builds/46331
Can someone help me to figure out what is wrong?

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


[clang] Reland Print library module manifest path again (PR #84881)

2024-03-18 Thread Chuanqi Xu via cfe-commits

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


[clang] [codegen] Emit cleanups for branch in stmt-expr and coro suspensions [take-2] (PR #85398)

2024-03-18 Thread Utkarsh Saxena via cfe-commits

https://github.com/usx95 updated https://github.com/llvm/llvm-project/pull/85398

>From 0654f624b3b60026398e8b0168623a85e3129630 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Fri, 15 Mar 2024 13:19:36 +
Subject: [PATCH 1/3] [codegen] Emit cleanups for branch in stmt-expr and coro
 suspensions

---
 clang/lib/CodeGen/CGCleanup.cpp |  7 +--
 clang/lib/CodeGen/CGExprAgg.cpp | 13 +++--
 2 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/clang/lib/CodeGen/CGCleanup.cpp b/clang/lib/CodeGen/CGCleanup.cpp
index f87caf050eeaa7..c22d4da0fefc3c 100644
--- a/clang/lib/CodeGen/CGCleanup.cpp
+++ b/clang/lib/CodeGen/CGCleanup.cpp
@@ -694,7 +694,8 @@ void CodeGenFunction::PopCleanupBlock(bool 
FallthroughIsBranchThrough) {
 
   // - whether there's a fallthrough
   llvm::BasicBlock *FallthroughSource = Builder.GetInsertBlock();
-  bool HasFallthrough = (FallthroughSource != nullptr && IsActive);
+  bool HasFallthrough =
+  FallthroughSource != nullptr && (IsActive || HasExistingBranches);
 
   // Branch-through fall-throughs leave the insertion point set to the
   // end of the last cleanup, which points to the current scope.  The
@@ -719,7 +720,9 @@ void CodeGenFunction::PopCleanupBlock(bool 
FallthroughIsBranchThrough) {
 
   // If we have a prebranched fallthrough into an inactive normal
   // cleanup, rewrite it so that it leads to the appropriate place.
-  if (Scope.isNormalCleanup() && HasPrebranchedFallthrough && !IsActive) {
+  if (Scope.isNormalCleanup() && HasPrebranchedFallthrough &&
+  !RequiresNormalCleanup) {
+assert(!IsActive);
 llvm::BasicBlock *prebranchDest;
 
 // If the prebranch is semantically branching through the next
diff --git a/clang/lib/CodeGen/CGExprAgg.cpp b/clang/lib/CodeGen/CGExprAgg.cpp
index 5190b22bcc1622..7e62599089b8df 100644
--- a/clang/lib/CodeGen/CGExprAgg.cpp
+++ b/clang/lib/CodeGen/CGExprAgg.cpp
@@ -15,6 +15,7 @@
 #include "CodeGenFunction.h"
 #include "CodeGenModule.h"
 #include "ConstantEmitter.h"
+#include "EHScopeStack.h"
 #include "TargetInfo.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/Attr.h"
@@ -1389,15 +1390,15 @@ AggExprEmitter::VisitLambdaExpr(LambdaExpr *E) {
 if (QualType::DestructionKind DtorKind =
 CurField->getType().isDestructedType()) {
   assert(LV.isSimple());
-  if (CGF.needsEHCleanup(DtorKind)) {
+  if (DtorKind) {
 if (!CleanupDominator)
   CleanupDominator = CGF.Builder.CreateAlignedLoad(
   CGF.Int8Ty,
   llvm::Constant::getNullValue(CGF.Int8PtrTy),
   CharUnits::One()); // placeholder
 
-CGF.pushDestroy(EHCleanup, LV.getAddress(CGF), CurField->getType(),
-CGF.getDestroyer(DtorKind), false);
+CGF.pushDestroy(NormalAndEHCleanup, LV.getAddress(CGF),
+CurField->getType(), CGF.getDestroyer(DtorKind), 
false);
 Cleanups.push_back(CGF.EHStack.stable_begin());
   }
 }
@@ -1806,9 +1807,9 @@ void AggExprEmitter::VisitCXXParenListOrInitListExpr(
 if (QualType::DestructionKind dtorKind
   = field->getType().isDestructedType()) {
   assert(LV.isSimple());
-  if (CGF.needsEHCleanup(dtorKind)) {
-CGF.pushDestroy(EHCleanup, LV.getAddress(CGF), field->getType(),
-CGF.getDestroyer(dtorKind), false);
+  if (dtorKind) {
+CGF.pushDestroy(NormalAndEHCleanup, LV.getAddress(CGF),
+field->getType(), CGF.getDestroyer(dtorKind), false);
 addCleanup(CGF.EHStack.stable_begin());
 pushedCleanup = true;
   }

>From 1b7c160b030f3a765d40723bbbf9a7daa4a1e090 Mon Sep 17 00:00:00 2001
From: Utkarsh Saxena 
Date: Fri, 15 Mar 2024 15:22:07 +
Subject: [PATCH 2/3] add tests

---
 .../control-flow-in-expr-cleanup.cpp  | 172 ++
 1 file changed, 172 insertions(+)
 create mode 100644 
clang/test/CodeGenCoroutines/control-flow-in-expr-cleanup.cpp

diff --git a/clang/test/CodeGenCoroutines/control-flow-in-expr-cleanup.cpp 
b/clang/test/CodeGenCoroutines/control-flow-in-expr-cleanup.cpp
new file mode 100644
index 00..d703532b5a10b9
--- /dev/null
+++ b/clang/test/CodeGenCoroutines/control-flow-in-expr-cleanup.cpp
@@ -0,0 +1,172 @@
+// RUN: %clang_cc1 --std=c++20 -triple x86_64-linux-gnu -emit-llvm %s -o - | 
FileCheck %s
+
+#include "Inputs/coroutine.h"
+
+struct Printy {
+  Printy(const char *name) : name(name) {}
+  ~Printy() {}
+  const char *name;
+};
+
+struct coroutine {
+  struct promise_type;
+  std::coroutine_handle handle;
+  ~coroutine() {
+if (handle) handle.destroy();
+  }
+};
+
+struct coroutine::promise_type {
+  coroutine get_return_object() {
+return {std::coroutine_handle::from_promise(*this)};
+  }
+  std::suspend_never initial_suspend() noexcept { return {}; }
+  std::suspend_always final_suspend() noexcept { return {}; }
+  void return_void() {}
+  void unhandled_exception() {}
+};
+
+struct Awaiter : 

[clang] fix unnecessary warning when using bitand with boolean operators (PR #81976)

2024-03-18 Thread Aaron Ballman via cfe-commits

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


[clang] ab28c1d - fix unnecessary warning when using bitand with boolean operators (#81976)

2024-03-18 Thread via cfe-commits

Author: Bhuminjay Soni
Date: 2024-03-18T08:19:44-04:00
New Revision: ab28c1de23f3880d7d2becf936fe560abe68e020

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

LOG: fix unnecessary warning when using bitand with boolean operators (#81976)

This pull request fixes #77601 where using the `bitand` operator with
boolean operands should not trigger the warning, as it would indicate an
intentional use of bitwise AND rather than a typo or error.

Fixes #77601

Added: 


Modified: 
clang/docs/ReleaseNotes.rst
clang/lib/Sema/SemaChecking.cpp
clang/test/Sema/warn-bitwise-and-bool.c
clang/test/Sema/warn-bitwise-or-bool.c

Removed: 




diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 125d51c42d507f..b4c90b1e3e5be2 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -250,6 +250,10 @@ Improvements to Clang's diagnostics
   such as attempting to call ``free`` on an unallocated object. Fixes
   `#79443 `_.
 
+- Clang no longer warns when the ``bitand`` operator is used with boolean
+  operands, distinguishing it from potential typographical errors or unintended
+  bitwise operations. Fixes #GH77601.
+
 Improvements to Clang's time-trace
 --
 

diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index de544a03b29846..a0b256ab5579ee 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -16605,12 +16605,26 @@ static void AnalyzeImplicitConversions(
 BO->getRHS()->isKnownToHaveBooleanValue() &&
 BO->getLHS()->HasSideEffects(S.Context) &&
 BO->getRHS()->HasSideEffects(S.Context)) {
-  S.Diag(BO->getBeginLoc(), diag::warn_bitwise_instead_of_logical)
-  << (BO->getOpcode() == BO_And ? "&" : "|") << OrigE->getSourceRange()
-  << FixItHint::CreateReplacement(
- BO->getOperatorLoc(),
- (BO->getOpcode() == BO_And ? "&&" : "||"));
-  S.Diag(BO->getBeginLoc(), diag::note_cast_operand_to_int);
+  SourceManager  = S.getSourceManager();
+  const LangOptions  = S.getLangOpts();
+  SourceLocation BLoc = BO->getOperatorLoc();
+  SourceLocation ELoc = Lexer::getLocForEndOfToken(BLoc, 0, SM, LO);
+  StringRef SR = clang::Lexer::getSourceText(
+  clang::CharSourceRange::getTokenRange(BLoc, ELoc), SM, LO);
+  // To reduce false positives, only issue the diagnostic if the operator
+  // is explicitly spelled as a punctuator. This suppresses the diagnostic
+  // when using 'bitand' or 'bitor' either as keywords in C++ or as macros
+  // in C, along with other macro spellings the user might invent.
+  if (SR.str() == "&" || SR.str() == "|") {
+
+S.Diag(BO->getBeginLoc(), diag::warn_bitwise_instead_of_logical)
+<< (BO->getOpcode() == BO_And ? "&" : "|")
+<< OrigE->getSourceRange()
+<< FixItHint::CreateReplacement(
+   BO->getOperatorLoc(),
+   (BO->getOpcode() == BO_And ? "&&" : "||"));
+S.Diag(BO->getBeginLoc(), diag::note_cast_operand_to_int);
+  }
 }
 
   // For conditional operators, we analyze the arguments as if they

diff  --git a/clang/test/Sema/warn-bitwise-and-bool.c 
b/clang/test/Sema/warn-bitwise-and-bool.c
index 6bec1be1abdef6..c30498e2bd8d1a 100644
--- a/clang/test/Sema/warn-bitwise-and-bool.c
+++ b/clang/test/Sema/warn-bitwise-and-bool.c
@@ -19,6 +19,8 @@ boolean baz(void) __attribute__((const));
 void sink(boolean);
 
 #define FOO foo()
+#define MY_AND &
+#define My_BITAND bitand
 
 void test(boolean a, boolean b, int *p, volatile int *q, int i) {
   b = a & b;
@@ -44,9 +46,12 @@ void test(boolean a, boolean b, int *p, volatile int *q, int 
i) {
   b = b & foo();
   b = bar() & (i > 4);
   b = (i == 7) & foo();
+  b = b MY_AND foo(); // OK, no warning expected
+
 #ifdef __cplusplus
-  b = foo() bitand bar(); // expected-warning {{use of bitwise '&' with 
boolean operands}}
-  // expected-note@-1 {{cast one or both operands to 
int to silence this warning}}
+  b = foo() bitand bar(); // Ok, no warning expected
+  b = foo() My_BITAND bar(); // Ok, no warning expected
+  
 #endif
 
   if (foo() & bar())  // expected-warning {{use of bitwise '&' with 
boolean operands}}
@@ -60,4 +65,5 @@ void test(boolean a, boolean b, int *p, volatile int *q, int 
i) {
 
   int n = i + 10;
   b = (n & (n - 1));
+
 }

diff  --git a/clang/test/Sema/warn-bitwise-or-bool.c 
b/clang/test/Sema/warn-bitwise-or-bool.c
index ae86790901aac5..e45ef28da0a70d 100644
--- a/clang/test/Sema/warn-bitwise-or-bool.c
+++ b/clang/test/Sema/warn-bitwise-or-bool.c
@@ 

[clang] fix unnecessary warning when using bitand with boolean operators (PR #81976)

2024-03-18 Thread Aaron Ballman via cfe-commits

https://github.com/AaronBallman updated 
https://github.com/llvm/llvm-project/pull/81976

>From 07c73f087a430f5115ecdfec23730c5afcab37f3 Mon Sep 17 00:00:00 2001
From: 11happy 
Date: Fri, 16 Feb 2024 14:26:36 +0530
Subject: [PATCH 1/4] fix unnecessary warning when using bitand with boolean

Signed-off-by: 11happy 
---
 clang/lib/Sema/SemaChecking.cpp | 24 ++--
 clang/test/Sema/warn-bitwise-and-bool.c |  4 ++--
 clang/test/Sema/warn-bitwise-or-bool.c  |  4 ++--
 3 files changed, 22 insertions(+), 10 deletions(-)

diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 502b24bcdf8b42..e43892cbf35890 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -16191,12 +16191,24 @@ static void AnalyzeImplicitConversions(
 BO->getRHS()->isKnownToHaveBooleanValue() &&
 BO->getLHS()->HasSideEffects(S.Context) &&
 BO->getRHS()->HasSideEffects(S.Context)) {
-  S.Diag(BO->getBeginLoc(), diag::warn_bitwise_instead_of_logical)
-  << (BO->getOpcode() == BO_And ? "&" : "|") << OrigE->getSourceRange()
-  << FixItHint::CreateReplacement(
- BO->getOperatorLoc(),
- (BO->getOpcode() == BO_And ? "&&" : "||"));
-  S.Diag(BO->getBeginLoc(), diag::note_cast_operand_to_int);
+  clang::SourceManager  = S.getSourceManager();
+  clang::LangOptions LO = S.getLangOpts();
+  clang::SourceLocation BLoc = BO->getOperatorLoc();
+  clang::SourceLocation ELoc =
+  clang::Lexer::getLocForEndOfToken(BLoc, 0, SM, LO);
+  llvm::StringRef SR = clang::Lexer::getSourceText(
+  clang::CharSourceRange::getTokenRange(BLoc, ELoc), SM, LO);
+
+  if (SR.str() == "&" || SR.str() == "|") {
+
+S.Diag(BO->getBeginLoc(), diag::warn_bitwise_instead_of_logical)
+<< (BO->getOpcode() == BO_And ? "&" : "|")
+<< OrigE->getSourceRange()
+<< FixItHint::CreateReplacement(
+   BO->getOperatorLoc(),
+   (BO->getOpcode() == BO_And ? "&&" : "||"));
+S.Diag(BO->getBeginLoc(), diag::note_cast_operand_to_int);
+  }
 }
 
   // For conditional operators, we analyze the arguments as if they
diff --git a/clang/test/Sema/warn-bitwise-and-bool.c 
b/clang/test/Sema/warn-bitwise-and-bool.c
index 6bec1be1abdef6..23e7afcc59f8aa 100644
--- a/clang/test/Sema/warn-bitwise-and-bool.c
+++ b/clang/test/Sema/warn-bitwise-and-bool.c
@@ -45,8 +45,8 @@ void test(boolean a, boolean b, int *p, volatile int *q, int 
i) {
   b = bar() & (i > 4);
   b = (i == 7) & foo();
 #ifdef __cplusplus
-  b = foo() bitand bar(); // expected-warning {{use of bitwise '&' with 
boolean operands}}
-  // expected-note@-1 {{cast one or both operands to 
int to silence this warning}}
+  b = foo() bitand bar(); // Ok, no warning expected
+  
 #endif
 
   if (foo() & bar())  // expected-warning {{use of bitwise '&' with 
boolean operands}}
diff --git a/clang/test/Sema/warn-bitwise-or-bool.c 
b/clang/test/Sema/warn-bitwise-or-bool.c
index ae86790901aac5..e84f59cf8f766a 100644
--- a/clang/test/Sema/warn-bitwise-or-bool.c
+++ b/clang/test/Sema/warn-bitwise-or-bool.c
@@ -45,8 +45,8 @@ void test(boolean a, boolean b, int *p, volatile int *q, int 
i) {
   b = bar() | (i > 4);
   b = (i == 7) | foo();
 #ifdef __cplusplus
-  b = foo() bitor bar();  // expected-warning {{use of bitwise '|' with 
boolean operands}}
-  // expected-note@-1 {{cast one or both operands to 
int to silence this warning}}
+  b = foo() bitor bar();  //Ok, no warning expected
+  
 #endif
 
   if (foo() | bar())  // expected-warning {{use of bitwise '|' with 
boolean operands}}

>From a0ba9e05bb9d0443f386fd57eef3b4e6e2bd1217 Mon Sep 17 00:00:00 2001
From: 11happy 
Date: Sat, 16 Mar 2024 16:11:00 +0530
Subject: [PATCH 2/4] add release notes and add tests

Signed-off-by: 11happy 
---
 clang/docs/ReleaseNotes.rst |  5 +
 clang/lib/Sema/SemaChecking.cpp | 16 +---
 clang/test/Sema/warn-bitwise-and-bool.c |  6 ++
 clang/test/Sema/warn-bitwise-or-bool.c  |  4 
 4 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 254e0a9cb72979..177f424abaa73c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -106,6 +106,11 @@ Improvements to Clang's diagnostics
 - Clang now applies syntax highlighting to the code snippets it
   prints.
 
+- Clang now does not warn in cases where bitand operator is 
+  intentionally used with boolean operands, distinguishing it
+  from potential typographical errors or unintended bitwise operations.
+  Fixes (`#77601 `)
+
 Improvements to Clang's time-trace
 --
 
diff --git a/clang/lib/Sema/SemaChecking.cpp 

[clang] fix unnecessary warning when using bitand with boolean operators (PR #81976)

2024-03-18 Thread Aaron Ballman via cfe-commits


@@ -250,6 +250,11 @@ Improvements to Clang's diagnostics
   such as attempting to call ``free`` on an unallocated object. Fixes
   `#79443 `_.
 
+- Clang now does not warn in cases where bitand operator is
+  intentionally used with boolean operands, distinguishing it
+  from potential typographical errors or unintended bitwise operations.
+  Fixes (`#77601 `)

AaronBallman wrote:

```suggestion
- Clang no longer warns when the ``bitand`` operator is used with boolean
  operands, distinguishing it from potential typographical errors or unintended
  bitwise operations. Fixes #GH77601.
```

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


[clang] fix unnecessary warning when using bitand with boolean operators (PR #81976)

2024-03-18 Thread Aaron Ballman via cfe-commits

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

LGTM with a small tweak to the release notes.

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


[clang] fix unnecessary warning when using bitand with boolean operators (PR #81976)

2024-03-18 Thread Aaron Ballman via cfe-commits

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


[clang] [analyzer] Wrap SymbolicRegions by ElementRegions before getting a FieldRegion (PR #85211)

2024-03-18 Thread via cfe-commits


@@ -451,6 +451,38 @@ void ProgramState::setStore(const StoreRef ) {
   store = newStoreStore;
 }
 
+/// FieldRegions are expected to be wrapped by an ElementRegion as a canonical
+/// representation. See f8643a9b31c4029942f67d4534c9139b45173504 why.
+static SVal wrapSymbolicRegion(const ProgramState , SVal Base) {

NagyDonat wrote:

Why is this a global static function and not a private method of 
`ProgramState`? Calling this function with `*this` as the first argument 
triggers my "Why is this trickery useful?" intuition; and if it could work as a 
method, then I would prefer that "more natural" solution.

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


[clang] [analyzer] Wrap SymbolicRegions by ElementRegions before getting a FieldRegion (PR #85211)

2024-03-18 Thread via cfe-commits

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

Looks good overall, my only inline comment is a minor stylistic question.

I think it's good that we're moving towards establishing the invariant that the 
parent of a FieldRegion should always be a typed value region (of a suitable 
type) for the sake of consistency. Do I understand it correctly that this is 
not too far away? Would it be possible to add an `assert` that mandates this?

On the other hand, I still feel that it's problematic that we're using 
`ElementRegion` to represent three different things (real element access, 
pointer arithmetic, type conversions). Even changing the name to something more 
general would be a step forward. Of course fixing this mess is a difficult 
long-term goal, and until then it's fine to work with the currently existing 
tools.

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


[clang] [analyzer] Wrap SymbolicRegions by ElementRegions before getting a FieldRegion (PR #85211)

2024-03-18 Thread via cfe-commits

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


[clang] [clang] Correct Microsoft mangling of lifetime extended temporary objects. (PR #85529)

2024-03-18 Thread via cfe-commits

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

This looks reasonable to me, but maybe give rnk and/or majnemer a day to 
comments as well since they're the real experts.

re: the incompatibility, yes if MSVC is mangling these now, clang should 
probably try to match.

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


[clang] [clang] Correct Microsoft mangling of lifetime extended temporary objects. (PR #85529)

2024-03-18 Thread via cfe-commits


@@ -54,6 +54,12 @@ ABI Changes in This Version
   inline member function that contains a static local variable with a dynamic
   initializer is declared with ``__declspec(dllimport)``. (#GH83616).
 
+- Fixed Microsoft name mangling of lifetime extended temporary objects. This
+  change corrects missing back reference registrations that could result in
+  incorrect back reference indexes and suprising demangled name results. Since
+  MSVC uses a different mangling for these objects, compatibility is not 
affected.
+  (#GH85423).

zmodem wrote:

> Commit 
> [e77de75](https://github.com/llvm/llvm-project/commit/e77de75d7e009daaadb03e9b1091c3a9a9c9d311)
>  claims that Microsoft doesn't have a mangling for these objects and that the 
> `$RT` mangling is a Clang invention. The claim that MSVC doesn't implement a 
> mangling for these doesn't seem right though. Consider 
> https://godbolt.org/z/n715zPbc6.

Looks like things have changed then. I tried the example code with MSVC 
18.00.31101.0 (from VS2013) and there the object is just `_$S1`:

```
??__E?singleton@RT1@@2ABU1@B@@YAXXZ PROC; 
??__E?singleton@RT1@@2ABU1@B@@YAXXZ, COMDAT
; File z:\tmp\a.cc
; Line 6
pushebp
mov ebp, esp
pushecx
call?f@@YA?AURT1@@XZ; f
mov DWORD PTR $T1[ebp], eax
mov eax, DWORD PTR $T1[ebp]
mov DWORD PTR _$S1, eax
mov DWORD PTR ?singleton@RT1@@2ABU1@B, OFFSET _$S1 ; RT1::singleton
mov esp, ebp
pop ebp
ret 0
```

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


[clang] fix unnecessary warning when using bitand with boolean operators (PR #81976)

2024-03-18 Thread Aaron Ballman via cfe-commits

AaronBallman wrote:

> currently the macro definition for both `&` and `bitand` is not giving any 
> warning however should the `&` one warn? or current working is correct 
> behaviour as expected?

The current behavior is what I'd expect. The idea being: if the user is using 
`&` directly, it's not clear whether they accidentally meant to use `&&` 
instead, but if they use something with an identifier (a macro, whether it's 
named `bitand` or not), then there's very little chance they meant `&&` instead.

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


[clang] [clang] Add /Zc:__STDC__ flag to clang-cl (PR #68690)

2024-03-18 Thread Aaron Ballman via cfe-commits


@@ -0,0 +1,11 @@
+// Note: %s must be preceded by --, otherwise it may be interpreted as a
+// command-line option, e.g. on Mac where %s is commonly under /Users.
+//
+// Note: see also cl-zc.cpp
+
+// RUN: %clang_cl /TC /dev/null /E -Xclang -dM /Zc:__STDC__- 2>&1 | FileCheck 
%s --check-prefix=ZCSTDCIGNORED
+// ZCSTDCIGNORED-NOT: #define __STDC__ 1
+// ZCSTDCIGNORED: argument unused during compilation
+
+// RUN: not %clang -Xclang -fno-ms-define-stdc %s 2>&1 | FileCheck %s 
--check-prefix="NOARG"

AaronBallman wrote:

@MaskRay -- see 
https://github.com/llvm/llvm-project/pull/68690#discussion_r1355620210 as to 
why I think it's valuable to have this test (but if you think it's not a useful 
test, I don't insist on it).

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


[clang] c2f75c7 - [clang][Interp] Handle CXXDefaultInitExpr of composite type

2024-03-18 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-03-18T12:59:56+01:00
New Revision: c2f75c7159518e238e0185c0f4e615fedcd8a167

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

LOG: [clang][Interp] Handle CXXDefaultInitExpr of composite type

Added: 


Modified: 
clang/lib/AST/Interp/ByteCodeExprGen.cpp
clang/test/AST/Interp/records.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp 
b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 6cee3c1af9f66a..d943dcbe06507b 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -2916,11 +2916,7 @@ template 
 bool ByteCodeExprGen::VisitCXXDefaultInitExpr(
 const CXXDefaultInitExpr *E) {
   SourceLocScope SLS(this, E);
-  if (Initializing)
-return this->visitInitializer(E->getExpr());
-
-  assert(classify(E->getType()));
-  return this->visit(E->getExpr());
+  return this->delegate(E->getExpr());
 }
 
 template 

diff  --git a/clang/test/AST/Interp/records.cpp 
b/clang/test/AST/Interp/records.cpp
index d37d4410c763fb..0f76e0cfe99277 100644
--- a/clang/test/AST/Interp/records.cpp
+++ b/clang/test/AST/Interp/records.cpp
@@ -1264,3 +1264,24 @@ namespace {
   static_assert(true_type::value, "");
   static_assert(true_type::value, "");
 }
+
+#if __cplusplus >= 202002L
+namespace {
+  /// Used to crash because the CXXDefaultInitExpr is of compound type.
+  struct A {
+int 
+constexpr ~A() { --x; }
+  };
+  struct B {
+int 
+const A  = A{x};
+  };
+  constexpr int a() {
+int x = 1;
+int f = B{x}.x;
+B{x}; // both-warning {{expression result unused}}
+
+return 1;
+  }
+}
+#endif



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


[libclc] [libclc] Convert tabs to spaces in CMake (PR #85634)

2024-03-18 Thread Fraser Cormack via cfe-commits

frasercrmck wrote:

@tstellar are you the code owner for `libclc`?

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


[clang] [clang][analyzer] Improve BlockInCriticalSectionsChecker (PR #80029)

2024-03-18 Thread via cfe-commits
Endre =?utf-8?q?Fülöp?= ,
Endre =?utf-8?q?Fülöp?= 
Message-ID:
In-Reply-To: 



@@ -20,48 +20,178 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+
+#include 
+#include 
+#include 
 
 using namespace clang;
 using namespace ento;
 
 namespace {
+
+struct CritSectionMarker {
+  const Expr *LockExpr{};
+  const MemRegion *LockReg{};
+
+  void Profile(llvm::FoldingSetNodeID ) const {
+ID.Add(LockExpr);
+ID.Add(LockReg);
+  }
+
+  [[nodiscard]] constexpr bool
+  operator==(const CritSectionMarker ) const noexcept {
+return LockExpr == Other.LockExpr && LockReg == Other.LockReg;
+  }
+  [[nodiscard]] constexpr bool
+  operator!=(const CritSectionMarker ) const noexcept {
+return !(*this == Other);
+  }
+};
+
+class CallDescriptionBasedMatcher {
+  CallDescription LockFn;
+  CallDescription UnlockFn;
+
+public:
+  CallDescriptionBasedMatcher(CallDescription &,
+  CallDescription &)
+  : LockFn(std::move(LockFn)), UnlockFn(std::move(UnlockFn)) {}
+  [[nodiscard]] bool matches(const CallEvent , bool IsLock) const {
+if (IsLock) {
+  return LockFn.matches(Call);
+}

NagyDonat wrote:

```suggestion
if (IsLock)
  return LockFn.matches(Call);
```
Bikeshedding: the coding standard says that braces shouldn't be used on simple 
single-statement bodies: 
https://llvm.org/docs/CodingStandards.html#don-t-use-braces-on-simple-single-statement-bodies-of-if-else-loop-statements

Unorthodox but (IMO) elegant alternative idea: replace the whole body of the 
function with
```
return (isLock ? LockFn : UnlockFn).matches(Call);
```

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


[clang] [clang][analyzer] Improve BlockInCriticalSectionsChecker (PR #80029)

2024-03-18 Thread via cfe-commits
Endre =?utf-8?q?Fülöp?= ,
Endre =?utf-8?q?Fülöp?= 
Message-ID:
In-Reply-To: 



@@ -20,48 +20,178 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+
+#include 
+#include 
+#include 
 
 using namespace clang;
 using namespace ento;
 
 namespace {
+
+struct CritSectionMarker {
+  const Expr *LockExpr{};
+  const MemRegion *LockReg{};
+
+  void Profile(llvm::FoldingSetNodeID ) const {
+ID.Add(LockExpr);
+ID.Add(LockReg);
+  }
+
+  [[nodiscard]] constexpr bool
+  operator==(const CritSectionMarker ) const noexcept {
+return LockExpr == Other.LockExpr && LockReg == Other.LockReg;
+  }
+  [[nodiscard]] constexpr bool
+  operator!=(const CritSectionMarker ) const noexcept {
+return !(*this == Other);
+  }
+};
+
+class CallDescriptionBasedMatcher {
+  CallDescription LockFn;
+  CallDescription UnlockFn;
+
+public:
+  CallDescriptionBasedMatcher(CallDescription &,
+  CallDescription &)
+  : LockFn(std::move(LockFn)), UnlockFn(std::move(UnlockFn)) {}
+  [[nodiscard]] bool matches(const CallEvent , bool IsLock) const {
+if (IsLock) {
+  return LockFn.matches(Call);
+}
+return UnlockFn.matches(Call);
+  }
+};
+
+class FirstArgMutexDescriptor : public CallDescriptionBasedMatcher {
+public:
+  FirstArgMutexDescriptor(CallDescription &, CallDescription &)
+  : CallDescriptionBasedMatcher(std::move(LockFn), std::move(UnlockFn)) {}
+
+  [[nodiscard]] const MemRegion *getRegion(const CallEvent , bool) const {
+return Call.getArgSVal(0).getAsRegion();
+  }
+};
+
+class MemberMutexDescriptor : public CallDescriptionBasedMatcher {
+public:
+  MemberMutexDescriptor(CallDescription &, CallDescription &)
+  : CallDescriptionBasedMatcher(std::move(LockFn), std::move(UnlockFn)) {}
+
+  [[nodiscard]] const MemRegion *getRegion(const CallEvent , bool) const {
+return cast(Call).getCXXThisVal().getAsRegion();
+  }
+};
+
+class RAIIMutexDescriptor {
+  mutable const IdentifierInfo *Guard{};
+  mutable bool IdentifierInfoInitialized{};
+  mutable llvm::SmallString<32> GuardName{};
+
+  void initIdentifierInfo(const CallEvent ) const {
+if (!IdentifierInfoInitialized) {
+  // In case of checking C code, or when the corresponding headers are not
+  // included, we might end up query the identifier table every time when
+  // this function is called instead of early returning it. To avoid this, 
a
+  // bool variable (IdentifierInfoInitialized) is used and the function 
will
+  // be run only once.
+  Guard = ()->getASTContext().Idents.get(
+  GuardName);
+  IdentifierInfoInitialized = true;
+}
+  }
+
+  template  bool matchesImpl(const CallEvent ) const {
+const T *C = dyn_cast();
+if (!C)
+  return false;
+const IdentifierInfo *II =
+cast(C->getDecl()->getParent())->getIdentifier();
+return II == Guard;
+  }
+
+public:
+  RAIIMutexDescriptor(StringRef GuardName) : GuardName(GuardName) {}
+  [[nodiscard]] bool matches(const CallEvent , bool IsLock) const {
+initIdentifierInfo(Call);
+if (IsLock) {
+  return matchesImpl(Call);
+}
+return matchesImpl(Call);
+  }
+  [[nodiscard]] const MemRegion *getRegion(const CallEvent ,
+   bool IsLock) const {
+const MemRegion *LockRegion = nullptr;
+if (IsLock) {
+  if (std::optional Object = Call.getReturnValueUnderConstruction()) 
{
+LockRegion = Object->getAsRegion();
+  }

NagyDonat wrote:

```suggestion
  if (std::optional Object = Call.getReturnValueUnderConstruction())
LockRegion = Object->getAsRegion();
```
Yet another brace tweak...

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


[clang] [clang][analyzer] Improve BlockInCriticalSectionsChecker (PR #80029)

2024-03-18 Thread via cfe-commits
Endre =?utf-8?q?Fülöp?= ,
Endre =?utf-8?q?Fülöp?= 
Message-ID:
In-Reply-To: 



@@ -20,48 +20,178 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+
+#include 
+#include 
+#include 
 
 using namespace clang;
 using namespace ento;
 
 namespace {
+
+struct CritSectionMarker {
+  const Expr *LockExpr{};
+  const MemRegion *LockReg{};
+
+  void Profile(llvm::FoldingSetNodeID ) const {
+ID.Add(LockExpr);
+ID.Add(LockReg);
+  }
+
+  [[nodiscard]] constexpr bool
+  operator==(const CritSectionMarker ) const noexcept {
+return LockExpr == Other.LockExpr && LockReg == Other.LockReg;
+  }
+  [[nodiscard]] constexpr bool
+  operator!=(const CritSectionMarker ) const noexcept {
+return !(*this == Other);
+  }
+};
+
+class CallDescriptionBasedMatcher {
+  CallDescription LockFn;
+  CallDescription UnlockFn;
+
+public:
+  CallDescriptionBasedMatcher(CallDescription &,
+  CallDescription &)
+  : LockFn(std::move(LockFn)), UnlockFn(std::move(UnlockFn)) {}
+  [[nodiscard]] bool matches(const CallEvent , bool IsLock) const {
+if (IsLock) {
+  return LockFn.matches(Call);
+}
+return UnlockFn.matches(Call);
+  }
+};
+
+class FirstArgMutexDescriptor : public CallDescriptionBasedMatcher {
+public:
+  FirstArgMutexDescriptor(CallDescription &, CallDescription &)
+  : CallDescriptionBasedMatcher(std::move(LockFn), std::move(UnlockFn)) {}
+
+  [[nodiscard]] const MemRegion *getRegion(const CallEvent , bool) const {
+return Call.getArgSVal(0).getAsRegion();
+  }
+};
+
+class MemberMutexDescriptor : public CallDescriptionBasedMatcher {
+public:
+  MemberMutexDescriptor(CallDescription &, CallDescription &)
+  : CallDescriptionBasedMatcher(std::move(LockFn), std::move(UnlockFn)) {}
+
+  [[nodiscard]] const MemRegion *getRegion(const CallEvent , bool) const {
+return cast(Call).getCXXThisVal().getAsRegion();
+  }
+};
+
+class RAIIMutexDescriptor {
+  mutable const IdentifierInfo *Guard{};
+  mutable bool IdentifierInfoInitialized{};
+  mutable llvm::SmallString<32> GuardName{};
+
+  void initIdentifierInfo(const CallEvent ) const {
+if (!IdentifierInfoInitialized) {
+  // In case of checking C code, or when the corresponding headers are not
+  // included, we might end up query the identifier table every time when
+  // this function is called instead of early returning it. To avoid this, 
a
+  // bool variable (IdentifierInfoInitialized) is used and the function 
will
+  // be run only once.
+  Guard = ()->getASTContext().Idents.get(
+  GuardName);
+  IdentifierInfoInitialized = true;
+}
+  }
+
+  template  bool matchesImpl(const CallEvent ) const {
+const T *C = dyn_cast();
+if (!C)
+  return false;
+const IdentifierInfo *II =
+cast(C->getDecl()->getParent())->getIdentifier();
+return II == Guard;
+  }
+
+public:
+  RAIIMutexDescriptor(StringRef GuardName) : GuardName(GuardName) {}
+  [[nodiscard]] bool matches(const CallEvent , bool IsLock) const {
+initIdentifierInfo(Call);
+if (IsLock) {
+  return matchesImpl(Call);
+}

NagyDonat wrote:

```suggestion
if (IsLock)
  return matchesImpl(Call);
```
Bikeshedding as above.

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


[clang] [clang][analyzer] Improve BlockInCriticalSectionsChecker (PR #80029)

2024-03-18 Thread via cfe-commits
Endre =?utf-8?q?Fülöp?= ,
Endre =?utf-8?q?Fülöp?= 
Message-ID:
In-Reply-To: 


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

Thanks for simplifying the code :)

I added some stereotypical bikeshedding in inline comments, but apart from that 
the commit LGTM.

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


[clang] [clang][analyzer] Improve BlockInCriticalSectionsChecker (PR #80029)

2024-03-18 Thread via cfe-commits
Endre =?utf-8?q?Fülöp?= ,
Endre =?utf-8?q?Fülöp?= 
Message-ID:
In-Reply-To: 


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


[clang] [Clang][Sema] Fix a crash in lambda instantiation (PR #85565)

2024-03-18 Thread via cfe-commits


@@ -13714,6 +13714,12 @@ TreeTransform::TransformLambdaExpr(LambdaExpr 
*E) {
 
 // Capturing 'this' is trivial.
 if (C->capturesThis()) {
+  // We need ThisType here.
+  Sema::CXXThisScopeRAII ThisScope(
+  getSema(),
+  dyn_cast_or_null(

Sirraide wrote:

```suggestion
  dyn_cast_if_present(
```
`cast_or_null` and friends are deprecated.

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


[clang] [Clang][Sema] Fix a crash in lambda instantiation (PR #85565)

2024-03-18 Thread via cfe-commits


@@ -394,6 +394,7 @@ Bug Fixes to C++ Support
   expression references to an entity declared outside of the lambda. (#GH64808)
 - Clang's __builtin_bit_cast will now produce a constant value for records 
with empty bases. See:
   (#GH82383)
+- Fix a crash in lambda instantiation that missing set ``ThisType`` when 
checking capture. Fixes (#GH85343).

Sirraide wrote:

This sentence is really hard to parse; maybe something like this makes it a bit 
clearer what the actual change here is; if you can think of a better way of 
wording it, feel free to go w/ that instead.

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


[clang] [Clang][Sema] Fix a crash in lambda instantiation (PR #85565)

2024-03-18 Thread via cfe-commits


@@ -13714,6 +13714,12 @@ TreeTransform::TransformLambdaExpr(LambdaExpr 
*E) {
 
 // Capturing 'this' is trivial.
 if (C->capturesThis()) {
+  // We need ThisType here.

Sirraide wrote:

This comment doesn’t really explain anything. I’d suggest explaining *why*, not 
*that*, we need a `ThisScope` here.

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


[clang] [Clang][Sema] Fix a crash in lambda instantiation (PR #85565)

2024-03-18 Thread via cfe-commits


@@ -394,6 +394,7 @@ Bug Fixes to C++ Support
   expression references to an entity declared outside of the lambda. (#GH64808)
 - Clang's __builtin_bit_cast will now produce a constant value for records 
with empty bases. See:
   (#GH82383)
+- Fix a crash in lambda instantiation that missing set ``ThisType`` when 
checking capture. Fixes (#GH85343).

Sirraide wrote:

```suggestion
- Fix a crash when instantiating a lambda that captures ``this`` outside of its 
context. Fixes (#GH85343).
```

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


[clang] [Clang][Sema] Fix a crash in lambda instantiation (PR #85565)

2024-03-18 Thread via cfe-commits

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

Looks fine to me apart from a few minor things.

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


[clang] [Clang][Sema] Fix a crash in lambda instantiation (PR #85565)

2024-03-18 Thread via cfe-commits

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


[libclc] [libclc] Convert tabs to spaces in CMake (PR #85634)

2024-03-18 Thread Fraser Cormack via cfe-commits

https://github.com/frasercrmck created 
https://github.com/llvm/llvm-project/pull/85634

Having a mix of tabs and spaces makes the diff of any changes to the build 
system noisier than necessary. This commit unifies them to two spaces.

This includes some minor cosmetic changes such as with joining things on one 
line where appropriate.

There are other files in libclc which have tabs but those haven't been touched 
at this time. Those could come at another time if desired, though they might be 
more contentious as the project isn't clang-formatted at all and so that might 
invite larger discussions around formatting.

>From 97a5c5d9b6e9a3e38aee92cd6670abb395495c6e Mon Sep 17 00:00:00 2001
From: Fraser Cormack 
Date: Mon, 18 Mar 2024 11:27:55 +
Subject: [PATCH] [libclc] Convert tabs to spaces in CMake

Having a mix of tabs and spaces makes the diff of any changes to the
build system noisier than necessary. This commit unifies them to two
spaces.

This includes some minor cosmetic changes such as with joining things on
one line where appropriate.

There are other files in libclc which have tabs but those haven't been
touched at this time. Those could come at another time if desired,
though they might be more contentious as the project isn't
clang-formatted at all and so that might invite larger discussions
around formatting.
---
 libclc/CMakeLists.txt| 408 +++
 libclc/check_external_calls.sh   |  16 +-
 libclc/cmake/CMakeLLAsmInformation.cmake |   4 +-
 3 files changed, 206 insertions(+), 222 deletions(-)

diff --git a/libclc/CMakeLists.txt b/libclc/CMakeLists.txt
index 18f77940e76669..745b848fba4901 100644
--- a/libclc/CMakeLists.txt
+++ b/libclc/CMakeLists.txt
@@ -40,8 +40,7 @@ set( LIBCLC_MIN_LLVM "3.9.0" )
 set( LIBCLC_TARGETS_TO_BUILD "all"
 CACHE STRING "Semicolon-separated list of targets to build, or 'all'." )
 
-option( ENABLE_RUNTIME_SUBNORMAL "Enable runtime linking of subnormal support."
-OFF )
+option( ENABLE_RUNTIME_SUBNORMAL "Enable runtime linking of subnormal 
support." OFF )
 
 find_package(LLVM REQUIRED HINTS "${LLVM_CMAKE_DIR}")
 include(AddLLVM)
@@ -49,16 +48,16 @@ include(AddLLVM)
 message( "LLVM version: ${LLVM_PACKAGE_VERSION}" )
 
 if( ${LLVM_PACKAGE_VERSION} VERSION_LESS ${LIBCLC_MIN_LLVM} )
-   message( FATAL_ERROR "libclc needs at least LLVM ${LIBCLC_MIN_LLVM}" )
+  message( FATAL_ERROR "libclc needs at least LLVM ${LIBCLC_MIN_LLVM}" )
 endif()
 
 # mesa3d environment is only available since LLVM 4.0
 if( ${LLVM_PACKAGE_VERSION} VERSION_GREATER "3.9.0" )
-   set( LIBCLC_TARGETS_ALL ${LIBCLC_TARGETS_ALL} amdgcn-mesa-mesa3d )
+  set( LIBCLC_TARGETS_ALL ${LIBCLC_TARGETS_ALL} amdgcn-mesa-mesa3d )
 endif()
 
 if( LIBCLC_TARGETS_TO_BUILD STREQUAL "all" )
-   set( LIBCLC_TARGETS_TO_BUILD ${LIBCLC_TARGETS_ALL} )
+  set( LIBCLC_TARGETS_TO_BUILD ${LIBCLC_TARGETS_ALL} )
 endif()
 
 find_program( LLVM_CLANG clang PATHS ${LLVM_TOOLS_BINARY_DIR} NO_DEFAULT_PATH )
@@ -75,15 +74,15 @@ message( "opt: ${LLVM_OPT}" )
 message( "llvm-spirv: ${LLVM_SPIRV}" )
 message( "" )
 if( NOT LLVM_CLANG OR NOT LLVM_OPT OR NOT LLVM_AS OR NOT LLVM_LINK )
-   message( FATAL_ERROR "toolchain incomplete!" )
+  message( FATAL_ERROR "toolchain incomplete!" )
 endif()
 
 list( SORT LIBCLC_TARGETS_TO_BUILD )
 
 if( "spirv-mesa3d-" IN_LIST LIBCLC_TARGETS_TO_BUILD OR "spirv64-mesa3d-" 
IN_LIST LIBCLC_TARGETS_TO_BUILD )
-   if( NOT LLVM_SPIRV )
-   message( FATAL_ERROR "SPIR-V targets requested, but spirv-tools 
is not installed" )
-   endif()
+  if( NOT LLVM_SPIRV )
+message( FATAL_ERROR "SPIR-V targets requested, but spirv-tools is not 
installed" )
+  endif()
 endif()
 
 set( CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake )
@@ -99,8 +98,8 @@ set( LLVM_VERSION_DEFINE 
"-DHAVE_LLVM=0x${LLVM_VERSION_MAJOR}0${LLVM_VERSION_MIN
 
 # LLVM 13 enables standard includes by default
 if( ${LLVM_PACKAGE_VERSION} VERSION_GREATER "12.99.99" )
-   set( CMAKE_LLAsm_FLAGS "${CMAKE_LLAsm_FLAGS} 
-cl-no-stdinc")
-   set( CMAKE_CLC_FLAGS "${CMAKE_CLC_FLAGS} 
-cl-no-stdinc")
+  set( CMAKE_LLAsm_FLAGS "${CMAKE_LLAsm_FLAGS} -cl-no-stdinc" )
+  set( CMAKE_CLC_FLAGS "${CMAKE_CLC_FLAGS} -cl-no-stdinc" )
 endif()
 
 enable_language( CLC LLAsm )
@@ -142,14 +141,14 @@ set( cypress_aliases hemlock )
 set( barts_aliases turks caicos )
 set( cayman_aliases aruba )
 set( tahiti_aliases pitcairn verde oland hainan bonaire kabini kaveri hawaii
-   mullins tonga tongapro iceland carrizo fiji stoney polaris10 polaris11
-   gfx602 gfx705 gfx805
-   gfx900 gfx902 gfx904 gfx906 gfx908 gfx909 gfx90a gfx90c gfx940 gfx941 
gfx942
-   gfx1010 gfx1011 gfx1012 gfx1013
-   gfx1030 gfx1031 gfx1032 gfx1033 gfx1034 gfx1035 gfx1036
-   gfx1100 gfx1101 gfx1102 gfx1103
-   gfx1150 gfx1151
-   gfx1200 gfx1201
+  mullins tonga tongapro iceland carrizo fiji stoney polaris10 polaris11
+  gfx602 

[clang] [llvm] [AMDGPU] Enable OpenCL hostcall printf (WIP) (PR #72556)

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


@@ -3616,6 +3617,12 @@ unsigned FunctionDecl::getBuiltinID(bool 
ConsiderWrapperFunctions) const {
   if (!ConsiderWrapperFunctions && getStorageClass() == SC_Static)
 return 0;
 
+  // AMDGCN implementation supports printf as a builtin
+  // for OpenCL
+  if (Context.getTargetInfo().getTriple().isAMDGCN() &&
+  Context.getLangOpts().OpenCL && BuiltinID == AMDGPU::BIprintf)
+return BuiltinID;

vikramRH wrote:

I was referring to 
https://github.com/llvm/llvm-project/blob/3e6db602918435b6a5ac476f63f8b259e7e73af4/clang/lib/AST/Decl.cpp#L3633.
 This essentially means that even if frontend attaches the printf builtin ID to 
the decl (even after custom type checks), this would revert.

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


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-18 Thread Timm Baeder via cfe-commits
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= 
Message-ID:
In-Reply-To: 


https://github.com/tbaederr updated 
https://github.com/llvm/llvm-project/pull/84159

>From 1c06781e92b8fec78ae82b0d6a85965524d223d6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= 
Date: Mon, 18 Mar 2024 12:21:16 +0100
Subject: [PATCH 1/6] [clang][Interp] Handle CXXDefaultInitExpr of composite
 type

---
 clang/lib/AST/Interp/ByteCodeExprGen.cpp |  6 +-
 clang/test/AST/Interp/records.cpp| 21 +
 2 files changed, 22 insertions(+), 5 deletions(-)

diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp 
b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 6cee3c1af9f66a..d943dcbe06507b 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -2916,11 +2916,7 @@ template 
 bool ByteCodeExprGen::VisitCXXDefaultInitExpr(
 const CXXDefaultInitExpr *E) {
   SourceLocScope SLS(this, E);
-  if (Initializing)
-return this->visitInitializer(E->getExpr());
-
-  assert(classify(E->getType()));
-  return this->visit(E->getExpr());
+  return this->delegate(E->getExpr());
 }
 
 template 
diff --git a/clang/test/AST/Interp/records.cpp 
b/clang/test/AST/Interp/records.cpp
index d37d4410c763fb..0f76e0cfe99277 100644
--- a/clang/test/AST/Interp/records.cpp
+++ b/clang/test/AST/Interp/records.cpp
@@ -1264,3 +1264,24 @@ namespace {
   static_assert(true_type::value, "");
   static_assert(true_type::value, "");
 }
+
+#if __cplusplus >= 202002L
+namespace {
+  /// Used to crash because the CXXDefaultInitExpr is of compound type.
+  struct A {
+int 
+constexpr ~A() { --x; }
+  };
+  struct B {
+int 
+const A  = A{x};
+  };
+  constexpr int a() {
+int x = 1;
+int f = B{x}.x;
+B{x}; // both-warning {{expression result unused}}
+
+return 1;
+  }
+}
+#endif

>From 3f47e6fde4b0b05ac243d1afa69eb9adde650614 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= 
Date: Wed, 6 Mar 2024 08:36:52 +0100
Subject: [PATCH 2/6] Integral pointers

---
 clang/lib/AST/Interp/ByteCodeExprGen.cpp |  74 -
 clang/lib/AST/Interp/ByteCodeStmtGen.cpp |   2 +-
 clang/lib/AST/Interp/Descriptor.h|   1 +
 clang/lib/AST/Interp/FunctionPointer.h   |  10 +-
 clang/lib/AST/Interp/Interp.cpp  |   5 +
 clang/lib/AST/Interp/Interp.h|  89 --
 clang/lib/AST/Interp/InterpBlock.cpp |   4 +-
 clang/lib/AST/Interp/Opcodes.td  |  12 +
 clang/lib/AST/Interp/Pointer.cpp | 176 ---
 clang/lib/AST/Interp/Pointer.h   | 369 ---
 clang/lib/AST/Interp/PrimType.h  |   4 +
 clang/test/AST/Interp/c.c|  18 ++
 clang/test/AST/Interp/const-eval.c   | 194 
 13 files changed, 777 insertions(+), 181 deletions(-)
 create mode 100644 clang/test/AST/Interp/const-eval.c

diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp 
b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index d943dcbe06507b..464e598cdd77e8 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -173,10 +173,18 @@ bool ByteCodeExprGen::VisitCastExpr(const 
CastExpr *CE) {
 return this->emitCastFloatingIntegral(*ToT, CE);
   }
 
-  case CK_NullToPointer:
+  case CK_NullToPointer: {
 if (DiscardResult)
   return true;
-return this->emitNull(classifyPrim(CE->getType()), CE);
+
+const Descriptor *Desc = nullptr;
+const QualType PointeeType = CE->getType()->getPointeeType();
+if (!PointeeType.isNull()) {
+  if (std::optional T = classify(PointeeType))
+Desc = P.createDescriptor(SubExpr, *T);
+}
+return this->emitNull(classifyPrim(CE->getType()), Desc, CE);
+  }
 
   case CK_PointerToIntegral: {
 if (DiscardResult)
@@ -199,6 +207,34 @@ bool ByteCodeExprGen::VisitCastExpr(const 
CastExpr *CE) {
 return true;
   }
 
+  case CK_IntegralToPointer: {
+QualType IntType = SubExpr->getType();
+assert(IntType->isIntegralOrEnumerationType());
+if (!this->visit(SubExpr))
+  return false;
+// FIXME: I think the discard is wrong since the int->ptr cast might cause 
a
+// diagnostic.
+PrimType T = classifyPrim(IntType);
+if (DiscardResult)
+  return this->emitPop(T, CE);
+
+QualType PtrType = CE->getType();
+assert(PtrType->isPointerType());
+
+const Descriptor *Desc;
+if (std::optional T = classify(PtrType->getPointeeType())) {
+  Desc = P.createDescriptor(SubExpr, *T);
+} else if (PtrType->getPointeeType()->isVoidType())
+  Desc = nullptr;
+else {
+  Desc = P.createDescriptor(CE, PtrType->getPointeeType().getTypePtr(),
+Descriptor::InlineDescMD, true, false,
+/*IsMutable=*/false, nullptr);
+}
+
+return this->emitGetIntPtr(T, Desc, CE);
+  }
+
   case CK_AtomicToNonAtomic:
   case 

[clang] [clang-cl] Fix value of __FUNCTION__ in MSVC mode. (PR #84014)

2024-03-18 Thread via cfe-commits

Sirraide wrote:

>From what I can tell, it seems that Aaron is a lot more familiar w/ this part 
>of Clang than me, so I’ll leave it to him to comment on whether these changes 
>make sense.

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


[clang] [llvm] [AMDGPU] Enable OpenCL hostcall printf (WIP) (PR #72556)

2024-03-18 Thread Matt Arsenault via cfe-commits


@@ -3616,6 +3617,12 @@ unsigned FunctionDecl::getBuiltinID(bool 
ConsiderWrapperFunctions) const {
   if (!ConsiderWrapperFunctions && getStorageClass() == SC_Static)
 return 0;
 
+  // AMDGCN implementation supports printf as a builtin
+  // for OpenCL
+  if (Context.getTargetInfo().getTriple().isAMDGCN() &&
+  Context.getLangOpts().OpenCL && BuiltinID == AMDGPU::BIprintf)
+return BuiltinID;

arsenm wrote:

> . Meanwhile, can this go ahead as an AMDGPU specific workaround for now so 
> that we have the intended feature in place

No. That cleanup will never happen.

> PS :Ah, I see another issue . OpenCL v1.2 s6.9.f states none of the functions 
> defined in C99 headers are available. This would mean std printf is supposed 
> to be treated differently than OpenCL builtins and consequently the builtin 
> IDs assigned to them "need" to be different

That's not what that means 

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


[clang] [clang][dataflow] Make optional checker work for types derived from optional. (PR #84138)

2024-03-18 Thread via cfe-commits


@@ -129,19 +207,19 @@ auto inPlaceClass() {
 
 auto isOptionalNulloptConstructor() {
   return cxxConstructExpr(
-  hasOptionalType(),
+  hasOptionalOrDerivedType(),

martinboehme wrote:

> I would think that we don't know (and therefore can't model) the definition 
> of constructors, methods, operators on the derived class.

I agree in principle, but here we're looking specifically at a constructor that 
takes a `std::nullopt_t`. I'd say it's a pretty safe bet to assume this 
constructor is initializing the optional to be empty, even in a derived class 
(it would be _very_ confusing if it did anything else).

I believe it's also reasonable to conjecture about the behavior of the cases 
below that use `hasOptionalOrDerivedType()`, i.e. the `std::in_place_t` case 
and the "value or conversion constructor / assignment" cases.

`llvm::MaybeAlign` has 
[methods](https://github.com/llvm/llvm-project/blob/3e6db602918435b6a5ac476f63f8b259e7e73af4/llvm/include/llvm/Support/Alignment.h#L131)
 that correspond to these cases, and it seems desirable to model them correctly.

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


[clang] 3e6db60 - [RemoveDIs] Update Clang front end to handle DbgRecords (#84756)

2024-03-18 Thread Orlando Cazalet-Hyams via cfe-commits

Author: Orlando Cazalet-Hyams
Date: 2024-03-18T10:55:29Z
New Revision: 3e6db602918435b6a5ac476f63f8b259e7e73af4

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

LOG: [RemoveDIs] Update Clang front end to handle DbgRecords (#84756)

This patch fixes problems that pop up when clang emits DbgRecords
instead of debug intrinsics.

Note: this doesn't mean clang is emitting DbgRecords yet, because the
modules it creates are still always in the old debug mode. That will
come in a future patch.

Depends on #84739

Added: 


Modified: 
clang/lib/CodeGen/CGBlocks.cpp
clang/lib/CodeGen/CGStmtOpenMP.cpp
clang/test/CodeGenObjC/debug-info-blocks.m

Removed: 




diff  --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp
index 0cbace7b7f7bbd..ad0b50d799618e 100644
--- a/clang/lib/CodeGen/CGBlocks.cpp
+++ b/clang/lib/CodeGen/CGBlocks.cpp
@@ -1540,7 +1540,10 @@ llvm::Function *CodeGenFunction::GenerateBlockFunction(
   llvm::BasicBlock *resume = Builder.GetInsertBlock();
 
   // Go back to the entry.
-  ++entry_ptr;
+  if (entry_ptr->getNextNonDebugInstruction())
+entry_ptr = entry_ptr->getNextNonDebugInstruction()->getIterator();
+  else
+entry_ptr = entry->end();
   Builder.SetInsertPoint(entry, entry_ptr);
 
   // Emit debug information for all the DeclRefExprs.

diff  --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp 
b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 452ce6983f6ac1..8edcc4ceea9436 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -4749,10 +4749,10 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(
   if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
 (void)DI->EmitDeclareOfAutoVariable(SharedVar, ContextValue,
 CGF.Builder, false);
-  llvm::Instruction  = CGF.Builder.GetInsertBlock()->back();
   // Get the call dbg.declare instruction we just created and update
   // its DIExpression to add offset to base address.
-  if (auto DDI = dyn_cast()) {
+  auto UpdateExpr = [](llvm::LLVMContext , auto *Declare,
+   unsigned Offset) {
 SmallVector Ops;
 // Add offset to the base address if non zero.
 if (Offset) {
@@ -4760,9 +4760,21 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(
   Ops.push_back(Offset);
 }
 Ops.push_back(llvm::dwarf::DW_OP_deref);
-auto  = DDI->getContext();
-llvm::DIExpression *DIExpr = llvm::DIExpression::get(Ctx, Ops);
-Last.setOperand(2, llvm::MetadataAsValue::get(Ctx, DIExpr));
+Declare->setExpression(llvm::DIExpression::get(Ctx, Ops));
+  };
+  llvm::Instruction  = CGF.Builder.GetInsertBlock()->back();
+  if (auto DDI = dyn_cast())
+UpdateExpr(DDI->getContext(), DDI, Offset);
+  // If we're emitting using the new debug info format into a block
+  // without a terminator, the record will be "trailing".
+  assert(!Last.isTerminator() && "unexpected terminator");
+  if (auto *Marker =
+  CGF.Builder.GetInsertBlock()->getTrailingDbgRecords()) {
+for (llvm::DPValue  : llvm::reverse(
+ llvm::filterDbgVars(Marker->getDbgRecordRange( {
+  UpdateExpr(Last.getContext(), , Offset);
+  break;
+}
   }
 }
   }

diff  --git a/clang/test/CodeGenObjC/debug-info-blocks.m 
b/clang/test/CodeGenObjC/debug-info-blocks.m
index 14b29f222fbe8e..59171da016da1e 100644
--- a/clang/test/CodeGenObjC/debug-info-blocks.m
+++ b/clang/test/CodeGenObjC/debug-info-blocks.m
@@ -5,8 +5,8 @@
 
 // CHECK: define {{.*}}_block_invoke
 // CHECK: store ptr %.block_descriptor, ptr %[[ALLOCA:block.addr]], align
-// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr %[[ALLOCA]], metadata 
![[SELF:[0-9]+]], metadata !{{.*}})
 // CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr %d, metadata 
![[D:[0-9]+]], metadata !{{.*}})
+// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr %[[ALLOCA]], metadata 
![[SELF:[0-9]+]], metadata !{{.*}})
 
 // Test that we do emit scope info for the helper functions, and that the
 // parameters to these functions are marked as artificial (so the debugger



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


[clang] [llvm] [AMDGPU] Enable OpenCL hostcall printf (WIP) (PR #72556)

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

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


[clang] [clang][dataflow] Make optional checker work for types derived from optional. (PR #84138)

2024-03-18 Thread via cfe-commits


@@ -64,39 +64,117 @@ static bool hasOptionalClassName(const CXXRecordDecl ) {
   return false;
 }
 
+static const CXXRecordDecl *getOptionalBaseClass(const CXXRecordDecl *RD) {
+  if (RD == nullptr)
+return nullptr;
+  if (hasOptionalClassName(*RD))
+return RD;
+
+  if (!RD->hasDefinition())
+return nullptr;
+
+  for (const CXXBaseSpecifier  : RD->bases())
+if (const CXXRecordDecl *BaseClass =
+getOptionalBaseClass(Base.getType()->getAsCXXRecordDecl()))
+  return BaseClass;
+
+  return nullptr;
+}
+
 namespace {
 
 using namespace ::clang::ast_matchers;
 using LatticeTransferState = TransferState;
 
-AST_MATCHER(CXXRecordDecl, hasOptionalClassNameMatcher) {
-  return hasOptionalClassName(Node);
+AST_MATCHER(CXXRecordDecl, optionalClass) { return hasOptionalClassName(Node); 
}
+
+AST_MATCHER(CXXRecordDecl, optionalOrDerivedClass) {
+  return getOptionalBaseClass() != nullptr;
 }
 
-DeclarationMatcher optionalClass() {
-  return classTemplateSpecializationDecl(
-  hasOptionalClassNameMatcher(),
-  hasTemplateArgument(0, refersToType(type().bind("T";
+auto desugarsToOptionalType() {
+  return hasUnqualifiedDesugaredType(
+  recordType(hasDeclaration(cxxRecordDecl(optionalClass();
 }
 
-auto optionalOrAliasType() {
+auto desugarsToOptionalOrDerivedType() {
   return hasUnqualifiedDesugaredType(
-  recordType(hasDeclaration(optionalClass(;
+  recordType(hasDeclaration(cxxRecordDecl(optionalOrDerivedClass();
 }
 
-/// Matches any of the spellings of the optional types and sugar, aliases, etc.
-auto hasOptionalType() { return hasType(optionalOrAliasType()); }
+auto hasOptionalType() { return hasType(desugarsToOptionalType()); }
+
+/// Matches any of the spellings of the optional types and sugar, aliases,
+/// derived classes, etc.
+auto hasOptionalOrDerivedType() {
+  return hasType(desugarsToOptionalOrDerivedType());
+}
+
+QualType getPublicType(const Expr *E) {
+  auto *Cast = dyn_cast(E->IgnoreParens());
+  if (Cast == nullptr || Cast->getCastKind() != CK_UncheckedDerivedToBase) {
+QualType Ty = E->getType();
+if (Ty->isPointerType())
+  return Ty->getPointeeType();
+return Ty;
+  }
+
+  QualType Ty = getPublicType(Cast->getSubExpr());

martinboehme wrote:

I hope this has become clearer given the additional comments on what the loop 
is doing.

The idea behind doing the recursion first, then potentially throwing the result 
away, is that it makes the code proceed strictly along the patch from 
most-derived to most-base class.

Conceptually, we want to "drill down" into the `getImplicitObjectArgument()` to 
find the most-derived type, then walk back along the "cast path" towards the 
base until we find a point where we're no longer allowed to perform the cast. 
The code that was here expresses this most directly (the recursive call does 
the "drilling down"), but as you note, it's inefficient in the case where we 
need to throw away the result of the recursive call.

I've changed this to use tail recursion and have added comments that hopefully 
make it clear what the recursion is doing.

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


[clang] [llvm] [AMDGPU] Enable OpenCL hostcall printf (WIP) (PR #72556)

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

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


[clang] [llvm] [AMDGPU] Enable OpenCL hostcall printf (WIP) (PR #72556)

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


@@ -3616,6 +3617,12 @@ unsigned FunctionDecl::getBuiltinID(bool 
ConsiderWrapperFunctions) const {
   if (!ConsiderWrapperFunctions && getStorageClass() == SC_Static)
 return 0;
 
+  // AMDGCN implementation supports printf as a builtin
+  // for OpenCL
+  if (Context.getTargetInfo().getTriple().isAMDGCN() &&
+  Context.getLangOpts().OpenCL && BuiltinID == AMDGPU::BIprintf)
+return BuiltinID;

vikramRH wrote:

@arsenm, thanks for the info. CustomTypeChecking is a valid option. I'm not 
sure why OpenCL community did not consider this change despite OpenCL specs 
specifying the details. I could create a separate patch for this (probably 
folks from OCL community would provide further background). Meanwhile, can this 
go ahead as an AMDGPU specific workaround for now so that we have the intended 
feature in place ? (The frontend changes here can be reverted with that follow 
up patch )

PS :Also, I see another issue . OpenCL v1.2 s6.9.f states none of the functions 
defined in C99 headers are available. This would mean std printf is supposed to 
be treated differently than OpenCL builtins and consequently the builtin IDs 
assigned to them "need" to be different. If this understanding is correct, 
moving ahead with using same builtin ID as std printf is not the right way.

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


[clang] [clang][dataflow] Make optional checker work for types derived from optional. (PR #84138)

2024-03-18 Thread via cfe-commits


@@ -64,39 +64,117 @@ static bool hasOptionalClassName(const CXXRecordDecl ) {
   return false;
 }
 
+static const CXXRecordDecl *getOptionalBaseClass(const CXXRecordDecl *RD) {
+  if (RD == nullptr)
+return nullptr;
+  if (hasOptionalClassName(*RD))
+return RD;
+
+  if (!RD->hasDefinition())
+return nullptr;
+
+  for (const CXXBaseSpecifier  : RD->bases())
+if (const CXXRecordDecl *BaseClass =
+getOptionalBaseClass(Base.getType()->getAsCXXRecordDecl()))
+  return BaseClass;
+
+  return nullptr;
+}
+
 namespace {
 
 using namespace ::clang::ast_matchers;
 using LatticeTransferState = TransferState;
 
-AST_MATCHER(CXXRecordDecl, hasOptionalClassNameMatcher) {
-  return hasOptionalClassName(Node);
+AST_MATCHER(CXXRecordDecl, optionalClass) { return hasOptionalClassName(Node); 
}
+
+AST_MATCHER(CXXRecordDecl, optionalOrDerivedClass) {
+  return getOptionalBaseClass() != nullptr;
 }
 
-DeclarationMatcher optionalClass() {
-  return classTemplateSpecializationDecl(
-  hasOptionalClassNameMatcher(),
-  hasTemplateArgument(0, refersToType(type().bind("T";
+auto desugarsToOptionalType() {
+  return hasUnqualifiedDesugaredType(
+  recordType(hasDeclaration(cxxRecordDecl(optionalClass();
 }
 
-auto optionalOrAliasType() {
+auto desugarsToOptionalOrDerivedType() {
   return hasUnqualifiedDesugaredType(
-  recordType(hasDeclaration(optionalClass(;
+  recordType(hasDeclaration(cxxRecordDecl(optionalOrDerivedClass();
 }
 
-/// Matches any of the spellings of the optional types and sugar, aliases, etc.
-auto hasOptionalType() { return hasType(optionalOrAliasType()); }
+auto hasOptionalType() { return hasType(desugarsToOptionalType()); }
+
+/// Matches any of the spellings of the optional types and sugar, aliases,
+/// derived classes, etc.
+auto hasOptionalOrDerivedType() {
+  return hasType(desugarsToOptionalOrDerivedType());
+}
+
+QualType getPublicType(const Expr *E) {
+  auto *Cast = dyn_cast(E->IgnoreParens());
+  if (Cast == nullptr || Cast->getCastKind() != CK_UncheckedDerivedToBase) {
+QualType Ty = E->getType();
+if (Ty->isPointerType())
+  return Ty->getPointeeType();
+return Ty;
+  }
+
+  QualType Ty = getPublicType(Cast->getSubExpr());
+
+  // Is `Ty` the type of `*this`? In this special case, we can upcast to the
+  // base class even if the base is non-public.
+  bool TyIsThisType = isa(Cast->getSubExpr());
+
+  for (const CXXBaseSpecifier *Base : Cast->path()) {
+if (Base->getAccessSpecifier() != AS_public && !TyIsThisType)
+  break;
+Ty = Base->getType();
+TyIsThisType = false;
+  }
+
+  return Ty;
+}
+
+// Returns the least-derived type for the receiver of `MCE` that
+// `MCE.getImplicitObjectArgument()->IgnoreParentImpCasts()` can be downcast 
to.
+// Effectively, we upcast until we reach a non-public base class, unless that
+// base is a base of `*this`.
+//
+// This is needed to correctly match methods called on types derived from
+// `std::optional`.
+//
+// Say we have a `struct Derived : public std::optional {} d;` For a call
+// `d.has_value()`, the `getImplicitObjectArgument()` looks like this:
+//
+//   ImplicitCastExpr 'const std::__optional_storage_base' lvalue
+//   | 
__optional_storage_base)>
+//   `-DeclRefExpr 'Derived' lvalue Var 'd' 'Derived'
+//
+// The type of the implicit object argument is `__optional_storage_base`
+// (since this is the internal type that `has_value()` is declared on). If we
+// call `IgnoreParenImpCasts()` on the implicit object argument, we get the
+// `DeclRefExpr`, which has type `Derived`. Neither of these types is
+// `optional`, and hence neither is sufficient for querying whether we are
+// calling a method on `optional`.
+//
+// Instead, starting with the most derived type, we need to follow the chain of
+// casts
+QualType getPublicReceiverType(const CXXMemberCallExpr ) {
+  return getPublicType(MCE.getImplicitObjectArgument());
+}
+
+AST_MATCHER_P(CXXMemberCallExpr, publicReceiverType,
+  ast_matchers::internal::Matcher, InnerMatcher) {
+  return InnerMatcher.matches(getPublicReceiverType(Node), Finder, Builder);
+}
 
 auto isOptionalMemberCallWithNameMatcher(
 ast_matchers::internal::Matcher matcher,
 const std::optional  = std::nullopt) {
-  auto Exception = unless(Ignorable ? expr(anyOf(*Ignorable, cxxThisExpr()))
-: cxxThisExpr());
-  return cxxMemberCallExpr(
-  on(expr(Exception,
-  anyOf(hasOptionalType(),
-hasType(pointerType(pointee(optionalOrAliasType())),
-  callee(cxxMethodDecl(matcher)));
+  return cxxMemberCallExpr(Ignorable ? on(expr(unless(*Ignorable)))

martinboehme wrote:

> why drop the exclusion of calls on `this`?

We do this so that we can analyze member functions in classes that are derived 
from an optional class. See the new test `ClassDerivedPrivatelyFromOptional` 
(added in response to 

[clang] [clang][analyzer] Improve BlockInCriticalSectionsChecker (PR #80029)

2024-03-18 Thread Endre Fülöp via cfe-commits

https://github.com/gamesh411 updated 
https://github.com/llvm/llvm-project/pull/80029

From 346e2296869e750c7ec5bd75cf05f80a23b70569 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Endre=20F=C3=BCl=C3=B6p?= 
Date: Tue, 30 Jan 2024 11:33:30 +0100
Subject: [PATCH 1/3] [clang][analyzer] Improve BlockInCriticalSectionsChecker
 with multi-section and recursive mutex support

* Add support for multiple, potentially overlapping critical sections:
  The checker can now simultaneously handle several mutex's critical
  sections without confusing them.
* Implement the handling of recursive mutexes:
  By identifying the lock events, recursive mutexes are now supported.
  A lock event is a pair of a lock expression and the SVal of the mutex
  that it locks, so even multiple locks of the same mutex (and even by
  the same expression) is now supported.
* Refine the note tags generated by the checker:
  The note tags now correctly show just for mutexes those are
  active at point of error, and multiple acqisitions of the same mutex
  are also noted.
---
 .../BlockInCriticalSectionChecker.cpp | 391 ++
 .../Analysis/block-in-critical-section.cpp| 270 +---
 2 files changed, 515 insertions(+), 146 deletions(-)

diff --git 
a/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp 
b/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
index 66e080adb1382b..74ec4b73bd8b5f 100644
--- a/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/BlockInCriticalSectionChecker.cpp
@@ -20,48 +20,180 @@
 #include "clang/StaticAnalyzer/Core/PathSensitive/CallDescription.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
 #include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringExtras.h"
+
+#include 
+#include 
+#include 
 
 using namespace clang;
 using namespace ento;
 
 namespace {
+
+struct CritSectionMarker {
+  const Expr *LockExpr{};
+  const MemRegion *LockReg{};
+
+  void Profile(llvm::FoldingSetNodeID ) const {
+ID.Add(LockExpr);
+ID.Add(LockReg);
+  }
+
+  [[nodiscard]] constexpr bool
+  operator==(const CritSectionMarker ) const noexcept {
+return LockExpr == Other.LockExpr && LockReg == Other.LockReg;
+  }
+  [[nodiscard]] constexpr bool
+  operator!=(const CritSectionMarker ) const noexcept {
+return !(*this == Other);
+  }
+};
+
+class FirstArgMutexDescriptor {
+  CallDescription LockFn;
+  CallDescription UnlockFn;
+
+public:
+  FirstArgMutexDescriptor(CallDescription &, CallDescription &)
+  : LockFn(std::move(LockFn)), UnlockFn(std::move(UnlockFn)) {}
+  [[nodiscard]] bool matchesLock(const CallEvent ) const {
+return LockFn.matches(Call) && Call.getNumArgs() > 0;
+  }
+  [[nodiscard]] bool matchesUnlock(const CallEvent ) const {
+return UnlockFn.matches(Call) && Call.getNumArgs() > 0;
+  }
+  [[nodiscard]] const MemRegion *getLockRegion(const CallEvent ) const {
+return Call.getArgSVal(0).getAsRegion();
+  }
+  [[nodiscard]] const MemRegion *getUnlockRegion(const CallEvent ) const {
+return Call.getArgSVal(0).getAsRegion();
+  }
+};
+
+class MemberMutexDescriptor {
+  CallDescription LockFn;
+  CallDescription UnlockFn;
+
+public:
+  MemberMutexDescriptor(CallDescription &, CallDescription &)
+  : LockFn(std::move(LockFn)), UnlockFn(std::move(UnlockFn)) {}
+  [[nodiscard]] bool matchesLock(const CallEvent ) const {
+return LockFn.matches(Call);
+  }
+  bool matchesUnlock(const CallEvent ) const {
+return UnlockFn.matches(Call);
+  }
+  [[nodiscard]] const MemRegion *getLockRegion(const CallEvent ) const {
+return cast(Call).getCXXThisVal().getAsRegion();
+  }
+  [[nodiscard]] const MemRegion *getUnlockRegion(const CallEvent ) const {
+return cast(Call).getCXXThisVal().getAsRegion();
+  }
+};
+
+class RAIIMutexDescriptor {
+  mutable const IdentifierInfo *Guard{};
+  mutable bool IdentifierInfoInitialized{};
+  mutable llvm::SmallString<32> GuardName{};
+
+  void initIdentifierInfo(const CallEvent ) const {
+if (!IdentifierInfoInitialized) {
+  // In case of checking C code, or when the corresponding headers are not
+  // included, we might end up query the identifier table every time when
+  // this function is called instead of early returning it. To avoid this, 
a
+  // bool variable (IdentifierInfoInitialized) is used and the function 
will
+  // be run only once.
+  Guard = ()->getASTContext().Idents.get(
+  GuardName);
+  IdentifierInfoInitialized = true;
+}
+  }
+
+public:
+  RAIIMutexDescriptor(StringRef GuardName) : GuardName(GuardName) {}
+  [[nodiscard]] bool matchesLock(const CallEvent 

[clang] [clang][dataflow] Make optional checker work for types derived from optional. (PR #84138)

2024-03-18 Thread via cfe-commits


@@ -64,39 +64,117 @@ static bool hasOptionalClassName(const CXXRecordDecl ) {
   return false;
 }
 
+static const CXXRecordDecl *getOptionalBaseClass(const CXXRecordDecl *RD) {
+  if (RD == nullptr)
+return nullptr;
+  if (hasOptionalClassName(*RD))
+return RD;
+
+  if (!RD->hasDefinition())
+return nullptr;
+
+  for (const CXXBaseSpecifier  : RD->bases())
+if (const CXXRecordDecl *BaseClass =
+getOptionalBaseClass(Base.getType()->getAsCXXRecordDecl()))
+  return BaseClass;
+
+  return nullptr;
+}
+
 namespace {
 
 using namespace ::clang::ast_matchers;
 using LatticeTransferState = TransferState;
 
-AST_MATCHER(CXXRecordDecl, hasOptionalClassNameMatcher) {
-  return hasOptionalClassName(Node);
+AST_MATCHER(CXXRecordDecl, optionalClass) { return hasOptionalClassName(Node); 
}
+
+AST_MATCHER(CXXRecordDecl, optionalOrDerivedClass) {
+  return getOptionalBaseClass() != nullptr;
 }
 
-DeclarationMatcher optionalClass() {
-  return classTemplateSpecializationDecl(
-  hasOptionalClassNameMatcher(),
-  hasTemplateArgument(0, refersToType(type().bind("T";
+auto desugarsToOptionalType() {
+  return hasUnqualifiedDesugaredType(
+  recordType(hasDeclaration(cxxRecordDecl(optionalClass();
 }
 
-auto optionalOrAliasType() {
+auto desugarsToOptionalOrDerivedType() {
   return hasUnqualifiedDesugaredType(
-  recordType(hasDeclaration(optionalClass(;
+  recordType(hasDeclaration(cxxRecordDecl(optionalOrDerivedClass();
 }
 
-/// Matches any of the spellings of the optional types and sugar, aliases, etc.
-auto hasOptionalType() { return hasType(optionalOrAliasType()); }
+auto hasOptionalType() { return hasType(desugarsToOptionalType()); }
+
+/// Matches any of the spellings of the optional types and sugar, aliases,
+/// derived classes, etc.
+auto hasOptionalOrDerivedType() {
+  return hasType(desugarsToOptionalOrDerivedType());
+}
+
+QualType getPublicType(const Expr *E) {
+  auto *Cast = dyn_cast(E->IgnoreParens());
+  if (Cast == nullptr || Cast->getCastKind() != CK_UncheckedDerivedToBase) {
+QualType Ty = E->getType();
+if (Ty->isPointerType())
+  return Ty->getPointeeType();
+return Ty;
+  }
+
+  QualType Ty = getPublicType(Cast->getSubExpr());
+
+  // Is `Ty` the type of `*this`? In this special case, we can upcast to the
+  // base class even if the base is non-public.
+  bool TyIsThisType = isa(Cast->getSubExpr());
+
+  for (const CXXBaseSpecifier *Base : Cast->path()) {
+if (Base->getAccessSpecifier() != AS_public && !TyIsThisType)
+  break;
+Ty = Base->getType();
+TyIsThisType = false;
+  }

martinboehme wrote:

> Is the idea that we want the last in the list of base classes?

Exactly. I've added comments that will hopefully make it clearer what is going 
on here.

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


[clang] f362e12 - [clang-format] Make header self-contained

2024-03-18 Thread Benjamin Kramer via cfe-commits

Author: Benjamin Kramer
Date: 2024-03-18T11:23:38+01:00
New Revision: f362e12aab9ce07b836a2622fc987cda8b6ab6f8

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

LOG: [clang-format] Make header self-contained

These includes were removed in 426e6945897afbec01c042bec4771522a2aac176

Added: 


Modified: 
clang/lib/Format/FormatInternal.h

Removed: 




diff  --git a/clang/lib/Format/FormatInternal.h 
b/clang/lib/Format/FormatInternal.h
index 87974a853365c6..60c5bf6b786b04 100644
--- a/clang/lib/Format/FormatInternal.h
+++ b/clang/lib/Format/FormatInternal.h
@@ -15,6 +15,11 @@
 #ifndef LLVM_CLANG_LIB_FORMAT_FORMATINTERNAL_H
 #define LLVM_CLANG_LIB_FORMAT_FORMATINTERNAL_H
 
+#include "clang/Basic/LLVM.h"
+#include "clang/Format/Format.h"
+#include "clang/Tooling/Core/Replacement.h"
+#include 
+
 namespace clang {
 namespace format {
 namespace internal {



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


[clang] 92122b0 - Revert "[RemoveDIs] Update Clang front end to handle DbgRecords (#84756)"

2024-03-18 Thread Orlando Cazalet-Hyams via cfe-commits

Author: Orlando Cazalet-Hyams
Date: 2024-03-18T10:13:35Z
New Revision: 92122b0b4b514ea6c081e428f47ef1bf9d4f0f17

URL: 
https://github.com/llvm/llvm-project/commit/92122b0b4b514ea6c081e428f47ef1bf9d4f0f17
DIFF: 
https://github.com/llvm/llvm-project/commit/92122b0b4b514ea6c081e428f47ef1bf9d4f0f17.diff

LOG: Revert "[RemoveDIs] Update Clang front end to handle DbgRecords (#84756)"

This reverts commit 6f60ad7e9a3508f19d54c827cf11f7930a0685ee.

Buildbots: https://lab.llvm.org/buildbot/#/builders/196/builds/47206

Added: 


Modified: 
clang/lib/CodeGen/CGBlocks.cpp
clang/lib/CodeGen/CGStmtOpenMP.cpp
clang/test/CodeGenObjC/debug-info-blocks.m

Removed: 




diff  --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp
index 768b786c6426df..0cbace7b7f7bbd 100644
--- a/clang/lib/CodeGen/CGBlocks.cpp
+++ b/clang/lib/CodeGen/CGBlocks.cpp
@@ -1540,10 +1540,7 @@ llvm::Function *CodeGenFunction::GenerateBlockFunction(
   llvm::BasicBlock *resume = Builder.GetInsertBlock();
 
   // Go back to the entry.
-  if (entry_ptr->getNextNonDebugInstruction())
-entry_ptr = entry_ptr->getNextNonDebugInstruction()->getIterator();
-  else 
-entry_ptr = entry->end();
+  ++entry_ptr;
   Builder.SetInsertPoint(entry, entry_ptr);
 
   // Emit debug information for all the DeclRefExprs.

diff  --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp 
b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index d7c18146b71b16..452ce6983f6ac1 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -4749,10 +4749,10 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(
   if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
 (void)DI->EmitDeclareOfAutoVariable(SharedVar, ContextValue,
 CGF.Builder, false);
+  llvm::Instruction  = CGF.Builder.GetInsertBlock()->back();
   // Get the call dbg.declare instruction we just created and update
   // its DIExpression to add offset to base address.
-  auto UpdateExpr = [](llvm::LLVMContext , auto *Declare,
-   unsigned Offset) {
+  if (auto DDI = dyn_cast()) {
 SmallVector Ops;
 // Add offset to the base address if non zero.
 if (Offset) {
@@ -4760,21 +4760,9 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(
   Ops.push_back(Offset);
 }
 Ops.push_back(llvm::dwarf::DW_OP_deref);
-Declare->setExpression(llvm::DIExpression::get(Ctx, Ops));
-  };
-  llvm::Instruction  = CGF.Builder.GetInsertBlock()->back();
-  if (auto DDI = dyn_cast())
-UpdateExpr(DDI->getContext(), DDI, Offset);
-  // If we're emitting using the new debug info format into a block
-  // without a terminator, the record will be "trailing".
-  assert(!Last.isTerminator() && "unexpected terminator");
-  if (auto *Marker =
-  CGF.Builder.GetInsertBlock()->getTrailingDPValues()) {
-for (llvm::DPValue  : llvm::reverse(
- llvm::DPValue::filter(Marker->getDbgValueRange( {
-  UpdateExpr(Last.getContext(), , Offset);
-  break;
-}
+auto  = DDI->getContext();
+llvm::DIExpression *DIExpr = llvm::DIExpression::get(Ctx, Ops);
+Last.setOperand(2, llvm::MetadataAsValue::get(Ctx, DIExpr));
   }
 }
   }

diff  --git a/clang/test/CodeGenObjC/debug-info-blocks.m 
b/clang/test/CodeGenObjC/debug-info-blocks.m
index 59171da016da1e..14b29f222fbe8e 100644
--- a/clang/test/CodeGenObjC/debug-info-blocks.m
+++ b/clang/test/CodeGenObjC/debug-info-blocks.m
@@ -5,8 +5,8 @@
 
 // CHECK: define {{.*}}_block_invoke
 // CHECK: store ptr %.block_descriptor, ptr %[[ALLOCA:block.addr]], align
-// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr %d, metadata 
![[D:[0-9]+]], metadata !{{.*}})
 // CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr %[[ALLOCA]], metadata 
![[SELF:[0-9]+]], metadata !{{.*}})
+// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr %d, metadata 
![[D:[0-9]+]], metadata !{{.*}})
 
 // Test that we do emit scope info for the helper functions, and that the
 // parameters to these functions are marked as artificial (so the debugger



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


[clang] 3e4170a - Revert "Fix formatting in #84756"

2024-03-18 Thread Orlando Cazalet-Hyams via cfe-commits

Author: Orlando Cazalet-Hyams
Date: 2024-03-18T10:13:12Z
New Revision: 3e4170a587adb789b77ede799d09139b50ebe5bc

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

LOG: Revert "Fix formatting in #84756"

This reverts commit b097b3dc2ba2517621a5e3da3237a77ed0e7586f.

Buildbots: https://lab.llvm.org/buildbot/#/builders/196/builds/47206

Added: 


Modified: 
clang/lib/CodeGen/CGBlocks.cpp

Removed: 




diff  --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp
index ad0b50d799618e..768b786c6426df 100644
--- a/clang/lib/CodeGen/CGBlocks.cpp
+++ b/clang/lib/CodeGen/CGBlocks.cpp
@@ -1542,7 +1542,7 @@ llvm::Function *CodeGenFunction::GenerateBlockFunction(
   // Go back to the entry.
   if (entry_ptr->getNextNonDebugInstruction())
 entry_ptr = entry_ptr->getNextNonDebugInstruction()->getIterator();
-  else
+  else 
 entry_ptr = entry->end();
   Builder.SetInsertPoint(entry, entry_ptr);
 



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


[clang] b097b3d - Fix formatting in #84756

2024-03-18 Thread Orlando Cazalet-Hyams via cfe-commits

Author: Orlando Cazalet-Hyams
Date: 2024-03-18T10:01:51Z
New Revision: b097b3dc2ba2517621a5e3da3237a77ed0e7586f

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

LOG: Fix formatting in #84756

Added: 


Modified: 
clang/lib/CodeGen/CGBlocks.cpp

Removed: 




diff  --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp
index 768b786c6426df..ad0b50d799618e 100644
--- a/clang/lib/CodeGen/CGBlocks.cpp
+++ b/clang/lib/CodeGen/CGBlocks.cpp
@@ -1542,7 +1542,7 @@ llvm::Function *CodeGenFunction::GenerateBlockFunction(
   // Go back to the entry.
   if (entry_ptr->getNextNonDebugInstruction())
 entry_ptr = entry_ptr->getNextNonDebugInstruction()->getIterator();
-  else 
+  else
 entry_ptr = entry->end();
   Builder.SetInsertPoint(entry, entry_ptr);
 



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


[clang] [RemoveDIs] Update Clang front end to handle DbgRecords (PR #84756)

2024-03-18 Thread Orlando Cazalet-Hyams via cfe-commits

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


[clang] 6f60ad7 - [RemoveDIs] Update Clang front end to handle DbgRecords (#84756)

2024-03-18 Thread via cfe-commits

Author: Orlando Cazalet-Hyams
Date: 2024-03-18T09:59:58Z
New Revision: 6f60ad7e9a3508f19d54c827cf11f7930a0685ee

URL: 
https://github.com/llvm/llvm-project/commit/6f60ad7e9a3508f19d54c827cf11f7930a0685ee
DIFF: 
https://github.com/llvm/llvm-project/commit/6f60ad7e9a3508f19d54c827cf11f7930a0685ee.diff

LOG: [RemoveDIs] Update Clang front end to handle DbgRecords (#84756)

This patch fixes problems that pop up when clang emits DbgRecords
instead of debug intrinsics.

Note: this doesn't mean clang is emitting DbgRecords yet, because the
modules it creates are still always in the old debug mode. That will
come in a future patch.

Depends on #84739

Added: 


Modified: 
clang/lib/CodeGen/CGBlocks.cpp
clang/lib/CodeGen/CGStmtOpenMP.cpp
clang/test/CodeGenObjC/debug-info-blocks.m

Removed: 




diff  --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp
index 0cbace7b7f7bbd..768b786c6426df 100644
--- a/clang/lib/CodeGen/CGBlocks.cpp
+++ b/clang/lib/CodeGen/CGBlocks.cpp
@@ -1540,7 +1540,10 @@ llvm::Function *CodeGenFunction::GenerateBlockFunction(
   llvm::BasicBlock *resume = Builder.GetInsertBlock();
 
   // Go back to the entry.
-  ++entry_ptr;
+  if (entry_ptr->getNextNonDebugInstruction())
+entry_ptr = entry_ptr->getNextNonDebugInstruction()->getIterator();
+  else 
+entry_ptr = entry->end();
   Builder.SetInsertPoint(entry, entry_ptr);
 
   // Emit debug information for all the DeclRefExprs.

diff  --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp 
b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 452ce6983f6ac1..d7c18146b71b16 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -4749,10 +4749,10 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(
   if (CGF.CGM.getCodeGenOpts().hasReducedDebugInfo())
 (void)DI->EmitDeclareOfAutoVariable(SharedVar, ContextValue,
 CGF.Builder, false);
-  llvm::Instruction  = CGF.Builder.GetInsertBlock()->back();
   // Get the call dbg.declare instruction we just created and update
   // its DIExpression to add offset to base address.
-  if (auto DDI = dyn_cast()) {
+  auto UpdateExpr = [](llvm::LLVMContext , auto *Declare,
+   unsigned Offset) {
 SmallVector Ops;
 // Add offset to the base address if non zero.
 if (Offset) {
@@ -4760,9 +4760,21 @@ void CodeGenFunction::EmitOMPTaskBasedDirective(
   Ops.push_back(Offset);
 }
 Ops.push_back(llvm::dwarf::DW_OP_deref);
-auto  = DDI->getContext();
-llvm::DIExpression *DIExpr = llvm::DIExpression::get(Ctx, Ops);
-Last.setOperand(2, llvm::MetadataAsValue::get(Ctx, DIExpr));
+Declare->setExpression(llvm::DIExpression::get(Ctx, Ops));
+  };
+  llvm::Instruction  = CGF.Builder.GetInsertBlock()->back();
+  if (auto DDI = dyn_cast())
+UpdateExpr(DDI->getContext(), DDI, Offset);
+  // If we're emitting using the new debug info format into a block
+  // without a terminator, the record will be "trailing".
+  assert(!Last.isTerminator() && "unexpected terminator");
+  if (auto *Marker =
+  CGF.Builder.GetInsertBlock()->getTrailingDPValues()) {
+for (llvm::DPValue  : llvm::reverse(
+ llvm::DPValue::filter(Marker->getDbgValueRange( {
+  UpdateExpr(Last.getContext(), , Offset);
+  break;
+}
   }
 }
   }

diff  --git a/clang/test/CodeGenObjC/debug-info-blocks.m 
b/clang/test/CodeGenObjC/debug-info-blocks.m
index 14b29f222fbe8e..59171da016da1e 100644
--- a/clang/test/CodeGenObjC/debug-info-blocks.m
+++ b/clang/test/CodeGenObjC/debug-info-blocks.m
@@ -5,8 +5,8 @@
 
 // CHECK: define {{.*}}_block_invoke
 // CHECK: store ptr %.block_descriptor, ptr %[[ALLOCA:block.addr]], align
-// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr %[[ALLOCA]], metadata 
![[SELF:[0-9]+]], metadata !{{.*}})
 // CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr %d, metadata 
![[D:[0-9]+]], metadata !{{.*}})
+// CHECK-NEXT: call void @llvm.dbg.declare(metadata ptr %[[ALLOCA]], metadata 
![[SELF:[0-9]+]], metadata !{{.*}})
 
 // Test that we do emit scope info for the helper functions, and that the
 // parameters to these functions are marked as artificial (so the debugger



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


[clang] [clang][dataflow] Make optional checker work for types derived from optional. (PR #84138)

2024-03-18 Thread via cfe-commits


@@ -64,39 +64,117 @@ static bool hasOptionalClassName(const CXXRecordDecl ) {
   return false;
 }
 
+static const CXXRecordDecl *getOptionalBaseClass(const CXXRecordDecl *RD) {
+  if (RD == nullptr)
+return nullptr;
+  if (hasOptionalClassName(*RD))
+return RD;
+
+  if (!RD->hasDefinition())
+return nullptr;
+
+  for (const CXXBaseSpecifier  : RD->bases())
+if (const CXXRecordDecl *BaseClass =
+getOptionalBaseClass(Base.getType()->getAsCXXRecordDecl()))
+  return BaseClass;
+
+  return nullptr;
+}
+
 namespace {
 
 using namespace ::clang::ast_matchers;
 using LatticeTransferState = TransferState;
 
-AST_MATCHER(CXXRecordDecl, hasOptionalClassNameMatcher) {
-  return hasOptionalClassName(Node);
+AST_MATCHER(CXXRecordDecl, optionalClass) { return hasOptionalClassName(Node); 
}
+
+AST_MATCHER(CXXRecordDecl, optionalOrDerivedClass) {
+  return getOptionalBaseClass() != nullptr;
 }
 
-DeclarationMatcher optionalClass() {
-  return classTemplateSpecializationDecl(
-  hasOptionalClassNameMatcher(),
-  hasTemplateArgument(0, refersToType(type().bind("T";
+auto desugarsToOptionalType() {
+  return hasUnqualifiedDesugaredType(
+  recordType(hasDeclaration(cxxRecordDecl(optionalClass();
 }
 
-auto optionalOrAliasType() {
+auto desugarsToOptionalOrDerivedType() {
   return hasUnqualifiedDesugaredType(
-  recordType(hasDeclaration(optionalClass(;
+  recordType(hasDeclaration(cxxRecordDecl(optionalOrDerivedClass();
 }
 
-/// Matches any of the spellings of the optional types and sugar, aliases, etc.
-auto hasOptionalType() { return hasType(optionalOrAliasType()); }
+auto hasOptionalType() { return hasType(desugarsToOptionalType()); }
+
+/// Matches any of the spellings of the optional types and sugar, aliases,
+/// derived classes, etc.
+auto hasOptionalOrDerivedType() {
+  return hasType(desugarsToOptionalOrDerivedType());
+}
+
+QualType getPublicType(const Expr *E) {
+  auto *Cast = dyn_cast(E->IgnoreParens());
+  if (Cast == nullptr || Cast->getCastKind() != CK_UncheckedDerivedToBase) {
+QualType Ty = E->getType();
+if (Ty->isPointerType())
+  return Ty->getPointeeType();
+return Ty;
+  }
+
+  QualType Ty = getPublicType(Cast->getSubExpr());
+
+  // Is `Ty` the type of `*this`? In this special case, we can upcast to the
+  // base class even if the base is non-public.
+  bool TyIsThisType = isa(Cast->getSubExpr());
+
+  for (const CXXBaseSpecifier *Base : Cast->path()) {

martinboehme wrote:

I've submitted https://github.com/llvm/llvm-project/pull/85623 to add 
documentation.

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


[clang] [clang][NFC] Add documentation for `CastExpr::path()`. (PR #85623)

2024-03-18 Thread via cfe-commits

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


[clang] [clang][NFC] Add documentation for `CastExpr::path()`. (PR #85623)

2024-03-18 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: None (martinboehme)


Changes

This didn't have any documentation, so I had to do some experimenting in
godbolt when I used this in https://github.com/llvm/llvm-project/pull/84138,
and my reviewer later also had some
[questions](https://github.com/llvm/llvm-project/pull/84138#discussion_r1524855434)
about this, so I figured it would be worth adding documentation.


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


1 Files Affected:

- (modified) clang/include/clang/AST/Expr.h (+9) 


``diff
diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 446bec4081e869..8c4db4828477d0 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -3552,6 +3552,15 @@ class CastExpr : public Expr {
   /// function that it invokes.
   NamedDecl *getConversionFunction() const;
 
+  /// Path through the class hierarchy taken by a `DerivedToBase` or
+  /// `UncheckedDerivedToBase` cast. For each derived-to-base edge in the path,
+  /// the path contains a `CXXBaseSpecifier` for the base class of that edge;
+  /// the entries are ordered from derived class to base class.
+  ///
+  /// For example, given classes `Base`, `Intermediate : public Base` and
+  /// `Derived : public Intermediate`, the path for a cast from `Derived *` to
+  /// `Base *` contains two entries: One for `Intermediate`, and one for 
`Base`,
+  /// in that order.
   typedef CXXBaseSpecifier **path_iterator;
   typedef const CXXBaseSpecifier *const *path_const_iterator;
   bool path_empty() const { return path_size() == 0; }

``




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


[clang] [clang][NFC] Add documentation for `CastExpr::path()`. (PR #85623)

2024-03-18 Thread via cfe-commits

https://github.com/martinboehme created 
https://github.com/llvm/llvm-project/pull/85623

This didn't have any documentation, so I had to do some experimenting in
godbolt when I used this in https://github.com/llvm/llvm-project/pull/84138,
and my reviewer later also had some
[questions](https://github.com/llvm/llvm-project/pull/84138#discussion_r1524855434)
about this, so I figured it would be worth adding documentation.


>From 369410916bd61671f81702c4654bd48bfc3c6c53 Mon Sep 17 00:00:00 2001
From: Martin Braenne 
Date: Mon, 18 Mar 2024 09:51:23 +
Subject: [PATCH] [clang][NFC] Add documentation for `CastExpr::path()`.

This didn't have any documentation, so I had to do some experimenting in
godbolt when I used this in https://github.com/llvm/llvm-project/pull/84138,
and my reviewer later also had some
[questions](https://github.com/llvm/llvm-project/pull/84138#discussion_r1524855434)
about this, so I figured it would be worth adding documentation.
---
 clang/include/clang/AST/Expr.h | 9 +
 1 file changed, 9 insertions(+)

diff --git a/clang/include/clang/AST/Expr.h b/clang/include/clang/AST/Expr.h
index 446bec4081e869..8c4db4828477d0 100644
--- a/clang/include/clang/AST/Expr.h
+++ b/clang/include/clang/AST/Expr.h
@@ -3552,6 +3552,15 @@ class CastExpr : public Expr {
   /// function that it invokes.
   NamedDecl *getConversionFunction() const;
 
+  /// Path through the class hierarchy taken by a `DerivedToBase` or
+  /// `UncheckedDerivedToBase` cast. For each derived-to-base edge in the path,
+  /// the path contains a `CXXBaseSpecifier` for the base class of that edge;
+  /// the entries are ordered from derived class to base class.
+  ///
+  /// For example, given classes `Base`, `Intermediate : public Base` and
+  /// `Derived : public Intermediate`, the path for a cast from `Derived *` to
+  /// `Base *` contains two entries: One for `Intermediate`, and one for 
`Base`,
+  /// in that order.
   typedef CXXBaseSpecifier **path_iterator;
   typedef const CXXBaseSpecifier *const *path_const_iterator;
   bool path_empty() const { return path_size() == 0; }

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


[clang] [RemoveDIs] Update Clang front end to handle DbgRecords (PR #84756)

2024-03-18 Thread Stephen Tozer via cfe-commits

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

It's been a bit without any comments, probably safe now to land this.

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


[clang] [clang][Interp] Merge ByteCodeExprGen and ByteCodeStmtGen (PR #83683)

2024-03-18 Thread via cfe-commits
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= 
Message-ID:
In-Reply-To: 


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 5143a1241362616840af826d18c067025dae 
bac423c77cd62604f6bd27d258a91832fc0bc0d2 -- clang/lib/AST/Interp/Context.cpp 
clang/lib/AST/Interp/EvalEmitter.h clang/lib/AST/Interp/Program.cpp 
clang/test/AST/Interp/literals.cpp clang/lib/AST/Interp/Compiler.cpp 
clang/lib/AST/Interp/Compiler.h
``





View the diff from clang-format here.


``diff
diff --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index 60d3d899d2..e04c04cd73 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -1815,8 +1815,7 @@ bool Compiler::VisitTypeTraitExpr(const 
TypeTraitExpr *E) {
 }
 
 template 
-bool Compiler::VisitArrayTypeTraitExpr(
-const ArrayTypeTraitExpr *E) {
+bool Compiler::VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) {
   if (DiscardResult)
 return true;
   return this->emitConst(E->getValue(), E);
@@ -2290,8 +2289,7 @@ bool Compiler::VisitPseudoObjectExpr(const 
PseudoObjectExpr *E) {
 }
 
 template 
-bool Compiler::VisitPackIndexingExpr(
-const PackIndexingExpr *E) {
+bool Compiler::VisitPackIndexingExpr(const PackIndexingExpr *E) {
   return this->delegate(E->getSelectedExpr());
 }
 
@@ -3815,8 +3813,7 @@ bool Compiler::VisitUnaryOperator(const 
UnaryOperator *E) {
 }
 
 template 
-bool Compiler::VisitComplexUnaryOperator(
-const UnaryOperator *E) {
+bool Compiler::VisitComplexUnaryOperator(const UnaryOperator *E) {
   const Expr *SubExpr = E->getSubExpr();
   assert(SubExpr->getType()->isAnyComplexType());
 
@@ -4129,9 +4126,8 @@ bool Compiler::emitComplexBoolCast(const Expr 
*E) {
 }
 
 template 
-bool Compiler::emitComplexComparison(const Expr *LHS,
- const Expr *RHS,
- const BinaryOperator *E) {
+bool Compiler::emitComplexComparison(const Expr *LHS, const Expr *RHS,
+  const BinaryOperator *E) {
   assert(E->isComparisonOp());
   assert(!Initializing);
   assert(!DiscardResult);

``




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


[clang] [Driver,AArch64] Remove AArch32-specific -m[no-]unaligned-access (PR #85441)

2024-03-18 Thread Peter Smith via cfe-commits

https://github.com/smithp35 commented:

If possible I would prefer to keep -m[no-]unaligned-access for AArch64.

The history of this option name derives from Arm's proprietary compiler 
https://developer.arm.com/documentation/dui0472/m/Compiler-Command-line-Options/--unaligned-accessno-unaligned-access
 which has been carried forward for the LLVM based Arm Compiler 
https://developer.arm.com/documentation/101754/0621/armclang-Reference/armclang-Command-line-Options/-munaligned-access---mno-unaligned-access?lang=en

Yes the proprietary compiler can always put this back as a downstream change. 
However we are trying to introduce more use of upstream clang and it would help 
migration of these projects if they didn't need to change.

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


[clang] [clang][dataflow] Fix `getResultObjectLocation()` on `CXXDefaultArgExpr`. (PR #85072)

2024-03-18 Thread via cfe-commits

https://github.com/martinboehme updated 
https://github.com/llvm/llvm-project/pull/85072

>From dfa4da9e6a3d8a343e1fdf0ed72670148fec5a59 Mon Sep 17 00:00:00 2001
From: Martin Braenne 
Date: Thu, 14 Mar 2024 08:46:06 +
Subject: [PATCH 1/2] [clang][dataflow] Fix `getResultObjectLocation()` on
 `CXXDefaultArgExpr`.

This patch includes a test that causes an assertion failure without the other
changes in this patch.
---
 .../FlowSensitive/DataflowEnvironment.cpp |  1 +
 clang/lib/Analysis/FlowSensitive/Transfer.cpp |  6 
 .../Analysis/FlowSensitive/TransferTest.cpp   | 30 +++
 3 files changed, 37 insertions(+)

diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp 
b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
index 1d2bd9a9b08af3..cc1ebd511191a9 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -771,6 +771,7 @@ static bool isOriginalRecordConstructor(const Expr 
) {
 return !Init->isSemanticForm() || !Init->isTransparent();
   return isa(RecordPRValue) || isa(RecordPRValue) 
||
  isa(RecordPRValue) ||
+ isa(RecordPRValue) ||
  isa(RecordPRValue) ||
  // The framework currently does not propagate the objects created in
  // the two branches of a `ConditionalOperator` because there is no way
diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp 
b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
index 04aa2831df0558..ea166fcdb89e20 100644
--- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -450,6 +450,12 @@ class TransferVisitor : public 
ConstStmtVisitor {
 Env.setStorageLocation(*S, *MemberLoc);
   }
 
+  void VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *S) {
+const Expr *ArgExpr = S->getExpr();
+assert(ArgExpr != nullptr);
+propagateValueOrStorageLocation(*ArgExpr, *S, Env);
+  }
+
   void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *S) {
 const Expr *InitExpr = S->getExpr();
 assert(InitExpr != nullptr);
diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp 
b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
index a8c282f140b4cd..86c7f32f0104be 100644
--- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -2924,6 +2924,36 @@ TEST(TransferTest, ResultObjectLocation) {
   });
 }
 
+TEST(TransferTest, ResultObjectLocationForDefaultArgExpr) {
+  std::string Code = R"(
+struct S {};
+void funcWithDefaultArg(S s = S());
+void target() {
+  funcWithDefaultArg();
+  // [[p]]
+}
+  )";
+
+  using ast_matchers::cxxDefaultArgExpr;
+  using ast_matchers::match;
+  using ast_matchers::selectFirst;
+  runDataflow(
+  Code,
+  [](const llvm::StringMap> ,
+ ASTContext ) {
+const Environment  = getEnvironmentAtAnnotation(Results, "p");
+
+auto *DefaultArg = selectFirst(
+"default_arg",
+match(cxxDefaultArgExpr().bind("default_arg"), ASTCtx));
+ASSERT_NE(DefaultArg, nullptr);
+
+// The values for default arguments aren't modeled; we merely verify
+// that we can get a result object location for a default arg.
+Env.getResultObjectLocation(*DefaultArg);
+  });
+}
+
 TEST(TransferTest, ResultObjectLocationForDefaultInitExpr) {
   std::string Code = R"(
 struct S {};

>From 5abe5edeca3641a6d797f9450fe2b201c01baa9c Mon Sep 17 00:00:00 2001
From: Martin Braenne 
Date: Mon, 18 Mar 2024 09:37:04 +
Subject: [PATCH 2/2] fixup! [clang][dataflow] Fix `getResultObjectLocation()`
 on `CXXDefaultArgExpr`.

---
 clang/lib/Analysis/FlowSensitive/Transfer.cpp | 13 +
 1 file changed, 13 insertions(+)

diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp 
b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
index ea166fcdb89e20..8b44bcb4e3caeb 100644
--- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -454,6 +454,19 @@ class TransferVisitor : public 
ConstStmtVisitor {
 const Expr *ArgExpr = S->getExpr();
 assert(ArgExpr != nullptr);
 propagateValueOrStorageLocation(*ArgExpr, *S, Env);
+
+// If this is a prvalue of record type, we consider it to be an "original
+// record constructor", which we always require to have a `RecordValue`.
+// So make sure we have a value if we didn't propagate one above.
+if (S->isPRValue() && S->getType()->isRecordType()) {
+  if (Env.getValue(*S) == nullptr) {
+Value *Val = Env.createValue(S->getType());
+// We're guaranteed to always be able to create a value for record
+// types.
+assert(Val != nullptr);
+Env.setValue(*S, *Val);
+  }
+}
   }
 
   void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *S) {

___
cfe-commits mailing 

[clang] [llvm] Adapted MemRegion::getDescriptiveName to handle ElementRegions (PR #85104)

2024-03-18 Thread via cfe-commits

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


[clang] [llvm] Adapted MemRegion::getDescriptiveName to handle ElementRegions (PR #85104)

2024-03-18 Thread via cfe-commits

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

LGMT, thanks for adding the testcases!

I agree that the "sometimes reports the wrong variable" situation is a very 
significant improvement over the old "always infinite loop" situation; but this 
"convert a symbol to a variable name" step was completely missing from the old 
code, so I think it's relevant to mention that this commit implements it in a 
way that's not entirely correct.

I think it would be good to highlight this limitation with a FIXME comment (and 
perhaps a testcase), but I don't want to significantly delay the resolution of 
the infinite loop bug.

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


[clang] [compiler-rt] [clang][UBSan] Add implicit conversion check for bitfields (PR #75481)

2024-03-18 Thread Axel Lundberg via cfe-commits

Zonotora wrote:

Also, I don't have commit access (first PR here), someone has to commit on my 
behalf!

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


[clang] [clang][dataflow] Model assignment to derived class from base. (PR #85064)

2024-03-18 Thread via cfe-commits


@@ -212,8 +212,23 @@ TEST(TransferTest, CopyRecordFromDerivedToBase) {
   // [[p]]
 }
   )";
+  auto SyntheticFieldCallback = [](QualType Ty) -> llvm::StringMap {
+CXXRecordDecl *ADecl = nullptr;
+if (Ty.getAsString() == "A")
+  ADecl = Ty->getAsCXXRecordDecl();
+else if (Ty.getAsString() == "B")
+  ADecl = Ty->getAsCXXRecordDecl()
+  ->bases_begin()
+  ->getType()
+  ->getAsCXXRecordDecl();
+else
+  return {};
+QualType IntTy = getFieldNamed(ADecl, "i")->getType();
+return {{"synth_int", IntTy}};
+  };
+  // Copy derived to base class.

martinboehme wrote:

This means that the following lines test the case of copying from the derived 
class to the base class, whereas another piece of the test further down tests 
the case of copying from the base class to the derived class. I'm not sure how 
I could word this better -- I've reworded slightly to "Test copying derived to 
base class", as maybe it wasn't clear that I was describing the behavior to be 
tested?

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


[clang] [clang][dataflow] Model assignment to derived class from base. (PR #85064)

2024-03-18 Thread via cfe-commits

https://github.com/martinboehme updated 
https://github.com/llvm/llvm-project/pull/85064

>From 9362adfb0d1a61cb56b897f31fd9f2ead1605383 Mon Sep 17 00:00:00 2001
From: Martin Braenne 
Date: Wed, 13 Mar 2024 12:07:24 +
Subject: [PATCH 1/3] [clang][dataflow] Model assignment to derived class from
 base.

This is a relatively rare case, but

- It's still nice to get this right,
- We can remove the special case for this in `VisitCXXOperatorCallExpr()` (that
  simply bails out), and
- With this in place, I can avoid having to add a similar special case in an
  upcoming patch.
---
 .../clang/Analysis/FlowSensitive/RecordOps.h  |  6 +-
 .../lib/Analysis/FlowSensitive/RecordOps.cpp  | 94 +++
 clang/lib/Analysis/FlowSensitive/Transfer.cpp |  9 --
 .../Analysis/FlowSensitive/RecordOpsTest.cpp  | 46 -
 .../Analysis/FlowSensitive/TransferTest.cpp   | 25 -
 5 files changed, 126 insertions(+), 54 deletions(-)

diff --git a/clang/include/clang/Analysis/FlowSensitive/RecordOps.h 
b/clang/include/clang/Analysis/FlowSensitive/RecordOps.h
index 783e53e980aa2c..8fad45fc11d81e 100644
--- a/clang/include/clang/Analysis/FlowSensitive/RecordOps.h
+++ b/clang/include/clang/Analysis/FlowSensitive/RecordOps.h
@@ -31,7 +31,11 @@ namespace dataflow {
 ///
 /// Requirements:
 ///
-///  `Src` and `Dst` must have the same canonical unqualified type.
+///  Either:
+///- `Src` and `Dest` must have the same canonical unqualified type, or
+///- The type of `Src` must be derived from `Dest`, or
+///- The type of `Dest` must be derived from `Src` (in this case, any 
fields
+///  that are only present in `Dest` are not overwritten).
 void copyRecord(RecordStorageLocation , RecordStorageLocation ,
 Environment );
 
diff --git a/clang/lib/Analysis/FlowSensitive/RecordOps.cpp 
b/clang/lib/Analysis/FlowSensitive/RecordOps.cpp
index da4dd6dc078515..4fc4c15a07a1ce 100644
--- a/clang/lib/Analysis/FlowSensitive/RecordOps.cpp
+++ b/clang/lib/Analysis/FlowSensitive/RecordOps.cpp
@@ -14,18 +14,52 @@
 
 #define DEBUG_TYPE "dataflow"
 
-void clang::dataflow::copyRecord(RecordStorageLocation ,
- RecordStorageLocation , Environment ) 
{
+namespace clang::dataflow {
+
+static void copyField(const ValueDecl *Field, StorageLocation *SrcFieldLoc,
+  StorageLocation *DstFieldLoc, RecordStorageLocation ,
+  Environment ) {
+  assert(Field->getType()->isReferenceType() ||
+ (SrcFieldLoc != nullptr && DstFieldLoc != nullptr));
+
+  if (Field->getType()->isRecordType()) {
+copyRecord(cast(*SrcFieldLoc),
+   cast(*DstFieldLoc), Env);
+  } else if (Field->getType()->isReferenceType()) {
+Dst.setChild(*Field, SrcFieldLoc);
+  } else {
+if (Value *Val = Env.getValue(*SrcFieldLoc))
+  Env.setValue(*DstFieldLoc, *Val);
+else
+  Env.clearValue(*DstFieldLoc);
+  }
+}
+
+static void copySyntheticField(QualType FieldType, StorageLocation 
,
+   StorageLocation , Environment ) 
{
+  if (FieldType->isRecordType()) {
+copyRecord(cast(SrcFieldLoc),
+   cast(DstFieldLoc), Env);
+  } else {
+if (Value *Val = Env.getValue(SrcFieldLoc))
+  Env.setValue(DstFieldLoc, *Val);
+else
+  Env.clearValue(DstFieldLoc);
+  }
+}
+
+void copyRecord(RecordStorageLocation , RecordStorageLocation ,
+Environment ) {
   auto SrcType = Src.getType().getCanonicalType().getUnqualifiedType();
   auto DstType = Dst.getType().getCanonicalType().getUnqualifiedType();
 
   auto SrcDecl = SrcType->getAsCXXRecordDecl();
   auto DstDecl = DstType->getAsCXXRecordDecl();
 
-  bool compatibleTypes =
+  [[maybe_unused]] bool compatibleTypes =
   SrcType == DstType ||
-  (SrcDecl && DstDecl && SrcDecl->isDerivedFrom(DstDecl));
-  (void)compatibleTypes;
+  (SrcDecl != nullptr && DstDecl != nullptr &&
+   (SrcDecl->isDerivedFrom(DstDecl) || DstDecl->isDerivedFrom(SrcDecl)));
 
   LLVM_DEBUG({
 if (!compatibleTypes) {
@@ -35,45 +69,27 @@ void clang::dataflow::copyRecord(RecordStorageLocation ,
   });
   assert(compatibleTypes);
 
-  for (auto [Field, DstFieldLoc] : Dst.children()) {
-StorageLocation *SrcFieldLoc = Src.getChild(*Field);
-
-assert(Field->getType()->isReferenceType() ||
-   (SrcFieldLoc != nullptr && DstFieldLoc != nullptr));
-
-if (Field->getType()->isRecordType()) {
-  copyRecord(cast(*SrcFieldLoc),
- cast(*DstFieldLoc), Env);
-} else if (Field->getType()->isReferenceType()) {
-  Dst.setChild(*Field, SrcFieldLoc);
-} else {
-  if (Value *Val = Env.getValue(*SrcFieldLoc))
-Env.setValue(*DstFieldLoc, *Val);
-  else
-Env.clearValue(*DstFieldLoc);
-}
-  }
-
-  for (const auto &[Name, SynthFieldLoc] : Src.synthetic_fields()) {
-if (SynthFieldLoc->getType()->isRecordType()) {
-  copyRecord(*cast(SynthFieldLoc),
- 

[clang] [llvm] Use timeTraceAsyncProfilerBegin for Source span (PR #83961)

2024-03-18 Thread Takuto Ikuta via cfe-commits

https://github.com/atetubou updated 
https://github.com/llvm/llvm-project/pull/83961

>From 6e2521733cdc49971529977cb81c731dd2816b42 Mon Sep 17 00:00:00 2001
From: Takuto Ikuta 
Date: Mon, 18 Mar 2024 18:03:00 +0900
Subject: [PATCH 1/2] git squash commit for support_new_trace.

90ebde07f7fa426a37dd4bdc362e1a809aaf0844
Expose TimeTraceProfiler for Async Events

8bf598f71d37f5404671dbb1840c7bed0ed87b42
assert
---
 llvm/include/llvm/Support/TimeProfiler.h|  34 +--
 llvm/lib/Support/TimeProfiler.cpp   | 101 ++--
 llvm/unittests/Support/TimeProfilerTest.cpp |  11 +++
 3 files changed, 107 insertions(+), 39 deletions(-)

diff --git a/llvm/include/llvm/Support/TimeProfiler.h 
b/llvm/include/llvm/Support/TimeProfiler.h
index 454a65f70231f4..31f7df10916db9 100644
--- a/llvm/include/llvm/Support/TimeProfiler.h
+++ b/llvm/include/llvm/Support/TimeProfiler.h
@@ -86,6 +86,8 @@ class raw_pwrite_stream;
 struct TimeTraceProfiler;
 TimeTraceProfiler *getTimeTraceProfilerInstance();
 
+struct TimeTraceProfilerEntry;
+
 /// Initialize the time trace profiler.
 /// This sets up the global \p TimeTraceProfilerInstance
 /// variable to be the profiler instance.
@@ -120,19 +122,30 @@ Error timeTraceProfilerWrite(StringRef PreferredFileName,
 /// Profiler copies the string data, so the pointers can be given into
 /// temporaries. Time sections can be hierarchical; every Begin must have a
 /// matching End pair but they can nest.
-void timeTraceProfilerBegin(StringRef Name, StringRef Detail);
-void timeTraceProfilerBegin(StringRef Name,
-llvm::function_ref Detail);
+TimeTraceProfilerEntry *timeTraceProfilerBegin(StringRef Name,
+   StringRef Detail);
+TimeTraceProfilerEntry *
+timeTraceProfilerBegin(StringRef Name,
+   llvm::function_ref Detail);
+
+/// Manually begin a time section, with the given \p Name and \p Detail.
+/// This starts Async Events having \p Name as a category which is shown
+/// separately from other traces. See
+/// 
https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview#heading=h.jh64i9l3vwa1
+/// for more details.
+TimeTraceProfilerEntry *timeTraceAsyncProfilerBegin(StringRef Name,
+StringRef Detail);
 
 /// Manually end the last time section.
 void timeTraceProfilerEnd();
+void timeTraceProfilerEnd(TimeTraceProfilerEntry *E);
 
 /// The TimeTraceScope is a helper class to call the begin and end functions
 /// of the time trace profiler.  When the object is constructed, it begins
 /// the section; and when it is destroyed, it stops it. If the time profiler
 /// is not initialized, the overhead is a single branch.
-struct TimeTraceScope {
-
+class TimeTraceScope {
+public:
   TimeTraceScope() = delete;
   TimeTraceScope(const TimeTraceScope &) = delete;
   TimeTraceScope =(const TimeTraceScope &) = delete;
@@ -141,20 +154,23 @@ struct TimeTraceScope {
 
   TimeTraceScope(StringRef Name) {
 if (getTimeTraceProfilerInstance() != nullptr)
-  timeTraceProfilerBegin(Name, StringRef(""));
+  Entry = timeTraceProfilerBegin(Name, StringRef(""));
   }
   TimeTraceScope(StringRef Name, StringRef Detail) {
 if (getTimeTraceProfilerInstance() != nullptr)
-  timeTraceProfilerBegin(Name, Detail);
+  Entry = timeTraceProfilerBegin(Name, Detail);
   }
   TimeTraceScope(StringRef Name, llvm::function_ref Detail) {
 if (getTimeTraceProfilerInstance() != nullptr)
-  timeTraceProfilerBegin(Name, Detail);
+  Entry = timeTraceProfilerBegin(Name, Detail);
   }
   ~TimeTraceScope() {
 if (getTimeTraceProfilerInstance() != nullptr)
-  timeTraceProfilerEnd();
+  timeTraceProfilerEnd(Entry);
   }
+
+private:
+  TimeTraceProfilerEntry *Entry = nullptr;
 };
 
 } // end namespace llvm
diff --git a/llvm/lib/Support/TimeProfiler.cpp 
b/llvm/lib/Support/TimeProfiler.cpp
index 4d625b3eb5b170..092028dd2a5b34 100644
--- a/llvm/lib/Support/TimeProfiler.cpp
+++ b/llvm/lib/Support/TimeProfiler.cpp
@@ -11,6 +11,7 @@
 
//===--===//
 
 #include "llvm/Support/TimeProfiler.h"
+#include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/STLFunctionalExtras.h"
 #include "llvm/ADT/StringMap.h"
 #include "llvm/Support/JSON.h"
@@ -20,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -64,17 +66,19 @@ using CountAndDurationType = std::pair;
 using NameAndCountAndDurationType =
 std::pair;
 
+} // anonymous namespace
+
 /// Represents an open or completed time section entry to be captured.
-struct TimeTraceProfilerEntry {
+struct llvm::TimeTraceProfilerEntry {
   const TimePointType Start;
   TimePointType End;
   const std::string Name;
   const std::string Detail;
-
+  const bool AsyncEvent = false;
   TimeTraceProfilerEntry(TimePointType &, TimePointType &, std::string &,
- 

[clang] [clang][dataflow] Model assignment to derived class from base. (PR #85064)

2024-03-18 Thread via cfe-commits


@@ -35,45 +69,27 @@ void clang::dataflow::copyRecord(RecordStorageLocation ,
   });
   assert(compatibleTypes);
 
-  for (auto [Field, DstFieldLoc] : Dst.children()) {
-StorageLocation *SrcFieldLoc = Src.getChild(*Field);
-
-assert(Field->getType()->isReferenceType() ||
-   (SrcFieldLoc != nullptr && DstFieldLoc != nullptr));
-
-if (Field->getType()->isRecordType()) {
-  copyRecord(cast(*SrcFieldLoc),
- cast(*DstFieldLoc), Env);
-} else if (Field->getType()->isReferenceType()) {
-  Dst.setChild(*Field, SrcFieldLoc);
-} else {
-  if (Value *Val = Env.getValue(*SrcFieldLoc))
-Env.setValue(*DstFieldLoc, *Val);
-  else
-Env.clearValue(*DstFieldLoc);
-}
-  }
-
-  for (const auto &[Name, SynthFieldLoc] : Src.synthetic_fields()) {
-if (SynthFieldLoc->getType()->isRecordType()) {
-  copyRecord(*cast(SynthFieldLoc),
- cast(Dst.getSyntheticField(Name)), 
Env);
-} else {
-  if (Value *Val = Env.getValue(*SynthFieldLoc))
-Env.setValue(Dst.getSyntheticField(Name), *Val);
-  else
-Env.clearValue(Dst.getSyntheticField(Name));
-}
+  if (SrcType == DstType || (SrcDecl != nullptr && DstDecl != nullptr &&
+ SrcDecl->isDerivedFrom(DstDecl))) {
+for (auto [Field, DstFieldLoc] : Dst.children())
+  copyField(Field, Src.getChild(*Field), DstFieldLoc, Dst, Env);
+for (const auto &[Name, DstFieldLoc] : Dst.synthetic_fields())
+  copySyntheticField(DstFieldLoc->getType(), Src.getSyntheticField(Name),
+ *DstFieldLoc, Env);
+  } else {
+for (auto [Field, SrcFieldLoc] : Src.children())
+  copyField(Field, SrcFieldLoc, Dst.getChild(*Field), Dst, Env);
+for (const auto &[Name, SrcFieldLoc] : Src.synthetic_fields())
+  copySyntheticField(SrcFieldLoc->getType(), *SrcFieldLoc,

martinboehme wrote:

No, this is just a convention, but I'm not sure this is documented anywhere. 
I'll send a PR documenting this.

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


[clang] [compiler-rt] [clang][UBSan] Add implicit conversion check for bitfields (PR #75481)

2024-03-18 Thread Axel Lundberg via cfe-commits

https://github.com/Zonotora updated 
https://github.com/llvm/llvm-project/pull/75481

>From 42207b6369b22db7e8400f290be8c6ee75a5278a Mon Sep 17 00:00:00 2001
From: Zonotora 
Date: Sat, 16 Dec 2023 19:33:21 +0100
Subject: [PATCH 1/3] [clang] Extract negativity check lambda to function

---
 clang/lib/CodeGen/CGExprScalar.cpp | 41 ++
 1 file changed, 19 insertions(+), 22 deletions(-)

diff --git a/clang/lib/CodeGen/CGExprScalar.cpp 
b/clang/lib/CodeGen/CGExprScalar.cpp
index 8536570087ad0f..74d94259572dc2 100644
--- a/clang/lib/CodeGen/CGExprScalar.cpp
+++ b/clang/lib/CodeGen/CGExprScalar.cpp
@@ -1103,6 +1103,21 @@ void ScalarExprEmitter::EmitIntegerTruncationCheck(Value 
*Src, QualType SrcType,
 {Src, Dst});
 }
 
+static llvm::Value *EmitIsNegativeTestHelper(Value *V, QualType VType,
+ const char *Name,
+ CGBuilderTy ) {
+  bool VSigned = VType->isSignedIntegerOrEnumerationType();
+  llvm::Type *VTy = V->getType();
+  if (!VSigned) {
+// If the value is unsigned, then it is never negative.
+return llvm::ConstantInt::getFalse(VTy->getContext());
+  }
+  llvm::Constant *Zero = llvm::ConstantInt::get(VTy, 0);
+  return Builder.CreateICmp(llvm::ICmpInst::ICMP_SLT, V, Zero,
+llvm::Twine(Name) + "." + V->getName() +
+".negativitycheck");
+};
+
 // Should be called within CodeGenFunction::SanitizerScope RAII scope.
 // Returns 'i1 false' when the conversion Src -> Dst changed the sign.
 static std::pair Value * {
-// Is this value a signed type?
-bool VSigned = VType->isSignedIntegerOrEnumerationType();
-llvm::Type *VTy = V->getType();
-if (!VSigned) {
-  // If the value is unsigned, then it is never negative.
-  // FIXME: can we encounter non-scalar VTy here?
-  return llvm::ConstantInt::getFalse(VTy->getContext());
-}
-// Get the zero of the same type with which we will be comparing.
-llvm::Constant *Zero = llvm::ConstantInt::get(VTy, 0);
-// %V.isnegative = icmp slt %V, 0
-// I.e is %V *strictly* less than zero, does it have negative value?
-return Builder.CreateICmp(llvm::ICmpInst::ICMP_SLT, V, Zero,
-  llvm::Twine(Name) + "." + V->getName() +
-  ".negativitycheck");
-  };
-
   // 1. Was the old Value negative?
-  llvm::Value *SrcIsNegative = EmitIsNegativeTest(Src, SrcType, "src");
+  llvm::Value *SrcIsNegative =
+  EmitIsNegativeTestHelper(Src, SrcType, "src", Builder);
   // 2. Is the new Value negative?
-  llvm::Value *DstIsNegative = EmitIsNegativeTest(Dst, DstType, "dst");
+  llvm::Value *DstIsNegative =
+  EmitIsNegativeTestHelper(Dst, DstType, "dst", Builder);
   // 3. Now, was the 'negativity status' preserved during the conversion?
   //NOTE: conversion from negative to zero is considered to change the 
sign.
   //(We want to get 'false' when the conversion changed the sign)

>From 77fed882c1d6bbe4cbe16feea337df0b9c3f83cf Mon Sep 17 00:00:00 2001
From: Zonotora 
Date: Sat, 16 Dec 2023 19:36:04 +0100
Subject: [PATCH 2/3] [clang][UBSan] Add implicit conversion check for
 bitfields

This patch implements the implicit truncation and implicit
sign change checks for bitfields.
---
 clang/docs/ReleaseNotes.rst   |   7 +
 clang/docs/UndefinedBehaviorSanitizer.rst |  19 +-
 clang/include/clang/Basic/Sanitizers.def  |  20 +-
 clang/lib/CodeGen/CGExpr.cpp  |  37 ++-
 clang/lib/CodeGen/CGExprScalar.cpp| 218 +-
 clang/lib/CodeGen/CodeGenFunction.h   |  15 ++
 .../test/CodeGen/ubsan-bitfield-conversion.c  |  61 +
 .../CodeGenCXX/ubsan-bitfield-conversion.cpp  |  94 
 compiler-rt/lib/ubsan/ubsan_handlers.cpp  |  27 ++-
 compiler-rt/lib/ubsan/ubsan_handlers.h|   1 +
 10 files changed, 461 insertions(+), 38 deletions(-)
 create mode 100644 clang/test/CodeGen/ubsan-bitfield-conversion.c
 create mode 100644 clang/test/CodeGenCXX/ubsan-bitfield-conversion.cpp

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 125d51c42d507f..0e72e519c9018c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -179,6 +179,10 @@ Non-comprehensive list of changes in this release
 
 New Compiler Flags
 --
+- ``-fsanitize=implicit-bitfield-conversion`` checks implicit truncation and
+  sign change.
+- ``-fsanitize=implicit-integer-conversion`` a group that replaces the previous
+  group ``-fsanitize=implicit-conversion``.
 
 - ``-Wmissing-designated-field-initializers``, grouped under 
``-Wmissing-field-initializers``.
   This diagnostic can be disabled to make ``-Wmissing-field-initializers`` 
behave
@@ -192,6 +196,9 @@ Modified Compiler Flags
 - Added a new diagnostic flag ``-Wreturn-mismatch`` which is grouped under
   ``-Wreturn-type``, and moved 

[clang] [clang][dataflow] Model assignment to derived class from base. (PR #85064)

2024-03-18 Thread via cfe-commits


@@ -35,45 +69,27 @@ void clang::dataflow::copyRecord(RecordStorageLocation ,
   });
   assert(compatibleTypes);
 
-  for (auto [Field, DstFieldLoc] : Dst.children()) {
-StorageLocation *SrcFieldLoc = Src.getChild(*Field);
-
-assert(Field->getType()->isReferenceType() ||
-   (SrcFieldLoc != nullptr && DstFieldLoc != nullptr));
-
-if (Field->getType()->isRecordType()) {
-  copyRecord(cast(*SrcFieldLoc),
- cast(*DstFieldLoc), Env);
-} else if (Field->getType()->isReferenceType()) {
-  Dst.setChild(*Field, SrcFieldLoc);
-} else {
-  if (Value *Val = Env.getValue(*SrcFieldLoc))
-Env.setValue(*DstFieldLoc, *Val);
-  else
-Env.clearValue(*DstFieldLoc);
-}
-  }
-
-  for (const auto &[Name, SynthFieldLoc] : Src.synthetic_fields()) {
-if (SynthFieldLoc->getType()->isRecordType()) {
-  copyRecord(*cast(SynthFieldLoc),
- cast(Dst.getSyntheticField(Name)), 
Env);
-} else {
-  if (Value *Val = Env.getValue(*SynthFieldLoc))
-Env.setValue(Dst.getSyntheticField(Name), *Val);
-  else
-Env.clearValue(Dst.getSyntheticField(Name));
-}
+  if (SrcType == DstType || (SrcDecl != nullptr && DstDecl != nullptr &&
+ SrcDecl->isDerivedFrom(DstDecl))) {
+for (auto [Field, DstFieldLoc] : Dst.children())

martinboehme wrote:

I'm not sure exactly what you mean here? Do you mean whether we could factor 
out the whole if block into a lambda so that we can reuse it in the else block?

That doesn't work because the two blocks aren't symmetrical: In one case, we 
iterate over the children of `Src`, in the other we iterate over the children 
of `Dst`, but in both cases, the direction of the copy is the same (source to 
destination). I don't see how this could be factored out in a way that would 
make the code clearer than it is now.

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


[clang] [clang][dataflow] Model assignment to derived class from base. (PR #85064)

2024-03-18 Thread via cfe-commits


@@ -14,18 +14,52 @@
 
 #define DEBUG_TYPE "dataflow"
 
-void clang::dataflow::copyRecord(RecordStorageLocation ,
- RecordStorageLocation , Environment ) 
{
+namespace clang::dataflow {
+
+static void copyField(const ValueDecl *Field, StorageLocation *SrcFieldLoc,

martinboehme wrote:

> Should we pass `Field` by reference?

Yes, done!

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


[clang] [clang][dataflow] Model assignment to derived class from base. (PR #85064)

2024-03-18 Thread via cfe-commits


@@ -14,18 +14,52 @@
 
 #define DEBUG_TYPE "dataflow"
 
-void clang::dataflow::copyRecord(RecordStorageLocation ,
- RecordStorageLocation , Environment ) 
{
+namespace clang::dataflow {
+
+static void copyField(const ValueDecl *Field, StorageLocation *SrcFieldLoc,

martinboehme wrote:

> Could `SrcFieldLoc` be a ptr to const? (Same below).

I think what you want to express is that the source field location is only ever 
read from, while the destination field location is written to?

This isn't really how we use `StorageLocation` constness in the framework 
today. (Maybe we should -- that's a separate discussion -- though I'm not 
convinced about how much this would buy us.) Grepping for `const 
StorageLocation` yields only a few hits in the whole framework[^1], and I think 
that's for good reason: A `StorageLocation` is essentially immutable anyway; 
all of its method are const, as are almost all of the methods in the derived 
class `RecordStorageLocation`, with the exception of `setChild()` (which is a 
bit of a special case). It's similar in this respect to a 
[flyweight](https://en.wikipedia.org/wiki/Flyweight_pattern). So the 
distinction between `const StorageLocation *` and `StorageLocation *` doesn't 
mean much in practice, and I guess we've gravitated to the less verbose 
`StorageLocation`.

We _could_ consider using `StorageLocation` constness to encode "can this 
storage location be written to" (which I think is your intent?), which would 
entail changing the storage location parameter of `setValue(const 
StorageLocation &, Value &)` to be non-const, but that would be a pretty 
far-reaching change because I think we'd need to add const in a lot of places 
in the framework.

[^1]: Notably, `setValue(const StorageLocation &, Value &)` is one of them, so 
passing a const storage location does not prevent us from writing to that 
storage location.

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


[clang] [compiler-rt] [clang][UBSan] Add implicit conversion check for bitfields (PR #75481)

2024-03-18 Thread Axel Lundberg via cfe-commits

Zonotora wrote:

@LebedevRI LGTM?


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


[clang] [clang][dataflow] Model assignment to derived class from base. (PR #85064)

2024-03-18 Thread via cfe-commits

https://github.com/martinboehme updated 
https://github.com/llvm/llvm-project/pull/85064

>From 9362adfb0d1a61cb56b897f31fd9f2ead1605383 Mon Sep 17 00:00:00 2001
From: Martin Braenne 
Date: Wed, 13 Mar 2024 12:07:24 +
Subject: [PATCH 1/2] [clang][dataflow] Model assignment to derived class from
 base.

This is a relatively rare case, but

- It's still nice to get this right,
- We can remove the special case for this in `VisitCXXOperatorCallExpr()` (that
  simply bails out), and
- With this in place, I can avoid having to add a similar special case in an
  upcoming patch.
---
 .../clang/Analysis/FlowSensitive/RecordOps.h  |  6 +-
 .../lib/Analysis/FlowSensitive/RecordOps.cpp  | 94 +++
 clang/lib/Analysis/FlowSensitive/Transfer.cpp |  9 --
 .../Analysis/FlowSensitive/RecordOpsTest.cpp  | 46 -
 .../Analysis/FlowSensitive/TransferTest.cpp   | 25 -
 5 files changed, 126 insertions(+), 54 deletions(-)

diff --git a/clang/include/clang/Analysis/FlowSensitive/RecordOps.h 
b/clang/include/clang/Analysis/FlowSensitive/RecordOps.h
index 783e53e980aa2c..8fad45fc11d81e 100644
--- a/clang/include/clang/Analysis/FlowSensitive/RecordOps.h
+++ b/clang/include/clang/Analysis/FlowSensitive/RecordOps.h
@@ -31,7 +31,11 @@ namespace dataflow {
 ///
 /// Requirements:
 ///
-///  `Src` and `Dst` must have the same canonical unqualified type.
+///  Either:
+///- `Src` and `Dest` must have the same canonical unqualified type, or
+///- The type of `Src` must be derived from `Dest`, or
+///- The type of `Dest` must be derived from `Src` (in this case, any 
fields
+///  that are only present in `Dest` are not overwritten).
 void copyRecord(RecordStorageLocation , RecordStorageLocation ,
 Environment );
 
diff --git a/clang/lib/Analysis/FlowSensitive/RecordOps.cpp 
b/clang/lib/Analysis/FlowSensitive/RecordOps.cpp
index da4dd6dc078515..4fc4c15a07a1ce 100644
--- a/clang/lib/Analysis/FlowSensitive/RecordOps.cpp
+++ b/clang/lib/Analysis/FlowSensitive/RecordOps.cpp
@@ -14,18 +14,52 @@
 
 #define DEBUG_TYPE "dataflow"
 
-void clang::dataflow::copyRecord(RecordStorageLocation ,
- RecordStorageLocation , Environment ) 
{
+namespace clang::dataflow {
+
+static void copyField(const ValueDecl *Field, StorageLocation *SrcFieldLoc,
+  StorageLocation *DstFieldLoc, RecordStorageLocation ,
+  Environment ) {
+  assert(Field->getType()->isReferenceType() ||
+ (SrcFieldLoc != nullptr && DstFieldLoc != nullptr));
+
+  if (Field->getType()->isRecordType()) {
+copyRecord(cast(*SrcFieldLoc),
+   cast(*DstFieldLoc), Env);
+  } else if (Field->getType()->isReferenceType()) {
+Dst.setChild(*Field, SrcFieldLoc);
+  } else {
+if (Value *Val = Env.getValue(*SrcFieldLoc))
+  Env.setValue(*DstFieldLoc, *Val);
+else
+  Env.clearValue(*DstFieldLoc);
+  }
+}
+
+static void copySyntheticField(QualType FieldType, StorageLocation 
,
+   StorageLocation , Environment ) 
{
+  if (FieldType->isRecordType()) {
+copyRecord(cast(SrcFieldLoc),
+   cast(DstFieldLoc), Env);
+  } else {
+if (Value *Val = Env.getValue(SrcFieldLoc))
+  Env.setValue(DstFieldLoc, *Val);
+else
+  Env.clearValue(DstFieldLoc);
+  }
+}
+
+void copyRecord(RecordStorageLocation , RecordStorageLocation ,
+Environment ) {
   auto SrcType = Src.getType().getCanonicalType().getUnqualifiedType();
   auto DstType = Dst.getType().getCanonicalType().getUnqualifiedType();
 
   auto SrcDecl = SrcType->getAsCXXRecordDecl();
   auto DstDecl = DstType->getAsCXXRecordDecl();
 
-  bool compatibleTypes =
+  [[maybe_unused]] bool compatibleTypes =
   SrcType == DstType ||
-  (SrcDecl && DstDecl && SrcDecl->isDerivedFrom(DstDecl));
-  (void)compatibleTypes;
+  (SrcDecl != nullptr && DstDecl != nullptr &&
+   (SrcDecl->isDerivedFrom(DstDecl) || DstDecl->isDerivedFrom(SrcDecl)));
 
   LLVM_DEBUG({
 if (!compatibleTypes) {
@@ -35,45 +69,27 @@ void clang::dataflow::copyRecord(RecordStorageLocation ,
   });
   assert(compatibleTypes);
 
-  for (auto [Field, DstFieldLoc] : Dst.children()) {
-StorageLocation *SrcFieldLoc = Src.getChild(*Field);
-
-assert(Field->getType()->isReferenceType() ||
-   (SrcFieldLoc != nullptr && DstFieldLoc != nullptr));
-
-if (Field->getType()->isRecordType()) {
-  copyRecord(cast(*SrcFieldLoc),
- cast(*DstFieldLoc), Env);
-} else if (Field->getType()->isReferenceType()) {
-  Dst.setChild(*Field, SrcFieldLoc);
-} else {
-  if (Value *Val = Env.getValue(*SrcFieldLoc))
-Env.setValue(*DstFieldLoc, *Val);
-  else
-Env.clearValue(*DstFieldLoc);
-}
-  }
-
-  for (const auto &[Name, SynthFieldLoc] : Src.synthetic_fields()) {
-if (SynthFieldLoc->getType()->isRecordType()) {
-  copyRecord(*cast(SynthFieldLoc),
- 

[clang] [clang][C23] N3006 Underspecified object declarations (PR #79845)

2024-03-18 Thread Guillot Tony via cfe-commits

to268 wrote:

I have rebased my PR to include N3018 constexpr feature and reverted a 
formatted snippet of code that is not part of the PR.
I will add constexpr tests but I need to investigate why the constexpr keyword 
does not trigger the diagnostic (not sure if it's a constexpr implementation 
bug or something I need to handle in my PR (it does not really matter TBO)).

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


[clang] [llvm] [AArch64] Add soft-float ABI (PR #84146)

2024-03-18 Thread via cfe-commits

ostannard wrote:

Ping

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


[clang] [Clang] Implement P2718R0 "Lifetime extension in range-based for loops" (PR #76361)

2024-03-18 Thread Hubert Tong via cfe-commits


@@ -6375,12 +6383,16 @@ 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();

hubert-reinterpretcast wrote:

> @hubert-reinterpretcast Could you please give me an example where 
> `CXXDefaultInitExpr` has to be lifetime-extended?

https://github.com/llvm/llvm-project/issues/85613

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


[clang] [clang][C23] N3006 Underspecified object declarations (PR #79845)

2024-03-18 Thread Guillot Tony via cfe-commits

https://github.com/to268 updated https://github.com/llvm/llvm-project/pull/79845

>From f463907db6a68422c2f28d08593ab21e42c6a497 Mon Sep 17 00:00:00 2001
From: Guillot Tony 
Date: Mon, 29 Jan 2024 15:14:32 +0100
Subject: [PATCH 1/3] Implementation base of N3006 Underspecified object
 declarations

---
 clang/docs/ReleaseNotes.rst   |  3 +++
 .../clang/Basic/DiagnosticSemaKinds.td|  2 ++
 clang/lib/Sema/SemaExpr.cpp   | 27 +++
 clang/test/C/C2x/n3006.c  | 27 +++
 clang/test/Parser/c2x-underspecified-decls.c  | 12 +
 clang/www/c_status.html   |  2 +-
 6 files changed, 72 insertions(+), 1 deletion(-)
 create mode 100644 clang/test/C/C2x/n3006.c
 create mode 100644 clang/test/Parser/c2x-underspecified-decls.c

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 125d51c42d507f..3b4a9291b6f7f0 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -163,6 +163,9 @@ C23 Feature Support
 - Clang now supports `N3018 The constexpr specifier for object definitions`
   `_.
 
+- Clang now diagnoses `N3006 Underspecified object declarations
+  `_.
+
 Non-comprehensive list of changes in this release
 -
 
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 8e97902564af08..b336b5f63367c1 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -7685,6 +7685,8 @@ def err_attribute_arm_mve_polymorphism : Error<
   "'__clang_arm_mve_strict_polymorphism' attribute can only be applied to an 
MVE/NEON vector type">;
 def err_attribute_webassembly_funcref : Error<
   "'__funcref' attribute can only be applied to a function pointer type">;
+def err_c23_underspecified_object_declaration: Error<
+  "'%select{struct||union||enum}0 %1' is defined as an 
underspecified object initializer">;
 
 def warn_setter_getter_impl_required : Warning<
   "property %0 requires method %1 to be defined - "
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 8725b09f8546cf..6395690e0edeb9 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -7813,6 +7813,33 @@ Sema::BuildCompoundLiteralExpr(SourceLocation LParenLoc, 
TypeSourceInfo *TInfo,
diag::err_variable_object_no_init))
 return ExprError();
 }
+  } else if (LangOpts.C23 &&
+ (literalType->isRecordType() || literalType->isEnumeralType())) {
+// C23 6.2.1p7: Structure, union, and enumeration tags have scope that
+// begins just after the appearance of the tag in a type specifier that
+// declares the tag.
+// [...]
+// An ordinary identifier that has an underspecified definition has scope
+// that starts when the definition is completed; if the same ordinary
+// identifier declares another entity with a scope that encloses the 
current
+// block, that declaration is hidden as soon as the inner declarator is
+// completed*.)
+// [...]
+// *) That means, that the outer declaration is not visible for the
+// initializer.
+auto Range = SourceRange(LParenLoc, RParenLoc);
+const auto *Tag = literalType->castAs();
+const auto  = Tag->getDecl()->getSourceRange();
+
+// We should diagnose underspecified declaration, unless the identifier has
+// been diagnosed as being a redefinition, since the tag is made anonymous.
+if (Range.fullyContains(TagRange) && Tag->getDecl()->getIdentifier()) {
+  Diag(TagRange.getBegin(),
+   diag::err_c23_underspecified_object_declaration)
+  << (unsigned)Tag->getDecl()->getTagKind()
+  << Tag->getDecl()->getName() << TagRange;
+  return ExprError();
+}
   } else if (!literalType->isDependentType() &&
  RequireCompleteType(LParenLoc, literalType,
diag::err_typecheck_decl_incomplete_type,
diff --git a/clang/test/C/C2x/n3006.c b/clang/test/C/C2x/n3006.c
new file mode 100644
index 00..15efc0ccd6d323
--- /dev/null
+++ b/clang/test/C/C2x/n3006.c
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -std=c2x -verify %s
+
+/* WG14 N3006: Full
+ * Underspecified object declarations
+ */
+
+struct S1 { int x, y; };// expected-note {{previous definition is 
here}}
+union U1 { int a; double b; };  // expected-note {{previous definition is 
here}}
+enum E1 { FOO, BAR };   // expected-note {{previous definition is 
here}}
+
+auto normal_struct = (struct S1){ 1, 2 };
+auto underspecified_struct = (struct S2 { int x, y; }){ 1, 2 };   // 
expected-error {{'struct S2' is defined as an underspecified object 
initializer}}
+auto underspecified_struct_redef = (struct 

[clang] [clang][dataflow] Fix `getResultObjectLocation()` on `CXXDefaultArgExpr`. (PR #85072)

2024-03-18 Thread via cfe-commits

https://github.com/martinboehme updated 
https://github.com/llvm/llvm-project/pull/85072

>From dfa4da9e6a3d8a343e1fdf0ed72670148fec5a59 Mon Sep 17 00:00:00 2001
From: Martin Braenne 
Date: Thu, 14 Mar 2024 08:46:06 +
Subject: [PATCH] [clang][dataflow] Fix `getResultObjectLocation()` on
 `CXXDefaultArgExpr`.

This patch includes a test that causes an assertion failure without the other
changes in this patch.
---
 .../FlowSensitive/DataflowEnvironment.cpp |  1 +
 clang/lib/Analysis/FlowSensitive/Transfer.cpp |  6 
 .../Analysis/FlowSensitive/TransferTest.cpp   | 30 +++
 3 files changed, 37 insertions(+)

diff --git a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp 
b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
index 1d2bd9a9b08af3..cc1ebd511191a9 100644
--- a/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
+++ b/clang/lib/Analysis/FlowSensitive/DataflowEnvironment.cpp
@@ -771,6 +771,7 @@ static bool isOriginalRecordConstructor(const Expr 
) {
 return !Init->isSemanticForm() || !Init->isTransparent();
   return isa(RecordPRValue) || isa(RecordPRValue) 
||
  isa(RecordPRValue) ||
+ isa(RecordPRValue) ||
  isa(RecordPRValue) ||
  // The framework currently does not propagate the objects created in
  // the two branches of a `ConditionalOperator` because there is no way
diff --git a/clang/lib/Analysis/FlowSensitive/Transfer.cpp 
b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
index 04aa2831df0558..ea166fcdb89e20 100644
--- a/clang/lib/Analysis/FlowSensitive/Transfer.cpp
+++ b/clang/lib/Analysis/FlowSensitive/Transfer.cpp
@@ -450,6 +450,12 @@ class TransferVisitor : public 
ConstStmtVisitor {
 Env.setStorageLocation(*S, *MemberLoc);
   }
 
+  void VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *S) {
+const Expr *ArgExpr = S->getExpr();
+assert(ArgExpr != nullptr);
+propagateValueOrStorageLocation(*ArgExpr, *S, Env);
+  }
+
   void VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *S) {
 const Expr *InitExpr = S->getExpr();
 assert(InitExpr != nullptr);
diff --git a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp 
b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
index a8c282f140b4cd..86c7f32f0104be 100644
--- a/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
+++ b/clang/unittests/Analysis/FlowSensitive/TransferTest.cpp
@@ -2924,6 +2924,36 @@ TEST(TransferTest, ResultObjectLocation) {
   });
 }
 
+TEST(TransferTest, ResultObjectLocationForDefaultArgExpr) {
+  std::string Code = R"(
+struct S {};
+void funcWithDefaultArg(S s = S());
+void target() {
+  funcWithDefaultArg();
+  // [[p]]
+}
+  )";
+
+  using ast_matchers::cxxDefaultArgExpr;
+  using ast_matchers::match;
+  using ast_matchers::selectFirst;
+  runDataflow(
+  Code,
+  [](const llvm::StringMap> ,
+ ASTContext ) {
+const Environment  = getEnvironmentAtAnnotation(Results, "p");
+
+auto *DefaultArg = selectFirst(
+"default_arg",
+match(cxxDefaultArgExpr().bind("default_arg"), ASTCtx));
+ASSERT_NE(DefaultArg, nullptr);
+
+// The values for default arguments aren't modeled; we merely verify
+// that we can get a result object location for a default arg.
+Env.getResultObjectLocation(*DefaultArg);
+  });
+}
+
 TEST(TransferTest, ResultObjectLocationForDefaultInitExpr) {
   std::string Code = R"(
 struct S {};

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


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-18 Thread via cfe-commits
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= 
Message-ID:
In-Reply-To: 


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 5143a1241362616840af826d18c067025dae 
6b7b99579fb50c338617af58d3e82ec099430f35 -- clang/test/AST/Interp/const-eval.c 
clang/lib/AST/Interp/ByteCodeExprGen.cpp 
clang/lib/AST/Interp/ByteCodeStmtGen.cpp clang/lib/AST/Interp/Descriptor.h 
clang/lib/AST/Interp/FunctionPointer.h clang/lib/AST/Interp/Interp.cpp 
clang/lib/AST/Interp/Interp.h clang/lib/AST/Interp/InterpBlock.cpp 
clang/lib/AST/Interp/Pointer.cpp clang/lib/AST/Interp/Pointer.h 
clang/lib/AST/Interp/PrimType.h clang/test/AST/Interp/c.c 
clang/test/AST/Interp/functions.cpp
``





View the diff from clang-format here.


``diff
diff --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/Interp/Pointer.h
index 7521d44e3a..387a3e9fd2 100644
--- a/clang/lib/AST/Interp/Pointer.h
+++ b/clang/lib/AST/Interp/Pointer.h
@@ -390,7 +390,8 @@ public:
 // If this points inside a dummy block, return true.
 // FIXME: This might change in the future. If it does, we need
 // to set the proper Ctor/Dtor functions for dummy Descriptors.
-if (asBlockPointer().Base != 0 && asBlockPointer().Base != 
sizeof(InlineDescriptor) && isDummy())
+if (asBlockPointer().Base != 0 &&
+asBlockPointer().Base != sizeof(InlineDescriptor) && isDummy())
   return true;
 return getFieldDesc()->isUnknownSizeArray();
   }

``




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


[clang] [clang][Interp] Integral pointers (PR #84159)

2024-03-18 Thread Timm Baeder via cfe-commits
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= ,
Timm =?utf-8?q?Bäder?= 
Message-ID:
In-Reply-To: 


https://github.com/tbaederr updated 
https://github.com/llvm/llvm-project/pull/84159

>From 7d49f0f7310c86fae986f0b84bfbf2bb6e79a745 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= 
Date: Wed, 6 Mar 2024 08:36:52 +0100
Subject: [PATCH 1/5] Integral pointers

---
 clang/lib/AST/Interp/ByteCodeExprGen.cpp |  74 -
 clang/lib/AST/Interp/ByteCodeStmtGen.cpp |   2 +-
 clang/lib/AST/Interp/Descriptor.h|   1 +
 clang/lib/AST/Interp/FunctionPointer.h   |  10 +-
 clang/lib/AST/Interp/Interp.cpp  |   5 +
 clang/lib/AST/Interp/Interp.h|  89 --
 clang/lib/AST/Interp/InterpBlock.cpp |   4 +-
 clang/lib/AST/Interp/Opcodes.td  |  12 +
 clang/lib/AST/Interp/Pointer.cpp | 176 ---
 clang/lib/AST/Interp/Pointer.h   | 368 ---
 clang/lib/AST/Interp/PrimType.h  |   4 +
 clang/test/AST/Interp/c.c|  18 ++
 clang/test/AST/Interp/const-eval.c   | 194 
 13 files changed, 776 insertions(+), 181 deletions(-)
 create mode 100644 clang/test/AST/Interp/const-eval.c

diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp 
b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 6cee3c1af9f66a..65b68f70b890e4 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -173,10 +173,18 @@ bool ByteCodeExprGen::VisitCastExpr(const 
CastExpr *CE) {
 return this->emitCastFloatingIntegral(*ToT, CE);
   }
 
-  case CK_NullToPointer:
+  case CK_NullToPointer: {
 if (DiscardResult)
   return true;
-return this->emitNull(classifyPrim(CE->getType()), CE);
+
+const Descriptor *Desc = nullptr;
+const QualType PointeeType = CE->getType()->getPointeeType();
+if (!PointeeType.isNull()) {
+  if (std::optional T = classify(PointeeType))
+Desc = P.createDescriptor(SubExpr, *T);
+}
+return this->emitNull(classifyPrim(CE->getType()), Desc, CE);
+  }
 
   case CK_PointerToIntegral: {
 if (DiscardResult)
@@ -199,6 +207,34 @@ bool ByteCodeExprGen::VisitCastExpr(const 
CastExpr *CE) {
 return true;
   }
 
+  case CK_IntegralToPointer: {
+QualType IntType = SubExpr->getType();
+assert(IntType->isIntegralOrEnumerationType());
+if (!this->visit(SubExpr))
+  return false;
+// FIXME: I think the discard is wrong since the int->ptr cast might cause 
a
+// diagnostic.
+PrimType T = classifyPrim(IntType);
+if (DiscardResult)
+  return this->emitPop(T, CE);
+
+QualType PtrType = CE->getType();
+assert(PtrType->isPointerType());
+
+const Descriptor *Desc;
+if (std::optional T = classify(PtrType->getPointeeType())) {
+  Desc = P.createDescriptor(SubExpr, *T);
+} else if (PtrType->getPointeeType()->isVoidType())
+  Desc = nullptr;
+else {
+  Desc = P.createDescriptor(CE, PtrType->getPointeeType().getTypePtr(),
+Descriptor::InlineDescMD, true, false,
+/*IsMutable=*/false, nullptr);
+}
+
+return this->emitGetIntPtr(T, Desc, CE);
+  }
+
   case CK_AtomicToNonAtomic:
   case CK_ConstructorConversion:
   case CK_FunctionToPointerDecay:
@@ -207,13 +243,31 @@ bool ByteCodeExprGen::VisitCastExpr(const 
CastExpr *CE) {
   case CK_UserDefinedConversion:
 return this->delegate(SubExpr);
 
-  case CK_BitCast:
+  case CK_BitCast: {
+// Reject bitcasts to atomic types.
 if (CE->getType()->isAtomicType()) {
   if (!this->discard(SubExpr))
 return false;
   return this->emitInvalidCast(CastKind::Reinterpret, CE);
 }
-return this->delegate(SubExpr);
+
+if (DiscardResult)
+  return this->discard(SubExpr);
+
+std::optional FromT = classify(SubExpr->getType());
+std::optional ToT = classifyPrim(CE->getType());
+if (!FromT || !ToT)
+  return false;
+
+assert(isPtrType(*FromT));
+assert(isPtrType(*ToT));
+if (FromT == ToT)
+  return this->delegate(SubExpr);
+
+if (!this->visit(SubExpr))
+  return false;
+return this->emitDecayPtr(*FromT, *ToT, CE);
+  }
 
   case CK_IntegralToBoolean:
   case CK_IntegralCast: {
@@ -245,7 +299,7 @@ bool ByteCodeExprGen::VisitCastExpr(const CastExpr 
*CE) {
 if (!this->visit(SubExpr))
   return false;
 
-if (!this->emitNull(PtrT, CE))
+if (!this->emitNull(PtrT, nullptr, CE))
   return false;
 
 return this->emitNE(PtrT, CE);
@@ -454,7 +508,7 @@ bool ByteCodeExprGen::VisitBinaryOperator(const 
BinaryOperator *BO) {
 
   // Pointer arithmetic special case.
   if (BO->getOpcode() == BO_Add || BO->getOpcode() == BO_Sub) {
-if (T == PT_Ptr || (LT == PT_Ptr && RT == PT_Ptr))
+if (isPtrType(*T) || (isPtrType(*LT) && isPtrType(*RT)))
   return this->VisitPointerArithBinOp(BO);
   }
 
@@ -2322,7 +2376,7 @@ bool ByteCodeExprGen::visitBool(const Expr *E) {
 

[clang] [clang] Set correct FPOptions if attribute 'optnone' presents (PR #85605)

2024-03-18 Thread Serge Pavlov via cfe-commits

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


[clang] add some missing Kinds to libclang python bindings (PR #85571)

2024-03-18 Thread via cfe-commits

16bit-ykiko wrote:

Pinging @Endilll and @linux4life798 for review. 

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


[clang] add some missing Kinds to libclang python bindings (PR #85571)

2024-03-18 Thread via cfe-commits

https://github.com/16bit-ykiko edited 
https://github.com/llvm/llvm-project/pull/85571
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang] Fix assertion failure when printing atomic apvalues (PR #85259)

2024-03-18 Thread Timm Baeder via cfe-commits

tbaederr wrote:

Ping

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


[clang] [clang] Set correct FPOptions if attribute 'optnone' presents (PR #85605)

2024-03-18 Thread John McCall via cfe-commits

rjmccall wrote:

Hmm.  Is there some sort of optimization in IRGen that we need to suppress 
here, or is it something in LLVM code gen?  Presumably normal LLVM optimization 
passes all just skip `optnone` functions.

Mostly I'm wondering how far we're expected to go with `optnone`.

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


[clang] [AArch64][PAC][clang][ELF] Support PAuth ABI compatibility tag (PR #85235)

2024-03-18 Thread Daniil Kovalev via cfe-commits

https://github.com/kovdan01 updated 
https://github.com/llvm/llvm-project/pull/85235

>From eef1d790d1ec8cb9e0dda2b534c4ef19002ade35 Mon Sep 17 00:00:00 2001
From: Daniil Kovalev 
Date: Thu, 14 Mar 2024 12:19:26 +0300
Subject: [PATCH 1/2] [PAC][clang] Define ptrauth driver flags and preprocessor
 features

Define the following clang driver flags:

- `-fptrauth-intrinsics`: `PointerAuth.intrinsics()` in `LangOptions`,
  `ptrauth_intrinsics` preprocessor feature;

- `-fptrauth-calls`: `PointerAuth.calls()` in `LangOptions`, `ptrauth_calls` and
  and `ptrauth_member_function_pointer_type_discrimination` preprocessor
  features;

- `-fptrauth-returns`: `PointerAuth.returns()` in `LangOptions`,
  `ptrauth_returns` preprocessor feature;

- `-fptrauth-auth-traps`: `PointerAuth.authTraps()` in `LangOptions`;

- `-fptrauth-vtable-pointer-address-discrimination`:
  `PointerAuth.vtptrAddressDiscrimination()` in `LangOptions`,
  `ptrauth_vtable_pointer_address_discrimination` preprocessor feature;

- `-fptrauth-vtable-pointer-type-discrimination`:
  `PointerAuth.vtptrTypeDiscrimination()` in `LangOptions`,
  `ptrauth_vtable_pointer_type_discrimination` preprocessor feature;

- `-fptrauth-init-fini`: `PointerAuth.initFini()` in `LangOptions`,
  `ptrauth_init_fini` preprocessor feature.

The patch only defines the flags and having corresponding `LangOptions`
set does not affect codegen yet.

Co-authored-by: Ahmed Bougacha 
---
 clang/include/clang/Basic/Features.def|   7 ++
 clang/include/clang/Basic/LangOptions.h   |  18 
 clang/include/clang/Driver/Options.td |  26 +
 clang/lib/Driver/ToolChains/Clang.cpp |  31 ++
 clang/lib/Frontend/CompilerInvocation.cpp |  33 +++
 clang/test/Driver/ptrauth.c   |  32 ++
 clang/test/Preprocessor/ptrauth.c | 113 ++
 7 files changed, 260 insertions(+)
 create mode 100644 clang/test/Driver/ptrauth.c
 create mode 100644 clang/test/Preprocessor/ptrauth.c

diff --git a/clang/include/clang/Basic/Features.def 
b/clang/include/clang/Basic/Features.def
index 5fad5fc3623cb6..182a44a1079ef2 100644
--- a/clang/include/clang/Basic/Features.def
+++ b/clang/include/clang/Basic/Features.def
@@ -101,6 +101,13 @@ FEATURE(memory_sanitizer,
 FEATURE(thread_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Thread))
 FEATURE(dataflow_sanitizer, LangOpts.Sanitize.has(SanitizerKind::DataFlow))
 FEATURE(scudo, LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo))
+FEATURE(ptrauth_intrinsics, LangOpts.PointerAuth.intrinsics())
+FEATURE(ptrauth_calls, LangOpts.PointerAuth.calls())
+FEATURE(ptrauth_returns, LangOpts.PointerAuth.returns())
+FEATURE(ptrauth_vtable_pointer_address_discrimination, 
LangOpts.PointerAuth.vtptrAddressDiscrimination())
+FEATURE(ptrauth_vtable_pointer_type_discrimination, 
LangOpts.PointerAuth.vtptrTypeDiscrimination())
+FEATURE(ptrauth_member_function_pointer_type_discrimination, 
LangOpts.PointerAuth.calls())
+FEATURE(ptrauth_init_fini, LangOpts.PointerAuth.initFini())
 FEATURE(swiftasynccc,
   PP.getTargetInfo().checkCallingConvention(CC_SwiftAsync) ==
   clang::TargetInfo::CCCR_OK)
diff --git a/clang/include/clang/Basic/LangOptions.h 
b/clang/include/clang/Basic/LangOptions.h
index 862952d336ef31..e9ade66a8df2ac 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -532,6 +532,24 @@ class LangOptions : public LangOptionsBase {
   // implementation on real-world examples.
   std::string OpenACCMacroOverride;
 
+  struct {
+bool Flags[7] = {false};
+bool intrinsics() const { return Flags[0]; }
+bool () { return Flags[0]; }
+bool calls() const { return Flags[1]; }
+bool () { return Flags[1]; }
+bool returns() const { return Flags[2]; }
+bool () { return Flags[2]; }
+bool authTraps() const { return Flags[3]; }
+bool () { return Flags[3]; }
+bool vtptrAddressDiscrimination() const { return Flags[4]; }
+bool () { return Flags[4]; }
+bool vtptrTypeDiscrimination() const { return Flags[5]; }
+bool () { return Flags[5]; }
+bool initFini() const { return Flags[6]; }
+bool () { return Flags[6]; }
+  } PointerAuth;
+
   LangOptions();
 
   /// Set language defaults for the given input language and
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index aca8c9b0d5487a..868b164d8f7174 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4085,6 +4085,32 @@ defm strict_return : BoolFOption<"strict-return",
 " of a non-void function as unreachable">,
   PosFlag>;
 
+let Group = f_Group in {
+  let Visibility = [ClangOption,CC1Option] in {
+def fptrauth_intrinsics : Flag<["-"], "fptrauth-intrinsics">,
+  HelpText<"Enable pointer-authentication intrinsics">;
+def fptrauth_calls : Flag<["-"], "fptrauth-calls">,
+  HelpText<"Enable signing and authentication of all indirect calls">;
+def fptrauth_returns : 

[clang] [clang] Set correct FPOptions if attribute 'optnone' presents (PR #85605)

2024-03-18 Thread via cfe-commits

llvmbot wrote:




@llvm/pr-subscribers-clang

Author: Serge Pavlov (spavloff)


Changes

Attribute `optnone` must turn off all optimizations including fast-math ones. 
Actually AST nodes in the 'optnone' function still had fast-math flags. This 
change implements fixing FP options before function body is parsed.

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


5 Files Affected:

- (modified) clang/include/clang/Basic/LangOptions.h (+11) 
- (modified) clang/include/clang/Sema/Sema.h (+1) 
- (modified) clang/lib/Parse/ParseStmt.cpp (+4) 
- (modified) clang/lib/Sema/SemaDecl.cpp (+10) 
- (modified) clang/test/AST/ast-dump-fpfeatures.cpp (+11) 


``diff
diff --git a/clang/include/clang/Basic/LangOptions.h 
b/clang/include/clang/Basic/LangOptions.h
index 08fc706e3cbf74..19c60a8cb5e946 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -842,6 +842,8 @@ class FPOptions {
   /// Return difference with the given option set.
   FPOptionsOverride getChangesFrom(const FPOptions ) const;
 
+  void applyChanges(FPOptionsOverride FPO);
+
   // We can define most of the accessors automatically:
 #define OPTION(NAME, TYPE, WIDTH, PREVIOUS)
\
   TYPE get##NAME() const { 
\
@@ -923,6 +925,11 @@ class FPOptionsOverride {
   setAllowFPContractAcrossStatement();
   }
 
+  void setDisallowOptimizations() {
+setFPPreciseEnabled(true);
+setDisallowFPContract();
+  }
+
   storage_type getAsOpaqueInt() const {
 return (static_cast(Options.getAsOpaqueInt())
 << FPOptions::StorageBitSize) |
@@ -979,6 +986,10 @@ inline FPOptionsOverride FPOptions::getChangesFrom(const 
FPOptions ) const
   return getChangesSlow(Base);
 }
 
+inline void FPOptions::applyChanges(FPOptionsOverride FPO) {
+  *this = FPO.applyOverrides(*this);
+}
+
 /// Describes the kind of translation unit being processed.
 enum TranslationUnitKind {
   /// The translation unit is a complete translation unit.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 95ea5ebc7f1ac1..ccc2ded67589ec 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -3222,6 +3222,7 @@ class Sema final {
   Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D,
 SkipBodyInfo *SkipBody = nullptr,
 FnBodyKind BodyKind = FnBodyKind::Other);
+  void applyFunctionAttributesBeforeParsingBody(Decl *FD);
 
   /// Determine whether we can delay parsing the body of a function or
   /// function template until it is used, assuming we don't care about emitting
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 76a3fa8f2627de..489ae9f167b95d 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -2508,6 +2508,10 @@ Decl *Parser::ParseFunctionStatementBody(Decl *Decl, 
ParseScope ) {
   Sema::PragmaStackSentinelRAII
 PragmaStackSentinel(Actions, "InternalPragmaState", IsCXXMethod);
 
+  // Some function attributes (like OptimizeNoneAttr) affect FP options.
+  Sema::FPFeaturesStateRAII SaveFPFeatures(Actions);
+  Actions.applyFunctionAttributesBeforeParsingBody(Decl);
+
   // Do not enter a scope for the brace, as the arguments are in the same scope
   // (the function body) as the body itself.  Instead, just read the statement
   // list and put it into a CompoundStmt for safe keeping.
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 5850cd0ab6b9aa..59c327515dba70 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -15919,6 +15919,16 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope 
*FnBodyScope, Decl *D,
   return D;
 }
 
+void Sema::applyFunctionAttributesBeforeParsingBody(Decl *FD) {
+  if (FD->hasAttr()) {
+FPOptionsOverride FPO;
+FPO.setDisallowOptimizations();
+CurFPFeatures.applyChanges(FPO);
+FpPragmaStack.CurrentValue =
+CurFPFeatures.getChangesFrom(FPOptions(LangOpts));
+  }
+}
+
 /// Given the set of return statements within a function body,
 /// compute the variables that are subject to the named return value
 /// optimization.
diff --git a/clang/test/AST/ast-dump-fpfeatures.cpp 
b/clang/test/AST/ast-dump-fpfeatures.cpp
index da0011602a728e..f6e9d3637417e6 100644
--- a/clang/test/AST/ast-dump-fpfeatures.cpp
+++ b/clang/test/AST/ast-dump-fpfeatures.cpp
@@ -187,3 +187,14 @@ float func_18(float x, float y) {
 // CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward
 // CHECK:   ReturnStmt
 // CHECK: BinaryOperator {{.*}} ConstRoundingMode=downward
+
+#pragma float_control(precise, off)
+__attribute__((optnone))
+float func_19(float x, float y) {
+  return x + y;
+}
+
+// CHECK-LABEL: FunctionDecl {{.*}} func_19 'float (float, float)'
+// CHECK: CompoundStmt {{.*}} MathErrno=1
+// CHECK:   ReturnStmt
+// 

[clang] [clang] Set correct FPOptions if attribute 'optnone' presents (PR #85605)

2024-03-18 Thread Serge Pavlov via cfe-commits

https://github.com/spavloff created 
https://github.com/llvm/llvm-project/pull/85605

Attribute `optnone` must turn off all optimizations including fast-math ones. 
Actually AST nodes in the 'optnone' function still had fast-math flags. This 
change implements fixing FP options before function body is parsed.

>From 24c96a1f43b8d2e0977331c92aec1c14ccc504a2 Mon Sep 17 00:00:00 2001
From: Serge Pavlov 
Date: Mon, 18 Mar 2024 13:20:15 +0700
Subject: [PATCH] [clang] Set correct FPOptions if attribute 'optnone' presents

Attribute `optnone` must turn off all optimizations including fast-math
ones. Actually AST nodes in the 'optnone' function still had fast-math
flags. This change implements fixing FP options before function body is
parsed.
---
 clang/include/clang/Basic/LangOptions.h | 11 +++
 clang/include/clang/Sema/Sema.h |  1 +
 clang/lib/Parse/ParseStmt.cpp   |  4 
 clang/lib/Sema/SemaDecl.cpp | 10 ++
 clang/test/AST/ast-dump-fpfeatures.cpp  | 11 +++
 5 files changed, 37 insertions(+)

diff --git a/clang/include/clang/Basic/LangOptions.h 
b/clang/include/clang/Basic/LangOptions.h
index 08fc706e3cbf74..19c60a8cb5e946 100644
--- a/clang/include/clang/Basic/LangOptions.h
+++ b/clang/include/clang/Basic/LangOptions.h
@@ -842,6 +842,8 @@ class FPOptions {
   /// Return difference with the given option set.
   FPOptionsOverride getChangesFrom(const FPOptions ) const;
 
+  void applyChanges(FPOptionsOverride FPO);
+
   // We can define most of the accessors automatically:
 #define OPTION(NAME, TYPE, WIDTH, PREVIOUS)
\
   TYPE get##NAME() const { 
\
@@ -923,6 +925,11 @@ class FPOptionsOverride {
   setAllowFPContractAcrossStatement();
   }
 
+  void setDisallowOptimizations() {
+setFPPreciseEnabled(true);
+setDisallowFPContract();
+  }
+
   storage_type getAsOpaqueInt() const {
 return (static_cast(Options.getAsOpaqueInt())
 << FPOptions::StorageBitSize) |
@@ -979,6 +986,10 @@ inline FPOptionsOverride FPOptions::getChangesFrom(const 
FPOptions ) const
   return getChangesSlow(Base);
 }
 
+inline void FPOptions::applyChanges(FPOptionsOverride FPO) {
+  *this = FPO.applyOverrides(*this);
+}
+
 /// Describes the kind of translation unit being processed.
 enum TranslationUnitKind {
   /// The translation unit is a complete translation unit.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 95ea5ebc7f1ac1..ccc2ded67589ec 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -3222,6 +3222,7 @@ class Sema final {
   Decl *ActOnStartOfFunctionDef(Scope *S, Decl *D,
 SkipBodyInfo *SkipBody = nullptr,
 FnBodyKind BodyKind = FnBodyKind::Other);
+  void applyFunctionAttributesBeforeParsingBody(Decl *FD);
 
   /// Determine whether we can delay parsing the body of a function or
   /// function template until it is used, assuming we don't care about emitting
diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp
index 76a3fa8f2627de..489ae9f167b95d 100644
--- a/clang/lib/Parse/ParseStmt.cpp
+++ b/clang/lib/Parse/ParseStmt.cpp
@@ -2508,6 +2508,10 @@ Decl *Parser::ParseFunctionStatementBody(Decl *Decl, 
ParseScope ) {
   Sema::PragmaStackSentinelRAII
 PragmaStackSentinel(Actions, "InternalPragmaState", IsCXXMethod);
 
+  // Some function attributes (like OptimizeNoneAttr) affect FP options.
+  Sema::FPFeaturesStateRAII SaveFPFeatures(Actions);
+  Actions.applyFunctionAttributesBeforeParsingBody(Decl);
+
   // Do not enter a scope for the brace, as the arguments are in the same scope
   // (the function body) as the body itself.  Instead, just read the statement
   // list and put it into a CompoundStmt for safe keeping.
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 5850cd0ab6b9aa..59c327515dba70 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -15919,6 +15919,16 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope 
*FnBodyScope, Decl *D,
   return D;
 }
 
+void Sema::applyFunctionAttributesBeforeParsingBody(Decl *FD) {
+  if (FD->hasAttr()) {
+FPOptionsOverride FPO;
+FPO.setDisallowOptimizations();
+CurFPFeatures.applyChanges(FPO);
+FpPragmaStack.CurrentValue =
+CurFPFeatures.getChangesFrom(FPOptions(LangOpts));
+  }
+}
+
 /// Given the set of return statements within a function body,
 /// compute the variables that are subject to the named return value
 /// optimization.
diff --git a/clang/test/AST/ast-dump-fpfeatures.cpp 
b/clang/test/AST/ast-dump-fpfeatures.cpp
index da0011602a728e..f6e9d3637417e6 100644
--- a/clang/test/AST/ast-dump-fpfeatures.cpp
+++ b/clang/test/AST/ast-dump-fpfeatures.cpp
@@ -187,3 +187,14 @@ float func_18(float x, float y) {
 // CHECK: CompoundStmt {{.*}} ConstRoundingMode=downward
 // CHECK: 

[clang] [llvm] [PowerPC] Fix behavior of rldimi/rlwimi/rlwnm builtins (PR #85040)

2024-03-18 Thread Qiu Chaofan via cfe-commits

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


[clang] 65ae09e - [PowerPC] Fix behavior of rldimi/rlwimi/rlwnm builtins (#85040)

2024-03-18 Thread via cfe-commits

Author: Qiu Chaofan
Date: 2024-03-18T14:17:16+08:00
New Revision: 65ae09eeb6773b14189fc67051870c8fc4eb9ae3

URL: 
https://github.com/llvm/llvm-project/commit/65ae09eeb6773b14189fc67051870c8fc4eb9ae3
DIFF: 
https://github.com/llvm/llvm-project/commit/65ae09eeb6773b14189fc67051870c8fc4eb9ae3.diff

LOG: [PowerPC] Fix behavior of rldimi/rlwimi/rlwnm builtins (#85040)

rldimi is 64-bit instruction, so the corresponding builtin should not
be available in 32-bit mode. Rotate amount should be in range and
cases when mask is zero needs special handling.

This change also swaps the first and second operands of rldimi/rlwimi
to match previous behavior. For masks not ending at bit 63-SH,
rotation will be inserted before rldimi.

Added: 


Modified: 
clang/lib/Sema/SemaChecking.cpp
clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-error.c
clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-rotate.c
llvm/lib/Target/PowerPC/PPCISelLowering.cpp
llvm/test/CodeGen/PowerPC/rldimi.ll
llvm/test/CodeGen/PowerPC/rlwimi.ll
llvm/test/CodeGen/PowerPC/rlwinm.ll

Removed: 




diff  --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp
index 46b783862e4e42..de544a03b29846 100644
--- a/clang/lib/Sema/SemaChecking.cpp
+++ b/clang/lib/Sema/SemaChecking.cpp
@@ -5189,6 +5189,7 @@ static bool isPPC_64Builtin(unsigned BuiltinID) {
   case PPC::BI__builtin_ppc_fetch_and_andlp:
   case PPC::BI__builtin_ppc_fetch_and_orlp:
   case PPC::BI__builtin_ppc_fetch_and_swaplp:
+  case PPC::BI__builtin_ppc_rldimi:
 return true;
   }
   return false;
@@ -5290,8 +5291,10 @@ bool Sema::CheckPPCBuiltinFunctionCall(const TargetInfo 
, unsigned BuiltinID,
   case PPC::BI__builtin_ppc_rlwnm:
 return SemaValueIsRunOfOnes(TheCall, 2);
   case PPC::BI__builtin_ppc_rlwimi:
+return SemaBuiltinConstantArgRange(TheCall, 2, 0, 31) ||
+   SemaValueIsRunOfOnes(TheCall, 3);
   case PPC::BI__builtin_ppc_rldimi:
-return SemaBuiltinConstantArg(TheCall, 2, Result) ||
+return SemaBuiltinConstantArgRange(TheCall, 2, 0, 63) ||
SemaValueIsRunOfOnes(TheCall, 3);
   case PPC::BI__builtin_ppc_addex: {
 if (SemaBuiltinConstantArgRange(TheCall, 2, 0, 3))

diff  --git a/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-error.c 
b/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-error.c
index 5f57d7575c859a..272e0222dc9e41 100644
--- a/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-error.c
+++ b/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-error.c
@@ -24,13 +24,16 @@ void test_trap(void) {
   __tw(ia, ib, 0); //expected-error {{argument value 0 is outside the valid 
range [1, 31]}}
 }
 
+#ifdef __PPC64__
 void test_builtin_ppc_rldimi() {
   unsigned int shift;
   unsigned long long mask;
   unsigned long long res = __builtin_ppc_rldimi(ull, ull, shift, 7); // 
expected-error {{argument to '__builtin_ppc_rldimi' must be a constant integer}}
   res = __builtin_ppc_rldimi(ull, ull, 63, mask);// 
expected-error {{argument to '__builtin_ppc_rldimi' must be a constant integer}}
   res = __builtin_ppc_rldimi(ull, ull, 63, 0x0F00);  // 
expected-error {{argument 3 value should represent a contiguous bit field}}
+  res = __builtin_ppc_rldimi(ull, ull, 64, 0x);  // 
expected-error {{argument value 64 is outside the valid range [0, 63]}}
 }
+#endif
 
 void test_builtin_ppc_rlwimi() {
   unsigned int shift;
@@ -83,6 +86,10 @@ void testalignx(const void *pointer, unsigned int alignment) 
{
 }
 
 #ifndef __PPC64__
+unsigned long long testrldimi32() {
+  return __rldimi(ull, ui, 3, 0x78ULL); //expected-error {{this builtin is 
only available on 64-bit targets}}
+}
+
 long long testbpermd(long long bit_selector, long long source) {
   return __bpermd(bit_selector, source); //expected-error {{this builtin is 
only available on 64-bit targets}}
 }

diff  --git a/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-rotate.c 
b/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-rotate.c
index b218547c00d931..4773d6cb1a0cfd 100644
--- a/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-rotate.c
+++ b/clang/test/CodeGen/PowerPC/builtins-ppc-xlcompat-rotate.c
@@ -1,8 +1,10 @@
 // REQUIRES: powerpc-registered-target
 // RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu \
-// RUN:   -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s
+// RUN:   -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s \
+// RUN:   -check-prefixes=PPC64,CHECK
 // RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu \
-// RUN:   -emit-llvm %s -o - -target-cpu pwr8 | FileCheck %s
+// RUN:   -emit-llvm %s -o - -target-cpu pwr8 | FileCheck %s \
+// RUN:   -check-prefixes=PPC64,CHECK
 // RUN: %clang_cc1 -triple powerpc-unknown-aix \
 // RUN:   -emit-llvm %s -o - -target-cpu pwr7 | FileCheck %s
 // RUN: %clang_cc1 -triple powerpc64-unknown-aix \
@@ -11,18 +13,20 @@
 extern unsigned int ui;
 extern unsigned 

<    1   2   3   4