[PATCH] D157252: [clang][ExprConst] Handle 0 type size in builtin_memcpy etc.

2023-10-23 Thread Timm Bäder via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGaaaece65a80f: [clang][ExprConst] Handle 0 type size in 
builtin_memcpy etc. (authored by tbaeder).

Changed prior to commit:
  https://reviews.llvm.org/D157252?vs=557826&id=557859#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157252

Files:
  clang/lib/AST/ExprConstant.cpp
  clang/test/Sema/builtin-memcpy.c


Index: clang/test/Sema/builtin-memcpy.c
===
--- /dev/null
+++ clang/test/Sema/builtin-memcpy.c
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 %s -fsyntax-only -verify=c
+// RUN: %clang_cc1 -x c++ %s -fsyntax-only -verify=cxx
+
+// cxx-no-diagnostics
+
+
+/// Zero-sized structs should not crash.
+int b() {
+  struct {  } a[10];
+  __builtin_memcpy(&a[2], a, 2); // c-warning {{buffer has size 0, but size 
argument is 2}}
+  return 0;
+}
+
+#ifdef __cplusplus
+// FIXME: This is UB and GCC correctly diagnoses it. Clang should do the same.
+constexpr int b2() {
+  struct {  } a[10];
+  __builtin_memcpy(&a[2], a, 2);
+  return 0;
+}
+static_assert(b2() == 0, "");
+#endif
Index: clang/lib/AST/ExprConstant.cpp
===
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -9545,6 +9545,8 @@
 
 // Figure out how many T's we're copying.
 uint64_t TSize = Info.Ctx.getTypeSizeInChars(T).getQuantity();
+if (TSize == 0)
+  return false;
 if (!WChar) {
   uint64_t Remainder;
   llvm::APInt OrigN = N;


Index: clang/test/Sema/builtin-memcpy.c
===
--- /dev/null
+++ clang/test/Sema/builtin-memcpy.c
@@ -0,0 +1,22 @@
+// RUN: %clang_cc1 %s -fsyntax-only -verify=c
+// RUN: %clang_cc1 -x c++ %s -fsyntax-only -verify=cxx
+
+// cxx-no-diagnostics
+
+
+/// Zero-sized structs should not crash.
+int b() {
+  struct {  } a[10];
+  __builtin_memcpy(&a[2], a, 2); // c-warning {{buffer has size 0, but size argument is 2}}
+  return 0;
+}
+
+#ifdef __cplusplus
+// FIXME: This is UB and GCC correctly diagnoses it. Clang should do the same.
+constexpr int b2() {
+  struct {  } a[10];
+  __builtin_memcpy(&a[2], a, 2);
+  return 0;
+}
+static_assert(b2() == 0, "");
+#endif
Index: clang/lib/AST/ExprConstant.cpp
===
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -9545,6 +9545,8 @@
 
 // Figure out how many T's we're copying.
 uint64_t TSize = Info.Ctx.getTypeSizeInChars(T).getQuantity();
+if (TSize == 0)
+  return false;
 if (!WChar) {
   uint64_t Remainder;
   llvm::APInt OrigN = N;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D154581: [clang][Interp] Track existing InitMaps in InterpState

2023-10-23 Thread Timm Bäder via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG3671a69470f3: [clang][Interp] Call destructors of local 
variables (authored by tbaeder).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154581

Files:
  clang/lib/AST/Interp/Descriptor.cpp
  clang/lib/AST/Interp/Descriptor.h
  clang/lib/AST/Interp/EvalEmitter.cpp
  clang/lib/AST/Interp/EvalEmitter.h
  clang/lib/AST/Interp/InterpBlock.h
  clang/lib/AST/Interp/InterpFrame.cpp
  clang/lib/AST/Interp/InterpState.cpp
  clang/lib/AST/Interp/Pointer.cpp
  clang/lib/AST/Interp/Pointer.h
  clang/test/AST/Interp/arrays.cpp

Index: clang/test/AST/Interp/arrays.cpp
===
--- clang/test/AST/Interp/arrays.cpp
+++ clang/test/AST/Interp/arrays.cpp
@@ -406,3 +406,52 @@
   static_assert(b[4] == '\0', "");
   static_assert(b[5] == '\0', "");
 }
+
+namespace NoInitMapLeak {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdivision-by-zero"
+#pragma clang diagnostic ignored "-Wc++20-extensions"
+  constexpr int testLeak() { // expected-error {{never produces a constant expression}} \
+ // ref-error {{never produces a constant expression}}
+int a[2];
+a[0] = 1;
+// interrupts interpretation.
+(void)(1 / 0); // expected-note 2{{division by zero}} \
+   // ref-note 2{{division by zero}}
+
+
+return 1;
+  }
+#pragma clang diagnostic pop
+  static_assert(testLeak() == 1, ""); // expected-error {{not an integral constant expression}} \
+  // expected-note {{in call to 'testLeak()'}} \
+  // ref-error {{not an integral constant expression}} \
+  // ref-note {{in call to 'testLeak()'}}
+
+
+  constexpr int a[] = {1,2,3,4/0,5}; // expected-error {{must be initialized by a constant expression}} \
+ // expected-note {{division by zero}} \
+ // ref-error {{must be initialized by a constant expression}} \
+ // ref-note {{division by zero}} \
+ // ref-note {{declared here}}
+
+  /// FIXME: This should fail in the new interpreter as well.
+  constexpr int b = a[0]; // ref-error {{must be initialized by a constant expression}} \
+  // ref-note {{is not a constant expression}} \
+  // ref-note {{declared here}}
+  static_assert(b == 1, ""); // ref-error {{not an integral constant expression}} \
+ // ref-note {{not a constant expression}}
+
+  constexpr int f() { // expected-error {{never produces a constant expression}} \
+  // ref-error {{never produces a constant expression}}
+int a[] = {19,2,3/0,4}; // expected-note 2{{division by zero}} \
+// expected-warning {{is undefined}} \
+// ref-note 2{{division by zero}} \
+// ref-warning {{is undefined}}
+return 1;
+  }
+  static_assert(f() == 1, ""); // expected-error {{not an integral constant expression}} \
+   // expected-note {{in call to}} \
+   // ref-error {{not an integral constant expression}} \
+   // ref-note {{in call to}}
+}
Index: clang/lib/AST/Interp/Pointer.h
===
--- clang/lib/AST/Interp/Pointer.h
+++ clang/lib/AST/Interp/Pointer.h
@@ -108,7 +108,7 @@
 if (getFieldDesc()->ElemDesc)
   Off += sizeof(InlineDescriptor);
 else
-  Off += sizeof(InitMap *);
+  Off += sizeof(InitMapPtr);
 return Pointer(Pointee, Base, Base + Off);
   }
 
@@ -147,7 +147,7 @@
 if (inPrimitiveArray()) {
   if (Offset != Base)
 return *this;
-  return Pointer(Pointee, Base, Offset + sizeof(InitMap *));
+  return Pointer(Pointee, Base, Offset + sizeof(InitMapPtr));
 }
 
 // Pointer is to a field or array element - enter it.
@@ -168,7 +168,7 @@
   // Revert to an outer one-past-end pointer.
   unsigned Adjust;
   if (inPrimitiveArray())
-Adjust = sizeof(InitMap *);
+Adjust = sizeof(InitMapPtr);
   else
 Adjust = sizeof(InlineDescriptor);
   return Pointer(Pointee, Base, Base + getSize() + Adjust);
@@ -257,7 +257,7 @@
   if (getFieldDesc()->ElemDesc)
 Adjust = sizeof(InlineDescriptor);
   else
-Adjust = sizeof(InitMap *);
+Adjust = sizeof(InitMapPtr);
 }
 return Offset - Base - Adjust;
   }
@@ -359,7 +359,7 @@
 assert(isLive() && "Invalid pointer");
 if (isArrayRoot())
   return *reinterpret_cast(Pointee->rawDat

[PATCH] D157252: [clang][ExprConst] Handle 0 type size in builtin_memcpy etc.

2023-10-21 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder updated this revision to Diff 557826.

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

https://reviews.llvm.org/D157252

Files:
  clang/lib/AST/ExprConstant.cpp
  clang/test/Sema/builtin-memcpy.c


Index: clang/test/Sema/builtin-memcpy.c
===
--- /dev/null
+++ clang/test/Sema/builtin-memcpy.c
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 %s -fsyntax-only -verify=c
+// RUN: %clang_cc1 -x c++ %s -fsyntax-only -verify=cxx
+
+// cxx-no-diagnostics
+
+
+/// Zero-sized structs should not crash.
+int b() {
+  struct {  } a[10];
+  __builtin_memcpy(&a[2], a, 2); // c-warning {{buffer has size 0, but size 
argument is 2}}
+  return 0;
+}
+
+#ifdef __cplusplus
+constexpr int b2() {
+  struct {  } a[10];
+  __builtin_memcpy(&a[2], a, 2);
+  return 0;
+}
+static_assert(b2() == 0, "");
+#endif
Index: clang/lib/AST/ExprConstant.cpp
===
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -9545,6 +9545,8 @@
 
 // Figure out how many T's we're copying.
 uint64_t TSize = Info.Ctx.getTypeSizeInChars(T).getQuantity();
+if (TSize == 0)
+  return false;
 if (!WChar) {
   uint64_t Remainder;
   llvm::APInt OrigN = N;


Index: clang/test/Sema/builtin-memcpy.c
===
--- /dev/null
+++ clang/test/Sema/builtin-memcpy.c
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 %s -fsyntax-only -verify=c
+// RUN: %clang_cc1 -x c++ %s -fsyntax-only -verify=cxx
+
+// cxx-no-diagnostics
+
+
+/// Zero-sized structs should not crash.
+int b() {
+  struct {  } a[10];
+  __builtin_memcpy(&a[2], a, 2); // c-warning {{buffer has size 0, but size argument is 2}}
+  return 0;
+}
+
+#ifdef __cplusplus
+constexpr int b2() {
+  struct {  } a[10];
+  __builtin_memcpy(&a[2], a, 2);
+  return 0;
+}
+static_assert(b2() == 0, "");
+#endif
Index: clang/lib/AST/ExprConstant.cpp
===
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -9545,6 +9545,8 @@
 
 // Figure out how many T's we're copying.
 uint64_t TSize = Info.Ctx.getTypeSizeInChars(T).getQuantity();
+if (TSize == 0)
+  return false;
 if (!WChar) {
   uint64_t Remainder;
   llvm::APInt OrigN = N;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D157252: [clang][ExprConst] Handle 0 type size in builtin_memcpy etc.

2023-10-21 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added inline comments.



Comment at: clang/test/Sema/builtin-memcpy.c:4-8
+int b() {
+  struct {  } a[10];
+  __builtin_memcpy(&a[2], a, 2); // expected-warning {{buffer has size 0, but 
size argument is 2}}
+  return 0;
+}

aaron.ballman wrote:
> The only other test I'd like to see is one like:
> ```
> constexpr int b() {
>   struct {  } a[10];
>   __builtin_memcpy(&a[2], a, 2); // UB here should be caught, right?
>   return 0;
> }
> 
> static_assert(b() == 0, "");
> ```
> (if that's follow-up work, that's fine too, just leave a test with a FIXME 
> comment.)
Nope, clang accepts that and GCC rejects the function when calling.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157252

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


[PATCH] D154581: [clang][Interp] Track existing InitMaps in InterpState

2023-10-19 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder marked an inline comment as done.
tbaeder added inline comments.



Comment at: clang/lib/AST/Interp/Descriptor.h:207
   /// Initializes the map with no fields set.
   InitMap(unsigned N);
 

aaron.ballman wrote:
> Now that this is public, can we make it `explicit` so we don't get accidental 
> conversions from `unsigned`?
Sure.


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

https://reviews.llvm.org/D154581

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


[PATCH] D154581: [clang][Interp] Track existing InitMaps in InterpState

2023-10-19 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder updated this revision to Diff 557801.

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

https://reviews.llvm.org/D154581

Files:
  clang/lib/AST/Interp/Descriptor.cpp
  clang/lib/AST/Interp/Descriptor.h
  clang/lib/AST/Interp/EvalEmitter.cpp
  clang/lib/AST/Interp/EvalEmitter.h
  clang/lib/AST/Interp/InterpBlock.h
  clang/lib/AST/Interp/InterpFrame.cpp
  clang/lib/AST/Interp/InterpState.cpp
  clang/lib/AST/Interp/Pointer.cpp
  clang/lib/AST/Interp/Pointer.h
  clang/test/AST/Interp/arrays.cpp

Index: clang/test/AST/Interp/arrays.cpp
===
--- clang/test/AST/Interp/arrays.cpp
+++ clang/test/AST/Interp/arrays.cpp
@@ -410,3 +410,52 @@
   static_assert(b[4] == '\0', "");
   static_assert(b[5] == '\0', "");
 }
+
+namespace NoInitMapLeak {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdivision-by-zero"
+#pragma clang diagnostic ignored "-Wc++20-extensions"
+  constexpr int testLeak() { // expected-error {{never produces a constant expression}} \
+ // ref-error {{never produces a constant expression}}
+int a[2];
+a[0] = 1;
+// interrupts interpretation.
+(void)(1 / 0); // expected-note 2{{division by zero}} \
+   // ref-note 2{{division by zero}}
+
+
+return 1;
+  }
+#pragma clang diagnostic pop
+  static_assert(testLeak() == 1, ""); // expected-error {{not an integral constant expression}} \
+  // expected-note {{in call to 'testLeak()'}} \
+  // ref-error {{not an integral constant expression}} \
+  // ref-note {{in call to 'testLeak()'}}
+
+
+  constexpr int a[] = {1,2,3,4/0,5}; // expected-error {{must be initialized by a constant expression}} \
+ // expected-note {{division by zero}} \
+ // ref-error {{must be initialized by a constant expression}} \
+ // ref-note {{division by zero}} \
+ // ref-note {{declared here}}
+
+  /// FIXME: This should fail in the new interpreter as well.
+  constexpr int b = a[0]; // ref-error {{must be initialized by a constant expression}} \
+  // ref-note {{is not a constant expression}} \
+  // ref-note {{declared here}}
+  static_assert(b == 1, ""); // ref-error {{not an integral constant expression}} \
+ // ref-note {{not a constant expression}}
+
+  constexpr int f() { // expected-error {{never produces a constant expression}} \
+  // ref-error {{never produces a constant expression}}
+int a[] = {19,2,3/0,4}; // expected-note 2{{division by zero}} \
+// expected-warning {{is undefined}} \
+// ref-note 2{{division by zero}} \
+// ref-warning {{is undefined}}
+return 1;
+  }
+  static_assert(f() == 1, ""); // expected-error {{not an integral constant expression}} \
+   // expected-note {{in call to}} \
+   // ref-error {{not an integral constant expression}} \
+   // ref-note {{in call to}}
+}
Index: clang/lib/AST/Interp/Pointer.h
===
--- clang/lib/AST/Interp/Pointer.h
+++ clang/lib/AST/Interp/Pointer.h
@@ -108,7 +108,7 @@
 if (getFieldDesc()->ElemDesc)
   Off += sizeof(InlineDescriptor);
 else
-  Off += sizeof(InitMap *);
+  Off += sizeof(InitMapPtr);
 return Pointer(Pointee, Base, Base + Off);
   }
 
@@ -147,7 +147,7 @@
 if (inPrimitiveArray()) {
   if (Offset != Base)
 return *this;
-  return Pointer(Pointee, Base, Offset + sizeof(InitMap *));
+  return Pointer(Pointee, Base, Offset + sizeof(InitMapPtr));
 }
 
 // Pointer is to a field or array element - enter it.
@@ -168,7 +168,7 @@
   // Revert to an outer one-past-end pointer.
   unsigned Adjust;
   if (inPrimitiveArray())
-Adjust = sizeof(InitMap *);
+Adjust = sizeof(InitMapPtr);
   else
 Adjust = sizeof(InlineDescriptor);
   return Pointer(Pointee, Base, Base + getSize() + Adjust);
@@ -257,7 +257,7 @@
   if (getFieldDesc()->ElemDesc)
 Adjust = sizeof(InlineDescriptor);
   else
-Adjust = sizeof(InitMap *);
+Adjust = sizeof(InitMapPtr);
 }
 return Offset - Base - Adjust;
   }
@@ -359,7 +359,7 @@
 assert(isLive() && "Invalid pointer");
 if (isArrayRoot())
   return *reinterpret_cast(Pointee->rawData() + Base +
-sizeof(InitMap *));
+sizeof(InitMapPtr));
 
 return *reinterpret_cast(Pointee->rawData() + Offset);
   }
@@ -367,7 +367,7 @@
   /// Dereferenc

[PATCH] D156453: [clang][Interp] Create only globals when initializing a global variable

2023-10-19 Thread Timm Bäder via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG311f725d9a6f: [clang][Interp] Create only globals when 
initializing a global variable (authored by tbaeder).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156453

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/test/AST/Interp/records.cpp
  clang/test/SemaCXX/paren-list-agg-init.cpp

Index: clang/test/SemaCXX/paren-list-agg-init.cpp
===
--- clang/test/SemaCXX/paren-list-agg-init.cpp
+++ clang/test/SemaCXX/paren-list-agg-init.cpp
@@ -1,4 +1,6 @@
 // RUN: %clang_cc1 -verify -std=c++20 %s -fsyntax-only
+// RUN: %clang_cc1 -verify -std=c++20 %s -fsyntax-only -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -verify=expected,beforecxx20 -Wc++20-extensions -std=c++20 %s -fsyntax-only -fexperimental-new-constant-interpreter
 // RUN: %clang_cc1 -verify=expected,beforecxx20 -Wc++20-extensions -std=c++20 %s -fsyntax-only
 
 struct A { // expected-note 4{{candidate constructor}}
Index: clang/test/AST/Interp/records.cpp
===
--- clang/test/AST/Interp/records.cpp
+++ clang/test/AST/Interp/records.cpp
@@ -1064,6 +1064,22 @@
   };
 
   constexpr B b(A(1),2);
+
+
+  struct O {
+int &&j;
+  };
+
+  /// Not constexpr!
+  O o1(0);
+  constinit O o2(0); // ref-error {{variable does not have a constant initializer}} \
+ // ref-note {{required by 'constinit' specifier}} \
+ // ref-note {{reference to temporary is not a constant expression}} \
+ // ref-note {{temporary created here}} \
+ // expected-error {{variable does not have a constant initializer}} \
+ // expected-note {{required by 'constinit' specifier}} \
+ // expected-note {{reference to temporary is not a constant expression}} \
+ // expected-note {{temporary created here}}
 }
 #endif
 
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -304,6 +304,9 @@
   /// Flag inidicating if we're initializing an already created
   /// variable. This is set in visitInitializer().
   bool Initializing = false;
+
+  /// Flag indicating if we're initializing a global variable.
+  bool GlobalDecl = false;
 };
 
 extern template class ByteCodeExprGen;
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -29,14 +29,20 @@
 template  class DeclScope final : public VariableScope {
 public:
   DeclScope(ByteCodeExprGen *Ctx, const ValueDecl *VD)
-  : VariableScope(Ctx), Scope(Ctx->P, VD) {}
+  : VariableScope(Ctx), Scope(Ctx->P, VD),
+OldGlobalDecl(Ctx->GlobalDecl) {
+Ctx->GlobalDecl = Context::shouldBeGloballyIndexed(VD);
+  }
 
   void addExtended(const Scope::Local &Local) override {
 return this->addLocal(Local);
   }
 
+  ~DeclScope() { this->Ctx->GlobalDecl = OldGlobalDecl; }
+
 private:
   Program::DeclScope Scope;
+  bool OldGlobalDecl;
 };
 
 /// Scope used to handle initialization methods.
@@ -1198,21 +1204,30 @@
   if (DiscardResult)
 return this->discard(SubExpr);
 
+  // When we're initializing a global variable *or* the storage duration of
+  // the temporary is explicitly static, create a global variable.
   std::optional SubExprT = classify(SubExpr);
-  if (E->getStorageDuration() == SD_Static) {
+  bool IsStatic = E->getStorageDuration() == SD_Static;
+  if (GlobalDecl || IsStatic) {
 std::optional GlobalIndex = P.createGlobal(E);
 if (!GlobalIndex)
   return false;
 
 const LifetimeExtendedTemporaryDecl *TempDecl =
 E->getLifetimeExtendedTemporaryDecl();
-assert(TempDecl);
+if (IsStatic)
+  assert(TempDecl);
 
 if (SubExprT) {
   if (!this->visit(SubExpr))
 return false;
-  if (!this->emitInitGlobalTemp(*SubExprT, *GlobalIndex, TempDecl, E))
-return false;
+  if (IsStatic) {
+if (!this->emitInitGlobalTemp(*SubExprT, *GlobalIndex, TempDecl, E))
+  return false;
+  } else {
+if (!this->emitInitGlobal(*SubExprT, *GlobalIndex, E))
+  return false;
+  }
   return this->emitGetPtrGlobal(*GlobalIndex, E);
 }
 
@@ -1221,7 +1236,9 @@
   return false;
 if (!this->visitInitializer(SubExpr))
   return false;
-return this->emitInitGlobalTempComp(TempDecl, E);
+if (IsStatic)
+  return this->emitInitGlobalTempComp(TempDecl, E);
+return true;
   }
 
   // For everyhing else, use local variables.
__

[PATCH] D154581: [clang][Interp] Track existing InitMaps in InterpState

2023-10-19 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added inline comments.



Comment at: clang/lib/AST/Interp/Descriptor.h:203
 
+public:
   /// Initializes the map with no fields set.

aaron.ballman wrote:
> This interface is now more confusing as to how to use because it now has a 
> public non-default constructor *and* an `initialize` method. Perhaps we 
> should rename `initialize` to `initializeMapElement` so it's clear that the 
> `initialize` method isn't for the map itself?
Made more things private and renamed `initialize()` and `isInitialized()`.


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

https://reviews.llvm.org/D154581

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


[PATCH] D154581: [clang][Interp] Track existing InitMaps in InterpState

2023-10-19 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder updated this revision to Diff 557773.

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

https://reviews.llvm.org/D154581

Files:
  clang/lib/AST/Interp/Descriptor.cpp
  clang/lib/AST/Interp/Descriptor.h
  clang/lib/AST/Interp/EvalEmitter.cpp
  clang/lib/AST/Interp/EvalEmitter.h
  clang/lib/AST/Interp/InterpBlock.h
  clang/lib/AST/Interp/InterpFrame.cpp
  clang/lib/AST/Interp/InterpState.cpp
  clang/lib/AST/Interp/Pointer.cpp
  clang/lib/AST/Interp/Pointer.h
  clang/test/AST/Interp/arrays.cpp

Index: clang/test/AST/Interp/arrays.cpp
===
--- clang/test/AST/Interp/arrays.cpp
+++ clang/test/AST/Interp/arrays.cpp
@@ -410,3 +410,52 @@
   static_assert(b[4] == '\0', "");
   static_assert(b[5] == '\0', "");
 }
+
+namespace NoInitMapLeak {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdivision-by-zero"
+#pragma clang diagnostic ignored "-Wc++20-extensions"
+  constexpr int testLeak() { // expected-error {{never produces a constant expression}} \
+ // ref-error {{never produces a constant expression}}
+int a[2];
+a[0] = 1;
+// interrupts interpretation.
+(void)(1 / 0); // expected-note 2{{division by zero}} \
+   // ref-note 2{{division by zero}}
+
+
+return 1;
+  }
+#pragma clang diagnostic pop
+  static_assert(testLeak() == 1, ""); // expected-error {{not an integral constant expression}} \
+  // expected-note {{in call to 'testLeak()'}} \
+  // ref-error {{not an integral constant expression}} \
+  // ref-note {{in call to 'testLeak()'}}
+
+
+  constexpr int a[] = {1,2,3,4/0,5}; // expected-error {{must be initialized by a constant expression}} \
+ // expected-note {{division by zero}} \
+ // ref-error {{must be initialized by a constant expression}} \
+ // ref-note {{division by zero}} \
+ // ref-note {{declared here}}
+
+  /// FIXME: This should fail in the new interpreter as well.
+  constexpr int b = a[0]; // ref-error {{must be initialized by a constant expression}} \
+  // ref-note {{is not a constant expression}} \
+  // ref-note {{declared here}}
+  static_assert(b == 1, ""); // ref-error {{not an integral constant expression}} \
+ // ref-note {{not a constant expression}}
+
+  constexpr int f() { // expected-error {{never produces a constant expression}} \
+  // ref-error {{never produces a constant expression}}
+int a[] = {19,2,3/0,4}; // expected-note 2{{division by zero}} \
+// expected-warning {{is undefined}} \
+// ref-note 2{{division by zero}} \
+// ref-warning {{is undefined}}
+return 1;
+  }
+  static_assert(f() == 1, ""); // expected-error {{not an integral constant expression}} \
+   // expected-note {{in call to}} \
+   // ref-error {{not an integral constant expression}} \
+   // ref-note {{in call to}}
+}
Index: clang/lib/AST/Interp/Pointer.h
===
--- clang/lib/AST/Interp/Pointer.h
+++ clang/lib/AST/Interp/Pointer.h
@@ -108,7 +108,7 @@
 if (getFieldDesc()->ElemDesc)
   Off += sizeof(InlineDescriptor);
 else
-  Off += sizeof(InitMap *);
+  Off += sizeof(InitMapPtr);
 return Pointer(Pointee, Base, Base + Off);
   }
 
@@ -147,7 +147,7 @@
 if (inPrimitiveArray()) {
   if (Offset != Base)
 return *this;
-  return Pointer(Pointee, Base, Offset + sizeof(InitMap *));
+  return Pointer(Pointee, Base, Offset + sizeof(InitMapPtr));
 }
 
 // Pointer is to a field or array element - enter it.
@@ -168,7 +168,7 @@
   // Revert to an outer one-past-end pointer.
   unsigned Adjust;
   if (inPrimitiveArray())
-Adjust = sizeof(InitMap *);
+Adjust = sizeof(InitMapPtr);
   else
 Adjust = sizeof(InlineDescriptor);
   return Pointer(Pointee, Base, Base + getSize() + Adjust);
@@ -257,7 +257,7 @@
   if (getFieldDesc()->ElemDesc)
 Adjust = sizeof(InlineDescriptor);
   else
-Adjust = sizeof(InitMap *);
+Adjust = sizeof(InitMapPtr);
 }
 return Offset - Base - Adjust;
   }
@@ -359,7 +359,7 @@
 assert(isLive() && "Invalid pointer");
 if (isArrayRoot())
   return *reinterpret_cast(Pointee->rawData() + Base +
-sizeof(InitMap *));
+sizeof(InitMapPtr));
 
 return *reinterpret_cast(Pointee->rawData() + Offset);
   }
@@ -367,7 +367,7 @@
   /// Dereferenc

[PATCH] D156453: [clang][Interp] Create only globals when initializing a global variable

2023-10-17 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added inline comments.



Comment at: clang/lib/AST/Interp/ByteCodeExprGen.cpp:1213
   std::optional SubExprT = classify(SubExpr);
-  if (E->getStorageDuration() == SD_Static) {
+  bool IsStatic = E->getStorageDuration() == SD_Static;
+  if (GlobalDecl || IsStatic) {

aaron.ballman wrote:
> tbaeder wrote:
> > aaron.ballman wrote:
> > > Should we be looking at the TLS kind of the extended declaration? 
> > > (`CheckCompleteVariableDeclaration()` is using `VarDecl::getTLSKind() == 
> > > VarDecl::TLS_Static`)
> > > 
> > > Would something along these lines work instead?
> > > ```
> > > bool EmitGlobalTemp = E->getStorageDuration() == SD_Static;
> > > if (!EmitGlobalTemp) {
> > >   if (const LifetimeExtendedTemporaryDecl *LETD = 
> > > E->getLifetimeExtendedTemporaryDecl()) {
> > > if (const auto *VD = 
> > > dyn_cast_if_present(LETD->getExtendingDecl()) {
> > >   EmitGlobalTemp= VD->getTLSKind() == VarDecl::TLS_Static;
> > > }
> > >   }
> > > }
> > > ```
> > That code definitely works for the current `AST/Interp/` tests, but we 
> > don't have tests for thread local stuff in there right now.
> Hmm, I think we'll need those tests: https://eel.is/c++draft/expr.const#5.2
> 
> That seems to be the only mention about thread local storage duration for 
> constant expressions in C++, so it might make sense to tackle that as part of 
> this change?
> 
> (I worry that we'll forget to come back to this detail later, basically. So 
> either we should have failing test coverage showing we need a fix, an issue 
> in GitHub so we know to come back to it, etc. or just do the work up front 
> given that it's closely related.)
I've pushed 
https://github.com/llvm/llvm-project/commit/11f5e5eb90c883d4b9ddba318e8fc57914b22ef3

As you can see, the problem also exists for static variables. I think this 
needs additional checks at interpretation time, or even new opcodes to check 
the declaration when the initializer is computed. So I'd rather have this in a 
separate followup patch.


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

https://reviews.llvm.org/D156453

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


[PATCH] D156453: [clang][Interp] Create only globals when initializing a global variable

2023-10-15 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added inline comments.



Comment at: clang/lib/AST/Interp/ByteCodeExprGen.cpp:1213
   std::optional SubExprT = classify(SubExpr);
-  if (E->getStorageDuration() == SD_Static) {
+  bool IsStatic = E->getStorageDuration() == SD_Static;
+  if (GlobalDecl || IsStatic) {

aaron.ballman wrote:
> Should we be looking at the TLS kind of the extended declaration? 
> (`CheckCompleteVariableDeclaration()` is using `VarDecl::getTLSKind() == 
> VarDecl::TLS_Static`)
> 
> Would something along these lines work instead?
> ```
> bool EmitGlobalTemp = E->getStorageDuration() == SD_Static;
> if (!EmitGlobalTemp) {
>   if (const LifetimeExtendedTemporaryDecl *LETD = 
> E->getLifetimeExtendedTemporaryDecl()) {
> if (const auto *VD = 
> dyn_cast_if_present(LETD->getExtendingDecl()) {
>   EmitGlobalTemp= VD->getTLSKind() == VarDecl::TLS_Static;
> }
>   }
> }
> ```
That code definitely works for the current `AST/Interp/` tests, but we don't 
have tests for thread local stuff in there right now.


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

https://reviews.llvm.org/D156453

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


[PATCH] D156453: [clang][Interp] Create only globals when initializing a global variable

2023-10-15 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder updated this revision to Diff 557713.
tbaeder marked an inline comment as done.

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

https://reviews.llvm.org/D156453

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/test/AST/Interp/records.cpp
  clang/test/SemaCXX/paren-list-agg-init.cpp

Index: clang/test/SemaCXX/paren-list-agg-init.cpp
===
--- clang/test/SemaCXX/paren-list-agg-init.cpp
+++ clang/test/SemaCXX/paren-list-agg-init.cpp
@@ -1,4 +1,6 @@
 // RUN: %clang_cc1 -verify -std=c++20 %s -fsyntax-only
+// RUN: %clang_cc1 -verify -std=c++20 %s -fsyntax-only -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -verify=expected,beforecxx20 -Wc++20-extensions -std=c++20 %s -fsyntax-only -fexperimental-new-constant-interpreter
 // RUN: %clang_cc1 -verify=expected,beforecxx20 -Wc++20-extensions -std=c++20 %s -fsyntax-only
 
 struct A { // expected-note 4{{candidate constructor}}
Index: clang/test/AST/Interp/records.cpp
===
--- clang/test/AST/Interp/records.cpp
+++ clang/test/AST/Interp/records.cpp
@@ -1064,5 +1064,21 @@
   };
 
   constexpr B b(A(1),2);
+
+
+  struct O {
+int &&j;
+  };
+
+  /// Not constexpr!
+  O o1(0);
+  constinit O o2(0); // ref-error {{variable does not have a constant initializer}} \
+ // ref-note {{required by 'constinit' specifier}} \
+ // ref-note {{reference to temporary is not a constant expression}} \
+ // ref-note {{temporary created here}} \
+ // expected-error {{variable does not have a constant initializer}} \
+ // expected-note {{required by 'constinit' specifier}} \
+ // expected-note {{reference to temporary is not a constant expression}} \
+ // expected-note {{temporary created here}}
 }
 #endif
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -305,6 +305,9 @@
   /// Flag inidicating if we're initializing an already created
   /// variable. This is set in visitInitializer().
   bool Initializing = false;
+
+  /// Flag indicating if we're initializing a global variable.
+  bool GlobalDecl = false;
 };
 
 extern template class ByteCodeExprGen;
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -29,14 +29,20 @@
 template  class DeclScope final : public VariableScope {
 public:
   DeclScope(ByteCodeExprGen *Ctx, const ValueDecl *VD)
-  : VariableScope(Ctx), Scope(Ctx->P, VD) {}
+  : VariableScope(Ctx), Scope(Ctx->P, VD),
+OldGlobalDecl(Ctx->GlobalDecl) {
+Ctx->GlobalDecl = Context::shouldBeGloballyIndexed(VD);
+  }
 
   void addExtended(const Scope::Local &Local) override {
 return this->addLocal(Local);
   }
 
+  ~DeclScope() { this->Ctx->GlobalDecl = OldGlobalDecl; }
+
 private:
   Program::DeclScope Scope;
+  bool OldGlobalDecl;
 };
 
 /// Scope used to handle initialization methods.
@@ -1269,21 +1275,30 @@
   if (DiscardResult)
 return this->discard(SubExpr);
 
+  // When we're initializing a global variable *or* the storage duration of
+  // the temporary is explicitly static, create a global variable.
   std::optional SubExprT = classify(SubExpr);
-  if (E->getStorageDuration() == SD_Static) {
+  bool IsStatic = E->getStorageDuration() == SD_Static;
+  if (GlobalDecl || IsStatic) {
 std::optional GlobalIndex = P.createGlobal(E);
 if (!GlobalIndex)
   return false;
 
 const LifetimeExtendedTemporaryDecl *TempDecl =
 E->getLifetimeExtendedTemporaryDecl();
-assert(TempDecl);
+if (IsStatic)
+  assert(TempDecl);
 
 if (SubExprT) {
   if (!this->visit(SubExpr))
 return false;
-  if (!this->emitInitGlobalTemp(*SubExprT, *GlobalIndex, TempDecl, E))
-return false;
+  if (IsStatic) {
+if (!this->emitInitGlobalTemp(*SubExprT, *GlobalIndex, TempDecl, E))
+  return false;
+  } else {
+if (!this->emitInitGlobal(*SubExprT, *GlobalIndex, E))
+  return false;
+  }
   return this->emitGetPtrGlobal(*GlobalIndex, E);
 }
 
@@ -1292,7 +1307,9 @@
   return false;
 if (!this->visitInitializer(SubExpr))
   return false;
-return this->emitInitGlobalTempComp(TempDecl, E);
+if (IsStatic)
+  return this->emitInitGlobalTempComp(TempDecl, E);
+return true;
   }
 
   // For everyhing else, use local variables.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D157252: [clang][ExprConst] Handle 0 type size in builtin_memcpy etc.

2023-10-15 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157252

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


[PATCH] D156453: [clang][Interp] Create only globals when initializing a global variable

2023-10-13 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156453

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


[PATCH] D158069: [clang][Interp] Fix getIndex() for composite array elements

2023-10-12 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added inline comments.



Comment at: clang/unittests/AST/Interp/CMakeLists.txt:2
+add_clang_unittest(InterpTests
+  Descriptor.cpp
+  )

thakis wrote:
> Why is this in a separate executable instead of in ASTTests? So it can have 
> fewer deps?
Mostly because running ASTTests takes very long


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D158069

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


[PATCH] D158069: [clang][Interp] Fix getIndex() for composite array elements

2023-10-12 Thread Timm Bäder via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG2f43ace0f48f: [clang][Interp] Fix expected values for 
Pointer API (authored by tbaeder).

Changed prior to commit:
  https://reviews.llvm.org/D158069?vs=557656&id=557689#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D158069

Files:
  clang/lib/AST/Interp/Context.h
  clang/lib/AST/Interp/Pointer.h
  clang/unittests/AST/CMakeLists.txt
  clang/unittests/AST/Interp/CMakeLists.txt
  clang/unittests/AST/Interp/Descriptor.cpp

Index: clang/unittests/AST/Interp/Descriptor.cpp
===
--- /dev/null
+++ clang/unittests/AST/Interp/Descriptor.cpp
@@ -0,0 +1,385 @@
+#include "../../../lib/AST/Interp/Descriptor.h"
+#include "../../../lib/AST/Interp/Context.h"
+#include "../../../lib/AST/Interp/Program.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Tooling/Tooling.h"
+#include "gtest/gtest.h"
+
+using namespace clang;
+using namespace clang::interp;
+using namespace clang::ast_matchers;
+
+/// Inspect generated Descriptors as well as the pointers we create.
+///
+TEST(Descriptor, Primitives) {
+  constexpr char Code[] =
+  "struct A { bool a; bool b; };\n"
+  "struct S {\n"
+  "  float f;\n"
+  "  char s[4];\n"
+  "  A a[3];\n"
+  "  short l[3][3];\n"
+  "};\n"
+  "constexpr S d = {0.0, \"foo\", {{true, false}, {false, true}, {false, false}},\n"
+  "  {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}};\n";
+
+  auto AST = tooling::buildASTFromCodeWithArgs(
+  Code, {"-fexperimental-new-constant-interpreter"});
+
+  const VarDecl *D = selectFirst(
+  "d", match(varDecl().bind("d"), AST->getASTContext()));
+  ASSERT_NE(D, nullptr);
+
+  const auto &Ctx = AST->getASTContext().getInterpContext();
+  Program &Prog = Ctx.getProgram();
+  // Global is registered.
+  ASSERT_TRUE(Prog.getGlobal(D));
+
+  // Get a Pointer to the global.
+  const Pointer &GlobalPtr = Prog.getPtrGlobal(*Prog.getGlobal(D));
+
+  // Test Descriptor of the struct S.
+  const Descriptor *GlobalDesc = GlobalPtr.getFieldDesc();
+  ASSERT_TRUE(GlobalDesc == GlobalPtr.getDeclDesc());
+
+  ASSERT_TRUE(GlobalDesc->asDecl() == D);
+  ASSERT_FALSE(GlobalDesc->asExpr());
+  ASSERT_TRUE(GlobalDesc->asValueDecl() == D);
+  ASSERT_FALSE(GlobalDesc->asFieldDecl());
+  ASSERT_FALSE(GlobalDesc->asRecordDecl());
+
+  // Still true because this is a global variable.
+  ASSERT_TRUE(GlobalDesc->getMetadataSize() == 0);
+  ASSERT_FALSE(GlobalDesc->isPrimitiveArray());
+  ASSERT_FALSE(GlobalDesc->isCompositeArray());
+  ASSERT_FALSE(GlobalDesc->isZeroSizeArray());
+  ASSERT_FALSE(GlobalDesc->isUnknownSizeArray());
+  ASSERT_FALSE(GlobalDesc->isPrimitive());
+  ASSERT_FALSE(GlobalDesc->isArray());
+  ASSERT_TRUE(GlobalDesc->isRecord());
+
+  // Test the Record for the struct S.
+  const Record *SRecord = GlobalDesc->ElemRecord;
+  ASSERT_TRUE(SRecord);
+  ASSERT_TRUE(SRecord->getNumFields() == 4);
+  ASSERT_TRUE(SRecord->getNumBases() == 0);
+  ASSERT_FALSE(SRecord->getDestructor());
+
+  // First field.
+  const Record::Field *F1 = SRecord->getField(0u);
+  ASSERT_TRUE(F1);
+  ASSERT_FALSE(F1->isBitField());
+  ASSERT_TRUE(F1->Desc->isPrimitive());
+
+  // Second field.
+  const Record::Field *F2 = SRecord->getField(1u);
+  ASSERT_TRUE(F2);
+  ASSERT_FALSE(F2->isBitField());
+  ASSERT_TRUE(F2->Desc->isArray());
+  ASSERT_FALSE(F2->Desc->isCompositeArray());
+  ASSERT_TRUE(F2->Desc->isPrimitiveArray());
+  ASSERT_FALSE(F2->Desc->isPrimitive());
+  ASSERT_FALSE(F2->Desc->ElemDesc);
+  ASSERT_EQ(F2->Desc->getNumElems(), 4u);
+  ASSERT_TRUE(F2->Desc->getElemSize() > 0);
+
+  // Third field.
+  const Record::Field *F3 = SRecord->getField(2u);
+  ASSERT_TRUE(F3);
+  ASSERT_FALSE(F3->isBitField());
+  ASSERT_TRUE(F3->Desc->isArray());
+  ASSERT_TRUE(F3->Desc->isCompositeArray());
+  ASSERT_FALSE(F3->Desc->isPrimitiveArray());
+  ASSERT_FALSE(F3->Desc->isPrimitive());
+  ASSERT_TRUE(F3->Desc->ElemDesc);
+  ASSERT_EQ(F3->Desc->getNumElems(), 3u);
+  ASSERT_TRUE(F3->Desc->getElemSize() > 0);
+
+  // Fourth field.
+  // Multidimensional arrays are treated as composite arrays, even
+  // if the value type is primitive.
+  const Record::Field *F4 = SRecord->getField(3u);
+  ASSERT_TRUE(F4);
+  ASSERT_FALSE(F4->isBitField());
+  ASSERT_TRUE(F4->Desc->isArray());
+  ASSERT_TRUE(F4->Desc->isCompositeArray());
+  ASSERT_FALSE(F4->Desc->isPrimitiveArray());
+  ASSERT_FALSE(F4->Desc->isPrimitive());
+  ASSERT_TRUE(F4->Desc->ElemDesc);
+  ASSERT_EQ(F4->Desc->getNumElems(), 3u);
+  ASSERT_TRUE(F4->Desc->getElemSize() > 0);
+  ASSERT_TRUE(F4->Desc->ElemDesc->isPrimitiveArray());
+
+  // Check pointer stuff.
+  // Global variables have no inline des

[PATCH] D153001: [clang][ThreadSafety] Add __builtin_instance_member (WIP)

2023-10-11 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder abandoned this revision.
tbaeder added a comment.

As discussed via other channels, this is going nowhere and we will take another 
approach, if any.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D153001

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


[PATCH] D154581: [clang][Interp] Track existing InitMaps in InterpState

2023-10-10 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added inline comments.



Comment at: clang/lib/AST/Interp/Descriptor.cpp:42
 const Descriptor *D) {
+  new (Ptr) InitMapPtr(std::nullopt);
+

aaron.ballman wrote:
> This worries me a little bit for a few reasons, but it might be okay:
> 
> * What validates that the bytes pointed to by `Ptr` are aligned properly for 
> an `InitMapPtr` object? Perhaps we need an `alignas` in the function 
> signature to ensure correct alignment of those bytes?
> * `InitMapPtr` is `std::optional>>` 
> and I *think* using placement new will ensure we have correct objects in all 
> the expected places, but I'm not 100% sure because we're calling the 
> `nullopt` constructor here.
> * I *think* it is correct that you are not assigning the result of the 
> placement `new` expression into anything; and I think we need this placement 
> `new` because of the `reinterpret_cast` happening in `dtorArrayTy()`. But it 
> is a bit strange to see the placement `new` hanging off on its own like this. 
> Might be worth some comments explaining. 
> 
> CC @hubert.reinterpretcast @rsmith in case my assessment is incorrect.
I thought using placement new would just call the normal constructors anyway?

BTW, does using a `shared_ptr` here even make sense? Since this is allocated in 
the `Block`, we need to call the constructor and destructors manually anyway.


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

https://reviews.llvm.org/D154581

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


[PATCH] D154581: [clang][Interp] Track existing InitMaps in InterpState

2023-10-10 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder updated this revision to Diff 557670.
tbaeder marked an inline comment as done.

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

https://reviews.llvm.org/D154581

Files:
  clang/lib/AST/Interp/Descriptor.cpp
  clang/lib/AST/Interp/Descriptor.h
  clang/lib/AST/Interp/EvalEmitter.cpp
  clang/lib/AST/Interp/EvalEmitter.h
  clang/lib/AST/Interp/InterpBlock.h
  clang/lib/AST/Interp/InterpFrame.cpp
  clang/lib/AST/Interp/InterpState.cpp
  clang/lib/AST/Interp/Pointer.cpp
  clang/lib/AST/Interp/Pointer.h
  clang/test/AST/Interp/arrays.cpp

Index: clang/test/AST/Interp/arrays.cpp
===
--- clang/test/AST/Interp/arrays.cpp
+++ clang/test/AST/Interp/arrays.cpp
@@ -390,3 +390,52 @@
   static_assert(b[4] == '\0', "");
   static_assert(b[5] == '\0', "");
 }
+
+namespace NoInitMapLeak {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdivision-by-zero"
+#pragma clang diagnostic ignored "-Wc++20-extensions"
+  constexpr int testLeak() { // expected-error {{never produces a constant expression}} \
+ // ref-error {{never produces a constant expression}}
+int a[2];
+a[0] = 1;
+// interrupts interpretation.
+(void)(1 / 0); // expected-note 2{{division by zero}} \
+   // ref-note 2{{division by zero}}
+
+
+return 1;
+  }
+#pragma clang diagnostic pop
+  static_assert(testLeak() == 1, ""); // expected-error {{not an integral constant expression}} \
+  // expected-note {{in call to 'testLeak()'}} \
+  // ref-error {{not an integral constant expression}} \
+  // ref-note {{in call to 'testLeak()'}}
+
+
+  constexpr int a[] = {1,2,3,4/0,5}; // expected-error {{must be initialized by a constant expression}} \
+ // expected-note {{division by zero}} \
+ // ref-error {{must be initialized by a constant expression}} \
+ // ref-note {{division by zero}} \
+ // ref-note {{declared here}}
+
+  /// FIXME: This should fail in the new interpreter as well.
+  constexpr int b = a[0]; // ref-error {{must be initialized by a constant expression}} \
+  // ref-note {{is not a constant expression}} \
+  // ref-note {{declared here}}
+  static_assert(b == 1, ""); // ref-error {{not an integral constant expression}} \
+ // ref-note {{not a constant expression}}
+
+  constexpr int f() { // expected-error {{never produces a constant expression}} \
+  // ref-error {{never produces a constant expression}}
+int a[] = {19,2,3/0,4}; // expected-note 2{{division by zero}} \
+// expected-warning {{is undefined}} \
+// ref-note 2{{division by zero}} \
+// ref-warning {{is undefined}}
+return 1;
+  }
+  static_assert(f() == 1, ""); // expected-error {{not an integral constant expression}} \
+   // expected-note {{in call to}} \
+   // ref-error {{not an integral constant expression}} \
+   // ref-note {{in call to}}
+}
Index: clang/lib/AST/Interp/Pointer.h
===
--- clang/lib/AST/Interp/Pointer.h
+++ clang/lib/AST/Interp/Pointer.h
@@ -99,7 +99,7 @@
 if (getFieldDesc()->ElemDesc)
   Off += sizeof(InlineDescriptor);
 else
-  Off += sizeof(InitMap *);
+  Off += sizeof(InitMapPtr);
 return Pointer(Pointee, Base, Base + Off);
   }
 
@@ -138,7 +138,7 @@
 if (inPrimitiveArray()) {
   if (Offset != Base)
 return *this;
-  return Pointer(Pointee, Base, Offset + sizeof(InitMap *));
+  return Pointer(Pointee, Base, Offset + sizeof(InitMapPtr));
 }
 
 // Pointer is to a field or array element - enter it.
@@ -159,7 +159,7 @@
   // Revert to an outer one-past-end pointer.
   unsigned Adjust;
   if (inPrimitiveArray())
-Adjust = sizeof(InitMap *);
+Adjust = sizeof(InitMapPtr);
   else
 Adjust = sizeof(InlineDescriptor);
   return Pointer(Pointee, Base, Base + getSize() + Adjust);
@@ -248,7 +248,7 @@
   if (getFieldDesc()->ElemDesc)
 Adjust = sizeof(InlineDescriptor);
   else
-Adjust = sizeof(InitMap *);
+Adjust = sizeof(InitMapPtr);
 }
 return Offset - Base - Adjust;
   }
@@ -344,7 +344,7 @@
 assert(isLive() && "Invalid pointer");
 if (isArrayRoot())
   return *reinterpret_cast(Pointee->rawData() + Base +
-sizeof(InitMap *));
+sizeof(InitMapPtr));
 
 return *reinterpret_cast(Pointee->rawData() + Offset);
  

[PATCH] D155548: [clang][ExprConst] Short-circuit ConstantExpr evaluation

2023-10-10 Thread Timm Bäder via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGb4343aba9fa1: [clang][ExprConst] Short-circuit ConstantExpr 
evaluation (authored by tbaeder).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D155548

Files:
  clang/lib/AST/ExprConstant.cpp


Index: clang/lib/AST/ExprConstant.cpp
===
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -15327,6 +15327,17 @@
 return true;
   }
 
+  if (const auto *CE = dyn_cast(Exp)) {
+if (CE->hasAPValueResult()) {
+  Result.Val = CE->getAPValueResult();
+  IsConst = true;
+  return true;
+}
+
+// The SubExpr is usually just an IntegerLiteral.
+return FastEvaluateAsRValue(CE->getSubExpr(), Result, Ctx, IsConst);
+  }
+
   // This case should be rare, but we need to check it before we check on
   // the type below.
   if (Exp->getType().isNull()) {


Index: clang/lib/AST/ExprConstant.cpp
===
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -15327,6 +15327,17 @@
 return true;
   }
 
+  if (const auto *CE = dyn_cast(Exp)) {
+if (CE->hasAPValueResult()) {
+  Result.Val = CE->getAPValueResult();
+  IsConst = true;
+  return true;
+}
+
+// The SubExpr is usually just an IntegerLiteral.
+return FastEvaluateAsRValue(CE->getSubExpr(), Result, Ctx, IsConst);
+  }
+
   // This case should be rare, but we need to check it before we check on
   // the type below.
   if (Exp->getType().isNull()) {
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D156212: [clang][Interp] Implement remaining strcmp builtins

2023-10-10 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

I have a local patch that implements these builtins by doing a bitcast to a 
buffer first. There is a comment in `ExprConstant.cpp` that talks about the 
same thing. That path probably makes more sense? I'd abandon this review then.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156212

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


[PATCH] D154951: [clang][Interp] __builtin_bit_cast, Take 2

2023-10-10 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder abandoned this revision.
tbaeder added a comment.

Abandoning this since I've migrated it to Github: 
https://github.com/llvm/llvm-project/pull/68288


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154951

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


[PATCH] D158069: [clang][Interp] Fix getIndex() for composite array elements

2023-10-09 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder updated this revision to Diff 557656.

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

https://reviews.llvm.org/D158069

Files:
  clang/lib/AST/Interp/Context.h
  clang/lib/AST/Interp/Pointer.h
  clang/unittests/AST/CMakeLists.txt
  clang/unittests/AST/Interp/CMakeLists.txt
  clang/unittests/AST/Interp/Descriptor.cpp

Index: clang/unittests/AST/Interp/Descriptor.cpp
===
--- /dev/null
+++ clang/unittests/AST/Interp/Descriptor.cpp
@@ -0,0 +1,388 @@
+#define INCLUDED_FROM_UNITTEST
+#include "../../../lib/AST/Interp/Context.h"
+#include "../../../lib/AST/Interp/Pointer.h"
+#undef INCLUDED_FROM_UNITTEST
+#include "../../../lib/AST/Interp/Descriptor.h"
+#include "../../../lib/AST/Interp/Program.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Tooling/Tooling.h"
+#include "gtest/gtest.h"
+
+using namespace clang;
+using namespace clang::interp;
+using namespace clang::ast_matchers;
+
+/// Inspect generated Descriptors as well as the pointers we create.
+///
+TEST(Descriptor, Primitives) {
+  constexpr char Code[] = "struct A { bool a; bool b; };\n"
+  "struct S {\n"
+  "  float f;\n"
+  "  char s[4];\n"
+  "  A a[3];\n"
+  "  short l[3][3];\n"
+  "};\n"
+  "constexpr S d = {0.0, \"foo\", {{true, false}, "
+  "{false, true}, {false, false}},\n"
+  "  {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}};\n";
+
+  auto AST = tooling::buildASTFromCodeWithArgs(
+  Code, {"-fexperimental-new-constant-interpreter"});
+
+  const VarDecl *D = selectFirst(
+  "d", match(varDecl().bind("d"), AST->getASTContext()));
+  ASSERT_NE(D, nullptr);
+
+  const auto &Ctx = AST->getASTContext().getInterpContext();
+  Program &Prog = Ctx.getProgram();
+  // Global is registered.
+  ASSERT_TRUE(Prog.getGlobal(D));
+
+  // Get a Pointer to the global.
+  const Pointer &GlobalPtr = Prog.getPtrGlobal(*Prog.getGlobal(D));
+
+  // Test Descriptor of the struct S.
+  const Descriptor *GlobalDesc = GlobalPtr.getFieldDesc();
+  ASSERT_TRUE(GlobalDesc == GlobalPtr.getDeclDesc());
+
+  ASSERT_TRUE(GlobalDesc->asDecl() == D);
+  ASSERT_FALSE(GlobalDesc->asExpr());
+  ASSERT_TRUE(GlobalDesc->asValueDecl() == D);
+  ASSERT_FALSE(GlobalDesc->asFieldDecl());
+  ASSERT_FALSE(GlobalDesc->asRecordDecl());
+
+  // Still true because this is a global variable.
+  ASSERT_TRUE(GlobalDesc->getMetadataSize() == 0);
+  ASSERT_FALSE(GlobalDesc->isPrimitiveArray());
+  ASSERT_FALSE(GlobalDesc->isCompositeArray());
+  ASSERT_FALSE(GlobalDesc->isZeroSizeArray());
+  ASSERT_FALSE(GlobalDesc->isUnknownSizeArray());
+  ASSERT_FALSE(GlobalDesc->isPrimitive());
+  ASSERT_FALSE(GlobalDesc->isArray());
+  ASSERT_TRUE(GlobalDesc->isRecord());
+
+  // Test the Record for the struct S.
+  const Record *SRecord = GlobalDesc->ElemRecord;
+  ASSERT_TRUE(SRecord);
+  ASSERT_TRUE(SRecord->getNumFields() == 4);
+  ASSERT_TRUE(SRecord->getNumBases() == 0);
+  ASSERT_FALSE(SRecord->getDestructor());
+
+  // First field.
+  const Record::Field *F1 = SRecord->getField(0u);
+  ASSERT_TRUE(F1);
+  // ASSERT_FALSE(F1->isBitField());
+  ASSERT_TRUE(F1->Desc->isPrimitive());
+
+  // Second field.
+  const Record::Field *F2 = SRecord->getField(1u);
+  ASSERT_TRUE(F2);
+  // ASSERT_FALSE(F2->isBitField());
+  ASSERT_TRUE(F2->Desc->isArray());
+  ASSERT_FALSE(F2->Desc->isCompositeArray());
+  ASSERT_TRUE(F2->Desc->isPrimitiveArray());
+  ASSERT_FALSE(F2->Desc->isPrimitive());
+  ASSERT_FALSE(F2->Desc->ElemDesc);
+  ASSERT_EQ(F2->Desc->getNumElems(), 4u);
+  ASSERT_TRUE(F2->Desc->getElemSize() > 0);
+
+  // Third field.
+  const Record::Field *F3 = SRecord->getField(2u);
+  ASSERT_TRUE(F3);
+  // ASSERT_FALSE(F3->isBitField());
+  ASSERT_TRUE(F3->Desc->isArray());
+  ASSERT_TRUE(F3->Desc->isCompositeArray());
+  ASSERT_FALSE(F3->Desc->isPrimitiveArray());
+  ASSERT_FALSE(F3->Desc->isPrimitive());
+  ASSERT_TRUE(F3->Desc->ElemDesc);
+  ASSERT_EQ(F3->Desc->getNumElems(), 3u);
+  ASSERT_TRUE(F3->Desc->getElemSize() > 0);
+
+  // Fourth field.
+  // Multidimensional arrays are treated as composite arrays, even
+  // if the value type is primitive.
+  const Record::Field *F4 = SRecord->getField(3u);
+  ASSERT_TRUE(F4);
+  // ASSERT_FALSE(F4->isBitField());
+  ASSERT_TRUE(F4->Desc->isArray());
+  ASSERT_TRUE(F4->Desc->isCompositeArray());
+  ASSERT_FALSE(F4->Desc->isPrimitiveArray());
+  ASSERT_FALSE(F4->Desc->isPrimitive());
+  ASSERT_TRUE(F4->Desc->ElemDesc);
+  ASSERT_EQ(F4->Desc->getNumElems(), 3u);
+  ASSERT_TRUE(F4->Desc->getElemSize() > 0);
+  ASSERT_TRUE(F4->Desc->ElemDesc->isPrimitiveArray());
+
+  // Check pointer stuff.
+  // Global variables have no inline descriptor (yet)

[PATCH] D158069: [clang][Interp] Fix getIndex() for composite array elements

2023-10-09 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added inline comments.



Comment at: clang/lib/AST/Interp/Pointer.h:81-88
+  /// Equality operators are just for tests.
+  bool operator==(const Pointer &P) const {
+return Pointee == P.Pointee && Base == P.Base && Offset == P.Offset;
+  }
+
+  bool operator!=(const Pointer &P) const {
+return Pointee != P.Pointee || Base != P.Base || Offset != P.Offset;

aaron.ballman wrote:
> tbaeder wrote:
> > aaron.ballman wrote:
> > > tbaeder wrote:
> > > > aaron.ballman wrote:
> > > > > Same here -- can these be private and friended?
> > > > Don't you need a class to friend something? I only have the `TEST(...)` 
> > > > function in the unit test, so I can't do that, right?
> > > `FRIEND_TEST` does this, I believe: 
> > > https://google.github.io/googletest/reference/testing.html#FRIEND_TEST
> > Is this something we should be doing? There's nothing else in clang using 
> > `FRIEND_TEST` and only stuff in `Testing/` includes gtest.h.
> It's a tradeoff as to whether we want to expose private implementation 
> details as part of a public interface just to enable unit testing, or whether 
> we want to sprinkle unit testing annotations around the private 
> implementation details just to enable unit testing. Personally, I prefer 
> having cleaner public interfaces; otherwise we end up with people using the 
> implementation details of a class and it's harder to refactor in the future. 
> I'm not certain how others feel, though.
I think `FRIEND_TEST` just doesn't work because I can't import a gtest header 
from the `clangAST` library.

What I //can// do is just wrap those things in a `#ifdef IN_UNITTEST` and 
define than before including those headers (all of this  code is in headers 
right now) in the `unittest/AST/Interp/Descriptor.cpp`.


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

https://reviews.llvm.org/D158069

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


[PATCH] D157252: [clang][ExprConst] Handle 0 type size in builtin_memcpy etc.

2023-10-09 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157252

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


[PATCH] D154581: [clang][Interp] Track existing InitMaps in InterpState

2023-10-09 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


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

https://reviews.llvm.org/D154581

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


[PATCH] D154262: [clang][Interp] LambdaThisCaptures

2023-10-05 Thread Timm Bäder via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG57147bb25303: [clang][Interp] Support LambdaThisCaptures 
(authored by tbaeder).

Changed prior to commit:
  https://reviews.llvm.org/D154262?vs=536427&id=557605#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154262

Files:
  clang/lib/AST/Interp/ByteCodeEmitter.cpp
  clang/lib/AST/Interp/ByteCodeEmitter.h
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/EvalEmitter.h
  clang/test/AST/Interp/lambda.cpp


Index: clang/test/AST/Interp/lambda.cpp
===
--- clang/test/AST/Interp/lambda.cpp
+++ clang/test/AST/Interp/lambda.cpp
@@ -179,3 +179,24 @@
   }
   static_assert(heh() == 1.0);
 }
+
+namespace ThisCapture {
+  class Foo {
+  public:
+int b = 32;
+int a;
+
+constexpr Foo() : a([this](){ return b + 1;}()) {}
+
+constexpr int Aplus2() const {
+  auto F = [this]() {
+return a + 2;
+  };
+
+  return F();
+}
+  };
+  constexpr Foo F;
+  static_assert(F.a == 33, "");
+  static_assert(F.Aplus2() == (33 + 2), "");
+}
Index: clang/lib/AST/Interp/EvalEmitter.h
===
--- clang/lib/AST/Interp/EvalEmitter.h
+++ clang/lib/AST/Interp/EvalEmitter.h
@@ -73,7 +73,8 @@
   llvm::DenseMap Params;
   /// Lambda captures.
   llvm::DenseMap LambdaCaptures;
-  unsigned LambdaThisCapture;
+  /// Offset of the This parameter in a lambda record.
+  unsigned LambdaThisCapture = 0;
   /// Local descriptors.
   llvm::SmallVector, 2> Descriptors;
 
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -2305,6 +2305,10 @@
 bool ByteCodeExprGen::VisitCXXThisExpr(const CXXThisExpr *E) {
   if (DiscardResult)
 return true;
+
+  if (this->LambdaThisCapture > 0)
+return this->emitGetThisFieldPtr(this->LambdaThisCapture, E);
+
   return this->emitThis(E);
 }
 
Index: clang/lib/AST/Interp/ByteCodeEmitter.h
===
--- clang/lib/AST/Interp/ByteCodeEmitter.h
+++ clang/lib/AST/Interp/ByteCodeEmitter.h
@@ -67,7 +67,8 @@
   llvm::DenseMap Params;
   /// Lambda captures.
   llvm::DenseMap LambdaCaptures;
-  unsigned LambdaThisCapture;
+  /// Offset of the This parameter in a lambda record.
+  unsigned LambdaThisCapture = 0;
   /// Local descriptors.
   llvm::SmallVector, 2> Descriptors;
 
Index: clang/lib/AST/Interp/ByteCodeEmitter.cpp
===
--- clang/lib/AST/Interp/ByteCodeEmitter.cpp
+++ clang/lib/AST/Interp/ByteCodeEmitter.cpp
@@ -64,8 +64,8 @@
 this->LambdaCaptures[Cap.first] = {
 Offset, Cap.second->getType()->isReferenceType()};
   }
-  // FIXME: LambdaThisCapture
-  (void)LTC;
+  if (LTC)
+this->LambdaThisCapture = R->getField(LTC)->Offset;
 }
   }
 


Index: clang/test/AST/Interp/lambda.cpp
===
--- clang/test/AST/Interp/lambda.cpp
+++ clang/test/AST/Interp/lambda.cpp
@@ -179,3 +179,24 @@
   }
   static_assert(heh() == 1.0);
 }
+
+namespace ThisCapture {
+  class Foo {
+  public:
+int b = 32;
+int a;
+
+constexpr Foo() : a([this](){ return b + 1;}()) {}
+
+constexpr int Aplus2() const {
+  auto F = [this]() {
+return a + 2;
+  };
+
+  return F();
+}
+  };
+  constexpr Foo F;
+  static_assert(F.a == 33, "");
+  static_assert(F.Aplus2() == (33 + 2), "");
+}
Index: clang/lib/AST/Interp/EvalEmitter.h
===
--- clang/lib/AST/Interp/EvalEmitter.h
+++ clang/lib/AST/Interp/EvalEmitter.h
@@ -73,7 +73,8 @@
   llvm::DenseMap Params;
   /// Lambda captures.
   llvm::DenseMap LambdaCaptures;
-  unsigned LambdaThisCapture;
+  /// Offset of the This parameter in a lambda record.
+  unsigned LambdaThisCapture = 0;
   /// Local descriptors.
   llvm::SmallVector, 2> Descriptors;
 
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -2305,6 +2305,10 @@
 bool ByteCodeExprGen::VisitCXXThisExpr(const CXXThisExpr *E) {
   if (DiscardResult)
 return true;
+
+  if (this->LambdaThisCapture > 0)
+return this->emitGetThisFieldPtr(this->LambdaThisCapture, E);
+
   return this->emitThis(E);
 }
 
Index: clang/lib/AST/Interp/ByteCodeEmitter.h
===
--- clang/lib/AST/Interp/ByteCodeEmitter.h
+++ clang/lib/AST/Interp/ByteCodeEmitter.h
@@ -67,7 +67,8 @@
 

[PATCH] D158516: [clang][Interp] Only lazily visit constant globals

2023-10-05 Thread Timm Bäder via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG4d7f4a7c82cb: [clang][Interp] Only lazily visit constant 
globals (authored by tbaeder).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D158516

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/test/AST/Interp/c.c


Index: clang/test/AST/Interp/c.c
===
--- clang/test/AST/Interp/c.c
+++ clang/test/AST/Interp/c.c
@@ -14,11 +14,15 @@
// pedantic-expected-warning {{not an integer 
constant expression}}
 _Static_assert(!!1, "");
 
-/// FIXME: Should also be rejected in the new interpreter
-int a = (1 == 1 ? 5 : 3);
+int a = (1 == 1 ? 5 : 3); // expected-note {{declared here}} \
+  // pedantic-expected-note {{declared here}}
 _Static_assert(a == 5, ""); // ref-error {{not an integral constant 
expression}} \
 // pedantic-ref-error {{not an integral constant 
expression}} \
-// pedantic-expected-warning {{not an integer 
constant expression}}
+// expected-error {{not an integral constant 
expression}} \
+// expected-note {{read of non-const variable}} \
+// pedantic-expected-error {{not an integral 
constant expression}} \
+// pedantic-expected-note {{read of non-const 
variable}}
+
 
 const int b = 3;
 _Static_assert(b == 3, ""); // pedantic-ref-warning {{not an integer constant 
expression}} \
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -2536,7 +2536,8 @@
   // This happens in C.
   if (!Ctx.getLangOpts().CPlusPlus) {
 if (const auto *VD = dyn_cast(D);
-VD && VD->hasGlobalStorage() && VD->getAnyInitializer()) {
+VD && VD->hasGlobalStorage() && VD->getAnyInitializer() &&
+VD->getType().isConstQualified()) {
   if (!this->visitVarDecl(VD))
 return false;
   // Retry.


Index: clang/test/AST/Interp/c.c
===
--- clang/test/AST/Interp/c.c
+++ clang/test/AST/Interp/c.c
@@ -14,11 +14,15 @@
// pedantic-expected-warning {{not an integer constant expression}}
 _Static_assert(!!1, "");
 
-/// FIXME: Should also be rejected in the new interpreter
-int a = (1 == 1 ? 5 : 3);
+int a = (1 == 1 ? 5 : 3); // expected-note {{declared here}} \
+  // pedantic-expected-note {{declared here}}
 _Static_assert(a == 5, ""); // ref-error {{not an integral constant expression}} \
 // pedantic-ref-error {{not an integral constant expression}} \
-// pedantic-expected-warning {{not an integer constant expression}}
+// expected-error {{not an integral constant expression}} \
+// expected-note {{read of non-const variable}} \
+// pedantic-expected-error {{not an integral constant expression}} \
+// pedantic-expected-note {{read of non-const variable}}
+
 
 const int b = 3;
 _Static_assert(b == 3, ""); // pedantic-ref-warning {{not an integer constant expression}} \
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -2536,7 +2536,8 @@
   // This happens in C.
   if (!Ctx.getLangOpts().CPlusPlus) {
 if (const auto *VD = dyn_cast(D);
-VD && VD->hasGlobalStorage() && VD->getAnyInitializer()) {
+VD && VD->hasGlobalStorage() && VD->getAnyInitializer() &&
+VD->getType().isConstQualified()) {
   if (!this->visitVarDecl(VD))
 return false;
   // Retry.
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D156453: [clang][Interp] Create only globals when initializing a global variable

2023-10-04 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

It gets interpreted as a constant expression in 
`Sema::CheckCompleteVariableInitialization()`:

  * #0: Context.cpp:73  
clang::interp::Context::evaluateAsInitializer(this=0x60805d20, 
Parent=0x7fff6dc2a8d0, VD=0x62173b48, Result=0x62199e90)
#1: ExprConstant.cpp:15600  
clang::Expr::EvaluateAsInitializer(this=0x62199e40, 
Value=0x62199e90, Ctx=0x62a00200, VD=0x62173b48, 
Notes=0x7fff6deac850, IsConstantInitialization=true) const
#2: Decl.cpp:2555  
clang::VarDecl::evaluateValueImpl(this=0x62173b48, 
Notes=0x7fff6deac850, IsConstantInitialization=true) const
#3: Decl.cpp:2626  
clang::VarDecl::checkForConstantInitialization(this=0x62173b48, 
Notes=0x7fff6deac850) const
#4: SemaDecl.cpp:14399  
clang::Sema::CheckCompleteVariableDeclaration(this=0x6290a200, 
var=0x62173b48)


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156453

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


[PATCH] D158069: [clang][Interp] Fix getIndex() for composite array elements

2023-10-02 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added inline comments.



Comment at: clang/lib/AST/Interp/Pointer.h:81-88
+  /// Equality operators are just for tests.
+  bool operator==(const Pointer &P) const {
+return Pointee == P.Pointee && Base == P.Base && Offset == P.Offset;
+  }
+
+  bool operator!=(const Pointer &P) const {
+return Pointee != P.Pointee || Base != P.Base || Offset != P.Offset;

aaron.ballman wrote:
> tbaeder wrote:
> > aaron.ballman wrote:
> > > Same here -- can these be private and friended?
> > Don't you need a class to friend something? I only have the `TEST(...)` 
> > function in the unit test, so I can't do that, right?
> `FRIEND_TEST` does this, I believe: 
> https://google.github.io/googletest/reference/testing.html#FRIEND_TEST
Is this something we should be doing? There's nothing else in clang using 
`FRIEND_TEST` and only stuff in `Testing/` includes gtest.h.


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

https://reviews.llvm.org/D158069

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


[PATCH] D158516: [clang][Interp] Only lazily visit constant globals

2023-10-02 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D158516

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


[PATCH] D157252: [clang][ExprConst] Handle 0 type size in builtin_memcpy etc.

2023-10-02 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157252

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


[PATCH] D156453: [clang][Interp] Create only globals when initializing a global variable

2023-10-02 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156453

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


[PATCH] D154262: [clang][Interp] LambdaThisCaptures

2023-10-02 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154262

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


[PATCH] D156565: Diagnose use of VLAs in C++ by default

2023-10-02 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added inline comments.



Comment at: clang/test/SemaCXX/offsetof.cpp:31
+  int array1[__builtin_offsetof(HasArray, array[i])]; // expected-warning 
{{variable length arrays are a Clang extension}} \
+ new-interp-note 
{{function parameter 'i' with unknown value cannot be used in a constant 
expression}}
 }

aaron.ballman wrote:
> jyknight wrote:
> > Weird that new-interp adds the diagnostic for C++98 mode. I wonder if that 
> > indicates a bug (e.g. if in new-interp we accidentally use C++11 rules for 
> > C++98)?
> CC @tbaeder 
https://github.com/llvm/llvm-project/pull/67990


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

https://reviews.llvm.org/D156565

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


[PATCH] D158069: [clang][Interp] Fix getIndex() for composite array elements

2023-09-30 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added inline comments.



Comment at: clang/lib/AST/Interp/Pointer.h:81-88
+  /// Equality operators are just for tests.
+  bool operator==(const Pointer &P) const {
+return Pointee == P.Pointee && Base == P.Base && Offset == P.Offset;
+  }
+
+  bool operator!=(const Pointer &P) const {
+return Pointee != P.Pointee || Base != P.Base || Offset != P.Offset;

aaron.ballman wrote:
> Same here -- can these be private and friended?
Don't you need a class to friend something? I only have the `TEST(...)` 
function in the unit test, so I can't do that, right?


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

https://reviews.llvm.org/D158069

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


[PATCH] D155572: [clang][Interp] Start implementing binary operators for complex types

2023-09-29 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added inline comments.



Comment at: clang/test/AST/Interp/complex.cpp:119-124
+  using Bobble = _Complex float;
+  constexpr _Complex float A = { 13.0, 2.0 };
+  constexpr Bobble B = { 2.0, 1.0  };
+  constexpr _Complex float D = A - B;
+  static_assert(__real(D) == 11.0, "");
+  static_assert(__imag(D) == 1.0, "");

aaron.ballman wrote:
> Should this be under the `Sub` namespace instead of hanging out by itself?
Yeah I guess it should.


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

https://reviews.llvm.org/D155572

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


[PATCH] D158069: [clang][Interp] Fix getIndex() for composite array elements

2023-09-27 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


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

https://reviews.llvm.org/D158069

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


[PATCH] D158516: [clang][Interp] Only lazily visit constant globals

2023-09-25 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D158516

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


[PATCH] D156453: [clang][Interp] Create only globals when initializing a global variable

2023-09-25 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156453

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


[PATCH] D157252: [clang][ExprConst] Handle 0 type size in builtin_memcpy etc.

2023-09-25 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157252

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


[PATCH] D154581: [clang][Interp] Track existing InitMaps in InterpState

2023-09-25 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


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

https://reviews.llvm.org/D154581

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


[PATCH] D154262: [clang][Interp] LambdaThisCaptures

2023-09-25 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154262

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


[PATCH] D155572: [clang][Interp] Start implementing binary operators for complex types

2023-09-22 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


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

https://reviews.llvm.org/D155572

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


[PATCH] D158069: [clang][Interp] Fix getIndex() for composite array elements

2023-09-20 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added inline comments.



Comment at: clang/lib/AST/Interp/Context.h:88
+  /// Returns the program. This is only needed for unittests.
+  Program &getProgram() const { return *P.get(); }
+

cor3ntin wrote:
> This should return a const ref
Things like `getGlobal()` aren't const so that doesn't work.



Comment at: clang/lib/AST/Interp/Pointer.h:342
+
+// narrow()ed element in a composite array.
+if (Base > 0 && Base == Offset)

cor3ntin wrote:
> Can you be a bit more verbose here? I can't figure out what is happening from 
> the comment!
For primitive arrays, the elements don't have inline descriptors:

```
 Offset
 │
 ▼
┌┬───┬───┬───┬───┬───┬─┐
│InitMap │ 1 │ 2 │ 3 │ 4 │ 5 │ ... │
└┴───┴───┴───┴───┴───┴─┘
▲
│
Base
```

If the array elements are composite elements themselves however, we can have a 
pointer that refers to the array element:

```
   Offset
   │
   ▼
┌──┬───┬──┬───┐
│InlineDesc│'a'│InlineDesc│'b'│
└──┴───┴──┴───┘
▲
│
Base
```

(so things like `isArrayElement()` return `true`) as well as a pointer that 
_only_ refers to the composite element (after a call to `narrow()`:

```
   Offset
   │
   ▼
┌──┬───┬──┬───┐
│InlineDesc│'a'│InlineDesc│'b'│
└──┴───┴──┴───┘
   ▲
   │
   Base
```

For the latter, the expected value of `getIndex()` is `0`, since it is (as far 
as the pointer knows) _not_ an array element.


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

https://reviews.llvm.org/D158069

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


[PATCH] D158069: [clang][Interp] Fix getIndex() for composite array elements

2023-09-19 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder updated this revision to Diff 557097.
tbaeder marked an inline comment as done.

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

https://reviews.llvm.org/D158069

Files:
  clang/lib/AST/Interp/Context.h
  clang/lib/AST/Interp/Pointer.h
  clang/unittests/AST/CMakeLists.txt
  clang/unittests/AST/Interp/CMakeLists.txt
  clang/unittests/AST/Interp/Descriptor.cpp

Index: clang/unittests/AST/Interp/Descriptor.cpp
===
--- /dev/null
+++ clang/unittests/AST/Interp/Descriptor.cpp
@@ -0,0 +1,385 @@
+#include "../../../lib/AST/Interp/Descriptor.h"
+#include "../../../lib/AST/Interp/Context.h"
+#include "../../../lib/AST/Interp/Program.h"
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/Decl.h"
+#include "clang/ASTMatchers/ASTMatchFinder.h"
+#include "clang/ASTMatchers/ASTMatchers.h"
+#include "clang/Tooling/Tooling.h"
+#include "gtest/gtest.h"
+
+using namespace clang;
+using namespace clang::interp;
+using namespace clang::ast_matchers;
+
+/// Inspect generated Descriptors as well as the pointers we create.
+///
+TEST(Descriptor, Primitives) {
+  constexpr char Code[] =
+  "struct A { bool a; bool b; };\n"
+  "struct S {\n"
+  "  float f;\n"
+  "  char s[4];\n"
+  "  A a[3];\n"
+  "  short l[3][3];\n"
+  "};\n"
+  "constexpr S d = {0.0, \"foo\", {{true, false}, {false, true}, {false, false}},\n"
+  "  {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}};\n";
+
+  auto AST = tooling::buildASTFromCodeWithArgs(
+  Code, {"-fexperimental-new-constant-interpreter"});
+
+  const VarDecl *D = selectFirst(
+  "d", match(varDecl().bind("d"), AST->getASTContext()));
+  ASSERT_NE(D, nullptr);
+
+  const auto &Ctx = AST->getASTContext().getInterpContext();
+  Program &Prog = Ctx.getProgram();
+  // Global is registered.
+  ASSERT_TRUE(Prog.getGlobal(D));
+
+  // Get a Pointer to the global.
+  const Pointer &GlobalPtr = Prog.getPtrGlobal(*Prog.getGlobal(D));
+
+  // Test Descriptor of the struct S.
+  const Descriptor *GlobalDesc = GlobalPtr.getFieldDesc();
+  ASSERT_TRUE(GlobalDesc == GlobalPtr.getDeclDesc());
+
+  ASSERT_TRUE(GlobalDesc->asDecl() == D);
+  ASSERT_FALSE(GlobalDesc->asExpr());
+  ASSERT_TRUE(GlobalDesc->asValueDecl() == D);
+  ASSERT_FALSE(GlobalDesc->asFieldDecl());
+  ASSERT_FALSE(GlobalDesc->asRecordDecl());
+
+  // Still true because this is a global variable.
+  ASSERT_TRUE(GlobalDesc->getMetadataSize() == 0);
+  ASSERT_FALSE(GlobalDesc->isPrimitiveArray());
+  ASSERT_FALSE(GlobalDesc->isCompositeArray());
+  ASSERT_FALSE(GlobalDesc->isZeroSizeArray());
+  ASSERT_FALSE(GlobalDesc->isUnknownSizeArray());
+  ASSERT_FALSE(GlobalDesc->isPrimitive());
+  ASSERT_FALSE(GlobalDesc->isArray());
+  ASSERT_TRUE(GlobalDesc->isRecord());
+
+  // Test the Record for the struct S.
+  const Record *SRecord = GlobalDesc->ElemRecord;
+  ASSERT_TRUE(SRecord);
+  ASSERT_TRUE(SRecord->getNumFields() == 4);
+  ASSERT_TRUE(SRecord->getNumBases() == 0);
+  ASSERT_FALSE(SRecord->getDestructor());
+
+  // First field.
+  const Record::Field *F1 = SRecord->getField(0u);
+  ASSERT_TRUE(F1);
+  ASSERT_FALSE(F1->isBitField());
+  ASSERT_TRUE(F1->Desc->isPrimitive());
+
+  // Second field.
+  const Record::Field *F2 = SRecord->getField(1u);
+  ASSERT_TRUE(F2);
+  ASSERT_FALSE(F2->isBitField());
+  ASSERT_TRUE(F2->Desc->isArray());
+  ASSERT_FALSE(F2->Desc->isCompositeArray());
+  ASSERT_TRUE(F2->Desc->isPrimitiveArray());
+  ASSERT_FALSE(F2->Desc->isPrimitive());
+  ASSERT_FALSE(F2->Desc->ElemDesc);
+  ASSERT_EQ(F2->Desc->getNumElems(), 4u);
+  ASSERT_TRUE(F2->Desc->getElemSize() > 0);
+
+  // Third field.
+  const Record::Field *F3 = SRecord->getField(2u);
+  ASSERT_TRUE(F3);
+  ASSERT_FALSE(F3->isBitField());
+  ASSERT_TRUE(F3->Desc->isArray());
+  ASSERT_TRUE(F3->Desc->isCompositeArray());
+  ASSERT_FALSE(F3->Desc->isPrimitiveArray());
+  ASSERT_FALSE(F3->Desc->isPrimitive());
+  ASSERT_TRUE(F3->Desc->ElemDesc);
+  ASSERT_EQ(F3->Desc->getNumElems(), 3u);
+  ASSERT_TRUE(F3->Desc->getElemSize() > 0);
+
+  // Fourth field.
+  // Multidimensional arrays are treated as composite arrays, even
+  // if the value type is primitive.
+  const Record::Field *F4 = SRecord->getField(3u);
+  ASSERT_TRUE(F4);
+  ASSERT_FALSE(F4->isBitField());
+  ASSERT_TRUE(F4->Desc->isArray());
+  ASSERT_TRUE(F4->Desc->isCompositeArray());
+  ASSERT_FALSE(F4->Desc->isPrimitiveArray());
+  ASSERT_FALSE(F4->Desc->isPrimitive());
+  ASSERT_TRUE(F4->Desc->ElemDesc);
+  ASSERT_EQ(F4->Desc->getNumElems(), 3u);
+  ASSERT_TRUE(F4->Desc->getElemSize() > 0);
+  ASSERT_TRUE(F4->Desc->ElemDesc->isPrimitiveArray());
+
+  // Check pointer stuff.
+  // Global variables have no inline descriptor (yet).
+  ASSERT_TRUE(GlobalPtr.isRoot());
+  ASSERT_TRUE(GlobalPtr.isLive());
+  ASSERT_FALSE(GlobalPtr.isZero());
+  ASSERT_FALSE(GlobalPtr.isField());
+  ASSERT_TRUE(GlobalPtr.getFieldDesc() == GlobalPtr.getDeclDesc());
+  ASSERT_TRUE(GlobalPtr.getOffset() == 0);

[PATCH] D152504: [clang][ThreadSafety] Analyze cleanup functions

2023-09-19 Thread Timm Bäder via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
tbaeder marked an inline comment as done.
Closed by commit rGcf8e189a99f9: [clang][TSA] Thread safety cleanup functions 
(authored by tbaeder).

Changed prior to commit:
  https://reviews.llvm.org/D152504?vs=556838&id=557042#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D152504

Files:
  clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
  clang/lib/Analysis/ThreadSafety.cpp
  clang/lib/Analysis/ThreadSafetyCommon.cpp
  clang/test/Sema/warn-thread-safety-analysis.c

Index: clang/test/Sema/warn-thread-safety-analysis.c
===
--- clang/test/Sema/warn-thread-safety-analysis.c
+++ clang/test/Sema/warn-thread-safety-analysis.c
@@ -72,6 +72,8 @@
   return *p;
 }
 
+void unlock_scope(struct Mutex *const *mu) __attribute__((release_capability(**mu)));
+
 int main(void) {
 
   Foo_fun1(1); // expected-warning{{calling function 'Foo_fun1' requires holding mutex 'mu2'}} \
@@ -127,6 +129,13 @@
 // expected-note@-1{{mutex released here}}
   mutex_shared_unlock(&mu1);// expected-warning {{releasing mutex 'mu1' that was not held}}
 
+  /// Cleanup functions
+  {
+struct Mutex* const __attribute__((cleanup(unlock_scope))) scope = &mu1;
+mutex_exclusive_lock(scope);  // Note that we have to lock through scope, because no alias analysis!
+// Cleanup happens automatically -> no warning.
+  }
+
   return 0;
 }
 
Index: clang/lib/Analysis/ThreadSafetyCommon.cpp
===
--- clang/lib/Analysis/ThreadSafetyCommon.cpp
+++ clang/lib/Analysis/ThreadSafetyCommon.cpp
@@ -110,7 +110,8 @@
 /// \param D   The declaration to which the attribute is attached.
 /// \param DeclExp An expression involving the Decl to which the attribute
 ///is attached.  E.g. the call to a function.
-/// \param SelfS-expression to substitute for a \ref CXXThisExpr.
+/// \param SelfS-expression to substitute for a \ref CXXThisExpr in a call,
+///or argument to a cleanup function.
 CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp,
const NamedDecl *D,
const Expr *DeclExp,
@@ -144,7 +145,11 @@
 
   if (Self) {
 assert(!Ctx.SelfArg && "Ambiguous self argument");
-Ctx.SelfArg = Self;
+assert(isa(D) && "Self argument requires function");
+if (isa(D))
+  Ctx.SelfArg = Self;
+else
+  Ctx.FunArgs = Self;
 
 // If the attribute has no arguments, then assume the argument is "this".
 if (!AttrExp)
@@ -312,8 +317,14 @@
   ? (cast(D)->getCanonicalDecl() == Canonical)
   : (cast(D)->getCanonicalDecl() == Canonical)) {
 // Substitute call arguments for references to function parameters
-assert(I < Ctx->NumArgs);
-return translate(Ctx->FunArgs[I], Ctx->Prev);
+if (const Expr *const *FunArgs =
+Ctx->FunArgs.dyn_cast()) {
+  assert(I < Ctx->NumArgs);
+  return translate(FunArgs[I], Ctx->Prev);
+}
+
+assert(I == 0);
+return Ctx->FunArgs.get();
   }
 }
 // Map the param back to the param of the original function declaration
Index: clang/lib/Analysis/ThreadSafety.cpp
===
--- clang/lib/Analysis/ThreadSafety.cpp
+++ clang/lib/Analysis/ThreadSafety.cpp
@@ -1773,7 +1773,8 @@
 ///
 /// \param Exp   The call expression.
 /// \param D The callee declaration.
-/// \param Self  If \p Exp = nullptr, the implicit this argument.
+/// \param Self  If \p Exp = nullptr, the implicit this argument or the argument
+///  of an implicitly called cleanup function.
 /// \param Loc   If \p Exp = nullptr, the location.
 void BuildLockset::handleCall(const Expr *Exp, const NamedDecl *D,
   til::LiteralPtr *Self, SourceLocation Loc) {
@@ -2417,6 +2418,15 @@
 AD.getTriggerStmt()->getEndLoc());
   break;
 }
+
+case CFGElement::CleanupFunction: {
+  const CFGCleanupFunction &CF = BI.castAs();
+  LocksetBuilder.handleCall(/*Exp=*/nullptr, CF.getFunctionDecl(),
+SxBuilder.createVariable(CF.getVarDecl()),
+CF.getVarDecl()->getLocation());
+  break;
+}
+
 case CFGElement::TemporaryDtor: {
   auto TD = BI.castAs();
 
Index: clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
===
--- clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
+++ clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
@@ -361,7 +36

[PATCH] D157385: [clang][CFG] Cleanup functions

2023-09-19 Thread Timm Bäder via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGad4a51302777: [clang][CFG] Cleanup functions (authored by 
tbaeder).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157385

Files:
  clang/include/clang/Analysis/CFG.h
  clang/lib/Analysis/CFG.cpp
  clang/lib/Analysis/PathDiagnostic.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
  clang/test/Analysis/scopes-cfg-output.cpp

Index: clang/test/Analysis/scopes-cfg-output.cpp
===
--- clang/test/Analysis/scopes-cfg-output.cpp
+++ clang/test/Analysis/scopes-cfg-output.cpp
@@ -1419,3 +1419,68 @@
 }
   }
 }
+
+// CHECK:  [B1]
+// CHECK-NEXT:   1: CFGScopeBegin(i)
+// CHECK-NEXT:   2: int i __attribute__((cleanup(cleanup_int)));
+// CHECK-NEXT:   3: CleanupFunction (cleanup_int)
+// CHECK-NEXT:   4: CFGScopeEnd(i)
+void cleanup_int(int *i);
+void test_cleanup_functions() {
+  int i __attribute__((cleanup(cleanup_int)));
+}
+
+// CHECK:  [B1]
+// CHECK-NEXT:1: 10
+// CHECK-NEXT:2: i
+// CHECK-NEXT:3: [B1.2] = [B1.1]
+// CHECK-NEXT:4: return;
+// CHECK-NEXT:5: CleanupFunction (cleanup_int)
+// CHECK-NEXT:6: CFGScopeEnd(i)
+// CHECK-NEXT:Preds (1): B3
+// CHECK-NEXT:Succs (1): B0
+// CHECK:  [B2]
+// CHECK-NEXT:1: return;
+// CHECK-NEXT:2: CleanupFunction (cleanup_int)
+// CHECK-NEXT:3: CFGScopeEnd(i)
+// CHECK-NEXT:Preds (1): B3
+// CHECK-NEXT:Succs (1): B0
+// CHECK:  [B3]
+// CHECK-NEXT:1: CFGScopeBegin(i)
+// CHECK-NEXT:2: int i __attribute__((cleanup(cleanup_int)));
+// CHECK-NEXT:3: m
+// CHECK-NEXT:4: [B3.3] (ImplicitCastExpr, LValueToRValue, int)
+// CHECK-NEXT:5: 1
+// CHECK-NEXT:6: [B3.4] == [B3.5]
+// CHECK-NEXT:T: if [B3.6]
+// CHECK-NEXT:Preds (1): B4
+// CHECK-NEXT:Succs (2): B2 B1
+void test_cleanup_functions2(int m) {
+  int i __attribute__((cleanup(cleanup_int)));
+
+  if (m == 1) {
+return;
+  }
+
+  i = 10;
+  return;
+}
+
+// CHECK:   [B1]
+// CHECK-NEXT:1: CFGScopeBegin(f)
+// CHECK-NEXT:2:  (CXXConstructExpr, [B1.3], F)
+// CHECK-NEXT:3: __attribute__((cleanup(cleanup_F))) F f;
+// CHECK-NEXT:4: CleanupFunction (cleanup_F)
+// CHECK-NEXT:5: [B1.3].~F() (Implicit destructor)
+// CHECK-NEXT:6: CFGScopeEnd(f)
+// CHECK-NEXT:Preds (1): B2
+// CHECK-NEXT:Succs (1): B0
+class F {
+public:
+  ~F();
+};
+void cleanup_F(F *f);
+
+void test() {
+  F f __attribute((cleanup(cleanup_F)));
+}
Index: clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
===
--- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -993,6 +993,7 @@
   ProcessLoopExit(E.castAs().getLoopStmt(), Pred);
   return;
 case CFGElement::LifetimeEnds:
+case CFGElement::CleanupFunction:
 case CFGElement::ScopeBegin:
 case CFGElement::ScopeEnd:
   return;
Index: clang/lib/Analysis/PathDiagnostic.cpp
===
--- clang/lib/Analysis/PathDiagnostic.cpp
+++ clang/lib/Analysis/PathDiagnostic.cpp
@@ -567,6 +567,7 @@
   }
   case CFGElement::ScopeBegin:
   case CFGElement::ScopeEnd:
+  case CFGElement::CleanupFunction:
 llvm_unreachable("not yet implemented!");
   case CFGElement::LifetimeEnds:
   case CFGElement::LoopExit:
Index: clang/lib/Analysis/CFG.cpp
===
--- clang/lib/Analysis/CFG.cpp
+++ clang/lib/Analysis/CFG.cpp
@@ -881,6 +881,10 @@
 B->appendAutomaticObjDtor(VD, S, cfg->getBumpVectorContext());
   }
 
+  void appendCleanupFunction(CFGBlock *B, VarDecl *VD) {
+B->appendCleanupFunction(VD, cfg->getBumpVectorContext());
+  }
+
   void appendLifetimeEnds(CFGBlock *B, VarDecl *VD, Stmt *S) {
 B->appendLifetimeEnds(VD, S, cfg->getBumpVectorContext());
   }
@@ -1346,7 +1350,8 @@
 return {};
   }
 
-  bool hasTrivialDestructor(VarDecl *VD);
+  bool hasTrivialDestructor(const VarDecl *VD) const;
+  bool needsAutomaticDestruction(const VarDecl *VD) const;
 };
 
 } // namespace
@@ -1861,14 +1866,14 @@
   if (B == E)
 return;
 
-  SmallVector DeclsNonTrivial;
-  DeclsNonTrivial.reserve(B.distance(E));
+  SmallVector DeclsNeedDestruction;
+  DeclsNeedDestruction.reserve(B.distance(E));
 
   for (VarDecl* D : llvm::make_range(B, E))
-if (!hasTrivialDestructor(D))
-  DeclsNonTrivial.push_back(D);
+if (needsAutomaticDestruction(D))
+  DeclsNeedDestruction.push_back(D);
 
-  for (VarDecl *VD : llvm::reverse(DeclsNonTrivial)) {
+  for (VarDecl *VD : llvm::reverse(DeclsNeedDestruction)) {
 if (BuildOpts.AddImplicitDtors) {
   // If this destructor is marked as a no-return destructor, we need to
   // create a new block for the destructor which does not have as a
@@ -1879,7 

[PATCH] D158595: [clang][Interp] Allow zero-init of primitives with an empty init list

2023-09-18 Thread Timm Bäder via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG52a55a717838: [clang][Interp] Allow zero-init of primitives 
with an empty init list (authored by tbaeder).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D158595

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/test/AST/Interp/literals.cpp


Index: clang/test/AST/Interp/literals.cpp
===
--- clang/test/AST/Interp/literals.cpp
+++ clang/test/AST/Interp/literals.cpp
@@ -91,6 +91,15 @@
// ref-error {{not an integral constant 
expression}} \
// ref-note {{outside the range of 
representable values}} \
 
+namespace PrimitiveEmptyInitList {
+  constexpr int a = {};
+  static_assert(a == 0, "");
+  constexpr bool b = {};
+  static_assert(!b, "");
+  constexpr double d = {};
+  static_assert(d == 0.0, "");
+}
+
 
 enum E {};
 constexpr E e = static_cast(0);
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -571,8 +571,10 @@
 
   // Primitive values.
   if (std::optional T = classify(E->getType())) {
-assert(E->getNumInits() == 1);
 assert(!DiscardResult);
+if (E->getNumInits() == 0)
+  return this->visitZeroInitializer(E->getType(), E);
+assert(E->getNumInits() == 1);
 return this->delegate(E->inits()[0]);
   }
 


Index: clang/test/AST/Interp/literals.cpp
===
--- clang/test/AST/Interp/literals.cpp
+++ clang/test/AST/Interp/literals.cpp
@@ -91,6 +91,15 @@
// ref-error {{not an integral constant expression}} \
// ref-note {{outside the range of representable values}} \
 
+namespace PrimitiveEmptyInitList {
+  constexpr int a = {};
+  static_assert(a == 0, "");
+  constexpr bool b = {};
+  static_assert(!b, "");
+  constexpr double d = {};
+  static_assert(d == 0.0, "");
+}
+
 
 enum E {};
 constexpr E e = static_cast(0);
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -571,8 +571,10 @@
 
   // Primitive values.
   if (std::optional T = classify(E->getType())) {
-assert(E->getNumInits() == 1);
 assert(!DiscardResult);
+if (E->getNumInits() == 0)
+  return this->visitZeroInitializer(E->getType(), E);
+assert(E->getNumInits() == 1);
 return this->delegate(E->inits()[0]);
   }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D158516: [clang][Interp] Only lazily visit constant globals

2023-09-18 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D158516

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


[PATCH] D157252: [clang][ExprConst] Handle 0 type size in builtin_memcpy etc.

2023-09-18 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157252

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


[PATCH] D156453: [clang][Interp] Create only globals when initializing a global variable

2023-09-18 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156453

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


[PATCH] D154581: [clang][Interp] Track existing InitMaps in InterpState

2023-09-18 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


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

https://reviews.llvm.org/D154581

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


[PATCH] D154262: [clang][Interp] LambdaThisCaptures

2023-09-18 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154262

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


[PATCH] D156511: [clang][Interp] Diagnose more unkonwn DeclRefExprs

2023-09-15 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder closed this revision.
tbaeder added a comment.

Looks like I squashed this into https://reviews.llvm.org/D156509 for some 
reason.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156511

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


[PATCH] D156509: [clang][Interp] Diagnose unknown parameter values

2023-09-15 Thread Timm Bäder via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG23c39f9a9e14: [clang][Interp] Diagnose unknown parameter 
values (authored by tbaeder).

Changed prior to commit:
  https://reviews.llvm.org/D156509?vs=545193&id=556845#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156509

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/Interp.cpp
  clang/lib/AST/Interp/Interp.h
  clang/lib/AST/Interp/Opcodes.td
  clang/test/AST/Interp/c.c
  clang/test/AST/Interp/functions.cpp
  clang/test/AST/Interp/literals.cpp

Index: clang/test/AST/Interp/literals.cpp
===
--- clang/test/AST/Interp/literals.cpp
+++ clang/test/AST/Interp/literals.cpp
@@ -1088,3 +1088,31 @@
   int array[(intptr_t)(char*)0]; // ref-warning {{variable length array folded to constant array}} \
  // expected-warning {{variable length array folded to constant array}}
 }
+
+namespace InvalidDeclRefs {
+  bool b00; // ref-note {{declared here}} \
+// expected-note {{declared here}}
+  static_assert(b00, ""); // ref-error {{not an integral constant expression}} \
+  // ref-note {{read of non-const variable}} \
+  // expected-error {{not an integral constant expression}} \
+  // expected-note {{read of non-const variable}}
+
+  float b01; // ref-note {{declared here}} \
+ // expected-note {{declared here}}
+  static_assert(b01, ""); // ref-error {{not an integral constant expression}} \
+  // ref-note {{read of non-constexpr variable}} \
+  // expected-error {{not an integral constant expression}} \
+  // expected-note {{read of non-constexpr variable}}
+
+  extern const int b02; // ref-note {{declared here}} \
+// expected-note {{declared here}}
+  static_assert(b02, ""); // ref-error {{not an integral constant expression}} \
+  // ref-note {{initializer of 'b02' is unknown}} \
+  // expected-error {{not an integral constant expression}} \
+  // expected-note {{initializer of 'b02' is unknown}}
+
+  /// FIXME: This should also be diagnosed in the new interpreter.
+  int b03 = 3; // ref-note {{declared here}}
+  static_assert(b03, ""); // ref-error {{not an integral constant expression}} \
+  // ref-note {{read of non-const variable}}
+}
Index: clang/test/AST/Interp/functions.cpp
===
--- clang/test/AST/Interp/functions.cpp
+++ clang/test/AST/Interp/functions.cpp
@@ -1,5 +1,9 @@
 // RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify %s
+// RUN: %clang_cc1 -std=c++14 -fexperimental-new-constant-interpreter -verify %s
+// RUN: %clang_cc1 -std=c++20 -fexperimental-new-constant-interpreter -verify %s
 // RUN: %clang_cc1 -verify=ref %s
+// RUN: %clang_cc1 -std=c++14 -verify=ref %s
+// RUN: %clang_cc1 -std=c++20 -verify=ref %s
 
 constexpr void doNothing() {}
 constexpr int gimme5() {
@@ -307,3 +311,24 @@
   }
   static_assert((foo(),1) == 1, "");
 }
+
+namespace InvalidReclRefs {
+  void param(bool b) { // ref-note {{declared here}} \
+   // expected-note {{declared here}}
+static_assert(b, ""); // ref-error {{not an integral constant expression}} \
+  // ref-note {{function parameter 'b' with unknown value}} \
+  // expected-error {{not an integral constant expression}} \
+  // expected-note {{function parameter 'b' with unknown value}}
+static_assert(true ? true : b, "");
+  }
+
+#if __cplusplus >= 202002L
+  consteval void param2(bool b) { // ref-note {{declared here}} \
+ // expected-note {{declared here}}
+static_assert(b, ""); // ref-error {{not an integral constant expression}} \
+  // ref-note {{function parameter 'b' with unknown value}} \
+  // expected-error {{not an integral constant expression}} \
+  // expected-note {{function parameter 'b' with unknown value}}
+  }
+#endif
+}
Index: clang/test/AST/Interp/c.c
===
--- clang/test/AST/Interp/c.c
+++ clang/test/AST/Interp/c.c
@@ -3,8 +3,6 @@
 // RUN: %clang_cc1 -verify=ref -std=c11 %s
 // RUN: %clang_cc1 -pedantic -verify=pedantic-ref -std=c11 %s
 
-/// expected-no-diagnostics
-
 _Static_assert(1, "");
 _Static_assert(0 != 1, "");
 _Static_assert(1.0 == 1.0, ""); // pedantic-ref-warning {{not an integer constant expression}} \
@@ -26,3 +24,15 @@
 _Static_assert(b == 3, ""); // peda

[PATCH] D158702: [clang][Interp] Check pointer inc/dec ops for initialization

2023-09-15 Thread Timm Bäder via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG177f9ab2fbd8: [clang][Interp] Check pointer inc/dec ops for 
initialization (authored by tbaeder).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D158702

Files:
  clang/lib/AST/Interp/Interp.h
  clang/test/AST/Interp/literals.cpp

Index: clang/test/AST/Interp/literals.cpp
===
--- clang/test/AST/Interp/literals.cpp
+++ clang/test/AST/Interp/literals.cpp
@@ -509,36 +509,72 @@
   }
   static_assert(incBool(), "");
 
-  template
+  /// FIXME: The diagnostics for pre-inc/dec of pointers doesn't match the
+  /// current interpreter. But they are stil OK.
+  template
   constexpr int uninit() {
 T a;
-if constexpr (Inc)
-  ++a; // ref-note 2{{increment of uninitialized}} \
-   // expected-note 2{{increment of uninitialized}}
-else
-  --a; // ref-note 2{{decrement of uninitialized}} \
-   // expected-note 2{{decrement of uninitialized}}
+if constexpr (Inc) {
+  if (Pre)
+++a; // ref-note 3{{increment of uninitialized}} \
+ // expected-note 2{{increment of uninitialized}} \
+ // expected-note {{read of uninitialized}}
+  else
+a++; // ref-note 2{{increment of uninitialized}} \
+ // expected-note 2{{increment of uninitialized}}
+} else {
+  if (Pre)
+--a; // ref-note 3{{decrement of uninitialized}} \
+ // expected-note 2{{decrement of uninitialized}} \
+ // expected-note {{read of uninitialized}}
+  else
+a--; // ref-note 2{{decrement of uninitialized}} \
+ // expected-note 2{{decrement of uninitialized}}
+}
 return 1;
   }
-  static_assert(uninit(), ""); // ref-error {{not an integral constant expression}} \
-  // ref-note {{in call to 'uninit()'}} \
-  // expected-error {{not an integral constant expression}} \
-  // expected-note {{in call to 'uninit()'}}
-
-  static_assert(uninit(), ""); // ref-error {{not an integral constant expression}} \
-   // ref-note {{in call to 'uninit()'}} \
-   // expected-error {{not an integral constant expression}} \
-   // expected-note {{in call to 'uninit()'}}
-
-  static_assert(uninit(), ""); // ref-error {{not an integral constant expression}} \
-// ref-note {{in call to 'uninit()'}} \
-// expected-error {{not an integral constant expression}} \
-// expected-note {{in call to 'uninit()'}}
-
-  static_assert(uninit(), ""); // ref-error {{not an integral constant expression}} \
- // ref-note {{in call to 'uninit()'}} \
- // expected-error {{not an integral constant expression}} \
- // expected-note {{in call to 'uninit()'}}
+  static_assert(uninit(), ""); // ref-error {{not an integral constant expression}} \
+// ref-note {{in call to 'uninit()'}} \
+// expected-error {{not an integral constant expression}} \
+// expected-note {{in call to 'uninit()'}}
+  static_assert(uninit(), ""); // ref-error {{not an integral constant expression}} \
+ // ref-note {{in call to 'uninit()'}} \
+ // expected-error {{not an integral constant expression}} \
+ // expected-note {{in call to 'uninit()'}}
+
+  static_assert(uninit(), ""); // ref-error {{not an integral constant expression}} \
+  // ref-note {{in call to 'uninit()'}} \
+  // expected-error {{not an integral constant expression}} \
+  // expected-note {{in call to 'uninit()'}}
+  static_assert(uninit(), ""); // ref-error {{not an integral constant expression}} \
+   // ref-note {{in call to 'uninit()'}} \
+   // expected-error {{not an integral constant expression}} \
+   // expected-note {{in call to 'uninit()'}}
+  static_assert(uninit(), ""); // ref-error {{not an integral constant expression}} \
+  

[PATCH] D152504: [clang][ThreadSafety] Analyze cleanup functions

2023-09-15 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder updated this revision to Diff 556838.

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

https://reviews.llvm.org/D152504

Files:
  clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
  clang/lib/Analysis/ThreadSafety.cpp
  clang/lib/Analysis/ThreadSafetyCommon.cpp
  clang/test/Sema/warn-thread-safety-analysis.c

Index: clang/test/Sema/warn-thread-safety-analysis.c
===
--- clang/test/Sema/warn-thread-safety-analysis.c
+++ clang/test/Sema/warn-thread-safety-analysis.c
@@ -23,6 +23,7 @@
   __attribute__ ((shared_locks_required(__VA_ARGS__)))
 #define NO_THREAD_SAFETY_ANALYSIS  __attribute__ ((no_thread_safety_analysis))
 
+
 // Define the mutex struct.
 // Simplified only for test purpose.
 struct LOCKABLE Mutex {};
@@ -72,6 +73,8 @@
   return *p;
 }
 
+void unlock_scope(struct Mutex *const *mu) __attribute__((release_capability(**mu)));
+
 int main(void) {
 
   Foo_fun1(1); // expected-warning{{calling function 'Foo_fun1' requires holding mutex 'mu2'}} \
@@ -127,6 +130,13 @@
 // expected-note@-1{{mutex released here}}
   mutex_shared_unlock(&mu1);// expected-warning {{releasing mutex 'mu1' that was not held}}
 
+  /// Cleanup functions
+  {
+struct Mutex* const __attribute__((cleanup(unlock_scope))) scope = &mu1;
+mutex_exclusive_lock(scope);  // Note that we have to lock through scope, because no alias analysis!
+// Cleanup happens automatically -> no warning.
+  }
+
   return 0;
 }
 
Index: clang/lib/Analysis/ThreadSafetyCommon.cpp
===
--- clang/lib/Analysis/ThreadSafetyCommon.cpp
+++ clang/lib/Analysis/ThreadSafetyCommon.cpp
@@ -110,7 +110,8 @@
 /// \param D   The declaration to which the attribute is attached.
 /// \param DeclExp An expression involving the Decl to which the attribute
 ///is attached.  E.g. the call to a function.
-/// \param SelfS-expression to substitute for a \ref CXXThisExpr.
+/// \param SelfS-expression to substitute for a \ref CXXThisExpr in a call,
+///or argument to a cleanup function.
 CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp,
const NamedDecl *D,
const Expr *DeclExp,
@@ -144,7 +145,11 @@
 
   if (Self) {
 assert(!Ctx.SelfArg && "Ambiguous self argument");
-Ctx.SelfArg = Self;
+assert(isa(D) && "Self argument requires function");
+if (isa(D))
+  Ctx.SelfArg = Self;
+else
+  Ctx.FunArgs = Self;
 
 // If the attribute has no arguments, then assume the argument is "this".
 if (!AttrExp)
@@ -312,8 +317,14 @@
   ? (cast(D)->getCanonicalDecl() == Canonical)
   : (cast(D)->getCanonicalDecl() == Canonical)) {
 // Substitute call arguments for references to function parameters
-assert(I < Ctx->NumArgs);
-return translate(Ctx->FunArgs[I], Ctx->Prev);
+if (const Expr *const *FunArgs =
+Ctx->FunArgs.dyn_cast()) {
+  assert(I < Ctx->NumArgs);
+  return translate(FunArgs[I], Ctx->Prev);
+}
+
+assert(I == 0);
+return Ctx->FunArgs.get();
   }
 }
 // Map the param back to the param of the original function declaration
Index: clang/lib/Analysis/ThreadSafety.cpp
===
--- clang/lib/Analysis/ThreadSafety.cpp
+++ clang/lib/Analysis/ThreadSafety.cpp
@@ -1773,7 +1773,8 @@
 ///
 /// \param Exp   The call expression.
 /// \param D The callee declaration.
-/// \param Self  If \p Exp = nullptr, the implicit this argument.
+/// \param Self  If \p Exp = nullptr, the implicit this argument or the argument
+///  of an implicitly called cleanup function.
 /// \param Loc   If \p Exp = nullptr, the location.
 void BuildLockset::handleCall(const Expr *Exp, const NamedDecl *D,
   til::LiteralPtr *Self, SourceLocation Loc) {
@@ -2414,6 +2415,15 @@
 AD.getTriggerStmt()->getEndLoc());
   break;
 }
+
+case CFGElement::CleanupFunction: {
+  const CFGCleanupFunction &CF = BI.castAs();
+  LocksetBuilder.handleCall(/*Exp=*/nullptr, CF.getFunctionDecl(),
+SxBuilder.createVariable(CF.getVarDecl()),
+CF.getVarDecl()->getLocation());
+  break;
+}
+
 case CFGElement::TemporaryDtor: {
   auto TD = BI.castAs();
 
Index: clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
===
--- clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
+++ clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
@@ -361,7 +361,7 @@
 unsigned NumArgs = 0;
 
 // 

[PATCH] D157385: [clang][CFG] Cleanup functions

2023-09-15 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added inline comments.



Comment at: clang/test/Analysis/scopes-cfg-output.cpp:1472
+// CHECK-NEXT:2:  (CXXConstructExpr, [B1.3], F)
+// CHECK-NEXT:3: F f __attribute__((cleanup(cleanup_F)));
+// CHECK-NEXT:4: CleanupFunction (cleanup_F)

aaronpuchert wrote:
> The test failure in D152504 suggests that this needs to be written as
> ```
> __attribute__((cleanup(cleanup_F))) F f
> ```
> Maybe something changed upstream?
Right, not sure what changed.


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

https://reviews.llvm.org/D157385

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


[PATCH] D157385: [clang][CFG] Cleanup functions

2023-09-15 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder updated this revision to Diff 556836.
tbaeder marked an inline comment as done.

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

https://reviews.llvm.org/D157385

Files:
  clang/include/clang/Analysis/CFG.h
  clang/lib/Analysis/CFG.cpp
  clang/lib/Analysis/PathDiagnostic.cpp
  clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
  clang/test/Analysis/scopes-cfg-output.cpp

Index: clang/test/Analysis/scopes-cfg-output.cpp
===
--- clang/test/Analysis/scopes-cfg-output.cpp
+++ clang/test/Analysis/scopes-cfg-output.cpp
@@ -1419,3 +1419,68 @@
 }
   }
 }
+
+// CHECK:  [B1]
+// CHECK-NEXT:   1: CFGScopeBegin(i)
+// CHECK-NEXT:   2: int i __attribute__((cleanup(cleanup_int)));
+// CHECK-NEXT:   3: CleanupFunction (cleanup_int)
+// CHECK-NEXT:   4: CFGScopeEnd(i)
+void cleanup_int(int *i);
+void test_cleanup_functions() {
+  int i __attribute__((cleanup(cleanup_int)));
+}
+
+// CHECK:  [B1]
+// CHECK-NEXT:1: 10
+// CHECK-NEXT:2: i
+// CHECK-NEXT:3: [B1.2] = [B1.1]
+// CHECK-NEXT:4: return;
+// CHECK-NEXT:5: CleanupFunction (cleanup_int)
+// CHECK-NEXT:6: CFGScopeEnd(i)
+// CHECK-NEXT:Preds (1): B3
+// CHECK-NEXT:Succs (1): B0
+// CHECK:  [B2]
+// CHECK-NEXT:1: return;
+// CHECK-NEXT:2: CleanupFunction (cleanup_int)
+// CHECK-NEXT:3: CFGScopeEnd(i)
+// CHECK-NEXT:Preds (1): B3
+// CHECK-NEXT:Succs (1): B0
+// CHECK:  [B3]
+// CHECK-NEXT:1: CFGScopeBegin(i)
+// CHECK-NEXT:2: int i __attribute__((cleanup(cleanup_int)));
+// CHECK-NEXT:3: m
+// CHECK-NEXT:4: [B3.3] (ImplicitCastExpr, LValueToRValue, int)
+// CHECK-NEXT:5: 1
+// CHECK-NEXT:6: [B3.4] == [B3.5]
+// CHECK-NEXT:T: if [B3.6]
+// CHECK-NEXT:Preds (1): B4
+// CHECK-NEXT:Succs (2): B2 B1
+void test_cleanup_functions2(int m) {
+  int i __attribute__((cleanup(cleanup_int)));
+
+  if (m == 1) {
+return;
+  }
+
+  i = 10;
+  return;
+}
+
+// CHECK:   [B1]
+// CHECK-NEXT:1: CFGScopeBegin(f)
+// CHECK-NEXT:2:  (CXXConstructExpr, [B1.3], F)
+// CHECK-NEXT:3: __attribute__((cleanup(cleanup_F))) F f;
+// CHECK-NEXT:4: CleanupFunction (cleanup_F)
+// CHECK-NEXT:5: [B1.3].~F() (Implicit destructor)
+// CHECK-NEXT:6: CFGScopeEnd(f)
+// CHECK-NEXT:Preds (1): B2
+// CHECK-NEXT:Succs (1): B0
+class F {
+public:
+  ~F();
+};
+void cleanup_F(F *f);
+
+void test() {
+  F f __attribute((cleanup(cleanup_F)));
+}
Index: clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
===
--- clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -993,6 +993,7 @@
   ProcessLoopExit(E.castAs().getLoopStmt(), Pred);
   return;
 case CFGElement::LifetimeEnds:
+case CFGElement::CleanupFunction:
 case CFGElement::ScopeBegin:
 case CFGElement::ScopeEnd:
   return;
Index: clang/lib/Analysis/PathDiagnostic.cpp
===
--- clang/lib/Analysis/PathDiagnostic.cpp
+++ clang/lib/Analysis/PathDiagnostic.cpp
@@ -567,6 +567,7 @@
   }
   case CFGElement::ScopeBegin:
   case CFGElement::ScopeEnd:
+  case CFGElement::CleanupFunction:
 llvm_unreachable("not yet implemented!");
   case CFGElement::LifetimeEnds:
   case CFGElement::LoopExit:
Index: clang/lib/Analysis/CFG.cpp
===
--- clang/lib/Analysis/CFG.cpp
+++ clang/lib/Analysis/CFG.cpp
@@ -881,6 +881,10 @@
 B->appendAutomaticObjDtor(VD, S, cfg->getBumpVectorContext());
   }
 
+  void appendCleanupFunction(CFGBlock *B, VarDecl *VD) {
+B->appendCleanupFunction(VD, cfg->getBumpVectorContext());
+  }
+
   void appendLifetimeEnds(CFGBlock *B, VarDecl *VD, Stmt *S) {
 B->appendLifetimeEnds(VD, S, cfg->getBumpVectorContext());
   }
@@ -1346,7 +1350,8 @@
 return {};
   }
 
-  bool hasTrivialDestructor(VarDecl *VD);
+  bool hasTrivialDestructor(const VarDecl *VD) const;
+  bool needsAutomaticDestruction(const VarDecl *VD) const;
 };
 
 } // namespace
@@ -1861,14 +1866,14 @@
   if (B == E)
 return;
 
-  SmallVector DeclsNonTrivial;
-  DeclsNonTrivial.reserve(B.distance(E));
+  SmallVector DeclsNeedDestruction;
+  DeclsNeedDestruction.reserve(B.distance(E));
 
   for (VarDecl* D : llvm::make_range(B, E))
-if (!hasTrivialDestructor(D))
-  DeclsNonTrivial.push_back(D);
+if (needsAutomaticDestruction(D))
+  DeclsNeedDestruction.push_back(D);
 
-  for (VarDecl *VD : llvm::reverse(DeclsNonTrivial)) {
+  for (VarDecl *VD : llvm::reverse(DeclsNeedDestruction)) {
 if (BuildOpts.AddImplicitDtors) {
   // If this destructor is marked as a no-return destructor, we need to
   // create a new block for the destructor which does not have as a
@@ -1879,7 +1884,8 @@
 Ty = getReferenceInitTemporaryType(VD->getInit());
   Ty = Context->getBaseElementType(Ty

[PATCH] D157200: [clang][Interp] Visit Logical-not operand as bool

2023-09-15 Thread Timm Bäder via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGcd2f2c166203: [clang][Interp] Visit Logical-not operand as 
bool (authored by tbaeder).

Changed prior to commit:
  https://reviews.llvm.org/D157200?vs=547519&id=556833#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157200

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/test/AST/Interp/c.c


Index: clang/test/AST/Interp/c.c
===
--- clang/test/AST/Interp/c.c
+++ clang/test/AST/Interp/c.c
@@ -12,6 +12,9 @@
 _Static_assert(1 && 1.0, ""); // pedantic-ref-warning {{not an integer 
constant expression}} \
   // pedantic-expected-warning {{not an integer 
constant expression}}
 _Static_assert( (5 > 4) + (3 > 2) == 2, "");
+_Static_assert(!!1.0, ""); // pedantic-ref-warning {{not an integer constant 
expression}} \
+   // pedantic-expected-warning {{not an integer 
constant expression}}
+_Static_assert(!!1, "");
 
 /// FIXME: Should also be rejected in the new interpreter
 int a = (1 == 1 ? 5 : 3);
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -2378,10 +2378,18 @@
 return this->emitStore(*T, E);
   }
   case UO_LNot: // !x
-if (!this->visit(SubExpr))
+if (DiscardResult)
+  return this->discard(SubExpr);
+
+if (!this->visitBool(SubExpr))
   return false;
-// The Inv doesn't change anything, so skip it if we don't need the result.
-return DiscardResult ? this->emitPop(*T, E) : this->emitInvBool(E);
+
+if (!this->emitInvBool(E))
+  return false;
+
+if (PrimType ET = classifyPrim(E->getType()); ET != PT_Bool)
+  return this->emitCast(PT_Bool, ET, E);
+return true;
   case UO_Minus: // -x
 if (!this->visit(SubExpr))
   return false;


Index: clang/test/AST/Interp/c.c
===
--- clang/test/AST/Interp/c.c
+++ clang/test/AST/Interp/c.c
@@ -12,6 +12,9 @@
 _Static_assert(1 && 1.0, ""); // pedantic-ref-warning {{not an integer constant expression}} \
   // pedantic-expected-warning {{not an integer constant expression}}
 _Static_assert( (5 > 4) + (3 > 2) == 2, "");
+_Static_assert(!!1.0, ""); // pedantic-ref-warning {{not an integer constant expression}} \
+   // pedantic-expected-warning {{not an integer constant expression}}
+_Static_assert(!!1, "");
 
 /// FIXME: Should also be rejected in the new interpreter
 int a = (1 == 1 ? 5 : 3);
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -2378,10 +2378,18 @@
 return this->emitStore(*T, E);
   }
   case UO_LNot: // !x
-if (!this->visit(SubExpr))
+if (DiscardResult)
+  return this->discard(SubExpr);
+
+if (!this->visitBool(SubExpr))
   return false;
-// The Inv doesn't change anything, so skip it if we don't need the result.
-return DiscardResult ? this->emitPop(*T, E) : this->emitInvBool(E);
+
+if (!this->emitInvBool(E))
+  return false;
+
+if (PrimType ET = classifyPrim(E->getType()); ET != PT_Bool)
+  return this->emitCast(PT_Bool, ET, E);
+return true;
   case UO_Minus: // -x
 if (!this->visit(SubExpr))
   return false;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D157174: [clang][Interp] Convert logical binop operands to bool

2023-09-15 Thread Timm Bäder via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGa259005a215d: [clang][Interp] Convert logical binop operands 
to bool (authored by tbaeder).

Changed prior to commit:
  https://reviews.llvm.org/D157174?vs=547495&id=556832#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157174

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/test/AST/Interp/c.c

Index: clang/test/AST/Interp/c.c
===
--- clang/test/AST/Interp/c.c
+++ clang/test/AST/Interp/c.c
@@ -9,6 +9,8 @@
 _Static_assert(0 != 1, "");
 _Static_assert(1.0 == 1.0, ""); // pedantic-ref-warning {{not an integer constant expression}} \
 // pedantic-expected-warning {{not an integer constant expression}}
+_Static_assert(1 && 1.0, ""); // pedantic-ref-warning {{not an integer constant expression}} \
+  // pedantic-expected-warning {{not an integer constant expression}}
 _Static_assert( (5 > 4) + (3 > 2) == 2, "");
 
 /// FIXME: Should also be rejected in the new interpreter
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -394,18 +394,19 @@
   BinaryOperatorKind Op = E->getOpcode();
   const Expr *LHS = E->getLHS();
   const Expr *RHS = E->getRHS();
+  std::optional T = classify(E->getType());
 
   if (Op == BO_LOr) {
 // Logical OR. Visit LHS and only evaluate RHS if LHS was FALSE.
 LabelTy LabelTrue = this->getLabel();
 LabelTy LabelEnd = this->getLabel();
 
-if (!this->visit(LHS))
+if (!this->visitBool(LHS))
   return false;
 if (!this->jumpTrue(LabelTrue))
   return false;
 
-if (!this->visit(RHS))
+if (!this->visitBool(RHS))
   return false;
 if (!this->jump(LabelEnd))
   return false;
@@ -415,35 +416,36 @@
 this->fallthrough(LabelEnd);
 this->emitLabel(LabelEnd);
 
-if (DiscardResult)
-  return this->emitPopBool(E);
-
-return true;
-  }
-
-  // Logical AND.
-  // Visit LHS. Only visit RHS if LHS was TRUE.
-  LabelTy LabelFalse = this->getLabel();
-  LabelTy LabelEnd = this->getLabel();
+  } else {
+assert(Op == BO_LAnd);
+// Logical AND.
+// Visit LHS. Only visit RHS if LHS was TRUE.
+LabelTy LabelFalse = this->getLabel();
+LabelTy LabelEnd = this->getLabel();
 
-  if (!this->visit(LHS))
-return false;
-  if (!this->jumpFalse(LabelFalse))
-return false;
+if (!this->visitBool(LHS))
+  return false;
+if (!this->jumpFalse(LabelFalse))
+  return false;
 
-  if (!this->visit(RHS))
-return false;
-  if (!this->jump(LabelEnd))
-return false;
+if (!this->visitBool(RHS))
+  return false;
+if (!this->jump(LabelEnd))
+  return false;
 
-  this->emitLabel(LabelFalse);
-  this->emitConstBool(false, E);
-  this->fallthrough(LabelEnd);
-  this->emitLabel(LabelEnd);
+this->emitLabel(LabelFalse);
+this->emitConstBool(false, E);
+this->fallthrough(LabelEnd);
+this->emitLabel(LabelEnd);
+  }
 
   if (DiscardResult)
 return this->emitPopBool(E);
 
+  // For C, cast back to integer type.
+  assert(T);
+  if (T != PT_Bool)
+return this->emitCast(PT_Bool, *T, E);
   return true;
 }
 
@@ -815,17 +817,9 @@
   LabelTy LabelEnd = this->getLabel();   // Label after the operator.
   LabelTy LabelFalse = this->getLabel(); // Label for the false expr.
 
-  if (!this->visit(Condition))
+  if (!this->visitBool(Condition))
 return false;
 
-  // C special case: Convert to bool because our jump ops need that.
-  // TODO: We probably want this to be done in visitBool().
-  if (std::optional CondT = classify(Condition->getType());
-  CondT && CondT != PT_Bool) {
-if (!this->emitCast(*CondT, PT_Bool, E))
-  return false;
-  }
-
   if (!this->jumpFalse(LabelFalse))
 return false;
 
@@ -1551,9 +1545,29 @@
 
 template 
 bool ByteCodeExprGen::visitBool(const Expr *E) {
-  if (std::optional T = classify(E->getType()))
-return visit(E);
-  return this->bail(E);
+  std::optional T = classify(E->getType());
+  if (!T)
+return false;
+
+  if (!this->visit(E))
+return false;
+
+  if (T == PT_Bool)
+return true;
+
+  // Convert pointers to bool.
+  if (T == PT_Ptr || T == PT_FnPtr) {
+if (!this->emitNull(*T, E))
+  return false;
+return this->emitNE(*T, E);
+  }
+
+  // Or Floats.
+  if (T == PT_Float)
+return this->emitCastFloatingIntegralBool(E);
+
+  // Or anything else we can.
+  return this->emitCast(*T, PT_Bool, E);
 }
 
 template 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D156794: [clang][Interp] Lazily visit unknown global declarations

2023-09-14 Thread Timm Bäder via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rG6d73cca1864b: [clang][Interp] Lazily visit unknown global 
declarations (authored by tbaeder).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156794

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/test/AST/Interp/c.c


Index: clang/test/AST/Interp/c.c
===
--- clang/test/AST/Interp/c.c
+++ clang/test/AST/Interp/c.c
@@ -1,12 +1,23 @@
 // RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify %s
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -pedantic 
-verify=pedantic-expected %s
 // RUN: %clang_cc1 -verify=ref %s
+// RUN: %clang_cc1 -pedantic -verify=pedantic-ref %s
 
 /// expected-no-diagnostics
-/// ref-no-diagnostics
 
 _Static_assert(1, "");
 _Static_assert(0 != 1, "");
-_Static_assert(1.0 == 1.0, "");
+_Static_assert(1.0 == 1.0, ""); // pedantic-ref-warning {{not an integer 
constant expression}} \
+// pedantic-expected-warning {{not an integer 
constant expression}}
 _Static_assert( (5 > 4) + (3 > 2) == 2, "");
 
+/// FIXME: Should also be rejected in the new interpreter
 int a = (1 == 1 ? 5 : 3);
+_Static_assert(a == 5, ""); // ref-error {{not an integral constant 
expression}} \
+// pedantic-ref-error {{not an integral constant 
expression}} \
+// pedantic-expected-warning {{not an integer 
constant expression}}
+
+const int b = 3;
+_Static_assert(b == 3, ""); // pedantic-ref-warning {{not an integer constant 
expression}} \
+// pedantic-expected-warning {{not an integer 
constant expression}}
+
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -2459,6 +2459,17 @@
 return this->emitGetPtrThisField(Offset, E);
   }
 
+  // Lazily visit global declarations we haven't seen yet.
+  // This happens in C.
+  if (!Ctx.getLangOpts().CPlusPlus) {
+if (const auto *VD = dyn_cast(D);
+VD && VD->hasGlobalStorage() && VD->getAnyInitializer()) {
+  if (!this->visitVarDecl(VD))
+return false;
+  // Retry.
+  return this->VisitDeclRefExpr(E);
+}
+  }
   return false;
 }
 


Index: clang/test/AST/Interp/c.c
===
--- clang/test/AST/Interp/c.c
+++ clang/test/AST/Interp/c.c
@@ -1,12 +1,23 @@
 // RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify %s
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -pedantic -verify=pedantic-expected %s
 // RUN: %clang_cc1 -verify=ref %s
+// RUN: %clang_cc1 -pedantic -verify=pedantic-ref %s
 
 /// expected-no-diagnostics
-/// ref-no-diagnostics
 
 _Static_assert(1, "");
 _Static_assert(0 != 1, "");
-_Static_assert(1.0 == 1.0, "");
+_Static_assert(1.0 == 1.0, ""); // pedantic-ref-warning {{not an integer constant expression}} \
+// pedantic-expected-warning {{not an integer constant expression}}
 _Static_assert( (5 > 4) + (3 > 2) == 2, "");
 
+/// FIXME: Should also be rejected in the new interpreter
 int a = (1 == 1 ? 5 : 3);
+_Static_assert(a == 5, ""); // ref-error {{not an integral constant expression}} \
+// pedantic-ref-error {{not an integral constant expression}} \
+// pedantic-expected-warning {{not an integer constant expression}}
+
+const int b = 3;
+_Static_assert(b == 3, ""); // pedantic-ref-warning {{not an integer constant expression}} \
+// pedantic-expected-warning {{not an integer constant expression}}
+
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -2459,6 +2459,17 @@
 return this->emitGetPtrThisField(Offset, E);
   }
 
+  // Lazily visit global declarations we haven't seen yet.
+  // This happens in C.
+  if (!Ctx.getLangOpts().CPlusPlus) {
+if (const auto *VD = dyn_cast(D);
+VD && VD->hasGlobalStorage() && VD->getAnyInitializer()) {
+  if (!this->visitVarDecl(VD))
+return false;
+  // Retry.
+  return this->VisitDeclRefExpr(E);
+}
+  }
   return false;
 }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D155572: [clang][Interp] Start implementing binary operators for complex types

2023-09-14 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder updated this revision to Diff 556825.

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

https://reviews.llvm.org/D155572

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/test/AST/Interp/complex.cpp

Index: clang/test/AST/Interp/complex.cpp
===
--- clang/test/AST/Interp/complex.cpp
+++ clang/test/AST/Interp/complex.cpp
@@ -78,3 +78,48 @@
   constexpr _Complex double F9 = {0, 0};
   static_assert(!F9, "");
 }
+
+namespace BinOps {
+namespace Add {
+  constexpr _Complex float A = { 13.0, 2.0 };
+  constexpr _Complex float B = { 2.0, 1.0  };
+  constexpr _Complex float C = A + B;
+  static_assert(__real(C) == 15.0, "");
+  static_assert(__imag(C) == 3.0, "");
+
+  constexpr _Complex float D = B + A;
+  static_assert(__real(D) == 15.0, "");
+  static_assert(__imag(D) == 3.0, "");
+
+  constexpr _Complex unsigned int I1 = { 5,  10 };
+  constexpr _Complex unsigned int I2 = { 40, 2  };
+  constexpr _Complex unsigned int I3 = I1 + I2;
+  static_assert(__real(I3) == 45, "");
+  static_assert(__imag(I3) == 12, "");
+}
+
+namespace Sub {
+  constexpr _Complex float A = { 13.0, 2.0 };
+  constexpr _Complex float B = { 2.0, 1.0  };
+  constexpr _Complex float C = A - B;
+  static_assert(__real(C) == 11.0, "");
+  static_assert(__imag(C) == 1.0, "");
+
+  constexpr _Complex float D = B - A;
+  static_assert(__real(D) == -11.0, "");
+  static_assert(__imag(D) == -1.0, "");
+
+  constexpr _Complex unsigned int I1 = { 5,  10 };
+  constexpr _Complex unsigned int I2 = { 40, 2  };
+  constexpr _Complex unsigned int I3 = I1 - I2;
+  static_assert(__real(I3) == -35, "");
+  static_assert(__imag(I3) == 8, "");
+}
+
+  using Bobble = _Complex float;
+  constexpr _Complex float A = { 13.0, 2.0 };
+  constexpr Bobble B = { 2.0, 1.0  };
+  constexpr _Complex float D = A - B;
+  static_assert(__real(D) == 11.0, "");
+  static_assert(__imag(D) == 1.0, "");
+}
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -65,6 +65,7 @@
   bool VisitBinaryOperator(const BinaryOperator *E);
   bool VisitLogicalBinOp(const BinaryOperator *E);
   bool VisitPointerArithBinOp(const BinaryOperator *E);
+  bool VisitComplexBinOp(const BinaryOperator *E);
   bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E);
   bool VisitCallExpr(const CallExpr *E);
   bool VisitBuiltinCallExpr(const CallExpr *E);
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -290,6 +290,9 @@
   if (BO->isLogicalOp())
 return this->VisitLogicalBinOp(BO);
 
+  if (BO->getType()->isAnyComplexType())
+return this->VisitComplexBinOp(BO);
+
   const Expr *LHS = BO->getLHS();
   const Expr *RHS = BO->getRHS();
 
@@ -505,6 +508,107 @@
   return true;
 }
 
+template 
+bool ByteCodeExprGen::VisitComplexBinOp(const BinaryOperator *E) {
+  // FIXME: We expect a pointer on the stack here.
+  //   we should not do that, but that's part of a bigger rework.
+  const Expr *LHS = E->getLHS();
+  const Expr *RHS = E->getRHS();
+  PrimType LHSElemT = *this->classifyComplexElementType(LHS->getType());
+  PrimType RHSElemT = *this->classifyComplexElementType(RHS->getType());
+
+  unsigned LHSOffset = this->allocateLocalPrimitive(LHS, PT_Ptr, true, false);
+  unsigned RHSOffset = this->allocateLocalPrimitive(RHS, PT_Ptr, true, false);
+  unsigned ResultOffset = ~0u;
+  if (!this->DiscardResult)
+ResultOffset = this->allocateLocalPrimitive(E, PT_Ptr, true, false);
+
+  assert(LHSElemT == RHSElemT);
+
+  // Save result pointer in ResultOffset
+  if (!this->DiscardResult) {
+if (!this->emitDupPtr(E))
+  return false;
+if (!this->emitSetLocal(PT_Ptr, ResultOffset, E))
+  return false;
+  }
+
+  // Evaluate LHS and save value to LHSOffset.
+  if (!this->visit(LHS))
+return false;
+  if (!this->emitSetLocal(PT_Ptr, LHSOffset, E))
+return false;
+
+  // Same with RHS.
+  if (!this->visit(RHS))
+return false;
+  if (!this->emitSetLocal(PT_Ptr, RHSOffset, E))
+return false;
+
+  // Now we can get pointers to the LHS and RHS from the offsets above.
+  BinaryOperatorKind Op = E->getOpcode();
+  for (unsigned ElemIndex = 0; ElemIndex != 2; ++ElemIndex) {
+// Result pointer for the store later.
+if (!this->DiscardResult) {
+  if (!this->emitGetLocal(PT_Ptr, ResultOffset, E))
+return false;
+}
+
+if (!this->emitGetLocal(PT_Ptr, LHSOffset, E))
+  return false;
+if (!this->emitConstUint8(ElemIndex, E))
+  return false;
+if (!this->emitArrayElemPtrPopUint8(E))
+  return false;
+if (!this->emitLoadPop(LHSElemT, E))
+  return false;
+
+if (!this->emitGetLocal(PT_Ptr, RHSOf

[PATCH] D155572: [clang][Interp] Start implementing binary operators for complex types

2023-09-14 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

In D155572#4645997 , @aaron.ballman 
wrote:

> Hmmm, I think the answer is "no"... and "maybe." `_Complex` can only be 
> followed by `float`, `double`, or `long double` specifically per the C 
> standard. However, we also support `_Complex int` (and others) as an 
> extension, which starts to make `_Complex` look more like `_Atomic` in that 
> it augments an existing type, and so typedefs seem quite reasonable.

I know that much, I guess I was confused by the diagnostics:

  ../clang/test/AST/Interp/complex.cpp:121:18: warning: plain '_Complex' 
requires a type specifier; assuming '_Complex double'
121 |   using Gobble = _Complex Frobble;
|  ^
|   double




Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D155572

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


[PATCH] D155572: [clang][Interp] Start implementing binary operators for complex types

2023-09-14 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

In D155572#4542484 , @aaron.ballman 
wrote:

> In D155572#4541403 , @tbaeder wrote:
>
>> In D155572#4539457 , 
>> @aaron.ballman wrote:
>>
>>> Is this intended to not handle all the binary operators in this patch?
>>
>> Yes, just a subset for now.
>>
>>> And also, is this intended to only impact initializers?
>>
>> Yes, due to problems with (non-)initializers. This should work after 
>> https://reviews.llvm.org/D156027 though.
>
> Okay, thanks for confirmation! The only outstanding thing is adding coverage 
> for typedef types:
>
>   using Frobble = float;
>   using Bobble = _Complex float;
>   using Gobble = _Complex Frobble;
>   
>   constexpr _Complex Frobble A = { 13.0, 2.0 };
>   constexpr Bobble B = { 2.0, 1.0  };
>   constexpr Gobble C = { 3.0, 5.0 };
>   constexpr _Complex float D = A - B;
>   constexpr _Complex float E = C - B;
>   static_assert(__real(D) == 11.0, "");
>   static_assert(__imag(D) == 1.0, "");
>   static_assert(__real(E) == 1.0, "");
>   static_assert(__imag(E) == 4.0, "");

https://godbolt.org/z/59c8Y4sqz - Is that even supposed to work?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D155572

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


[PATCH] D158502: [clang][Interp] Actually consider ConstantExpr result

2023-09-14 Thread Timm Bäder via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG293ae0b4b45f: [clang][Interp] Actually consider ConstantExpr 
result (authored by tbaeder).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D158502

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.cpp


Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -634,8 +634,14 @@
 
 template 
 bool ByteCodeExprGen::VisitConstantExpr(const ConstantExpr *E) {
-  // TODO: Check if the ConstantExpr already has a value set and if so,
-  //   use that instead of evaluating it again.
+  // Try to emit the APValue directly, without visiting the subexpr.
+  // This will only fail if we can't emit the APValue, so won't emit any
+  // diagnostics or any double values.
+  std::optional T = classify(E->getType());
+  if (T && E->hasAPValueResult() &&
+  this->visitAPValue(E->getAPValueResult(), *T, E))
+return true;
+
   return this->delegate(E->getSubExpr());
 }
 


Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -634,8 +634,14 @@
 
 template 
 bool ByteCodeExprGen::VisitConstantExpr(const ConstantExpr *E) {
-  // TODO: Check if the ConstantExpr already has a value set and if so,
-  //   use that instead of evaluating it again.
+  // Try to emit the APValue directly, without visiting the subexpr.
+  // This will only fail if we can't emit the APValue, so won't emit any
+  // diagnostics or any double values.
+  std::optional T = classify(E->getType());
+  if (T && E->hasAPValueResult() &&
+  this->visitAPValue(E->getAPValueResult(), *T, E))
+return true;
+
   return this->delegate(E->getSubExpr());
 }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D158472: [clang][Diagnostics] Emit fix-it hint separately on overload resolution failure

2023-09-13 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

In D158472#4605228 , @hazohelet wrote:

> This breaks the one-note-for-one-overload-candidate rule of overload 
> resolution failure diagnostics 
> (https://github.com/llvm/llvm-project/blob/ff08c8e57e39d7970b65637595cdc221901f4ed1/clang/lib/Sema/SemaOverload.cpp#L11517-L11526),
>  but in most cases this change would produce less lines of diagnostics.
> If we don't like this additional note, we could instead suppress the fix-it 
> diagnostics when the fix-it location and the diagnosed candidate location are 
> not close (for example, more than 2 lines away).

IIRC @aaron.ballman usually has an opinion on rules like that.


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

https://reviews.llvm.org/D158472

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


[PATCH] D152504: [clang][ThreadSafety] Analyze cleanup functions

2023-09-12 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder updated this revision to Diff 556535.
tbaeder marked 3 inline comments as done.

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

https://reviews.llvm.org/D152504

Files:
  clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
  clang/lib/Analysis/ThreadSafety.cpp
  clang/lib/Analysis/ThreadSafetyCommon.cpp
  clang/test/Sema/warn-thread-safety-analysis.c

Index: clang/test/Sema/warn-thread-safety-analysis.c
===
--- clang/test/Sema/warn-thread-safety-analysis.c
+++ clang/test/Sema/warn-thread-safety-analysis.c
@@ -23,6 +23,7 @@
   __attribute__ ((shared_locks_required(__VA_ARGS__)))
 #define NO_THREAD_SAFETY_ANALYSIS  __attribute__ ((no_thread_safety_analysis))
 
+
 // Define the mutex struct.
 // Simplified only for test purpose.
 struct LOCKABLE Mutex {};
@@ -72,6 +73,8 @@
   return *p;
 }
 
+void unlock_scope(struct Mutex *const *mu) __attribute__((release_capability(**mu)));
+
 int main(void) {
 
   Foo_fun1(1); // expected-warning{{calling function 'Foo_fun1' requires holding mutex 'mu2'}} \
@@ -127,6 +130,13 @@
 // expected-note@-1{{mutex released here}}
   mutex_shared_unlock(&mu1);// expected-warning {{releasing mutex 'mu1' that was not held}}
 
+  /// Cleanup functions
+  {
+struct Mutex* const __attribute__((cleanup(unlock_scope))) scope = &mu1;
+mutex_exclusive_lock(scope);  // Note that we have to lock through scope, because no alias analysis!
+// Cleanup happens automatically -> no warning.
+  }
+
   return 0;
 }
 
Index: clang/lib/Analysis/ThreadSafetyCommon.cpp
===
--- clang/lib/Analysis/ThreadSafetyCommon.cpp
+++ clang/lib/Analysis/ThreadSafetyCommon.cpp
@@ -110,7 +110,8 @@
 /// \param D   The declaration to which the attribute is attached.
 /// \param DeclExp An expression involving the Decl to which the attribute
 ///is attached.  E.g. the call to a function.
-/// \param SelfS-expression to substitute for a \ref CXXThisExpr.
+/// \param SelfS-expression to substitute for a \ref CXXThisExpr in a call,
+///or argument to a cleanup function.
 CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp,
const NamedDecl *D,
const Expr *DeclExp,
@@ -144,7 +145,11 @@
 
   if (Self) {
 assert(!Ctx.SelfArg && "Ambiguous self argument");
-Ctx.SelfArg = Self;
+assert(isa(D) && "Self argument requires function");
+if (isa(D))
+  Ctx.SelfArg = Self;
+else
+  Ctx.FunArgs = Self;
 
 // If the attribute has no arguments, then assume the argument is "this".
 if (!AttrExp)
@@ -312,8 +317,14 @@
   ? (cast(D)->getCanonicalDecl() == Canonical)
   : (cast(D)->getCanonicalDecl() == Canonical)) {
 // Substitute call arguments for references to function parameters
-assert(I < Ctx->NumArgs);
-return translate(Ctx->FunArgs[I], Ctx->Prev);
+if (const Expr *const *FunArgs =
+Ctx->FunArgs.dyn_cast()) {
+  assert(I < Ctx->NumArgs);
+  return translate(FunArgs[I], Ctx->Prev);
+}
+
+assert(I == 0);
+return Ctx->FunArgs.get();
   }
 }
 // Map the param back to the param of the original function declaration
Index: clang/lib/Analysis/ThreadSafety.cpp
===
--- clang/lib/Analysis/ThreadSafety.cpp
+++ clang/lib/Analysis/ThreadSafety.cpp
@@ -2414,6 +2414,15 @@
 AD.getTriggerStmt()->getEndLoc());
   break;
 }
+
+case CFGElement::CleanupFunction: {
+  const CFGCleanupFunction &CF = BI.castAs();
+  LocksetBuilder.handleCall(/*Exp=*/nullptr, CF.getFunctionDecl(),
+SxBuilder.createVariable(CF.getVarDecl()),
+CF.getVarDecl()->getLocation());
+  break;
+}
+
 case CFGElement::TemporaryDtor: {
   auto TD = BI.castAs();
 
Index: clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
===
--- clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
+++ clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
@@ -361,7 +361,7 @@
 unsigned NumArgs = 0;
 
 // Function arguments
-const Expr *const *FunArgs = nullptr;
+llvm::PointerUnion FunArgs = nullptr;
 
 // is Self referred to with -> or .?
 bool SelfArrow = false;
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D158502: [clang][Interp] Actually consider ConstantExpr result

2023-09-11 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder updated this revision to Diff 556474.
tbaeder marked 2 inline comments as done.

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

https://reviews.llvm.org/D158502

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.cpp


Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -733,8 +733,14 @@
 
 template 
 bool ByteCodeExprGen::VisitConstantExpr(const ConstantExpr *E) {
-  // TODO: Check if the ConstantExpr already has a value set and if so,
-  //   use that instead of evaluating it again.
+  // Try to emit the APValue directly, without visiting the subexpr.
+  // This will only fail if we can't emit the APValue, so won't emit any
+  // diagnostics or any double values.
+  std::optional T = classify(E->getType());
+  if (T && E->hasAPValueResult() &&
+  this->visitAPValue(E->getAPValueResult(), *T, E))
+return true;
+
   return this->delegate(E->getSubExpr());
 }
 


Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -733,8 +733,14 @@
 
 template 
 bool ByteCodeExprGen::VisitConstantExpr(const ConstantExpr *E) {
-  // TODO: Check if the ConstantExpr already has a value set and if so,
-  //   use that instead of evaluating it again.
+  // Try to emit the APValue directly, without visiting the subexpr.
+  // This will only fail if we can't emit the APValue, so won't emit any
+  // diagnostics or any double values.
+  std::optional T = classify(E->getType());
+  if (T && E->hasAPValueResult() &&
+  this->visitAPValue(E->getAPValueResult(), *T, E))
+return true;
+
   return this->delegate(E->getSubExpr());
 }
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D158595: [clang][Interp] Allow zero-init of primitives with an empty init list

2023-09-11 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D158595

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


[PATCH] D158516: [clang][Interp] Only lazily visit constant globals

2023-09-11 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D158516

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


[PATCH] D157252: [clang][ExprConst] Handle 0 type size in builtin_memcpy etc.

2023-09-11 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157252

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


[PATCH] D156794: [clang][Interp] Lazily visit unknown global declarations

2023-09-11 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


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

https://reviews.llvm.org/D156794

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


[PATCH] D156453: [clang][Interp] Create only globals when initializing a global variable

2023-09-11 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156453

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


[PATCH] D154262: [clang][Interp] LambdaThisCaptures

2023-09-11 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154262

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


[PATCH] D154581: [clang][Interp] Track existing InitMaps in InterpState

2023-09-11 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


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

https://reviews.llvm.org/D154581

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


[PATCH] D156506: [clang][Interp] Check floating results for NaNs

2023-09-11 Thread Timm Bäder via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG4b5fe9c42d94: [clang][Interp] Check floating results for 
NaNs (authored by tbaeder).

Changed prior to commit:
  https://reviews.llvm.org/D156506?vs=545023&id=556407#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156506

Files:
  clang/lib/AST/Interp/Interp.cpp
  clang/lib/AST/Interp/Interp.h
  clang/test/AST/Interp/floats.cpp

Index: clang/test/AST/Interp/floats.cpp
===
--- clang/test/AST/Interp/floats.cpp
+++ clang/test/AST/Interp/floats.cpp
@@ -202,3 +202,18 @@
   static_assert(!(inf < nan), "");
   static_assert(!(inf > nan), "");
 }
+
+namespace nan {
+  constexpr double nan = __builtin_nan("");
+  static_assert(nan);
+
+  constexpr double D1 = 1 + nan; // ref-error {{must be initialized by a constant expression}} \
+ // ref-note {{produces a NaN}} \
+ // expected-error {{must be initialized by a constant expression}} \
+ // expected-note {{produces a NaN}}
+
+  constexpr double D2 = __builtin_inf() / __builtin_inf(); // ref-error {{must be initialized by a constant expression}} \
+   // ref-note {{produces a NaN}} \
+   // expected-error {{must be initialized by a constant expression}} \
+   // expected-note {{produces a NaN}}
+}
Index: clang/lib/AST/Interp/Interp.h
===
--- clang/lib/AST/Interp/Interp.h
+++ clang/lib/AST/Interp/Interp.h
@@ -172,7 +172,8 @@
 
 /// Checks if the result of a floating-point operation is valid
 /// in the current context.
-bool CheckFloatResult(InterpState &S, CodePtr OpPC, APFloat::opStatus Status);
+bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result,
+  APFloat::opStatus Status);
 
 /// Interpreter entry point.
 bool Interpret(InterpState &S, APValue &Result);
@@ -304,7 +305,7 @@
   Floating Result;
   auto Status = Floating::add(LHS, RHS, RM, &Result);
   S.Stk.push(Result);
-  return CheckFloatResult(S, OpPC, Status);
+  return CheckFloatResult(S, OpPC, Result, Status);
 }
 
 template ::T>
@@ -322,7 +323,7 @@
   Floating Result;
   auto Status = Floating::sub(LHS, RHS, RM, &Result);
   S.Stk.push(Result);
-  return CheckFloatResult(S, OpPC, Status);
+  return CheckFloatResult(S, OpPC, Result, Status);
 }
 
 template ::T>
@@ -340,7 +341,7 @@
   Floating Result;
   auto Status = Floating::mul(LHS, RHS, RM, &Result);
   S.Stk.push(Result);
-  return CheckFloatResult(S, OpPC, Status);
+  return CheckFloatResult(S, OpPC, Result, Status);
 }
 /// 1) Pops the RHS from the stack.
 /// 2) Pops the LHS from the stack.
@@ -443,7 +444,7 @@
   Floating Result;
   auto Status = Floating::div(LHS, RHS, RM, &Result);
   S.Stk.push(Result);
-  return CheckFloatResult(S, OpPC, Status);
+  return CheckFloatResult(S, OpPC, Result, Status);
 }
 
 //===--===//
@@ -622,7 +623,7 @@
 
   Ptr.deref() = Result;
 
-  return CheckFloatResult(S, OpPC, Status);
+  return CheckFloatResult(S, OpPC, Result, Status);
 }
 
 inline bool Incf(InterpState &S, CodePtr OpPC, llvm::RoundingMode RM) {
@@ -1525,7 +1526,7 @@
   auto Status = Floating::fromIntegral(FromAP, *Sem, RM, Result);
   S.Stk.push(Result);
 
-  return CheckFloatResult(S, OpPC, Status);
+  return CheckFloatResult(S, OpPC, Result, Status);
 }
 
 template ::T>
@@ -1550,7 +1551,7 @@
 }
 
 S.Stk.push(T(Result));
-return CheckFloatResult(S, OpPC, Status);
+return CheckFloatResult(S, OpPC, F, Status);
   }
 }
 
Index: clang/lib/AST/Interp/Interp.cpp
===
--- clang/lib/AST/Interp/Interp.cpp
+++ clang/lib/AST/Interp/Interp.cpp
@@ -495,13 +495,25 @@
   return false;
 }
 
-bool CheckFloatResult(InterpState &S, CodePtr OpPC, APFloat::opStatus Status) {
+bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result,
+  APFloat::opStatus Status) {
+  const SourceInfo &E = S.Current->getSource(OpPC);
+
+  // [expr.pre]p4:
+  //   If during the evaluation of an expression, the result is not
+  //   mathematically defined [...], the behavior is undefined.
+  // FIXME: C++ rules require us to not conform to IEEE 754 here.
+  if (Result.isNan()) {
+S.CCEDiag(E, diag::note_constexpr_float_arithmetic)
+<< /*NaN=*/true << S.Current->getRange(OpPC);
+return S.noteUndefinedBehavior();
+  }
+
   // In a constant context, assume that any dynamic rounding mode or FP
   // exception state matches the default fl

[PATCH] D156400: [clang][Interp] Implement __builtin_offsetof

2023-09-11 Thread Timm Bäder via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG87461d669684: [clang][Interp] Implement __builtin_offsetof 
(authored by tbaeder).

Changed prior to commit:
  https://reviews.llvm.org/D156400?vs=556339&id=556406#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156400

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/lib/AST/Interp/Interp.h
  clang/lib/AST/Interp/InterpBuiltin.cpp
  clang/lib/AST/Interp/Opcodes.td
  clang/test/AST/Interp/class-layout.cpp
  clang/test/AST/Interp/literals.cpp
  clang/test/SemaCXX/class-layout.cpp
  clang/test/SemaCXX/offsetof-0x.cpp
  clang/test/SemaCXX/offsetof.cpp

Index: clang/test/SemaCXX/offsetof.cpp
===
--- clang/test/SemaCXX/offsetof.cpp
+++ clang/test/SemaCXX/offsetof.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -fsyntax-only -verify %s -Winvalid-offsetof -std=c++98
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -fsyntax-only -verify %s -Winvalid-offsetof -std=c++98 -fexperimental-new-constant-interpreter
 
 struct NonPOD {
   virtual void f();
Index: clang/test/SemaCXX/offsetof-0x.cpp
===
--- clang/test/SemaCXX/offsetof-0x.cpp
+++ clang/test/SemaCXX/offsetof-0x.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -fsyntax-only -std=c++11 -verify %s -Winvalid-offsetof
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -fsyntax-only -std=c++11 -verify %s -Winvalid-offsetof -fexperimental-new-constant-interpreter
 
 struct NonPOD {
   virtual void f();
Index: clang/test/SemaCXX/class-layout.cpp
===
--- clang/test/SemaCXX/class-layout.cpp
+++ clang/test/SemaCXX/class-layout.cpp
@@ -14,6 +14,25 @@
 // RUN: %clang_cc1 -triple s390x-none-zos %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base
 // RUN: %clang_cc1 -triple s390x-none-zos %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=15 -DCLANG_ABI_COMPAT=15
 
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++98 -Wno-inaccessible-base -Wno-c++11-extensions
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-apple-darwin%s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=15
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-scei-ps4%s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=6
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-sie-ps5 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=6
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=6 -DCLANG_ABI_COMPAT=6
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=14 -DCLANG_ABI_COMPAT=14
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=15 -DCLANG_ABI_COMPAT=15
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=16 -DCLANG_ABI_COMPAT=16
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple powerpc-ibm-aix7.3.0.0 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=15
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple powerpc-ibm-aix7.3.0.0 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=15 -DCLANG_ABI_COMPAT=15
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple powerpc64-ibm-aix7.3.0.0 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=15
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple powerpc64-ibm-aix7.3.0.0 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=15 -DCLANG_ABI_COMPAT=15
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple s390x-none-zos %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple s390x-none-zos %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=15 -DCLANG_ABI_COMPAT=15
+
+
+
+
 // expected-no-di

[PATCH] D152504: [clang][ThreadSafety] Analyze cleanup functions

2023-09-11 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder updated this revision to Diff 556399.

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

https://reviews.llvm.org/D152504

Files:
  clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
  clang/lib/Analysis/ThreadSafety.cpp
  clang/lib/Analysis/ThreadSafetyCommon.cpp
  clang/test/Sema/warn-thread-safety-analysis.c

Index: clang/test/Sema/warn-thread-safety-analysis.c
===
--- clang/test/Sema/warn-thread-safety-analysis.c
+++ clang/test/Sema/warn-thread-safety-analysis.c
@@ -22,6 +22,8 @@
 #define SHARED_LOCKS_REQUIRED(...) \
   __attribute__ ((shared_locks_required(__VA_ARGS__)))
 #define NO_THREAD_SAFETY_ANALYSIS  __attribute__ ((no_thread_safety_analysis))
+#define CLEANUP(A) __attribute__ ((cleanup(A)))
+
 
 // Define the mutex struct.
 // Simplified only for test purpose.
@@ -72,6 +74,17 @@
   return *p;
 }
 
+void cleanup_int(int *unused) __attribute__((release_capability(mu1))) {
+  (void)unused;
+  mutex_exclusive_unlock(&mu1);
+}
+
+void broken_cleanup_int(int *unused) __attribute__((release_capability(mu1))) {
+  (void)unused;
+  mutex_exclusive_unlock(&mu1);
+  Bar_fun1(6); // expected-warning {{calling function 'Bar_fun1' requires holding mutex 'mu1' exclusively}}
+}
+
 int main(void) {
 
   Foo_fun1(1); // expected-warning{{calling function 'Foo_fun1' requires holding mutex 'mu2'}} \
@@ -127,6 +140,21 @@
 // expected-note@-1{{mutex released here}}
   mutex_shared_unlock(&mu1);// expected-warning {{releasing mutex 'mu1' that was not held}}
 
+  /// Cleanup functions
+  {
+mutex_exclusive_lock(&mu1);
+int CLEANUP(cleanup_int) i;
+
+Bar_fun1(3);
+  }
+  Bar_fun1(4); // expected-warning {{calling function 'Bar_fun1' requires holding mutex 'mu1' exclusively}}
+
+
+  {
+mutex_exclusive_lock(&mu1);
+int CLEANUP(broken_cleanup_int) i2;
+  }
+
   return 0;
 }
 
Index: clang/lib/Analysis/ThreadSafetyCommon.cpp
===
--- clang/lib/Analysis/ThreadSafetyCommon.cpp
+++ clang/lib/Analysis/ThreadSafetyCommon.cpp
@@ -110,7 +110,8 @@
 /// \param D   The declaration to which the attribute is attached.
 /// \param DeclExp An expression involving the Decl to which the attribute
 ///is attached.  E.g. the call to a function.
-/// \param SelfS-expression to substitute for a \ref CXXThisExpr.
+/// \param SelfS-expression to substitute for a \ref CXXThisExpr in a call,
+///or argument to a cleanup function.
 CapabilityExpr SExprBuilder::translateAttrExpr(const Expr *AttrExp,
const NamedDecl *D,
const Expr *DeclExp,
@@ -144,7 +145,11 @@
 
   if (Self) {
 assert(!Ctx.SelfArg && "Ambiguous self argument");
-Ctx.SelfArg = Self;
+assert(isa(D) && "Self argument requires function");
+if (isa(D))
+  Ctx.SelfArg = Self;
+else
+  Ctx.FunArgs = Self;
 
 // If the attribute has no arguments, then assume the argument is "this".
 if (!AttrExp)
@@ -312,8 +317,14 @@
   ? (cast(D)->getCanonicalDecl() == Canonical)
   : (cast(D)->getCanonicalDecl() == Canonical)) {
 // Substitute call arguments for references to function parameters
-assert(I < Ctx->NumArgs);
-return translate(Ctx->FunArgs[I], Ctx->Prev);
+if (const auto *const *FunArgs =
+Ctx->FunArgs.dyn_cast()) {
+  assert(I < Ctx->NumArgs);
+  return translate(FunArgs[I], Ctx->Prev);
+}
+
+assert(I == 0);
+return Ctx->FunArgs.get();
   }
 }
 // Map the param back to the param of the original function declaration
Index: clang/lib/Analysis/ThreadSafety.cpp
===
--- clang/lib/Analysis/ThreadSafety.cpp
+++ clang/lib/Analysis/ThreadSafety.cpp
@@ -2414,6 +2414,15 @@
 AD.getTriggerStmt()->getEndLoc());
   break;
 }
+
+case CFGElement::CleanupFunction: {
+  const CFGCleanupFunction &CF = BI.castAs();
+  LocksetBuilder.handleCall(/*Exp=*/nullptr, CF.getFunctionDecl(),
+SxBuilder.createVariable(CF.getVarDecl()),
+CF.getVarDecl()->getLocation());
+  break;
+}
+
 case CFGElement::TemporaryDtor: {
   auto TD = BI.castAs();
 
Index: clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
===
--- clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
+++ clang/include/clang/Analysis/Analyses/ThreadSafetyCommon.h
@@ -361,7 +361,7 @@
 unsigned NumArgs = 0;
 
 // Function arguments
-const Expr *const *FunArgs = nullptr;
+llvm::PointerUnion FunArgs = nullptr;
 
 // is Self

[PATCH] D156400: [clang][Interp] Implement __builtin_offsetof

2023-09-09 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder updated this revision to Diff 556339.
tbaeder marked 4 inline comments as done.

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

https://reviews.llvm.org/D156400

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/lib/AST/Interp/Interp.h
  clang/lib/AST/Interp/InterpBuiltin.cpp
  clang/lib/AST/Interp/Opcodes.td
  clang/test/AST/Interp/class-layout.cpp
  clang/test/AST/Interp/literals.cpp
  clang/test/SemaCXX/class-layout.cpp
  clang/test/SemaCXX/offsetof-0x.cpp
  clang/test/SemaCXX/offsetof.cpp

Index: clang/test/SemaCXX/offsetof.cpp
===
--- clang/test/SemaCXX/offsetof.cpp
+++ clang/test/SemaCXX/offsetof.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -fsyntax-only -verify %s -Winvalid-offsetof -std=c++98
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -fsyntax-only -verify %s -Winvalid-offsetof -std=c++98 -fexperimental-new-constant-interpreter
 
 struct NonPOD {
   virtual void f();
Index: clang/test/SemaCXX/offsetof-0x.cpp
===
--- clang/test/SemaCXX/offsetof-0x.cpp
+++ clang/test/SemaCXX/offsetof-0x.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -fsyntax-only -std=c++11 -verify %s -Winvalid-offsetof
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10.0.0 -fsyntax-only -std=c++11 -verify %s -Winvalid-offsetof -fexperimental-new-constant-interpreter
 
 struct NonPOD {
   virtual void f();
Index: clang/test/SemaCXX/class-layout.cpp
===
--- clang/test/SemaCXX/class-layout.cpp
+++ clang/test/SemaCXX/class-layout.cpp
@@ -14,6 +14,25 @@
 // RUN: %clang_cc1 -triple s390x-none-zos %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base
 // RUN: %clang_cc1 -triple s390x-none-zos %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=15 -DCLANG_ABI_COMPAT=15
 
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++98 -Wno-inaccessible-base -Wno-c++11-extensions
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-apple-darwin%s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=15
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-scei-ps4%s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=6
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-sie-ps5 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=6
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=6 -DCLANG_ABI_COMPAT=6
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=14 -DCLANG_ABI_COMPAT=14
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=15 -DCLANG_ABI_COMPAT=15
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple x86_64-unknown-unknown %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=16 -DCLANG_ABI_COMPAT=16
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple powerpc-ibm-aix7.3.0.0 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=15
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple powerpc-ibm-aix7.3.0.0 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=15 -DCLANG_ABI_COMPAT=15
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple powerpc64-ibm-aix7.3.0.0 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -DCLANG_ABI_COMPAT=15
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple powerpc64-ibm-aix7.3.0.0 %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=15 -DCLANG_ABI_COMPAT=15
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple s390x-none-zos %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -triple s390x-none-zos %s -fsyntax-only -verify -std=c++11 -Wno-inaccessible-base -fclang-abi-compat=15 -DCLANG_ABI_COMPAT=15
+
+
+
+
 // expected-no-diagnostics
 
 #if !defined(__MVS__) && !defined(_AIX)
Index: clang/test/AST/Interp/literals.cpp
===
--- clang/test/AST/Interp/literals.cpp
+++ clang/test/AST/Interp/literals.cpp
@@ -933,6 +933,7 @@
 (s

[PATCH] D156045: [clang][Interp] Enable existing source_location tests

2023-09-08 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

@hazohelet Thanks for noticing. Should be fixed via 
https://github.com/llvm/llvm-project/commit/f8074942c5a6f266abb1c4d1465a4d8115b22d43.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156045

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


[PATCH] D156047: [clang][Interp] Handle CXXParenListInitExprs

2023-09-06 Thread Timm Bäder via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG92ac46e703cf: [clang][Interp] Handle CXXParenListInitExprs 
(authored by tbaeder).

Changed prior to commit:
  https://reviews.llvm.org/D156047?vs=544692&id=556022#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156047

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/test/AST/Interp/records.cpp
  clang/test/SemaCXX/source_location.cpp

Index: clang/test/SemaCXX/source_location.cpp
===
--- clang/test/SemaCXX/source_location.cpp
+++ clang/test/SemaCXX/source_location.cpp
@@ -4,9 +4,9 @@
 // RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fms-extensions -DMS -fexceptions -verify %s
 // RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -fms-extensions -DMS -DUSE_CONSTEVAL -fexceptions -verify %s
 //
-/// FIXME: The -DPAREN_INIT one is missing for the new interpreter.
 // RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -verify %s
 // RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -DUSE_CONSTEVAL -fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -verify %s
+// RUN: %clang_cc1 -std=c++2b -fcxx-exceptions -DUSE_CONSTEVAL -DPAREN_INIT -fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -verify %s
 // RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fms-extensions -DMS -fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -verify %s
 // RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -fms-extensions -DMS -DUSE_CONSTEVAL -fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -verify %s
 // expected-no-diagnostics
Index: clang/test/AST/Interp/records.cpp
===
--- clang/test/AST/Interp/records.cpp
+++ clang/test/AST/Interp/records.cpp
@@ -941,7 +941,7 @@
   static_assert(foo(F()) == 0, "");
 }
 
-namespace ZeroInit {
+  namespace ZeroInit {
   struct F {
 int a;
   };
@@ -1052,3 +1052,17 @@
   };
 #endif
 }
+
+#if __cplusplus >= 202002L
+namespace ParenInit {
+  struct A {
+int a;
+  };
+
+  struct B : A {
+int b;
+  };
+
+  constexpr B b(A(1),2);
+}
+#endif
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -80,6 +80,7 @@
   bool VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *E);
   bool VisitArraySubscriptExpr(const ArraySubscriptExpr *E);
   bool VisitInitListExpr(const InitListExpr *E);
+  bool VisitCXXParenListInitExpr(const CXXParenListInitExpr *E);
   bool VisitConstantExpr(const ConstantExpr *E);
   bool VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *E);
   bool VisitMemberExpr(const MemberExpr *E);
@@ -199,6 +200,8 @@
 return this->emitPopPtr(I);
   }
 
+  bool visitInitList(ArrayRef Inits, const Expr *E);
+
   /// Creates a local primitive value.
   unsigned allocateLocalPrimitive(DeclTy &&Decl, PrimType Ty, bool IsConst,
   bool IsExtended = false);
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -511,6 +511,58 @@
   return this->emitArrayElemPtrPop(IndexT, E);
 }
 
+template 
+bool ByteCodeExprGen::visitInitList(ArrayRef Inits,
+ const Expr *E) {
+  assert(E->getType()->isRecordType());
+  const Record *R = getRecord(E->getType());
+
+  unsigned InitIndex = 0;
+  for (const Expr *Init : Inits) {
+if (!this->emitDupPtr(E))
+  return false;
+
+if (std::optional T = classify(Init)) {
+  const Record::Field *FieldToInit = R->getField(InitIndex);
+  if (!this->visit(Init))
+return false;
+  if (!this->emitInitField(*T, FieldToInit->Offset, E))
+return false;
+  if (!this->emitPopPtr(E))
+return false;
+  ++InitIndex;
+} else {
+  // Initializer for a direct base class.
+  if (const Record::Base *B = R->getBase(Init->getType())) {
+if (!this->emitGetPtrBasePop(B->Offset, Init))
+  return false;
+
+if (!this->visitInitializer(Init))
+  return false;
+
+if (!this->emitPopPtr(E))
+  return false;
+// Base initializers don't increase InitIndex, since they don't count
+// into the Record's fields.
+  } else {
+const Record::Field *FieldToInit = R->getField(InitIndex);
+// Non-primitive case. Get a pointer to the field-to-initialize
+// on the stack and recurse into visitInitializer().
+if (!this->emitGetPtrField(Field

[PATCH] D156045: [clang][Interp] Enable existing source_location tests

2023-09-06 Thread Timm Bäder via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG7e5809e7e7bc: [clang][Interp] Enable existing 
source_location tests (authored by tbaeder).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156045

Files:
  clang/test/SemaCXX/source_location.cpp


Index: clang/test/SemaCXX/source_location.cpp
===
--- clang/test/SemaCXX/source_location.cpp
+++ clang/test/SemaCXX/source_location.cpp
@@ -3,6 +3,12 @@
 // RUN: %clang_cc1 -std=c++2b -fcxx-exceptions -DUSE_CONSTEVAL -DPAREN_INIT 
-fexceptions -verify %s
 // RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fms-extensions -DMS 
-fexceptions -verify %s
 // RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -fms-extensions -DMS 
-DUSE_CONSTEVAL -fexceptions -verify %s
+//
+/// FIXME: The -DPAREN_INIT one is missing for the new interpreter.
+// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fexceptions 
-fexperimental-new-constant-interpreter -DNEW_INTERP -verify %s
+// RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -DUSE_CONSTEVAL -fexceptions 
-fexperimental-new-constant-interpreter -DNEW_INTERP -verify %s
+// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fms-extensions -DMS 
-fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -verify %s
+// RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -fms-extensions -DMS 
-DUSE_CONSTEVAL -fexceptions -fexperimental-new-constant-interpreter 
-DNEW_INTERP -verify %s
 // expected-no-diagnostics
 
 #define assert(...) ((__VA_ARGS__) ? ((void)0) : throw 42)
@@ -755,7 +761,7 @@
 [b = SL::current().line()] { return b; }()) {
   return a;
 }
-#ifdef USE_CONSTEVAL
+#if defined(USE_CONSTEVAL) && !defined(NEW_INTERP)
 static_assert(test_init_capture() == __LINE__ - 4);
 #else
 static_assert(test_init_capture() == __LINE__ );


Index: clang/test/SemaCXX/source_location.cpp
===
--- clang/test/SemaCXX/source_location.cpp
+++ clang/test/SemaCXX/source_location.cpp
@@ -3,6 +3,12 @@
 // RUN: %clang_cc1 -std=c++2b -fcxx-exceptions -DUSE_CONSTEVAL -DPAREN_INIT -fexceptions -verify %s
 // RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fms-extensions -DMS -fexceptions -verify %s
 // RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -fms-extensions -DMS -DUSE_CONSTEVAL -fexceptions -verify %s
+//
+/// FIXME: The -DPAREN_INIT one is missing for the new interpreter.
+// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -verify %s
+// RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -DUSE_CONSTEVAL -fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -verify %s
+// RUN: %clang_cc1 -std=c++1z -fcxx-exceptions -fms-extensions -DMS -fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -verify %s
+// RUN: %clang_cc1 -std=c++2a -fcxx-exceptions -fms-extensions -DMS -DUSE_CONSTEVAL -fexceptions -fexperimental-new-constant-interpreter -DNEW_INTERP -verify %s
 // expected-no-diagnostics
 
 #define assert(...) ((__VA_ARGS__) ? ((void)0) : throw 42)
@@ -755,7 +761,7 @@
 [b = SL::current().line()] { return b; }()) {
   return a;
 }
-#ifdef USE_CONSTEVAL
+#if defined(USE_CONSTEVAL) && !defined(NEW_INTERP)
 static_assert(test_init_capture() == __LINE__ - 4);
 #else
 static_assert(test_init_capture() == __LINE__ );
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D155627: [clang][Interp] Handle SourceLocExprs

2023-09-06 Thread Timm Bäder via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGb93d2d37e709: [clang][Interp] Handle SourceLocExprs 
(authored by tbaeder).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D155627

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/lib/AST/Interp/Program.cpp
  clang/test/AST/Interp/builtin-functions.cpp

Index: clang/test/AST/Interp/builtin-functions.cpp
===
--- clang/test/AST/Interp/builtin-functions.cpp
+++ clang/test/AST/Interp/builtin-functions.cpp
@@ -221,3 +221,31 @@
 namespace fabs {
   static_assert(__builtin_fabs(-14.0) == 14.0, "");
 }
+
+namespace std {
+struct source_location {
+  struct __impl {
+unsigned int _M_line;
+const char *_M_file_name;
+signed char _M_column;
+const char *_M_function_name;
+  };
+  using BuiltinT = decltype(__builtin_source_location()); // OK.
+};
+}
+
+namespace SourceLocation {
+  constexpr auto A = __builtin_source_location();
+  static_assert(A->_M_line == __LINE__ -1, "");
+  static_assert(A->_M_column == 22, "");
+  static_assert(__builtin_strcmp(A->_M_function_name, "") == 0, "");
+  static_assert(__builtin_strcmp(A->_M_file_name, __FILE__) == 0, "");
+
+  static_assert(__builtin_LINE() == __LINE__, "");
+
+  struct Foo {
+int a = __builtin_LINE();
+  };
+
+  static_assert(Foo{}.a == __LINE__, "");
+}
Index: clang/lib/AST/Interp/Program.cpp
===
--- clang/lib/AST/Interp/Program.cpp
+++ clang/lib/AST/Interp/Program.cpp
@@ -161,9 +161,12 @@
   const Expr *Init) {
   assert(!getGlobal(VD));
   bool IsStatic, IsExtern;
-  if (auto *Var = dyn_cast(VD)) {
+  if (const auto *Var = dyn_cast(VD)) {
 IsStatic = Context::shouldBeGloballyIndexed(VD);
 IsExtern = !Var->getAnyInitializer();
+  } else if (isa(VD)) {
+IsStatic = true;
+IsExtern = false;
   } else {
 IsStatic = false;
 IsExtern = true;
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -35,6 +35,7 @@
 template  class DeclScope;
 template  class OptionScope;
 template  class ArrayIndexScope;
+template  class SourceLocScope;
 
 /// Compilation context for expressions.
 template 
@@ -102,6 +103,7 @@
   bool VisitCXXReinterpretCastExpr(const CXXReinterpretCastExpr *E);
   bool VisitCXXNoexceptExpr(const CXXNoexceptExpr *E);
   bool VisitCXXConstructExpr(const CXXConstructExpr *E);
+  bool VisitSourceLocExpr(const SourceLocExpr *E);
 
 protected:
   bool visitExpr(const Expr *E) override;
@@ -154,6 +156,8 @@
 
   /// Creates and initializes a variable from the given decl.
   bool visitVarDecl(const VarDecl *VD);
+  /// Visit an APValue.
+  bool visitAPValue(const APValue &Val, PrimType ValType, const Expr *E);
 
   /// Visits an expression and converts it to a boolean.
   bool visitBool(const Expr *E);
@@ -210,6 +214,7 @@
   friend class DeclScope;
   friend class OptionScope;
   friend class ArrayIndexScope;
+  friend class SourceLocScope;
 
   /// Emits a zero initializer.
   bool visitZeroInitializer(QualType QT, const Expr *E);
@@ -239,12 +244,14 @@
   llvm::function_ref Indirect);
 
   /// Emits an APSInt constant.
+  bool emitConst(const llvm::APSInt &Value, PrimType Ty, const Expr *E);
   bool emitConst(const llvm::APSInt &Value, const Expr *E);
   bool emitConst(const llvm::APInt &Value, const Expr *E) {
 return emitConst(static_cast(Value), E);
   }
 
   /// Emits an integer constant.
+  template  bool emitConst(T Value, PrimType Ty, const Expr *E);
   template  bool emitConst(T Value, const Expr *E);
 
   /// Returns the CXXRecordDecl for the type of the given expression,
@@ -285,6 +292,9 @@
   /// Current argument index. Needed to emit ArrayInitIndexExpr.
   std::optional ArrayIndex;
 
+  /// DefaultInit- or DefaultArgExpr, needed for SourceLocExpr.
+  const Expr *SourceLocDefaultExpr = nullptr;
+
   /// Flag indicating if return value is to be discarded.
   bool DiscardResult = false;
 
@@ -444,6 +454,28 @@
   std::optional OldArrayIndex;
 };
 
+template  class SourceLocScope final {
+public:
+  SourceLocScope(ByteCodeExprGen *Ctx, const Expr *DefaultExpr)
+  : Ctx(Ctx) {
+assert(DefaultExpr);
+// We only switch if the current SourceLocDefaultExpr is null.
+if (!Ctx->SourceLocDefaultExpr) {
+  Enabled = true;
+  Ctx->SourceLocDefaultExpr = DefaultExpr;
+}
+  }
+
+  ~SourceLocScope() {
+if (Enabled)
+  Ctx->SourceLocDefaultExpr = nullptr;
+  }
+
+private:
+  ByteCodeExprGen *Ctx;
+  bool Enabled = false;
+};
+
 } // namespace interp
 } // namespace clang
 
I

[PATCH] D152246: [clang][ThreadSafety] Analyze known function pointer values

2023-09-06 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

@aaronpuchert Do you think warning on assignment of function pointers with 
mismatched attributes is would be a viable way forward? This is what 
https://github.com/elmarco/clang/commit/bac94282a5c8e3b0410ee8c0522fbdb872ade00c
 tries to implement IIUC.


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

https://reviews.llvm.org/D152246

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


[PATCH] D155627: [clang][Interp] Handle SourceLocExprs

2023-09-05 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

I do in https://reviews.llvm.org/D156045, but that depends on other commits 
(not sure which exactly right now though).


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

https://reviews.llvm.org/D155627

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


[PATCH] D153653: [clang][Interp] Make CXXTemporaryObjectExprs leave a value behind

2023-09-05 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder abandoned this revision.
tbaeder added a comment.

This was pushed as part of the initializer rework.


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

https://reviews.llvm.org/D153653

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


[PATCH] D156042: [clang][Interp] Implement __builtin_strlen

2023-09-05 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder closed this revision.
tbaeder added a comment.

This has been pushed already.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156042

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


[PATCH] D157619: [clang][Interp] Reject calling virtual constexpr functions in pre-c++20

2023-09-05 Thread Timm Bäder via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG5704dde30735: [clang][Interp] Reject calling virtual 
constexpr functions in pre-c++20 (authored by tbaeder).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157619

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/Context.cpp
  clang/lib/AST/Interp/Context.h
  clang/lib/AST/Interp/Interp.h
  clang/test/AST/Interp/records.cpp

Index: clang/test/AST/Interp/records.cpp
===
--- clang/test/AST/Interp/records.cpp
+++ clang/test/AST/Interp/records.cpp
@@ -871,6 +871,35 @@
 };
 #endif
 
+#if __cplusplus < 202002L
+namespace VirtualFromBase {
+  struct S1 {
+virtual int f() const;
+  };
+  struct S2 {
+virtual int f();
+  };
+  template  struct X : T {
+constexpr X() {}
+double d = 0.0;
+constexpr int f() { return sizeof(T); }
+  };
+
+  // Non-virtual f(), OK.
+  constexpr X> xxs1;
+  constexpr X *p = const_cast>*>(&xxs1);
+  static_assert(p->f() == sizeof(S1), "");
+
+  // Virtual f(), not OK.
+  constexpr X> xxs2;
+  constexpr X *q = const_cast>*>(&xxs2);
+  static_assert(q->f() == sizeof(X), ""); // ref-error {{not an integral constant expression}} \
+  // ref-note {{cannot evaluate call to virtual function}} \
+  // expected-error {{not an integral constant expression}} \
+  // expected-note {{cannot evaluate call to virtual function}}
+}
+#endif
+
 namespace CompositeDefaultArgs {
   struct Foo {
 int a;
Index: clang/lib/AST/Interp/Interp.h
===
--- clang/lib/AST/Interp/Interp.h
+++ clang/lib/AST/Interp/Interp.h
@@ -1765,7 +1765,15 @@
   DynamicDecl, StaticDecl, InitialFunction);
 
   if (Overrider != InitialFunction) {
-Func = S.P.getFunction(Overrider);
+// DR1872: An instantiated virtual constexpr function can't be called in a
+// constant expression (prior to C++20). We can still constant-fold such a
+// call.
+if (!S.getLangOpts().CPlusPlus20 && Overrider->isVirtual()) {
+  const Expr *E = S.Current->getExpr(OpPC);
+  S.CCEDiag(E, diag::note_constexpr_virtual_call) << E->getSourceRange();
+}
+
+Func = S.getContext().getOrCreateFunction(Overrider);
 
 const CXXRecordDecl *ThisFieldDecl =
 ThisPtr.getFieldDesc()->getType()->getAsCXXRecordDecl();
Index: clang/lib/AST/Interp/Context.h
===
--- clang/lib/AST/Interp/Context.h
+++ clang/lib/AST/Interp/Context.h
@@ -72,6 +72,9 @@
   getOverridingFunction(const CXXRecordDecl *DynamicDecl,
 const CXXRecordDecl *StaticDecl,
 const CXXMethodDecl *InitialFunction) const;
+
+  const Function *getOrCreateFunction(const FunctionDecl *FD);
+
   /// Returns whether we should create a global variable for the
   /// given ValueDecl.
   static bool shouldBeGloballyIndexed(const ValueDecl *VD) {
Index: clang/lib/AST/Interp/Context.cpp
===
--- clang/lib/AST/Interp/Context.cpp
+++ clang/lib/AST/Interp/Context.cpp
@@ -210,3 +210,24 @@
   "Couldn't find an overriding function in the class hierarchy?");
   return nullptr;
 }
+
+const Function *Context::getOrCreateFunction(const FunctionDecl *FD) {
+  assert(FD);
+  const Function *Func = P->getFunction(FD);
+  bool IsBeingCompiled = Func && !Func->isFullyCompiled();
+  bool WasNotDefined = Func && !Func->isConstexpr() && !Func->hasBody();
+
+  if (IsBeingCompiled)
+return Func;
+
+  if (!Func || WasNotDefined) {
+if (auto R = ByteCodeStmtGen(*this, *P).compileFunc(FD))
+  Func = *R;
+else {
+  llvm::consumeError(R.takeError());
+  return nullptr;
+}
+  }
+
+  return Func;
+}
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -1816,24 +1816,7 @@
 
 template 
 const Function *ByteCodeExprGen::getFunction(const FunctionDecl *FD) {
-  assert(FD);
-  const Function *Func = P.getFunction(FD);
-  bool IsBeingCompiled = Func && !Func->isFullyCompiled();
-  bool WasNotDefined = Func && !Func->isConstexpr() && !Func->hasBody();
-
-  if (IsBeingCompiled)
-return Func;
-
-  if (!Func || WasNotDefined) {
-if (auto R = ByteCodeStmtGen(Ctx, P).compileFunc(FD))
-  Func = *R;
-else {
-  llvm::consumeError(R.takeError());
-  return nullptr;
-}
-  }
-
-  return Func;
+  return Ctx.getOrCreateFunction(FD);
 }
 
 template 
___
cfe-commits m

[PATCH] D157596: [clang][Interp] Handle mixed floating/integral compound assign operators

2023-09-05 Thread Timm Bäder via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGadb1fb40e84d: [clang][Interp] Handle mixed floating/integral 
compound assign operators (authored by tbaeder).

Changed prior to commit:
  https://reviews.llvm.org/D157596?vs=551434&id=555839#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D157596

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/lib/AST/Interp/PrimType.h
  clang/test/AST/Interp/floats.cpp

Index: clang/test/AST/Interp/floats.cpp
===
--- clang/test/AST/Interp/floats.cpp
+++ clang/test/AST/Interp/floats.cpp
@@ -102,6 +102,38 @@
 return a[1];
   }
   static_assert(ff() == 3, "");
+
+  constexpr float intPlusDouble() {
+   int a = 0;
+   a += 2.0;
+
+   return a;
+  }
+  static_assert(intPlusDouble() == 2, "");
+
+  constexpr double doublePlusInt() {
+   double a = 0.0;
+   a += 2;
+
+   return a;
+  }
+  static_assert(doublePlusInt() == 2, "");
+
+  constexpr float boolPlusDouble() {
+   bool a = 0;
+   a += 1.0;
+
+   return a;
+  }
+  static_assert(boolPlusDouble(), "");
+
+  constexpr bool doublePlusbool() {
+   double a = 0.0;
+   a += true;
+
+   return a;
+  }
+  static_assert(doublePlusbool() == 1.0, "");
 }
 
 namespace unary {
Index: clang/lib/AST/Interp/PrimType.h
===
--- clang/lib/AST/Interp/PrimType.h
+++ clang/lib/AST/Interp/PrimType.h
@@ -56,7 +56,7 @@
   return OS;
 }
 
-constexpr bool isIntegralType(PrimType T) { return T <= PT_Uint64; }
+constexpr bool isIntegralType(PrimType T) { return T <= PT_Bool; }
 
 /// Mapping from primitive types to their representation.
 template  struct PrimConv;
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -265,6 +265,7 @@
 return FPO.getRoundingMode();
   }
 
+  bool emitPrimCast(PrimType FromT, PrimType ToT, QualType ToQT, const Expr *E);
   bool emitRecordDestruction(const Descriptor *Desc);
   bool emitDerivedToBaseCasts(const RecordType *DerivedType,
   const RecordType *BaseType, const Expr *E);
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -878,19 +878,22 @@
 template 
 bool ByteCodeExprGen::VisitFloatCompoundAssignOperator(
 const CompoundAssignOperator *E) {
-  assert(E->getType()->isFloatingType());
 
   const Expr *LHS = E->getLHS();
   const Expr *RHS = E->getRHS();
-  llvm::RoundingMode RM = getRoundingMode(E);
+  QualType LHSType = LHS->getType();
   QualType LHSComputationType = E->getComputationLHSType();
   QualType ResultType = E->getComputationResultType();
   std::optional LT = classify(LHSComputationType);
   std::optional RT = classify(ResultType);
 
+  assert(ResultType->isFloatingType());
+
   if (!LT || !RT)
 return false;
 
+  PrimType LHST = classifyPrim(LHSType);
+
   // C++17 onwards require that we evaluate the RHS first.
   // Compute RHS and save it in a temporary variable so we can
   // load it again later.
@@ -904,21 +907,19 @@
   // First, visit LHS.
   if (!visit(LHS))
 return false;
-  if (!this->emitLoad(*LT, E))
+  if (!this->emitLoad(LHST, E))
 return false;
 
   // If necessary, convert LHS to its computation type.
-  if (LHS->getType() != LHSComputationType) {
-const auto *TargetSemantics = &Ctx.getFloatSemantics(LHSComputationType);
-
-if (!this->emitCastFP(TargetSemantics, RM, E))
-  return false;
-  }
+  if (!this->emitPrimCast(LHST, classifyPrim(LHSComputationType),
+  LHSComputationType, E))
+return false;
 
   // Now load RHS.
   if (!this->emitGetLocal(*RT, TempOffset, E))
 return false;
 
+  llvm::RoundingMode RM = getRoundingMode(E);
   switch (E->getOpcode()) {
   case BO_AddAssign:
 if (!this->emitAddf(RM, E))
@@ -940,17 +941,12 @@
 return false;
   }
 
-  // If necessary, convert result to LHS's type.
-  if (LHS->getType() != ResultType) {
-const auto *TargetSemantics = &Ctx.getFloatSemantics(LHS->getType());
-
-if (!this->emitCastFP(TargetSemantics, RM, E))
-  return false;
-  }
+  if (!this->emitPrimCast(classifyPrim(ResultType), LHST, LHS->getType(), E))
+return false;
 
   if (DiscardResult)
-return this->emitStorePop(*LT, E);
-  return this->emitStore(*LT, E);
+return this->emitStorePop(LHST, E);
+  return this->emitStore(LHST, E);
 }
 
 template 
@@ -992,14 +988,6 @@
 bool ByteCodeExprGen::VisitCompoundAssignOperator(
 const CompoundAssignOperator *E) {
 
-  // Handle floating point op

[PATCH] D154189: [clang][Interp] Implement zero-init of record types

2023-09-05 Thread Timm Bäder via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG6d79f985b53e: [clang][Interp] Implement zero-init of record 
types (authored by tbaeder).

Changed prior to commit:
  https://reviews.llvm.org/D154189?vs=545367&id=555836#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154189

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/lib/AST/Interp/Descriptor.cpp
  clang/lib/AST/Interp/Descriptor.h
  clang/test/AST/Interp/records.cpp

Index: clang/test/AST/Interp/records.cpp
===
--- clang/test/AST/Interp/records.cpp
+++ clang/test/AST/Interp/records.cpp
@@ -911,3 +911,115 @@
   }
   static_assert(foo(F()) == 0, "");
 }
+
+namespace ZeroInit {
+  struct F {
+int a;
+  };
+
+  namespace Simple {
+struct A {
+  char a;
+  bool b;
+  int c[4];
+  float d;
+};
+constexpr int foo(A x) {
+  return x.a + static_cast(x.b) + x.c[0] + x.c[3] + static_cast(x.d);
+}
+static_assert(foo(A()) == 0, "");
+  }
+
+  namespace Inheritance {
+struct F2 : F {
+  float f;
+};
+
+constexpr int foo(F2 f) {
+  return (int)f.f + f.a;
+}
+static_assert(foo(F2()) == 0, "");
+  }
+
+  namespace BitFields {
+struct F {
+  unsigned a : 6;
+};
+constexpr int foo(F f) {
+  return f.a;
+}
+static_assert(foo(F()) == 0, "");
+  }
+
+  namespace Nested {
+struct F2 {
+  float f;
+  char c;
+};
+
+struct F {
+  F2 f2;
+  int i;
+};
+
+constexpr int foo(F f) {
+  return f.i + f.f2.f + f.f2.c;
+}
+static_assert(foo(F()) == 0, "");
+  }
+
+  namespace CompositeArrays {
+struct F2 {
+  float f;
+  char c;
+};
+
+struct F {
+  F2 f2[2];
+  int i;
+};
+
+constexpr int foo(F f) {
+  return f.i + f.f2[0].f + f.f2[0].c + f.f2[1].f + f.f2[1].c;
+}
+static_assert(foo(F()) == 0, "");
+  }
+
+  /// FIXME: This needs support for unions on the new interpreter.
+  /// We diagnose an uninitialized object in c++14.
+#if __cplusplus > 201402L
+  namespace Unions {
+struct F {
+  union {
+int a;
+char c[4];
+float f;
+  } U;
+  int i;
+};
+
+constexpr int foo(F f) {
+  return f.i + f.U.f; // ref-note {{read of member 'f' of union with active member 'a'}}
+}
+static_assert(foo(F()) == 0, ""); // ref-error {{not an integral constant expression}} \
+  // ref-note {{in call to}}
+  }
+#endif
+
+#if __cplusplus >= 202002L
+  namespace Failure {
+struct S {
+  int a;
+  F f{12};
+};
+constexpr int foo(S x) {
+  return x.a; // expected-note {{read of uninitialized object}} \
+  // ref-note {{read of uninitialized object}}
+}
+static_assert(foo(S()) == 0, ""); // expected-error {{not an integral constant expression}} \
+  // expected-note {{in call to}} \
+  // ref-error {{not an integral constant expression}} \
+  // ref-note {{in call to}}
+  };
+#endif
+}
Index: clang/lib/AST/Interp/Descriptor.h
===
--- clang/lib/AST/Interp/Descriptor.h
+++ clang/lib/AST/Interp/Descriptor.h
@@ -138,6 +138,7 @@
  bool IsTemporary, bool IsMutable);
 
   QualType getType() const;
+  QualType getElemQualType() const;
   SourceLocation getLocation() const;
 
   const Decl *asDecl() const { return Source.dyn_cast(); }
Index: clang/lib/AST/Interp/Descriptor.cpp
===
--- clang/lib/AST/Interp/Descriptor.cpp
+++ clang/lib/AST/Interp/Descriptor.cpp
@@ -285,6 +285,12 @@
   llvm_unreachable("Invalid descriptor type");
 }
 
+QualType Descriptor::getElemQualType() const {
+  assert(isArray());
+  const auto *AT = cast(getType());
+  return AT->getElementType();
+}
+
 SourceLocation Descriptor::getLocation() const {
   if (auto *D = Source.dyn_cast())
 return D->getLocation();
Index: clang/lib/AST/Interp/ByteCodeExprGen.h
===
--- clang/lib/AST/Interp/ByteCodeExprGen.h
+++ clang/lib/AST/Interp/ByteCodeExprGen.h
@@ -213,6 +213,7 @@
 
   /// Emits a zero initializer.
   bool visitZeroInitializer(QualType QT, const Expr *E);
+  bool visitZeroRecordInitializer(const Record *R, const Expr *E);
 
   enum class DerefKind {
 /// Value is read and pushed to stack.
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -1302,7 +

[PATCH] D155568: [clang][Interp] Make sure we push integers of the correct size

2023-09-05 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder closed this revision.
tbaeder added a comment.

This landed as 673ef8ceaece6c9a7194474ef7d97b3b240c0dc5 



Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D155568

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


[PATCH] D154581: [clang][Interp] Track existing InitMaps in InterpState

2023-09-05 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


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

https://reviews.llvm.org/D154581

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


[PATCH] D149149: [clang][Interp] Check one-past-the-end pointers in GetPtrField

2023-09-05 Thread Timm Bäder via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rGa13f036949b0: [clang][Interp] Check one-past-the-end 
pointers in GetPtrField (authored by tbaeder).

Changed prior to commit:
  https://reviews.llvm.org/D149149?vs=516763&id=555834#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D149149

Files:
  clang/lib/AST/Interp/Interp.cpp
  clang/lib/AST/Interp/Interp.h
  clang/test/AST/Interp/records.cpp

Index: clang/test/AST/Interp/records.cpp
===
--- clang/test/AST/Interp/records.cpp
+++ clang/test/AST/Interp/records.cpp
@@ -531,6 +531,29 @@
   //static_assert(b.a.f == 100, "");
 }
 
+namespace PointerArith {
+  struct A {};
+  struct B : A { int n; };
+
+  B b = {};
+  constexpr A *a1 = &b;
+  constexpr B *b1 = &b + 1;
+  constexpr B *b2 = &b + 0;
+
+#if 0
+  constexpr A *a2 = &b + 1; // expected-error {{must be initialized by a constant expression}} \
+// expected-note {{cannot access base class of pointer past the end of object}} \
+// ref-error {{must be initialized by a constant expression}} \
+// ref-note {{cannot access base class of pointer past the end of object}}
+
+#endif
+  constexpr const int *pn = &(&b + 1)->n; // expected-error {{must be initialized by a constant expression}} \
+  // expected-note {{cannot access field of pointer past the end of object}} \
+  // ref-error {{must be initialized by a constant expression}} \
+  // ref-note {{cannot access field of pointer past the end of object}}
+
+}
+
 #if __cplusplus >= 202002L
 namespace VirtualCalls {
 namespace Obvious {
Index: clang/lib/AST/Interp/Interp.h
===
--- clang/lib/AST/Interp/Interp.h
+++ clang/lib/AST/Interp/Interp.h
@@ -67,9 +67,9 @@
 bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
 CheckSubobjectKind CSK);
 
-/// Checks if accessing a base or derived record of the given pointer is valid.
-bool CheckBaseDerived(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
-  CheckSubobjectKind CSK);
+/// Checks if Ptr is a one-past-the-end pointer.
+bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
+CheckSubobjectKind CSK);
 
 /// Checks if a pointer points to const storage.
 bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
@@ -1121,6 +1121,9 @@
 return false;
   if (!CheckRange(S, OpPC, Ptr, CSK_Field))
 return false;
+  if (!CheckSubobject(S, OpPC, Ptr, CSK_Field))
+return false;
+
   S.Stk.push(Ptr.atField(Off));
   return true;
 }
@@ -1165,7 +1168,7 @@
   const Pointer &Ptr = S.Stk.pop();
   if (!CheckNull(S, OpPC, Ptr, CSK_Derived))
 return false;
-  if (!CheckBaseDerived(S, OpPC, Ptr, CSK_Derived))
+  if (!CheckSubobject(S, OpPC, Ptr, CSK_Derived))
 return false;
   S.Stk.push(Ptr.atFieldSub(Off));
   return true;
@@ -1175,7 +1178,7 @@
   const Pointer &Ptr = S.Stk.peek();
   if (!CheckNull(S, OpPC, Ptr, CSK_Base))
 return false;
-  if (!CheckBaseDerived(S, OpPC, Ptr, CSK_Base))
+  if (!CheckSubobject(S, OpPC, Ptr, CSK_Base))
 return false;
   S.Stk.push(Ptr.atField(Off));
   return true;
@@ -1185,7 +1188,7 @@
   const Pointer &Ptr = S.Stk.pop();
   if (!CheckNull(S, OpPC, Ptr, CSK_Base))
 return false;
-  if (!CheckBaseDerived(S, OpPC, Ptr, CSK_Base))
+  if (!CheckSubobject(S, OpPC, Ptr, CSK_Base))
 return false;
   S.Stk.push(Ptr.atField(Off));
   return true;
Index: clang/lib/AST/Interp/Interp.cpp
===
--- clang/lib/AST/Interp/Interp.cpp
+++ clang/lib/AST/Interp/Interp.cpp
@@ -213,8 +213,8 @@
   return false;
 }
 
-bool CheckBaseDerived(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
-  CheckSubobjectKind CSK) {
+bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
+CheckSubobjectKind CSK) {
   if (!Ptr.isOnePastEnd())
 return true;
 
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D155627: [clang][Interp] Handle SourceLocExprs

2023-09-05 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


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

https://reviews.llvm.org/D155627

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


[PATCH] D149133: [clang][Interp] BaseToDerived casts

2023-09-05 Thread Timm Bäder via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG12a789710e2b: [clang][Interp] BaseToDerived casts (authored 
by tbaeder).

Changed prior to commit:
  https://reviews.llvm.org/D149133?vs=516701&id=555828#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D149133

Files:
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.h
  clang/lib/AST/Interp/Interp.cpp
  clang/lib/AST/Interp/Interp.h
  clang/lib/AST/Interp/Opcodes.td
  clang/lib/AST/Interp/Pointer.h
  clang/test/AST/Interp/records.cpp

Index: clang/test/AST/Interp/records.cpp
===
--- clang/test/AST/Interp/records.cpp
+++ clang/test/AST/Interp/records.cpp
@@ -625,6 +625,58 @@
// ref-note {{in call to 'testS()'}}
 }
 
+namespace BaseToDerived {
+namespace A {
+  struct A {};
+  struct B : A { int n; };
+  struct C : B {};
+  C c = {};
+  constexpr C *pb = (C*)((A*)&c + 1); // expected-error {{must be initialized by a constant expression}} \
+  // expected-note {{cannot access derived class of pointer past the end of object}} \
+  // ref-error {{must be initialized by a constant expression}} \
+  // ref-note {{cannot access derived class of pointer past the end of object}}
+}
+namespace B {
+  struct A {};
+  struct Z {};
+  struct B : Z, A {
+int n;
+   constexpr B() : n(10) {}
+  };
+  struct C : B {
+   constexpr C() : B() {}
+  };
+
+  constexpr C c = {};
+  constexpr const A *pa = &c;
+  constexpr const C *cp = (C*)pa;
+  constexpr const B *cb = (B*)cp;
+
+  static_assert(cb->n == 10);
+  static_assert(cp->n == 10);
+}
+
+namespace C {
+  struct Base { int *a; };
+  struct Base2 : Base { int f[12]; };
+
+  struct Middle1 { int b[3]; };
+  struct Middle2 : Base2 { char c; };
+  struct Middle3 : Middle2 { char g[3]; };
+  struct Middle4 { int f[3]; };
+  struct Middle5 : Middle4, Middle3 { char g2[3]; };
+
+  struct NotQuiteDerived : Middle1, Middle5 { bool d; };
+  struct Derived : NotQuiteDerived { int e; };
+
+  constexpr NotQuiteDerived NQD1 = {};
+
+  constexpr Middle5 *M4 = (Middle5*)((Base2*)&NQD1);
+  static_assert(M4->a == nullptr);
+  static_assert(M4->g2[0] == 0);
+}
+}
+
 
 namespace VirtualDtors {
   class A {
Index: clang/lib/AST/Interp/Pointer.h
===
--- clang/lib/AST/Interp/Pointer.h
+++ clang/lib/AST/Interp/Pointer.h
@@ -109,6 +109,14 @@
 return Pointer(Pointee, Field, Field);
   }
 
+  /// Subtract the given offset from the current Base and Offset
+  /// of the pointer.
+  Pointer atFieldSub(unsigned Off) const {
+assert(Offset >= Off);
+unsigned O = Offset - Off;
+return Pointer(Pointee, O, O);
+  }
+
   /// Restricts the scope of an array element pointer.
   Pointer narrow() const {
 // Null pointers cannot be narrowed.
Index: clang/lib/AST/Interp/Opcodes.td
===
--- clang/lib/AST/Interp/Opcodes.td
+++ clang/lib/AST/Interp/Opcodes.td
@@ -293,6 +293,10 @@
   let Args = [ArgUint32];
 }
 
+def GetPtrDerivedPop : Opcode {
+  let Args = [ArgUint32];
+}
+
 // [Pointer] -> [Pointer]
 def GetPtrVirtBase : Opcode {
   // RecordDecl of base class.
Index: clang/lib/AST/Interp/Interp.h
===
--- clang/lib/AST/Interp/Interp.h
+++ clang/lib/AST/Interp/Interp.h
@@ -67,6 +67,10 @@
 bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
 CheckSubobjectKind CSK);
 
+/// Checks if accessing a base or derived record of the given pointer is valid.
+bool CheckBaseDerived(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
+  CheckSubobjectKind CSK);
+
 /// Checks if a pointer points to const storage.
 bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr);
 
@@ -1157,10 +1161,22 @@
   return true;
 }
 
+inline bool GetPtrDerivedPop(InterpState &S, CodePtr OpPC, uint32_t Off) {
+  const Pointer &Ptr = S.Stk.pop();
+  if (!CheckNull(S, OpPC, Ptr, CSK_Derived))
+return false;
+  if (!CheckBaseDerived(S, OpPC, Ptr, CSK_Derived))
+return false;
+  S.Stk.push(Ptr.atFieldSub(Off));
+  return true;
+}
+
 inline bool GetPtrBase(InterpState &S, CodePtr OpPC, uint32_t Off) {
   const Pointer &Ptr = S.Stk.peek();
   if (!CheckNull(S, OpPC, Ptr, CSK_Base))
 return false;
+  if (!CheckBaseDerived(S, OpPC, Ptr, CSK_Base))
+return false;
   S.Stk.push(Ptr.atField(Off));
   return true;
 }
@@ -1169,6 +1185,8 @@
   const Pointer &Ptr = S.Stk.pop();
   if (!CheckNull(S, OpPC, Ptr, CSK_Base))
 return false;
+  if (!CheckBaseDerived(S, OpPC, Ptr, CSK_Base))
+return false;
   S.

[PATCH] D156506: [clang][Interp] Check floating results for NaNs

2023-09-04 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

I thought this review wasn't clear at all on what's supposed to happen but 
since https://reviews.llvm.org/D157072 is going nowhere, I'll just push this 
one in the next few days.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D156506

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


[PATCH] D158361: [clang][Sema] Fix a copy/paste bug in ~Sema()

2023-09-04 Thread Timm Bäder via Phabricator via cfe-commits
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG84643bfa8723: [clang][Sema] Fix a copy/paste bug in ~Sema() 
(authored by tbaeder).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D158361

Files:
  clang/lib/Sema/Sema.cpp


Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -483,7 +483,7 @@
 
   // Delete cached satisfactions.
   std::vector Satisfactions;
-  Satisfactions.reserve(Satisfactions.size());
+  Satisfactions.reserve(SatisfactionCache.size());
   for (auto &Node : SatisfactionCache)
 Satisfactions.push_back(&Node);
   for (auto *Node : Satisfactions)


Index: clang/lib/Sema/Sema.cpp
===
--- clang/lib/Sema/Sema.cpp
+++ clang/lib/Sema/Sema.cpp
@@ -483,7 +483,7 @@
 
   // Delete cached satisfactions.
   std::vector Satisfactions;
-  Satisfactions.reserve(Satisfactions.size());
+  Satisfactions.reserve(SatisfactionCache.size());
   for (auto &Node : SatisfactionCache)
 Satisfactions.push_back(&Node);
   for (auto *Node : Satisfactions)
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D154262: [clang][Interp] LambdaThisCaptures

2023-09-04 Thread Timm Bäder via Phabricator via cfe-commits
tbaeder added a comment.

Ping


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D154262

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


  1   2   3   4   5   6   7   8   9   10   >