[clang] 53e8790 - [clang][Interp][NFC] Remove double using namespace stmt

2024-08-02 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-08-03T05:45:00+02:00
New Revision: 53e87908c67f158bfe196a3c7cec690dc5eed1fc

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

LOG: [clang][Interp][NFC] Remove double using namespace stmt

Added: 


Modified: 
clang/lib/AST/Interp/Interp.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp
index 3694253ae9782..9009cf820244d 100644
--- a/clang/lib/AST/Interp/Interp.cpp
+++ b/clang/lib/AST/Interp/Interp.cpp
@@ -26,8 +26,6 @@
 #include 
 #include 
 
-using namespace clang;
-
 using namespace clang;
 using namespace clang::interp;
 



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


[clang] 4d2c9d8 - [clang][Interp][NFC] Add more assertions to add/removePointer

2024-08-02 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-08-03T05:44:59+02:00
New Revision: 4d2c9d8cd849e8097f41b3c3b52e4475188b5489

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

LOG: [clang][Interp][NFC] Add more assertions to add/removePointer

Added: 


Modified: 
clang/lib/AST/Interp/InterpBlock.cpp
clang/lib/AST/Interp/Pointer.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/InterpBlock.cpp 
b/clang/lib/AST/Interp/InterpBlock.cpp
index 5ac778aeb6075..7a3962290edb4 100644
--- a/clang/lib/AST/Interp/InterpBlock.cpp
+++ b/clang/lib/AST/Interp/InterpBlock.cpp
@@ -31,9 +31,13 @@ void Block::addPointer(Pointer *P) {
   P->Next = Pointers;
   P->Prev = nullptr;
   Pointers = P;
+#ifndef NDEBUG
+  assert(hasPointer(P));
+#endif
 }
 
 void Block::removePointer(Pointer *P) {
+  assert(P->isBlockPointer());
   assert(P);
   if (IsStatic) {
 assert(!Pointers);
@@ -51,6 +55,10 @@ void Block::removePointer(Pointer *P) {
 P->Prev->Next = P->Next;
   if (P->Next)
 P->Next->Prev = P->Prev;
+  P->PointeeStorage.BS.Pointee = nullptr;
+#ifndef NDEBUG
+  assert(!hasPointer(P));
+#endif
 }
 
 void Block::cleanup() {

diff  --git a/clang/lib/AST/Interp/Pointer.cpp 
b/clang/lib/AST/Interp/Pointer.cpp
index afa9d19d62823..79fe317a61dff 100644
--- a/clang/lib/AST/Interp/Pointer.cpp
+++ b/clang/lib/AST/Interp/Pointer.cpp
@@ -60,6 +60,7 @@ Pointer::~Pointer() {
 
   if (Block *Pointee = PointeeStorage.BS.Pointee) {
 Pointee->removePointer(this);
+PointeeStorage.BS.Pointee = nullptr;
 Pointee->cleanup();
   }
 }
@@ -68,8 +69,15 @@ void Pointer::operator=(const Pointer ) {
   // If the current storage type is Block, we need to remove
   // this pointer from the block.
   if (isBlockPointer()) {
+if (P.isBlockPointer() && this->block() == P.block()) {
+  Offset = P.Offset;
+  PointeeStorage.BS.Base = P.PointeeStorage.BS.Base;
+  return;
+}
+
 if (Block *Pointee = PointeeStorage.BS.Pointee) {
   Pointee->removePointer(this);
+  PointeeStorage.BS.Pointee = nullptr;
   Pointee->cleanup();
 }
   }
@@ -96,8 +104,16 @@ void Pointer::operator=(Pointer &) {
   // If the current storage type is Block, we need to remove
   // this pointer from the block.
   if (isBlockPointer()) {
+if (P.isBlockPointer() && this->block() == P.block()) {
+  Offset = P.Offset;
+  PointeeStorage.BS.Base = P.PointeeStorage.BS.Base;
+  return;
+}
+
 if (Block *Pointee = PointeeStorage.BS.Pointee) {
+  assert(P.block() != this->block());
   Pointee->removePointer(this);
+  PointeeStorage.BS.Pointee = nullptr;
   Pointee->cleanup();
 }
   }



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


[clang] 13faed8 - [clang][Interp][NFC] Use move ctor in moveArrayTy

2024-08-02 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-08-03T05:44:59+02:00
New Revision: 13faed8737b3021e59c3df6db3066876ce831dc9

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

LOG: [clang][Interp][NFC] Use move ctor in moveArrayTy

Similar to what we did previously for primitive types, do it for
primitive arrays as well.

Added: 


Modified: 
clang/lib/AST/Interp/Descriptor.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Descriptor.cpp 
b/clang/lib/AST/Interp/Descriptor.cpp
index 671f2c03d7e5c..8becdca6f5c24 100644
--- a/clang/lib/AST/Interp/Descriptor.cpp
+++ b/clang/lib/AST/Interp/Descriptor.cpp
@@ -76,7 +76,7 @@ static void moveArrayTy(Block *, const std::byte *Src, 
std::byte *Dst,
   Src += sizeof(InitMapPtr);
   Dst += sizeof(InitMapPtr);
   for (unsigned I = 0, NE = D->getNumElems(); I < NE; ++I) {
-const auto *SrcPtr = _cast(Src)[I];
+auto *SrcPtr = _cast(const_cast(Src))[I];
 auto *DstPtr = _cast(Dst)[I];
 new (DstPtr) T(std::move(*SrcPtr));
   }



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


[clang] 400c7c7 - [clang][Interp][NFC] Simplify Pointer move/copy assignment op

2024-08-02 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-08-03T04:59:16+02:00
New Revision: 400c7c7cf2b15138aa674355983be74270de93bc

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

LOG: [clang][Interp][NFC] Simplify Pointer move/copy assignment op

Added: 


Modified: 
clang/lib/AST/Interp/Pointer.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Pointer.cpp 
b/clang/lib/AST/Interp/Pointer.cpp
index 3ac8bc2b09709..afa9d19d62823 100644
--- a/clang/lib/AST/Interp/Pointer.cpp
+++ b/clang/lib/AST/Interp/Pointer.cpp
@@ -67,12 +67,10 @@ Pointer::~Pointer() {
 void Pointer::operator=(const Pointer ) {
   // If the current storage type is Block, we need to remove
   // this pointer from the block.
-  bool WasBlockPointer = isBlockPointer();
-  if (StorageKind == Storage::Block) {
-Block *Old = PointeeStorage.BS.Pointee;
-if (WasBlockPointer && Old) {
-  PointeeStorage.BS.Pointee->removePointer(this);
-  Old->cleanup();
+  if (isBlockPointer()) {
+if (Block *Pointee = PointeeStorage.BS.Pointee) {
+  Pointee->removePointer(this);
+  Pointee->cleanup();
 }
   }
 
@@ -97,12 +95,10 @@ void Pointer::operator=(const Pointer ) {
 void Pointer::operator=(Pointer &) {
   // If the current storage type is Block, we need to remove
   // this pointer from the block.
-  bool WasBlockPointer = isBlockPointer();
-  if (StorageKind == Storage::Block) {
-Block *Old = PointeeStorage.BS.Pointee;
-if (WasBlockPointer && Old) {
-  PointeeStorage.BS.Pointee->removePointer(this);
-  Old->cleanup();
+  if (isBlockPointer()) {
+if (Block *Pointee = PointeeStorage.BS.Pointee) {
+  Pointee->removePointer(this);
+  Pointee->cleanup();
 }
   }
 



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


[clang] 803db1f - [clang][Interp][NFC] Add missing fallthrough when parsing While loops

2024-07-30 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-30T12:42:04+02:00
New Revision: 803db1f5254047b08b6887c52009d4e72e67a673

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

LOG: [clang][Interp][NFC] Add missing fallthrough when parsing While loops

Added: 


Modified: 
clang/lib/AST/Interp/Compiler.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index c07c1062f68a1..258e4ed645254 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -4373,6 +4373,7 @@ bool Compiler::visitWhileStmt(const WhileStmt 
*S) {
 
   if (!this->jump(CondLabel))
 return false;
+  this->fallthrough(EndLabel);
   this->emitLabel(EndLabel);
 
   return true;



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


[clang] 7e04937 - [clang][Interp][NFC] Improve InterpFrame::dump

2024-07-26 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-26T16:09:02+02:00
New Revision: 7e049373f4d26780f558f798b403a8477dd6af08

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

LOG: [clang][Interp][NFC] Improve InterpFrame::dump

Added: 


Modified: 
clang/lib/AST/Interp/Disasm.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Disasm.cpp b/clang/lib/AST/Interp/Disasm.cpp
index 867284ecf7f4b..5e3a5b9515b52 100644
--- a/clang/lib/AST/Interp/Disasm.cpp
+++ b/clang/lib/AST/Interp/Disasm.cpp
@@ -278,10 +278,15 @@ LLVM_DUMP_METHOD void InterpFrame::dump(llvm::raw_ostream 
,
   OS << "\n";
   OS.indent(Spaces) << "This: " << getThis() << "\n";
   OS.indent(Spaces) << "RVO: " << getRVOPtr() << "\n";
-
-  while (const InterpFrame *F = this->Caller) {
+  OS.indent(Spaces) << "Depth: " << Depth << "\n";
+  OS.indent(Spaces) << "ArgSize: " << ArgSize << "\n";
+  OS.indent(Spaces) << "Args: " << (void *)Args << "\n";
+  OS.indent(Spaces) << "FrameOffset: " << FrameOffset << "\n";
+  OS.indent(Spaces) << "FrameSize: " << (Func ? Func->getFrameSize() : 0)
+<< "\n";
+
+  for (const InterpFrame *F = this->Caller; F; F = F->Caller) {
 F->dump(OS, Indent + 1);
-F = F->Caller;
   }
 }
 



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


[clang] 7304936 - [clang][Interp] Add preliminary __builtin_constant_p implementation

2024-07-25 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-25T18:51:36+02:00
New Revision: 7304936479a7eb61adc9edcaf6ce56e4792590ad

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

LOG: [clang][Interp] Add preliminary __builtin_constant_p implementation

This is not perfect or complete, but it helps us pass the simple tests
and those tests where __builtin_constant_p is not the main subject of
testing.

Added: 
clang/test/AST/Interp/builtin-constant-p.cpp

Modified: 
clang/lib/AST/Interp/ByteCodeEmitter.cpp
clang/lib/AST/Interp/InterpBuiltin.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/ByteCodeEmitter.cpp 
b/clang/lib/AST/Interp/ByteCodeEmitter.cpp
index fee4432a8f661..a01fa15dc0b7d 100644
--- a/clang/lib/AST/Interp/ByteCodeEmitter.cpp
+++ b/clang/lib/AST/Interp/ByteCodeEmitter.cpp
@@ -28,7 +28,8 @@ using namespace clang::interp;
 /// but that is not correct for our use cases.
 static bool isUnevaluatedBuiltin(unsigned BuiltinID) {
   return BuiltinID == Builtin::BI__builtin_classify_type ||
- BuiltinID == Builtin::BI__builtin_os_log_format_buffer_size;
+ BuiltinID == Builtin::BI__builtin_os_log_format_buffer_size ||
+ BuiltinID == Builtin::BI__builtin_constant_p;
 }
 
 Function *ByteCodeEmitter::compileFunc(const FunctionDecl *FuncDecl) {

diff  --git a/clang/lib/AST/Interp/InterpBuiltin.cpp 
b/clang/lib/AST/Interp/InterpBuiltin.cpp
index c170042144acc..c59bbc8313edc 100644
--- a/clang/lib/AST/Interp/InterpBuiltin.cpp
+++ b/clang/lib/AST/Interp/InterpBuiltin.cpp
@@ -7,6 +7,8 @@
 
//===--===//
 #include "../ExprConstShared.h"
 #include "Boolean.h"
+#include "Compiler.h"
+#include "EvalEmitter.h"
 #include "Interp.h"
 #include "PrimType.h"
 #include "clang/AST/OSLog.h"
@@ -1127,6 +1129,73 @@ static bool interp__builtin_ptrauth_string_discriminator(
   return true;
 }
 
+// FIXME: This implementation is not complete.
+// The Compiler instance we create cannot access the current stack frame, local
+// variables, function parameters, etc. We also need protection from
+// side-effects, fatal errors, etc.
+static bool interp__builtin_constant_p(InterpState , CodePtr OpPC,
+   const InterpFrame *Frame,
+   const Function *Func,
+   const CallExpr *Call) {
+  const Expr *Arg = Call->getArg(0);
+  QualType ArgType = Arg->getType();
+
+  auto returnInt = [, Call](bool Value) -> bool {
+pushInteger(S, Value, Call->getType());
+return true;
+  };
+
+  // __builtin_constant_p always has one operand. The rules which gcc follows
+  // are not precisely documented, but are as follows:
+  //
+  //  - If the operand is of integral, floating, complex or enumeration type,
+  //and can be folded to a known value of that type, it returns 1.
+  //  - If the operand can be folded to a pointer to the first character
+  //of a string literal (or such a pointer cast to an integral type)
+  //or to a null pointer or an integer cast to a pointer, it returns 1.
+  //
+  // Otherwise, it returns 0.
+  //
+  // FIXME: GCC also intends to return 1 for literals of aggregate types, but
+  // its support for this did not work prior to GCC 9 and is not yet well
+  // understood.
+  if (ArgType->isIntegralOrEnumerationType() || ArgType->isFloatingType() ||
+  ArgType->isAnyComplexType() || ArgType->isPointerType() ||
+  ArgType->isNullPtrType()) {
+InterpStack Stk;
+Compiler C(S.Ctx, S.P, S, Stk);
+auto Res = C.interpretExpr(Arg, 
/*ConvertResultToRValue=*/Arg->isGLValue());
+if (Res.isInvalid()) {
+  C.cleanup();
+  Stk.clear();
+}
+
+const APValue  = Res.toAPValue();
+if (!Res.isInvalid() && LV.isLValue()) {
+  APValue::LValueBase Base = LV.getLValueBase();
+  if (Base.isNull()) {
+// A null base is acceptable.
+return returnInt(true);
+  } else if (const auto *E = Base.dyn_cast()) {
+if (!isa(E))
+  return returnInt(false);
+return returnInt(LV.getLValueOffset().isZero());
+  } else if (Base.is()) {
+// Surprisingly, GCC considers __builtin_constant_p((int)) to
+// evaluate to true.
+return returnInt(true);
+  } else {
+// Any other base is not constant enough for GCC.
+return returnInt(false);
+  }
+}
+
+return returnInt(!Res.isInvalid() && !Res.empty());
+  }
+
+  return returnInt(false);
+}
+
 bool InterpretBuiltin(InterpState , CodePtr OpPC, const Function *F,
   const CallExpr *Call) {
   const InterpFrame *Frame = S.Current;
@@ -1456,6 +1525,11 @@ bool InterpretBuiltin(InterpState , CodePtr OpPC, 
const Function *F,
   return 

[clang] 8608cc1 - [clang][Interp] Fix array element This chains

2024-07-24 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-25T06:45:48+02:00
New Revision: 8608cc1c89640bd3d8120f24c964af21310253b6

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

LOG: [clang][Interp] Fix array element This chains

The previous test was too minimal. If we actually do something after
initializing the nested array element, we end up causing a stack element
type mismatch.

Added: 


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

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index 4d5d725d6964c..df55d01b8b9d6 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -92,7 +92,7 @@ bool InitLink::emit(Compiler *Ctx, const Expr *E) 
const {
   case K_Elem:
 if (!Ctx->emitConstUint32(Offset, E))
   return false;
-return Ctx->emitArrayElemPtrUint32(E);
+return Ctx->emitArrayElemPtrPopUint32(E);
   default:
 llvm_unreachable("Unhandled InitLink kind");
   }
@@ -4156,7 +4156,8 @@ bool Compiler::VisitCXXThisExpr(const 
CXXThisExpr *E) {
   if (InitStackActive && !InitStack.empty()) {
 unsigned StartIndex = 0;
 for (StartIndex = InitStack.size() - 1; StartIndex > 0; --StartIndex) {
-  if (InitStack[StartIndex].Kind != InitLink::K_Field)
+  if (InitStack[StartIndex].Kind != InitLink::K_Field &&
+  InitStack[StartIndex].Kind != InitLink::K_Elem)
 break;
 }
 

diff  --git a/clang/test/AST/Interp/records.cpp 
b/clang/test/AST/Interp/records.cpp
index d77e5a5c782ce..9551630caf3d6 100644
--- a/clang/test/AST/Interp/records.cpp
+++ b/clang/test/AST/Interp/records.cpp
@@ -1551,8 +1551,12 @@ namespace ArrayInitChain {
 
   constexpr CustomOperandVal A[] = {
 {},
+{{"depctr_hold_cnt"},  12,   13},
   };
   static_assert(A[0].Str.S == nullptr, "");
   static_assert(A[0].Width == 0, "");
   static_assert(A[0].Mask == 1, "");
+
+  static_assert(A[1].Width == 12, "");
+  static_assert(A[1].Mask == 13, "");
 }



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


[clang] bb0300c - [clang][Interp] Fix initializing array subobjects with This pointers

2024-07-24 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-24T19:15:10+02:00
New Revision: bb0300cf7ce54bfbb1607348c89cb0525e12076b

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

LOG: [clang][Interp] Fix initializing array subobjects with This pointers

We need to select the right array element once we see the CXXThisExpr.

Added: 


Modified: 
clang/lib/AST/Interp/Compiler.cpp
clang/lib/AST/Interp/Compiler.h
clang/test/AST/Interp/records.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index 58a0852aca755..4d5d725d6964c 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -89,6 +89,10 @@ bool InitLink::emit(Compiler *Ctx, const Expr *E) 
const {
 return Ctx->emitGetPtrLocal(Offset, E);
   case K_Decl:
 return Ctx->visitDeclRef(D, E);
+  case K_Elem:
+if (!Ctx->emitConstUint32(Offset, E))
+  return false;
+return Ctx->emitArrayElemPtrUint32(E);
   default:
 llvm_unreachable("Unhandled InitLink kind");
   }
@@ -1556,6 +1560,7 @@ bool Compiler::visitArrayElemInit(unsigned 
ElemIndex,
 return this->emitInitElem(*T, ElemIndex, Init);
   }
 
+  InitLinkScope ILS(this, InitLink::Elem(ElemIndex));
   // Advance the pointer currently on the stack to the given
   // dimension.
   if (!this->emitConstUint32(ElemIndex, Init))

diff  --git a/clang/lib/AST/Interp/Compiler.h b/clang/lib/AST/Interp/Compiler.h
index 084f5aef25f8e..d22b29d29a92d 100644
--- a/clang/lib/AST/Interp/Compiler.h
+++ b/clang/lib/AST/Interp/Compiler.h
@@ -50,6 +50,7 @@ struct InitLink {
 K_Field = 1,
 K_Temp = 2,
 K_Decl = 3,
+K_Elem = 5,
   };
 
   static InitLink This() { return InitLink{K_This}; }
@@ -68,6 +69,11 @@ struct InitLink {
 IL.D = D;
 return IL;
   }
+  static InitLink Elem(unsigned Index) {
+InitLink IL{K_Elem};
+IL.Offset = Index;
+return IL;
+  }
 
   InitLink(uint8_t Kind) : Kind(Kind) {}
   template 

diff  --git a/clang/test/AST/Interp/records.cpp 
b/clang/test/AST/Interp/records.cpp
index 2fc88a0b1df6a..d77e5a5c782ce 100644
--- a/clang/test/AST/Interp/records.cpp
+++ b/clang/test/AST/Interp/records.cpp
@@ -1537,3 +1537,22 @@ namespace BitSet {
 Bitset()
   };
 }
+
+namespace ArrayInitChain {
+  struct StringLiteral {
+const char *S;
+  };
+
+  struct CustomOperandVal {
+StringLiteral Str;
+unsigned Width;
+unsigned Mask = Width + 1;
+  };
+
+  constexpr CustomOperandVal A[] = {
+{},
+  };
+  static_assert(A[0].Str.S == nullptr, "");
+  static_assert(A[0].Width == 0, "");
+  static_assert(A[0].Mask == 1, "");
+}



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


[clang] 338c35a - [clang][Interp] Fix calling variadic call operators

2024-07-24 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-24T17:06:24+02:00
New Revision: 338c35aabfbede9ba10a4f48a13e63f37d6f8c7c

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

LOG: [clang][Interp] Fix calling variadic call operators

Added: 


Modified: 
clang/lib/AST/Interp/Interp.cpp
clang/test/AST/Interp/cxx20.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp
index bf29b85041d82..3694253ae9782 100644
--- a/clang/lib/AST/Interp/Interp.cpp
+++ b/clang/lib/AST/Interp/Interp.cpp
@@ -233,7 +233,8 @@ void cleanupAfterFunctionCall(InterpState , CodePtr OpPC) 
{
   assert(false && "Can't get arguments from that expression type");
 
 assert(NumArgs >= CurFunc->getNumWrittenParams());
-NumVarArgs = NumArgs - CurFunc->getNumWrittenParams();
+NumVarArgs = NumArgs - (CurFunc->getNumWrittenParams() +
+isa(CallSite));
 for (unsigned I = 0; I != NumVarArgs; ++I) {
   const Expr *A = Args[NumArgs - 1 - I];
   popArg(S, A);

diff  --git a/clang/test/AST/Interp/cxx20.cpp b/clang/test/AST/Interp/cxx20.cpp
index 2faacbbf70fd7..da80454b7a820 100644
--- a/clang/test/AST/Interp/cxx20.cpp
+++ b/clang/test/AST/Interp/cxx20.cpp
@@ -827,3 +827,17 @@ namespace CheckingNullPtrForInitialization {
 return x;
   }
 }
+
+namespace VariadicCallOperator {
+  class F {
+  public:
+constexpr void operator()(int a, int b, ...) {}
+  };
+  constexpr int foo() {
+F f;
+
+f(1,2, 3);
+return 1;
+  }
+  constexpr int A = foo();
+}



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


[clang] 9f08ae8 - [clang][Interp][NFC] Fix getting the record decl from a pointer type

2024-07-24 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-24T16:54:38+02:00
New Revision: 9f08ae8d2dd1ff9ec3b033d099282dee05528413

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

LOG: [clang][Interp][NFC] Fix getting the record decl from a pointer type

Added: 


Modified: 
clang/lib/AST/Interp/Compiler.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index 0455eec3f0145..58a0852aca755 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -5281,8 +5281,8 @@ template 
 unsigned Compiler::collectBaseOffset(const QualType BaseType,
   const QualType DerivedType) {
   const auto extractRecordDecl = [](QualType Ty) -> const CXXRecordDecl * {
-if (const auto *PT = dyn_cast(Ty))
-  return PT->getPointeeType()->getAsCXXRecordDecl();
+if (const auto *R = Ty->getPointeeCXXRecordDecl())
+  return R;
 return Ty->getAsCXXRecordDecl();
   };
   const CXXRecordDecl *BaseDecl = extractRecordDecl(BaseType);



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


[clang] d36edf8 - [clang][Interp] Bail out on value dependent variable initializers

2024-07-24 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-24T12:11:06+02:00
New Revision: d36edf8146cfea9f0407e2fb26283297eb6a6ac4

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

LOG: [clang][Interp] Bail out on value dependent variable initializers

Added: 


Modified: 
clang/lib/AST/Interp/Compiler.cpp
clang/test/AST/Interp/literals.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index dbd2686b17f09..0455eec3f0145 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -3683,6 +3683,9 @@ VarCreationState Compiler::visitVarDecl(const 
VarDecl *VD, bool Topleve
   const Expr *Init = VD->getInit();
   std::optional VarT = classify(VD->getType());
 
+  if (Init && Init->isValueDependent())
+return false;
+
   if (Context::shouldBeGloballyIndexed(VD)) {
 auto checkDecl = [&]() -> bool {
   bool NeedsOp = !Toplevel && VD->isLocalVarDecl() && VD->isStaticLocal();

diff  --git a/clang/test/AST/Interp/literals.cpp 
b/clang/test/AST/Interp/literals.cpp
index 2b8abf665b20d..815fb67b9bbfc 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -1307,3 +1307,15 @@ namespace VolatileReads {
   static_assert(b, ""); // both-error {{not an integral constant expression}} \
 // both-note {{read of volatile-qualified type 'const 
volatile int' is not allowed in a constant expression}}
 }
+#if __cplusplus >= 201703L
+namespace {
+  struct C {
+int x;
+  };
+
+  template  void f() {
+const auto &[c] = *p;
+ // both-warning {{expression result unused}}
+  }
+}
+#endif



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


[clang] 0b262bb - [clang][Interp] Properly reject StmtExprs with Stmt result

2024-07-23 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-23T19:46:15+02:00
New Revision: 0b262bbb5713ebfdf66f40021711307e9c8d4bf5

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

LOG: [clang][Interp] Properly reject StmtExprs with Stmt result

Added: 


Modified: 
clang/lib/AST/Interp/Compiler.cpp
clang/test/AST/Interp/literals.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index 0fc93c14131e6..dbd2686b17f09 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -3194,13 +3194,9 @@ bool Compiler::VisitStmtExpr(const StmtExpr *E) 
{
 }
 
 assert(S == Result);
-if (const Expr *ResultExpr = dyn_cast(S)) {
-  if (DiscardResult)
-return this->discard(ResultExpr);
+if (const Expr *ResultExpr = dyn_cast(S))
   return this->delegate(ResultExpr);
-}
-
-return this->visitStmt(S);
+return this->emitUnsupported(E);
   }
 
   return BS.destroyLocals();

diff  --git a/clang/test/AST/Interp/literals.cpp 
b/clang/test/AST/Interp/literals.cpp
index 9cd65462a0af3..9c828afdef18b 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -1214,6 +1214,10 @@ namespace StmtExprs {
 return 76;
   }
   static_assert(foo() == 76, "");
+
+  namespace CrossFuncLabelDiff {
+constexpr long a(bool x) { return x ? 0 : (long)& + (0 && ({lbl: 
0;})); }
+  }
 }
 #endif
 



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


[clang] 5589f29 - [clang][Interp] Merge FunctionPointer into Pointer

2024-07-23 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-23T16:06:04+02:00
New Revision: 5589f2977117ec4685018472ca5f01355424bab9

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

LOG: [clang][Interp] Merge FunctionPointer into Pointer

Back when I introduced the FunctionPointer class, I assumed that we
can always know that a Pointer is not a FunctionPointer. With the
DecayPtr op, that changed somewhat, but the information whether a
Pointer was created through a FunctionPointer was lost.

However, we need this information, especially when we're in the
codegen stage.

Added: 


Modified: 
clang/lib/AST/Interp/FunctionPointer.h
clang/lib/AST/Interp/Interp.cpp
clang/lib/AST/Interp/Interp.h
clang/lib/AST/Interp/Pointer.cpp
clang/lib/AST/Interp/Pointer.h

Removed: 




diff  --git a/clang/lib/AST/Interp/FunctionPointer.h 
b/clang/lib/AST/Interp/FunctionPointer.h
index 0f2c6e571a1d8..d92cd32933fcd 100644
--- a/clang/lib/AST/Interp/FunctionPointer.h
+++ b/clang/lib/AST/Interp/FunctionPointer.h
@@ -23,11 +23,10 @@ class FunctionPointer final {
   bool Valid;
 
 public:
-  FunctionPointer(const Function *Func) : Func(Func), Valid(true) {
-assert(Func);
-  }
+  FunctionPointer() = default;
+  FunctionPointer(const Function *Func) : Func(Func), Valid(true) {}
 
-  FunctionPointer(uintptr_t IntVal = 0, const Descriptor *Desc = nullptr)
+  FunctionPointer(uintptr_t IntVal, const Descriptor *Desc = nullptr)
   : Func(reinterpret_cast(IntVal)), Valid(false) {}
 
   const Function *getFunction() const { return Func; }

diff  --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp
index 6fcd90e5f5849..bf29b85041d82 100644
--- a/clang/lib/AST/Interp/Interp.cpp
+++ b/clang/lib/AST/Interp/Interp.cpp
@@ -333,7 +333,7 @@ bool CheckConstant(InterpState , CodePtr OpPC, const 
Descriptor *Desc) {
 }
 
 static bool CheckConstant(InterpState , CodePtr OpPC, const Pointer ) {
-  if (Ptr.isIntegralPointer())
+  if (!Ptr.isBlockPointer())
 return true;
   return CheckConstant(S, OpPC, Ptr.getDeclDesc());
 }

diff  --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 8e96f78d90568..492802897f013 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -2811,6 +2811,13 @@ inline bool DecayPtr(InterpState , CodePtr OpPC) {
   using ToT = typename PrimConv::T;
 
   const FromT  = S.Stk.pop();
+
+  if constexpr (std::is_same_v &&
+std::is_same_v) {
+S.Stk.push(OldPtr.getFunction());
+return true;
+  }
+
   S.Stk.push(ToT(OldPtr.getIntegerRepresentation(), nullptr));
   return true;
 }

diff  --git a/clang/lib/AST/Interp/Pointer.cpp 
b/clang/lib/AST/Interp/Pointer.cpp
index 29579f5db40b6..3ac8bc2b09709 100644
--- a/clang/lib/AST/Interp/Pointer.cpp
+++ b/clang/lib/AST/Interp/Pointer.cpp
@@ -55,7 +55,7 @@ Pointer::Pointer(Pointer &)
 }
 
 Pointer::~Pointer() {
-  if (isIntegralPointer())
+  if (!isBlockPointer())
 return;
 
   if (Block *Pointee = PointeeStorage.BS.Pointee) {
@@ -87,6 +87,8 @@ void Pointer::operator=(const Pointer ) {
   PointeeStorage.BS.Pointee->addPointer(this);
   } else if (P.isIntegralPointer()) {
 PointeeStorage.Int = P.PointeeStorage.Int;
+  } else if (P.isFunctionPointer()) {
+PointeeStorage.Fn = P.PointeeStorage.Fn;
   } else {
 assert(false && "Unhandled storage kind");
   }
@@ -115,6 +117,8 @@ void Pointer::operator=(Pointer &) {
   PointeeStorage.BS.Pointee->addPointer(this);
   } else if (P.isIntegralPointer()) {
 PointeeStorage.Int = P.PointeeStorage.Int;
+  } else if (P.isFunctionPointer()) {
+PointeeStorage.Fn = P.PointeeStorage.Fn;
   } else {
 assert(false && "Unhandled storage kind");
   }
@@ -131,6 +135,8 @@ APValue Pointer::toAPValue(const ASTContext ) const {
CharUnits::fromQuantity(asIntPointer().Value + 
this->Offset),
Path,
/*IsOnePastEnd=*/false, /*IsNullPtr=*/false);
+  if (isFunctionPointer())
+return asFunctionPointer().toAPValue(ASTCtx);
 
   // Build the lvalue base from the block.
   const Descriptor *Desc = getDeclDesc();
@@ -263,7 +269,7 @@ std::string Pointer::toDiagnosticString(const ASTContext 
) const {
 }
 
 bool Pointer::isInitialized() const {
-  if (isIntegralPointer())
+  if (!isBlockPointer())
 return true;
 
   if (isRoot() && PointeeStorage.BS.Base == sizeof(GlobalInlineDescriptor)) {
@@ -299,7 +305,7 @@ bool Pointer::isInitialized() const {
 }
 
 void Pointer::initialize() const {
-  if (isIntegralPointer())
+  if (!isBlockPointer())
 return;
 
   assert(PointeeStorage.BS.Pointee && "Cannot initialize null pointer");
@@ -368,10 +374,15 @@ bool Pointer::hasSameBase(const Pointer , const Pointer 
) {
 
   if (A.isIntegralPointer() && 

[clang] 20d7fff - [clang][Interp] Fix atomic builtins with integral pointers

2024-07-23 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-23T13:15:32+02:00
New Revision: 20d7fff5eaaa9d78807035d63e5c503bfc1b497e

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

LOG: [clang][Interp] Fix atomic builtins with integral pointers

Check the integral pointer value.

Added: 


Modified: 
clang/lib/AST/Interp/InterpBuiltin.cpp
clang/test/AST/Interp/atomic.c

Removed: 




diff  --git a/clang/lib/AST/Interp/InterpBuiltin.cpp 
b/clang/lib/AST/Interp/InterpBuiltin.cpp
index 98928b3c22d7c..c170042144acc 100644
--- a/clang/lib/AST/Interp/InterpBuiltin.cpp
+++ b/clang/lib/AST/Interp/InterpBuiltin.cpp
@@ -942,15 +942,29 @@ static bool interp__builtin_atomic_lock_free(InterpState 
, CodePtr OpPC,
   if (Ptr.isZero())
 return returnBool(true);
 
-  QualType PointeeType = Call->getArg(1)
- ->IgnoreImpCasts()
- ->getType()
- ->castAs()
- ->getPointeeType();
-  // OK, we will inline operations on this object.
-  if (!PointeeType->isIncompleteType() &&
-  S.getCtx().getTypeAlignInChars(PointeeType) >= Size)
-return returnBool(true);
+  if (Ptr.isIntegralPointer()) {
+uint64_t IntVal = Ptr.getIntegerRepresentation();
+if (APSInt(APInt(64, IntVal, false), 
true).isAligned(Size.getAsAlign()))
+  return returnBool(true);
+  }
+
+  const Expr *PtrArg = Call->getArg(1);
+  // Otherwise, check if the type's alignment against Size.
+  if (const auto *ICE = dyn_cast(PtrArg)) {
+// Drop the potential implicit-cast to 'const volatile void*', getting
+// the underlying type.
+if (ICE->getCastKind() == CK_BitCast)
+  PtrArg = ICE->getSubExpr();
+  }
+
+  if (auto PtrTy = PtrArg->getType()->getAs()) {
+QualType PointeeType = PtrTy->getPointeeType();
+if (!PointeeType->isIncompleteType() &&
+S.getCtx().getTypeAlignInChars(PointeeType) >= Size) {
+  // OK, we will inline operations on this object.
+  return returnBool(true);
+}
+  }
 }
   }
 

diff  --git a/clang/test/AST/Interp/atomic.c b/clang/test/AST/Interp/atomic.c
index c5fd9ab222934..c8469d4a938b8 100644
--- a/clang/test/AST/Interp/atomic.c
+++ b/clang/test/AST/Interp/atomic.c
@@ -58,3 +58,16 @@ _Static_assert(atomic_is_lock_free((atomic_short*)0), "");
 _Static_assert(atomic_is_lock_free((atomic_int*)0), "");
 _Static_assert(atomic_is_lock_free((atomic_long*)0), "");
 _Static_assert(atomic_is_lock_free(0 + (atomic_char*)0), "");
+
+_Static_assert(__atomic_always_lock_free(1, (void*)1), "");
+_Static_assert(__atomic_always_lock_free(1, (void*)-1), "");
+_Static_assert(!__atomic_always_lock_free(4, (void*)2), "");
+_Static_assert(!__atomic_always_lock_free(4, (void*)-2), "");
+_Static_assert(__atomic_always_lock_free(4, (void*)4), "");
+_Static_assert(__atomic_always_lock_free(4, (void*)-4), "");
+
+_Static_assert(__atomic_always_lock_free(1, "string"), "");
+_Static_assert(!__atomic_always_lock_free(2, "string"), "");
+_Static_assert(__atomic_always_lock_free(2, (int[2]){}), "");
+void dummyfn();
+_Static_assert(__atomic_always_lock_free(2, dummyfn) || 1, "");



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


[clang] f18dd9e - Reapply "[Clang][Interp] `__builtin_os_log_format_buffer_size` should be an unevaluated builtin (#99895)"

2024-07-23 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-23T11:57:40+02:00
New Revision: f18dd9edec9c2135a8906d795258a8c5a24f74f3

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

LOG: Reapply "[Clang][Interp] `__builtin_os_log_format_buffer_size` should be 
an unevaluated builtin (#99895)"

This reverts commit 5f05d5ec8f9bb15c0ac29fce843a2c73165ac414.

Reapply the original commit without the test. The memory leak is caused
by a well known problem in the new constant interpreter.

Added: 


Modified: 
clang/lib/AST/Interp/ByteCodeEmitter.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/ByteCodeEmitter.cpp 
b/clang/lib/AST/Interp/ByteCodeEmitter.cpp
index a3d4c7d7392da..fee4432a8f661 100644
--- a/clang/lib/AST/Interp/ByteCodeEmitter.cpp
+++ b/clang/lib/AST/Interp/ByteCodeEmitter.cpp
@@ -27,7 +27,8 @@ using namespace clang::interp;
 /// Similar information is available via ASTContext::BuiltinInfo,
 /// but that is not correct for our use cases.
 static bool isUnevaluatedBuiltin(unsigned BuiltinID) {
-  return BuiltinID == Builtin::BI__builtin_classify_type;
+  return BuiltinID == Builtin::BI__builtin_classify_type ||
+ BuiltinID == Builtin::BI__builtin_os_log_format_buffer_size;
 }
 
 Function *ByteCodeEmitter::compileFunc(const FunctionDecl *FuncDecl) {



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


[clang] 613d2c3 - [clang][Interp][NFC] Avoid hitting an assertion in invalid code

2024-07-22 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-22T16:59:31+02:00
New Revision: 613d2c393992eee470405f1859aaf5fd1837e36c

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

LOG: [clang][Interp][NFC] Avoid hitting an assertion in invalid code

Added: 


Modified: 
clang/lib/AST/Interp/Pointer.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Pointer.cpp 
b/clang/lib/AST/Interp/Pointer.cpp
index 229007c6d720a..3324691cdb7b7 100644
--- a/clang/lib/AST/Interp/Pointer.cpp
+++ b/clang/lib/AST/Interp/Pointer.cpp
@@ -149,6 +149,10 @@ APValue Pointer::toAPValue(const ASTContext ) const 
{
   CharUnits Offset = CharUnits::Zero();
 
   auto getFieldOffset = [&](const FieldDecl *FD) -> CharUnits {
+// This shouldn't happen, but if it does, don't crash inside
+// getASTRecordLayout.
+if (FD->getParent()->isInvalidDecl())
+  return CharUnits::Zero();
 const ASTRecordLayout  = ASTCtx.getASTRecordLayout(FD->getParent());
 unsigned FieldIndex = FD->getFieldIndex();
 return ASTCtx.toCharUnitsFromBits(Layout.getFieldOffset(FieldIndex));



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


[clang] 5303ca1 - [clang][Interp] Start computing APValue offsets

2024-07-20 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-20T17:29:31+02:00
New Revision: 5303ca1496fc5f604f37c071d37821597788e83e

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

LOG: [clang][Interp] Start computing APValue offsets

For array elements, arrays roots and fields.

Added: 
clang/test/AST/Interp/codegen.cpp

Modified: 
clang/lib/AST/Interp/Pointer.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Pointer.cpp 
b/clang/lib/AST/Interp/Pointer.cpp
index f7bd76b260584..229007c6d720a 100644
--- a/clang/lib/AST/Interp/Pointer.cpp
+++ b/clang/lib/AST/Interp/Pointer.cpp
@@ -16,6 +16,7 @@
 #include "MemberPointer.h"
 #include "PrimType.h"
 #include "Record.h"
+#include "clang/AST/RecordLayout.h"
 
 using namespace clang;
 using namespace clang::interp;
@@ -141,25 +142,38 @@ APValue Pointer::toAPValue(const ASTContext ) 
const {
   else
 llvm_unreachable("Invalid allocation type");
 
-  if (isDummy() || isUnknownSizeArray() || Desc->asExpr())
+  if (isUnknownSizeArray() || Desc->asExpr())
 return APValue(Base, CharUnits::Zero(), Path,
/*IsOnePastEnd=*/isOnePastEnd(), /*IsNullPtr=*/false);
 
-  // TODO: compute the offset into the object.
   CharUnits Offset = CharUnits::Zero();
 
+  auto getFieldOffset = [&](const FieldDecl *FD) -> CharUnits {
+const ASTRecordLayout  = ASTCtx.getASTRecordLayout(FD->getParent());
+unsigned FieldIndex = FD->getFieldIndex();
+return ASTCtx.toCharUnitsFromBits(Layout.getFieldOffset(FieldIndex));
+  };
+
   // Build the path into the object.
   Pointer Ptr = *this;
   while (Ptr.isField() || Ptr.isArrayElement()) {
 if (Ptr.isArrayRoot()) {
   Path.push_back(APValue::LValuePathEntry(
   {Ptr.getFieldDesc()->asDecl(), /*IsVirtual=*/false}));
+
+  if (const auto *FD = dyn_cast(Ptr.getFieldDesc()->asDecl()))
+Offset += getFieldOffset(FD);
+
   Ptr = Ptr.getBase();
 } else if (Ptr.isArrayElement()) {
+  unsigned Index;
   if (Ptr.isOnePastEnd())
-
Path.push_back(APValue::LValuePathEntry::ArrayIndex(Ptr.getArray().getNumElems()));
+Index = Ptr.getArray().getNumElems();
   else
-Path.push_back(APValue::LValuePathEntry::ArrayIndex(Ptr.getIndex()));
+Index = Ptr.getIndex();
+
+  Offset += (Index * ASTCtx.getTypeSizeInChars(Ptr.getType()));
+  Path.push_back(APValue::LValuePathEntry::ArrayIndex(Index));
   Ptr = Ptr.getArray();
 } else {
   // TODO: figure out if base is virtual
@@ -170,12 +184,21 @@ APValue Pointer::toAPValue(const ASTContext ) 
const {
   if (const auto *BaseOrMember = Desc->asDecl()) {
 Path.push_back(APValue::LValuePathEntry({BaseOrMember, IsVirtual}));
 Ptr = Ptr.getBase();
+
+if (const auto *FD = dyn_cast(BaseOrMember))
+  Offset += getFieldOffset(FD);
+
 continue;
   }
   llvm_unreachable("Invalid field type");
 }
   }
 
+  // FIXME(perf): We compute the lvalue path above, but we can't supply it
+  // for dummy pointers (that causes crashes later in CheckConstantExpression).
+  if (isDummy())
+Path.clear();
+
   // We assemble the LValuePath starting from the innermost pointer to the
   // outermost one. SO in a.b.c, the first element in Path will refer to
   // the field 'c', while later code expects it to refer to 'a'.

diff  --git a/clang/test/AST/Interp/codegen.cpp 
b/clang/test/AST/Interp/codegen.cpp
new file mode 100644
index 0..8a0d070d19da3
--- /dev/null
+++ b/clang/test/AST/Interp/codegen.cpp
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -o - %s | FileCheck %s
+// RUN: %clang_cc1 -triple x86_64-linux -emit-llvm -o - %s 
-fexperimental-new-constant-interpreter | FileCheck %s
+
+
+int arr[2];
+// CHECK: @pastEnd = constant ptr getelementptr (i8, ptr @arr, i64 8)
+int  = arr[2];
+
+// CHECK: @F = constant ptr @arr, align 8
+int  = arr[0];
+
+struct S {
+  int a;
+  float c[3];
+};
+
+// CHECK: @s = global %struct.S zeroinitializer, align 4
+S s;
+// CHECK: @sp = constant ptr getelementptr (i8, ptr @s, i64 16), align 8
+float  = s.c[3];



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


[clang] 56a9f7c - [clang][Interp] Pass ASTContext to toAPValue()

2024-07-20 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-20T15:29:32+02:00
New Revision: 56a9f7ce611ba21f51043d91c965b59e116013f2

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

LOG: [clang][Interp] Pass ASTContext to toAPValue()

Not yet needed, but we need to ASTContext in a later patch when we start
computing proper values for the APValue offset.

Added: 


Modified: 
clang/lib/AST/Interp/Boolean.h
clang/lib/AST/Interp/Disasm.cpp
clang/lib/AST/Interp/EvalEmitter.cpp
clang/lib/AST/Interp/EvaluationResult.cpp
clang/lib/AST/Interp/Floating.h
clang/lib/AST/Interp/FunctionPointer.h
clang/lib/AST/Interp/Integral.h
clang/lib/AST/Interp/IntegralAP.h
clang/lib/AST/Interp/Interp.h
clang/lib/AST/Interp/MemberPointer.cpp
clang/lib/AST/Interp/MemberPointer.h
clang/lib/AST/Interp/Pointer.cpp
clang/lib/AST/Interp/Pointer.h
clang/unittests/AST/Interp/toAPValue.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Boolean.h b/clang/lib/AST/Interp/Boolean.h
index 1bfb26b1b669f..23f7286036764 100644
--- a/clang/lib/AST/Interp/Boolean.h
+++ b/clang/lib/AST/Interp/Boolean.h
@@ -56,7 +56,7 @@ class Boolean final {
   APSInt toAPSInt(unsigned NumBits) const {
 return APSInt(toAPSInt().zextOrTrunc(NumBits), true);
   }
-  APValue toAPValue() const { return APValue(toAPSInt()); }
+  APValue toAPValue(const ASTContext &) const { return APValue(toAPSInt()); }
 
   Boolean toUnsigned() const { return *this; }
 

diff  --git a/clang/lib/AST/Interp/Disasm.cpp b/clang/lib/AST/Interp/Disasm.cpp
index c6c6275593007..867284ecf7f4b 100644
--- a/clang/lib/AST/Interp/Disasm.cpp
+++ b/clang/lib/AST/Interp/Disasm.cpp
@@ -366,9 +366,9 @@ LLVM_DUMP_METHOD void EvaluationResult::dump() const {
 
 OS << "LValue: ";
 if (const auto *P = std::get_if())
-  P->toAPValue().printPretty(OS, ASTCtx, SourceType);
+  P->toAPValue(ASTCtx).printPretty(OS, ASTCtx, SourceType);
 else if (const auto *FP = std::get_if()) // Nope
-  FP->toAPValue().printPretty(OS, ASTCtx, SourceType);
+  FP->toAPValue(ASTCtx).printPretty(OS, ASTCtx, SourceType);
 OS << "\n";
 break;
   }

diff  --git a/clang/lib/AST/Interp/EvalEmitter.cpp 
b/clang/lib/AST/Interp/EvalEmitter.cpp
index 221bbfdc542ff..08536536ac3c2 100644
--- a/clang/lib/AST/Interp/EvalEmitter.cpp
+++ b/clang/lib/AST/Interp/EvalEmitter.cpp
@@ -145,7 +145,7 @@ template  bool EvalEmitter::emitRet(const 
SourceInfo ) {
 return false;
 
   using T = typename PrimConv::T;
-  EvalResult.setValue(S.Stk.pop().toAPValue());
+  EvalResult.setValue(S.Stk.pop().toAPValue(Ctx.getASTContext()));
   return true;
 }
 
@@ -181,7 +181,7 @@ template <> bool EvalEmitter::emitRet(const 
SourceInfo ) {
   return false;
 }
   } else {
-EvalResult.setValue(Ptr.toAPValue());
+EvalResult.setValue(Ptr.toAPValue(Ctx.getASTContext()));
   }
 
   return true;
@@ -285,7 +285,8 @@ void EvalEmitter::updateGlobalTemporaries() {
   APValue *Cached = Temp->getOrCreateValue(true);
 
   if (std::optional T = Ctx.classify(E->getType())) {
-TYPE_SWITCH(*T, { *Cached = Ptr.deref().toAPValue(); });
+TYPE_SWITCH(
+*T, { *Cached = Ptr.deref().toAPValue(Ctx.getASTContext()); });
   } else {
 if (std::optional APV =
 Ptr.toRValue(Ctx, Temp->getTemporaryExpr()->getType()))

diff  --git a/clang/lib/AST/Interp/EvaluationResult.cpp 
b/clang/lib/AST/Interp/EvaluationResult.cpp
index 0bebfd4ad984e..1b255711c7b36 100644
--- a/clang/lib/AST/Interp/EvaluationResult.cpp
+++ b/clang/lib/AST/Interp/EvaluationResult.cpp
@@ -21,9 +21,9 @@ APValue EvaluationResult::toAPValue() const {
   case LValue:
 // Either a pointer or a function pointer.
 if (const auto *P = std::get_if())
-  return P->toAPValue();
+  return P->toAPValue(Ctx->getASTContext());
 else if (const auto *FP = std::get_if())
-  return FP->toAPValue();
+  return FP->toAPValue(Ctx->getASTContext());
 else
   llvm_unreachable("Unhandled LValue type");
 break;
@@ -46,7 +46,7 @@ std::optional EvaluationResult::toRValue() const {
   if (const auto *P = std::get_if())
 return P->toRValue(*Ctx, getSourceType());
   else if (const auto *FP = std::get_if()) // Nope
-return FP->toAPValue();
+return FP->toAPValue(Ctx->getASTContext());
   llvm_unreachable("Unhandled lvalue kind");
 }
 

diff  --git a/clang/lib/AST/Interp/Floating.h b/clang/lib/AST/Interp/Floating.h
index e4ac76d8509fb..114487821880f 100644
--- a/clang/lib/AST/Interp/Floating.h
+++ b/clang/lib/AST/Interp/Floating.h
@@ -69,7 +69,7 @@ class Floating final {
   APSInt toAPSInt(unsigned NumBits = 0) const {
 return APSInt(F.bitcastToAPInt());
   }
-  APValue toAPValue() const { return APValue(F); }
+  APValue 

[clang] 155f6b4 - [clang][Interp] Fix reporting invalid new/delete expressions

2024-07-20 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-20T10:41:12+02:00
New Revision: 155f6b49d90357d4062aa97f035f42617565ee26

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

LOG: [clang][Interp] Fix reporting invalid new/delete expressions

This should be a CCEDiag call and we do *not* abort because of it.

Added: 


Modified: 
clang/lib/AST/Interp/Interp.cpp
clang/test/AST/Interp/new-delete.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp
index cd6fc60400ebd..6fcd90e5f5849 100644
--- a/clang/lib/AST/Interp/Interp.cpp
+++ b/clang/lib/AST/Interp/Interp.cpp
@@ -728,8 +728,8 @@ bool CheckDynamicMemoryAllocation(InterpState , CodePtr 
OpPC) {
 return true;
 
   const SourceInfo  = S.Current->getSource(OpPC);
-  S.FFDiag(E, diag::note_constexpr_new);
-  return false;
+  S.CCEDiag(E, diag::note_constexpr_new);
+  return true;
 }
 
 bool CheckNewDeleteForms(InterpState , CodePtr OpPC, bool NewWasArray,

diff  --git a/clang/test/AST/Interp/new-delete.cpp 
b/clang/test/AST/Interp/new-delete.cpp
index cb46426c0e3be..7a85def784920 100644
--- a/clang/test/AST/Interp/new-delete.cpp
+++ b/clang/test/AST/Interp/new-delete.cpp
@@ -560,4 +560,9 @@ constexpr int a() { // both-error {{never produces a 
constant expression}}
 }
 static_assert(a() == 1, ""); // both-error {{not an integral constant 
expression}} \
  // both-note {{in call to 'a()'}}
+
+
+static_assert(true ? *new int : 4, ""); // both-error {{expression is not an 
integral constant expression}} \
+// both-note {{read of uninitialized 
object is not allowed in a constant expression}}
+
 #endif



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


[clang] 0d26f65 - [clang][Interp] Emit diagnostics if final ltor conversion fails

2024-07-20 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-20T10:01:25+02:00
New Revision: 0d26f65414afe496b00ee803cc24722a9bf3f41d

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

LOG: [clang][Interp] Emit diagnostics if final ltor conversion fails

Added: 


Modified: 
clang/lib/AST/Interp/EvalEmitter.cpp
clang/test/AST/Interp/cxx11.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/EvalEmitter.cpp 
b/clang/lib/AST/Interp/EvalEmitter.cpp
index 59e78686b78ad..221bbfdc542ff 100644
--- a/clang/lib/AST/Interp/EvalEmitter.cpp
+++ b/clang/lib/AST/Interp/EvalEmitter.cpp
@@ -169,7 +169,9 @@ template <> bool EvalEmitter::emitRet(const 
SourceInfo ) {
   return false;
 // Never allow reading from a non-const pointer, unless the memory
 // has been created in this evaluation.
-if (!Ptr.isConst() && Ptr.block()->getEvalID() != Ctx.getEvalID())
+if (!Ptr.isZero() && Ptr.isBlockPointer() &&
+Ptr.block()->getEvalID() != Ctx.getEvalID() &&
+(!CheckLoad(S, OpPC, Ptr, AK_Read) || !Ptr.isConst()))
   return false;
 
 if (std::optional V =

diff  --git a/clang/test/AST/Interp/cxx11.cpp b/clang/test/AST/Interp/cxx11.cpp
index 92ab9b605f30d..cf2dfba079ef7 100644
--- a/clang/test/AST/Interp/cxx11.cpp
+++ b/clang/test/AST/Interp/cxx11.cpp
@@ -152,3 +152,11 @@ void A::f(SortOrder order) {
 return;
 }
 }
+
+namespace FinalLtorDiags {
+  template struct A {}; // both-note {{template parameter is declared 
here}}
+  int k;
+  int *q =  // both-note {{declared here}}
+  A c; // both-error {{non-type template argument of type 'int *' is not a 
constant expression}} \
+  // both-note {{read of non-constexpr variable 'q' is not allowed in 
a constant expression}}
+}



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


[clang] 06d2176 - [clang][Interp][NFC] Move global variable init case to the top

2024-07-20 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-20T08:26:06+02:00
New Revision: 06d2176d81cab1d3ed8d0c17f78c1d3ef65cbab8

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

LOG: [clang][Interp][NFC] Move global variable init case to the top

of the respective functions. Previously, we did not properly mark
global zero sized arrays as initialized.

Added: 


Modified: 
clang/lib/AST/Interp/Pointer.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Pointer.cpp 
b/clang/lib/AST/Interp/Pointer.cpp
index ff4da0fa805dc..b22b4b1918ba5 100644
--- a/clang/lib/AST/Interp/Pointer.cpp
+++ b/clang/lib/AST/Interp/Pointer.cpp
@@ -227,6 +227,12 @@ bool Pointer::isInitialized() const {
   if (isIntegralPointer())
 return true;
 
+  if (isRoot() && PointeeStorage.BS.Base == sizeof(GlobalInlineDescriptor)) {
+const GlobalInlineDescriptor  =
+*reinterpret_cast(block()->rawData());
+return GD.InitState == GlobalInitState::Initialized;
+  }
+
   assert(PointeeStorage.BS.Pointee &&
  "Cannot check if null pointer was initialized");
   const Descriptor *Desc = getFieldDesc();
@@ -249,12 +255,6 @@ bool Pointer::isInitialized() const {
   if (asBlockPointer().Base == 0)
 return true;
 
-  if (isRoot() && PointeeStorage.BS.Base == sizeof(GlobalInlineDescriptor)) {
-const GlobalInlineDescriptor  =
-*reinterpret_cast(block()->rawData());
-return GD.InitState == GlobalInitState::Initialized;
-  }
-
   // Field has its bit in an inline descriptor.
   return getInlineDesc()->IsInitialized;
 }
@@ -266,6 +266,13 @@ void Pointer::initialize() const {
   assert(PointeeStorage.BS.Pointee && "Cannot initialize null pointer");
   const Descriptor *Desc = getFieldDesc();
 
+  if (isRoot() && PointeeStorage.BS.Base == sizeof(GlobalInlineDescriptor)) {
+GlobalInlineDescriptor  = *reinterpret_cast(
+asBlockPointer().Pointee->rawData());
+GD.InitState = GlobalInitState::Initialized;
+return;
+  }
+
   assert(Desc);
   if (Desc->isPrimitiveArray()) {
 // Primitive global arrays don't have an initmap.
@@ -294,13 +301,6 @@ void Pointer::initialize() const {
 return;
   }
 
-  if (isRoot() && PointeeStorage.BS.Base == sizeof(GlobalInlineDescriptor)) {
-GlobalInlineDescriptor  = *reinterpret_cast(
-asBlockPointer().Pointee->rawData());
-GD.InitState = GlobalInitState::Initialized;
-return;
-  }
-
   // Field has its bit in an inline descriptor.
   assert(PointeeStorage.BS.Base != 0 &&
  "Only composite fields can be initialised");



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


[clang] 9145ffa - [clang][Interp] Only diagnose out of bounds enum values in C++

2024-07-19 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-19T16:06:49+02:00
New Revision: 9145ffa134ed57c25ec62879c1aeff50595d08be

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

LOG: [clang][Interp] Only diagnose out of bounds enum values in C++

Added: 


Modified: 
clang/lib/AST/Interp/Compiler.cpp
clang/test/Sema/switch.c

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index 7da711ed485db..ef579bc5d8972 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -468,7 +468,7 @@ bool Compiler::VisitCastExpr(const CastExpr *CE) {
 
 // Possibly diagnose casts to enum types if the target type does not
 // have a fixed size.
-if (CE->getType()->isEnumeralType()) {
+if (Ctx.getLangOpts().CPlusPlus && CE->getType()->isEnumeralType()) {
   if (const auto *ET = CE->getType().getCanonicalType()->getAs();
   ET && !ET->getDecl()->isFixed()) {
 if (!this->emitCheckEnumValue(*FromT, ET->getDecl(), CE))

diff  --git a/clang/test/Sema/switch.c b/clang/test/Sema/switch.c
index 69b34f96820d3..6e912d02d6cc7 100644
--- a/clang/test/Sema/switch.c
+++ b/clang/test/Sema/switch.c
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -fsyntax-only -verify -Wswitch-enum 
-Wcovered-switch-default -triple x86_64-linux-gnu %s
+// RUN: %clang_cc1 -fsyntax-only -verify -Wswitch-enum 
-Wcovered-switch-default -triple x86_64-linux-gnu %s 
-fexperimental-new-constant-interpreter
 void f (int z) { 
   while (z) { 
 default: z--;// expected-error {{statement not in switch}}



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


[clang] d31603e - [clang][Interp] Control InitStack activity state in visitInitList

2024-07-19 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-19T15:00:35+02:00
New Revision: d31603eefc2d8becfd1f41327b6a8db3e0e91a27

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

LOG: [clang][Interp] Control InitStack activity state in visitInitList

This doesn't change anything about the current tests, but helps
once those tests change because of #97308

Added: 


Modified: 
clang/lib/AST/Interp/Compiler.cpp
clang/lib/AST/Interp/Compiler.h

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index 24140b23c1f0b..7da711ed485db 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -1334,6 +1334,7 @@ bool Compiler::visitInitList(ArrayRef Inits,
 
 auto initPrimitiveField = [=](const Record::Field *FieldToInit,
   const Expr *Init, PrimType T) -> bool {
+  InitStackScope ISS(this, isa(Init));
   if (!this->visit(Init))
 return false;
 
@@ -1344,6 +1345,7 @@ bool Compiler::visitInitList(ArrayRef Inits,
 
 auto initCompositeField = [=](const Record::Field *FieldToInit,
   const Expr *Init) -> bool {
+  InitStackScope ISS(this, isa(Init));
   InitLinkScope ILS(this, InitLink::Field(FieldToInit->Offset));
   // Non-primitive case. Get a pointer to the field-to-initialize
   // on the stack and recurse into visitInitializer().
@@ -4088,12 +4090,7 @@ template 
 bool Compiler::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E) {
   SourceLocScope SLS(this, E);
 
-  bool Old = InitStackActive;
-  InitStackActive =
-  !(E->getUsedContext()->getDeclKind() == Decl::CXXConstructor);
-  bool Result = this->delegate(E->getExpr());
-  InitStackActive = Old;
-  return Result;
+  return this->delegate(E->getExpr());
 }
 
 template 
@@ -4151,6 +4148,9 @@ bool Compiler::VisitCXXThisExpr(const 
CXXThisExpr *E) {
   // instance pointer of the current function frame, but e.g. to the 
declaration
   // currently being initialized. Here we emit the necessary instruction(s) for
   // this scenario.
+  if (!InitStackActive || !E->isImplicit())
+return this->emitThis(E);
+
   if (InitStackActive && !InitStack.empty()) {
 unsigned StartIndex = 0;
 for (StartIndex = InitStack.size() - 1; StartIndex > 0; --StartIndex) {

diff  --git a/clang/lib/AST/Interp/Compiler.h b/clang/lib/AST/Interp/Compiler.h
index 6df723df2b444..084f5aef25f8e 100644
--- a/clang/lib/AST/Interp/Compiler.h
+++ b/clang/lib/AST/Interp/Compiler.h
@@ -33,6 +33,7 @@ template  class DestructorScope;
 template  class VariableScope;
 template  class DeclScope;
 template  class InitLinkScope;
+template  class InitStackScope;
 template  class OptionScope;
 template  class ArrayIndexScope;
 template  class SourceLocScope;
@@ -298,6 +299,7 @@ class Compiler : public ConstStmtVisitor, 
bool>,
   friend class DestructorScope;
   friend class DeclScope;
   friend class InitLinkScope;
+  friend class InitStackScope;
   friend class OptionScope;
   friend class ArrayIndexScope;
   friend class SourceLocScope;
@@ -612,6 +614,20 @@ template  class InitLinkScope final {
   Compiler *Ctx;
 };
 
+template  class InitStackScope final {
+public:
+  InitStackScope(Compiler *Ctx, bool Active)
+  : Ctx(Ctx), OldValue(Ctx->InitStackActive) {
+Ctx->InitStackActive = Active;
+  }
+
+  ~InitStackScope() { this->Ctx->InitStackActive = OldValue; }
+
+private:
+  Compiler *Ctx;
+  bool OldValue;
+};
+
 } // namespace interp
 } // namespace clang
 



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


[clang] 8c8e0dd - [clang][Interp][test] Use fixed triple in cxx11 test

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

Author: Timm Bäder
Date: 2024-07-18T18:25:08+02:00
New Revision: 8c8e0ddae96882247717b8ae1739abcf09726eab

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

LOG: [clang][Interp][test] Use fixed triple in cxx11 test

This uses 'long', which has a different size on Windows. The test
I copied this from also uses x86_64-linux.

This should fix the bot:
https://lab.llvm.org/buildbot/#/builders/81/builds/853

Added: 


Modified: 
clang/test/AST/Interp/cxx11.cpp

Removed: 




diff  --git a/clang/test/AST/Interp/cxx11.cpp b/clang/test/AST/Interp/cxx11.cpp
index c0b88f0e567e0..92ab9b605f30d 100644
--- a/clang/test/AST/Interp/cxx11.cpp
+++ b/clang/test/AST/Interp/cxx11.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -fexperimental-new-constant-interpreter 
-verify=both,expected -std=c++11 %s
-// RUN: %clang_cc1 -verify=both,ref -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-linux 
-fexperimental-new-constant-interpreter -verify=both,expected -std=c++11 %s
+// RUN: %clang_cc1 -triple x86_64-linux -verify=both,ref -std=c++11 %s
 
 namespace IntOrEnum {
   const int k = 0;



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


[clang] 9fae0c6 - Reapply "[clang][Interp] Fix CheckCallable for undefined-and-not-constexpr fns"

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

Author: Timm Bäder
Date: 2024-07-18T16:15:59+02:00
New Revision: 9fae0c6f9c05915a5daac5b368258a40e1fab237

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

LOG: Reapply "[clang][Interp] Fix CheckCallable for undefined-and-not-constexpr 
fns"

This reverts commit ad7aeb0ff58ebd29f68adb85c64e8010639e2a76.

Added: 
clang/test/AST/Interp/cxx2a.cpp

Modified: 
clang/lib/AST/Interp/Interp.cpp
clang/lib/AST/Interp/Interp.h

Removed: 




diff  --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp
index 2be9b5360d055..e6e9298982887 100644
--- a/clang/lib/AST/Interp/Interp.cpp
+++ b/clang/lib/AST/Interp/Interp.cpp
@@ -579,57 +579,62 @@ bool CheckCallable(InterpState , CodePtr OpPC, const 
Function *F) {
 return false;
   }
 
-  if (!F->isConstexpr() || !F->hasBody()) {
-const SourceLocation  = S.Current->getLocation(OpPC);
-if (S.getLangOpts().CPlusPlus11) {
-  const FunctionDecl *DiagDecl = F->getDecl();
+  if (F->isConstexpr() && F->hasBody() &&
+  (F->getDecl()->isConstexpr() || 
F->getDecl()->hasAttr()))
+return true;
 
-  // Invalid decls have been diagnosed before.
-  if (DiagDecl->isInvalidDecl())
-return false;
+  // Implicitly constexpr.
+  if (F->isLambdaStaticInvoker())
+return true;
 
-  // If this function is not constexpr because it is an inherited
-  // non-constexpr constructor, diagnose that directly.
-  const auto *CD = dyn_cast(DiagDecl);
-  if (CD && CD->isInheritingConstructor()) {
-const auto *Inherited = CD->getInheritedConstructor().getConstructor();
-if (!Inherited->isConstexpr())
-  DiagDecl = CD = Inherited;
-  }
+  const SourceLocation  = S.Current->getLocation(OpPC);
+  if (S.getLangOpts().CPlusPlus11) {
+const FunctionDecl *DiagDecl = F->getDecl();
+
+// Invalid decls have been diagnosed before.
+if (DiagDecl->isInvalidDecl())
+  return false;
+
+// If this function is not constexpr because it is an inherited
+// non-constexpr constructor, diagnose that directly.
+const auto *CD = dyn_cast(DiagDecl);
+if (CD && CD->isInheritingConstructor()) {
+  const auto *Inherited = CD->getInheritedConstructor().getConstructor();
+  if (!Inherited->isConstexpr())
+DiagDecl = CD = Inherited;
+}
 
-  // FIXME: If DiagDecl is an implicitly-declared special member function
-  // or an inheriting constructor, we should be much more explicit about 
why
-  // it's not constexpr.
-  if (CD && CD->isInheritingConstructor()) {
-S.FFDiag(Loc, diag::note_constexpr_invalid_inhctor, 1)
+// FIXME: If DiagDecl is an implicitly-declared special member function
+// or an inheriting constructor, we should be much more explicit about why
+// it's not constexpr.
+if (CD && CD->isInheritingConstructor()) {
+  S.FFDiag(Loc, diag::note_constexpr_invalid_inhctor, 1)
   << CD->getInheritedConstructor().getConstructor()->getParent();
-S.Note(DiagDecl->getLocation(), diag::note_declared_at);
-  } else {
-// Don't emit anything if the function isn't defined and we're checking
-// for a constant expression. It might be defined at the point we're
-// actually calling it.
-bool IsExtern = DiagDecl->getStorageClass() == SC_Extern;
-if (!DiagDecl->isDefined() && !IsExtern &&
-S.checkingPotentialConstantExpression())
-  return false;
+  S.Note(DiagDecl->getLocation(), diag::note_declared_at);
+} else {
+  // Don't emit anything if the function isn't defined and we're checking
+  // for a constant expression. It might be defined at the point we're
+  // actually calling it.
+  bool IsExtern = DiagDecl->getStorageClass() == SC_Extern;
+  if (!DiagDecl->isDefined() && !IsExtern && DiagDecl->isConstexpr() &&
+  S.checkingPotentialConstantExpression())
+return false;
 
-// If the declaration is defined, declared 'constexpr' _and_ has a 
body,
-// the below diagnostic doesn't add anything useful.
-if (DiagDecl->isDefined() && DiagDecl->isConstexpr() &&
-DiagDecl->hasBody())
-  return false;
+  // If the declaration is defined, declared 'constexpr' _and_ has a body,
+  // the below diagnostic doesn't add anything useful.
+  if (DiagDecl->isDefined() && DiagDecl->isConstexpr() &&
+  DiagDecl->hasBody())
+return false;
 
-S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1)
+  S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1)
   << DiagDecl->isConstexpr() << (bool)CD << DiagDecl;
-S.Note(DiagDecl->getLocation(), diag::note_declared_at);
-  }
-} else {
-  S.FFDiag(Loc, 

[clang] d00b355 - [clang][Interp] Fix CheckCallable for undefined-and-not-constexpr fns

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

Author: Timm Bäder
Date: 2024-07-18T15:22:02+02:00
New Revision: d00b35534d068510025d22e5bd9c4fdac45757fb

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

LOG: [clang][Interp] Fix CheckCallable for undefined-and-not-constexpr fns

Added: 
clang/test/AST/Interp/cxx2a.cpp

Modified: 
clang/lib/AST/Interp/Interp.cpp
clang/lib/AST/Interp/Interp.h

Removed: 




diff  --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp
index 2be9b5360d055..be47f72e65a29 100644
--- a/clang/lib/AST/Interp/Interp.cpp
+++ b/clang/lib/AST/Interp/Interp.cpp
@@ -579,57 +579,61 @@ bool CheckCallable(InterpState , CodePtr OpPC, const 
Function *F) {
 return false;
   }
 
-  if (!F->isConstexpr() || !F->hasBody()) {
-const SourceLocation  = S.Current->getLocation(OpPC);
-if (S.getLangOpts().CPlusPlus11) {
-  const FunctionDecl *DiagDecl = F->getDecl();
+  if (F->isConstexpr() && F->hasBody() && F->getDecl()->isConstexpr())
+return true;
 
-  // Invalid decls have been diagnosed before.
-  if (DiagDecl->isInvalidDecl())
-return false;
+  // Implicitly constexpr.
+  if (F->isLambdaStaticInvoker())
+return true;
 
-  // If this function is not constexpr because it is an inherited
-  // non-constexpr constructor, diagnose that directly.
-  const auto *CD = dyn_cast(DiagDecl);
-  if (CD && CD->isInheritingConstructor()) {
-const auto *Inherited = CD->getInheritedConstructor().getConstructor();
-if (!Inherited->isConstexpr())
-  DiagDecl = CD = Inherited;
-  }
+  const SourceLocation  = S.Current->getLocation(OpPC);
+  if (S.getLangOpts().CPlusPlus11) {
+const FunctionDecl *DiagDecl = F->getDecl();
+
+// Invalid decls have been diagnosed before.
+if (DiagDecl->isInvalidDecl())
+  return false;
+
+// If this function is not constexpr because it is an inherited
+// non-constexpr constructor, diagnose that directly.
+const auto *CD = dyn_cast(DiagDecl);
+if (CD && CD->isInheritingConstructor()) {
+  const auto *Inherited = CD->getInheritedConstructor().getConstructor();
+  if (!Inherited->isConstexpr())
+DiagDecl = CD = Inherited;
+}
 
-  // FIXME: If DiagDecl is an implicitly-declared special member function
-  // or an inheriting constructor, we should be much more explicit about 
why
-  // it's not constexpr.
-  if (CD && CD->isInheritingConstructor()) {
-S.FFDiag(Loc, diag::note_constexpr_invalid_inhctor, 1)
+// FIXME: If DiagDecl is an implicitly-declared special member function
+// or an inheriting constructor, we should be much more explicit about why
+// it's not constexpr.
+if (CD && CD->isInheritingConstructor()) {
+  S.FFDiag(Loc, diag::note_constexpr_invalid_inhctor, 1)
   << CD->getInheritedConstructor().getConstructor()->getParent();
-S.Note(DiagDecl->getLocation(), diag::note_declared_at);
-  } else {
-// Don't emit anything if the function isn't defined and we're checking
-// for a constant expression. It might be defined at the point we're
-// actually calling it.
-bool IsExtern = DiagDecl->getStorageClass() == SC_Extern;
-if (!DiagDecl->isDefined() && !IsExtern &&
-S.checkingPotentialConstantExpression())
-  return false;
+  S.Note(DiagDecl->getLocation(), diag::note_declared_at);
+} else {
+  // Don't emit anything if the function isn't defined and we're checking
+  // for a constant expression. It might be defined at the point we're
+  // actually calling it.
+  bool IsExtern = DiagDecl->getStorageClass() == SC_Extern;
+  if (!DiagDecl->isDefined() && !IsExtern && DiagDecl->isConstexpr() &&
+  S.checkingPotentialConstantExpression())
+return false;
 
-// If the declaration is defined, declared 'constexpr' _and_ has a 
body,
-// the below diagnostic doesn't add anything useful.
-if (DiagDecl->isDefined() && DiagDecl->isConstexpr() &&
-DiagDecl->hasBody())
-  return false;
+  // If the declaration is defined, declared 'constexpr' _and_ has a body,
+  // the below diagnostic doesn't add anything useful.
+  if (DiagDecl->isDefined() && DiagDecl->isConstexpr() &&
+  DiagDecl->hasBody())
+return false;
 
-S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1)
+  S.FFDiag(Loc, diag::note_constexpr_invalid_function, 1)
   << DiagDecl->isConstexpr() << (bool)CD << DiagDecl;
-S.Note(DiagDecl->getLocation(), diag::note_declared_at);
-  }
-} else {
-  S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
+  S.Note(DiagDecl->getLocation(), diag::note_declared_at);

[clang] fc65a96 - [clang][Interp] Run record destructors when deallocating dynamic memory

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

Author: Timm Bäder
Date: 2024-07-18T15:07:29+02:00
New Revision: fc65a9603bf16ed1fe98fbee6933bca9e2083384

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

LOG: [clang][Interp] Run record destructors when deallocating dynamic memory

Added: 


Modified: 
clang/lib/AST/Interp/Interp.cpp
clang/lib/AST/Interp/Interp.h
clang/test/AST/Interp/new-delete.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp
index fb63228f8aea8..2be9b5360d055 100644
--- a/clang/lib/AST/Interp/Interp.cpp
+++ b/clang/lib/AST/Interp/Interp.cpp
@@ -819,6 +819,81 @@ bool CheckNonNullArgs(InterpState , CodePtr OpPC, const 
Function *F,
   return true;
 }
 
+// FIXME: This is similar to code we already have in Compiler.cpp.
+// I think it makes sense to instead add the field and base destruction stuff
+// to the destructor Function itself. Then destroying a record would really
+// _just_ be calling its destructor. That would also help with the diagnostic
+// 
diff erence when the destructor or a field/base fails.
+static bool runRecordDestructor(InterpState , CodePtr OpPC,
+const Pointer ,
+const Descriptor *Desc) {
+  assert(Desc->isRecord());
+  const Record *R = Desc->ElemRecord;
+  assert(R);
+
+  // Fields.
+  for (const Record::Field  : llvm::reverse(R->fields())) {
+const Descriptor *D = Field.Desc;
+if (D->isRecord()) {
+  if (!runRecordDestructor(S, OpPC, BasePtr.atField(Field.Offset), D))
+return false;
+} else if (D->isCompositeArray()) {
+  const Descriptor *ElemDesc = Desc->ElemDesc;
+  assert(ElemDesc->isRecord());
+  for (unsigned I = 0; I != Desc->getNumElems(); ++I) {
+if (!runRecordDestructor(S, OpPC, BasePtr.atIndex(I).narrow(),
+ ElemDesc))
+  return false;
+  }
+}
+  }
+
+  // Destructor of this record.
+  if (const CXXDestructorDecl *Dtor = R->getDestructor();
+  Dtor && !Dtor->isTrivial()) {
+const Function *DtorFunc = S.getContext().getOrCreateFunction(Dtor);
+if (!DtorFunc)
+  return false;
+
+S.Stk.push(BasePtr);
+if (!Call(S, OpPC, DtorFunc, 0))
+  return false;
+  }
+
+  // Bases.
+  for (const Record::Base  : llvm::reverse(R->bases())) {
+if (!runRecordDestructor(S, OpPC, BasePtr.atField(Base.Offset), Base.Desc))
+  return false;
+  }
+
+  return true;
+}
+
+bool RunDestructors(InterpState , CodePtr OpPC, const Block *B) {
+  assert(B);
+  const Descriptor *Desc = B->getDescriptor();
+
+  if (Desc->isPrimitive() || Desc->isPrimitiveArray())
+return true;
+
+  assert(Desc->isRecord() || Desc->isCompositeArray());
+
+  if (Desc->isCompositeArray()) {
+const Descriptor *ElemDesc = Desc->ElemDesc;
+assert(ElemDesc->isRecord());
+
+Pointer RP(const_cast(B));
+for (unsigned I = 0; I != Desc->getNumElems(); ++I) {
+  if (!runRecordDestructor(S, OpPC, RP.atIndex(I).narrow(), ElemDesc))
+return false;
+}
+return true;
+  }
+
+  assert(Desc->isRecord());
+  return runRecordDestructor(S, OpPC, Pointer(const_cast(B)), Desc);
+}
+
 bool Interpret(InterpState , APValue ) {
   // The current stack frame when we started Interpret().
   // This is being used by the ops to determine wheter

diff  --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index b4f8c03280c85..17b3157cb40a9 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -2872,8 +2872,8 @@ inline bool AllocCN(InterpState , CodePtr OpPC, const 
Descriptor *ElementDesc,
   return true;
 }
 
+bool RunDestructors(InterpState , CodePtr OpPC, const Block *B);
 static inline bool Free(InterpState , CodePtr OpPC, bool DeleteIsArrayForm) {
-
   if (!CheckDynamicMemoryAllocation(S, OpPC))
 return false;
 
@@ -2904,6 +2904,10 @@ static inline bool Free(InterpState , CodePtr OpPC, 
bool DeleteIsArrayForm) {
   assert(Source);
   assert(BlockToDelete);
 
+  // Invoke destructors before deallocating the memory.
+  if (!RunDestructors(S, OpPC, BlockToDelete))
+return false;
+
   DynamicAllocator  = S.getAllocator();
   bool WasArrayAlloc = Allocator.isArrayAllocation(Source);
   const Descriptor *BlockDesc = BlockToDelete->getDescriptor();

diff  --git a/clang/test/AST/Interp/new-delete.cpp 
b/clang/test/AST/Interp/new-delete.cpp
index 04ce3ae5f6637..cb46426c0e3be 100644
--- a/clang/test/AST/Interp/new-delete.cpp
+++ b/clang/test/AST/Interp/new-delete.cpp
@@ -476,7 +476,80 @@ constexpr Sp ss[] = {Sp{new int{154}}}; // both-error 
{{must be initialized by a
 // both-note {{pointer to 
heap-allocated object}} \
 // both-note {{allocation 

[clang] 7aabdb8 - [clang][Interp][NFC] Protect ByteCodeEmitter against unfinished fns

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

Author: Timm Bäder
Date: 2024-07-18T09:05:48+02:00
New Revision: 7aabdb8776eb11b90d43162254db47df46806ec9

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

LOG: [clang][Interp][NFC] Protect ByteCodeEmitter against unfinished fns

This is similar to a check in TextNodeDumper.cpp. Without this, we will
crash later when trying to iterate over FuncDecl->params().

Added: 


Modified: 
clang/lib/AST/Interp/ByteCodeEmitter.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/ByteCodeEmitter.cpp 
b/clang/lib/AST/Interp/ByteCodeEmitter.cpp
index 17da77bc63c9b..a3d4c7d7392da 100644
--- a/clang/lib/AST/Interp/ByteCodeEmitter.cpp
+++ b/clang/lib/AST/Interp/ByteCodeEmitter.cpp
@@ -31,6 +31,12 @@ static bool isUnevaluatedBuiltin(unsigned BuiltinID) {
 }
 
 Function *ByteCodeEmitter::compileFunc(const FunctionDecl *FuncDecl) {
+
+  // Manually created functions that haven't been assigned proper
+  // parameters yet.
+  if (!FuncDecl->param_empty() && !FuncDecl->param_begin())
+return nullptr;
+
   bool IsLambdaStaticInvoker = false;
   if (const auto *MD = dyn_cast(FuncDecl);
   MD && MD->isLambdaStaticInvoker()) {



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


[clang] fbf8b82 - [clang][Interp][NFC] Be more cautious about Block initialization state

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

Author: Timm Bäder
Date: 2024-07-18T08:01:24+02:00
New Revision: fbf8b82cd02818c005bb39abbf550333bea6

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

LOG: [clang][Interp][NFC] Be more cautious about Block initialization state

... when moving a Block to a DeadBlock. Only invoke the MoveFn if the
old block was initialized at all.

Added: 


Modified: 
clang/lib/AST/Interp/InterpBlock.cpp
clang/lib/AST/Interp/InterpState.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/InterpBlock.cpp 
b/clang/lib/AST/Interp/InterpBlock.cpp
index 7bef5e678c074..5ac778aeb6075 100644
--- a/clang/lib/AST/Interp/InterpBlock.cpp
+++ b/clang/lib/AST/Interp/InterpBlock.cpp
@@ -110,6 +110,9 @@ DeadBlock::DeadBlock(DeadBlock *, Block *Blk)
 }
 
 void DeadBlock::free() {
+  if (B.IsInitialized)
+B.invokeDtor();
+
   if (Prev)
 Prev->Next = Next;
   if (Next)

diff  --git a/clang/lib/AST/Interp/InterpState.cpp 
b/clang/lib/AST/Interp/InterpState.cpp
index 332f551838b72..4ea05305540ee 100644
--- a/clang/lib/AST/Interp/InterpState.cpp
+++ b/clang/lib/AST/Interp/InterpState.cpp
@@ -69,13 +69,15 @@ void InterpState::deallocate(Block *B) {
 char *Memory =
 reinterpret_cast(std::malloc(sizeof(DeadBlock) + Size));
 auto *D = new (Memory) DeadBlock(DeadBlocks, B);
+std::memset(D->B.rawData(), 0, D->B.getSize());
 
 // Move data and metadata from the old block to the new (dead)block.
-if (Desc->MoveFn) {
+if (B->IsInitialized && Desc->MoveFn) {
   Desc->MoveFn(B, B->data(), D->data(), Desc);
   if (Desc->getMetadataSize() > 0)
 std::memcpy(D->rawData(), B->rawData(), Desc->getMetadataSize());
 }
+D->B.IsInitialized = B->IsInitialized;
 
 // We moved the contents over to the DeadBlock.
 B->IsInitialized = false;



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


[clang] 39d751a - [clang][Interp] Use an array root's field decl in the LValuePath

2024-07-17 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-17T11:26:50+02:00
New Revision: 39d751ad976ba9f5e8a1ad3880559faba38c3c3f

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

LOG: [clang][Interp] Use an array root's field decl in the LValuePath

Instead of pushing the index 0.

Added: 


Modified: 
clang/lib/AST/Interp/Pointer.cpp
clang/test/AST/Interp/functions.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Pointer.cpp 
b/clang/lib/AST/Interp/Pointer.cpp
index b2e3a7ff70881..ff4da0fa805dc 100644
--- a/clang/lib/AST/Interp/Pointer.cpp
+++ b/clang/lib/AST/Interp/Pointer.cpp
@@ -152,8 +152,9 @@ APValue Pointer::toAPValue() const {
   Pointer Ptr = *this;
   while (Ptr.isField() || Ptr.isArrayElement()) {
 if (Ptr.isArrayRoot()) {
-Path.push_back(APValue::LValuePathEntry::ArrayIndex(0));
-Ptr = Ptr.getBase();
+  Path.push_back(APValue::LValuePathEntry(
+  {Ptr.getFieldDesc()->asDecl(), /*IsVirtual=*/false}));
+  Ptr = Ptr.getBase();
 } else if (Ptr.isArrayElement()) {
   if (Ptr.isOnePastEnd())
 
Path.push_back(APValue::LValuePathEntry::ArrayIndex(Ptr.getArray().getNumElems()));

diff  --git a/clang/test/AST/Interp/functions.cpp 
b/clang/test/AST/Interp/functions.cpp
index fa29e08a30175..f190262ad3ebe 100644
--- a/clang/test/AST/Interp/functions.cpp
+++ b/clang/test/AST/Interp/functions.cpp
@@ -644,3 +644,21 @@ namespace FunctionCast {
  // both-warning {{are a Clang extension}}
   int b[(int)IntFn(f)()];// ok
 }
+
+#if __cplusplus >= 202002L
+namespace StableAddress {
+  template struct str {
+char arr[N];
+  };
+  // FIXME: Deduction guide not needed with P1816R0.
+  template str(const char (&)[N]) -> str;
+
+  template constexpr int sum() {
+int n = 0;
+for (char c : s.arr)
+  n += c;
+return n;
+  }
+  static_assert(sum() == 1234, "");
+}
+#endif



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


[clang] 72b3d7b - [clang][Interp] Makre sure we don't overflow Descriptor::AllocSize

2024-07-17 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-17T10:56:14+02:00
New Revision: 72b3d7bc87019ba7ef268ce322f90382f01b11af

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

LOG: [clang][Interp] Makre sure we don't overflow Descriptor::AllocSize

We allocate the metadata and the array elements in one allocation,
and we save its size in a field of type 'unsigned'. Makre sure the
full size of the allocation doesn't overflow the field.

Added: 


Modified: 
clang/lib/AST/Interp/Descriptor.cpp
clang/lib/AST/Interp/Descriptor.h

Removed: 




diff  --git a/clang/lib/AST/Interp/Descriptor.cpp 
b/clang/lib/AST/Interp/Descriptor.cpp
index a3801a01688c8..f7d1201f625bb 100644
--- a/clang/lib/AST/Interp/Descriptor.cpp
+++ b/clang/lib/AST/Interp/Descriptor.cpp
@@ -303,6 +303,7 @@ Descriptor::Descriptor(const DeclTy , PrimType Type, 
MetadataSize MD,
   IsArray(true), CtorFn(getCtorArrayPrim(Type)),
   DtorFn(getDtorArrayPrim(Type)), MoveFn(getMoveArrayPrim(Type)) {
   assert(Source && "Missing source");
+  assert(NumElems <= (MaxArrayElemBytes / ElemSize));
 }
 
 /// Primitive unknown-size arrays.

diff  --git a/clang/lib/AST/Interp/Descriptor.h 
b/clang/lib/AST/Interp/Descriptor.h
index f444b8a78e802..0dd97812e5a5c 100644
--- a/clang/lib/AST/Interp/Descriptor.h
+++ b/clang/lib/AST/Interp/Descriptor.h
@@ -13,6 +13,7 @@
 #ifndef LLVM_CLANG_AST_INTERP_DESCRIPTOR_H
 #define LLVM_CLANG_AST_INTERP_DESCRIPTOR_H
 
+#include "PrimType.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/Expr.h"
 
@@ -125,6 +126,11 @@ struct Descriptor final {
   static constexpr MetadataSize InlineDescMD = sizeof(InlineDescriptor);
   static constexpr MetadataSize GlobalMD = sizeof(GlobalInlineDescriptor);
 
+  /// Maximum number of bytes to be used for array elements.
+  static constexpr unsigned MaxArrayElemBytes =
+  std::numeric_limits::max() - sizeof(InitMapPtr) -
+  align(std::max(*InlineDescMD, *GlobalMD));
+
   /// Pointer to the record, if block contains records.
   const Record *const ElemRecord = nullptr;
   /// Descriptor of the array element.



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


[clang] 85cedd8 - [clang][Interp] Ignore incomplete records when visiting lambdas

2024-07-16 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-16T15:04:32+02:00
New Revision: 85cedd8e59be5eebad6292aee3b053f31afc8977

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

LOG: [clang][Interp] Ignore incomplete records when visiting lambdas

We need them to be complete so we have knowledge about all the
lambda captures.

Added: 


Modified: 
clang/lib/AST/Interp/ByteCodeEmitter.cpp
clang/lib/AST/Interp/Context.cpp
clang/test/AST/Interp/lambda.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/ByteCodeEmitter.cpp 
b/clang/lib/AST/Interp/ByteCodeEmitter.cpp
index ae777d555e916..17da77bc63c9b 100644
--- a/clang/lib/AST/Interp/ByteCodeEmitter.cpp
+++ b/clang/lib/AST/Interp/ByteCodeEmitter.cpp
@@ -93,6 +93,11 @@ Function *ByteCodeEmitter::compileFunc(const FunctionDecl 
*FuncDecl) {
 
 // Set up lambda capture to closure record field mapping.
 if (isLambdaCallOperator(MD)) {
+  // The parent record needs to be complete, we need to know about all
+  // the lambda captures.
+  if (!MD->getParent()->isCompleteDefinition())
+return nullptr;
+
   const Record *R = P.getOrCreateRecord(MD->getParent());
   llvm::DenseMap LC;
   FieldDecl *LTC;

diff  --git a/clang/lib/AST/Interp/Context.cpp 
b/clang/lib/AST/Interp/Context.cpp
index 913e8d514282a..b5e992c5a9ac1 100644
--- a/clang/lib/AST/Interp/Context.cpp
+++ b/clang/lib/AST/Interp/Context.cpp
@@ -31,6 +31,9 @@ bool Context::isPotentialConstantExpr(State , const 
FunctionDecl *FD) {
   if (!Func || !Func->hasBody())
 Func = Compiler(*this, *P).compileFunc(FD);
 
+  if (!Func)
+return false;
+
   APValue DummyResult;
   if (!Run(Parent, Func, DummyResult))
 return false;

diff  --git a/clang/test/AST/Interp/lambda.cpp 
b/clang/test/AST/Interp/lambda.cpp
index 0eb12643b1b7f..d68fe995e8fa1 100644
--- a/clang/test/AST/Interp/lambda.cpp
+++ b/clang/test/AST/Interp/lambda.cpp
@@ -280,3 +280,9 @@ namespace InvalidCapture {
 } ();
   }
 }
+
+constexpr int fn() {
+  int Capture = 42;
+  return [=]() constexpr { return Capture; }();
+}
+static_assert(fn() == 42, "");



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


[clang] 5b310a1 - [clang][Interp] Ignore lambda static invoker frames in backtraces

2024-07-16 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-16T13:57:41+02:00
New Revision: 5b310a1c3c5aabae325934a6475e93ea8b71cdc2

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

LOG: [clang][Interp] Ignore lambda static invoker frames in backtraces

See comment. No test but this is neccessary for a later commit.

Added: 


Modified: 
clang/lib/AST/Interp/InterpFrame.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/InterpFrame.cpp 
b/clang/lib/AST/Interp/InterpFrame.cpp
index 383380f485e03..d3f3e216b7eb2 100644
--- a/clang/lib/AST/Interp/InterpFrame.cpp
+++ b/clang/lib/AST/Interp/InterpFrame.cpp
@@ -158,7 +158,9 @@ void InterpFrame::describe(llvm::raw_ostream ) const {
   // diagnose them. The 'in call to' diagnostics for them add no value to the
   // user _and_ it doesn't generally work since the argument types don't always
   // match the function prototype. Just ignore them.
-  if (const auto *F = getFunction(); F && F->isBuiltin())
+  // Similarly, for lambda static invokers, we would just print __invoke().
+  if (const auto *F = getFunction();
+  F && (F->isBuiltin() || F->isLambdaStaticInvoker()))
 return;
 
   const FunctionDecl *F = getCallee();



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


[clang] d8f0611 - [clang][Interp] Allow ltor casts for null pointers

2024-07-16 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-16T08:28:51+02:00
New Revision: d8f0611acc2658ccc54d985044aa115716c6ad34

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

LOG: [clang][Interp] Allow ltor casts for null pointers

We can't read from them but we special-case them later.

Added: 


Modified: 
clang/lib/AST/Interp/EvalEmitter.cpp
clang/test/CodeGenCXX/nullptr.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/EvalEmitter.cpp 
b/clang/lib/AST/Interp/EvalEmitter.cpp
index 1a9444d38fdd5..74413baf6fc0c 100644
--- a/clang/lib/AST/Interp/EvalEmitter.cpp
+++ b/clang/lib/AST/Interp/EvalEmitter.cpp
@@ -152,7 +152,7 @@ template <> bool EvalEmitter::emitRet(const 
SourceInfo ) {
 
   // Implicitly convert lvalue to rvalue, if requested.
   if (ConvertResultToRValue) {
-if (!Ptr.isDereferencable())
+if (!Ptr.isZero() && !Ptr.isDereferencable())
   return false;
 // Never allow reading from a non-const pointer, unless the memory
 // has been created in this evaluation.

diff  --git a/clang/test/CodeGenCXX/nullptr.cpp 
b/clang/test/CodeGenCXX/nullptr.cpp
index ca76c55e2122d..0d8837b216bec 100644
--- a/clang/test/CodeGenCXX/nullptr.cpp
+++ b/clang/test/CodeGenCXX/nullptr.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -I%S -emit-llvm -o 
- %s | FileCheck %s
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -I%S -emit-llvm -o 
- %s -fexperimental-new-constant-interpreter | FileCheck %s
 
 #include 
 



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


[clang] ff96ad8 - [clang][Interp][NFC] Add Pointer::isDereferencable()

2024-07-15 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-16T07:24:08+02:00
New Revision: ff96ad84f52022af295d11749f106480e7292a89

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

LOG: [clang][Interp][NFC] Add Pointer::isDereferencable()

We currently have a few places where we check whether a pointer can
be read from at all. Add a function to do that.

Added: 


Modified: 
clang/lib/AST/Interp/Pointer.h

Removed: 




diff  --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/Interp/Pointer.h
index 6e9e8675306ef..28bc42985adb2 100644
--- a/clang/lib/AST/Interp/Pointer.h
+++ b/clang/lib/AST/Interp/Pointer.h
@@ -584,6 +584,7 @@ class Pointer {
 assert(isLive() && "Invalid pointer");
 assert(isBlockPointer());
 assert(asBlockPointer().Pointee);
+assert(isDereferencable());
 assert(Offset + sizeof(T) <=
asBlockPointer().Pointee->getDescriptor()->getAllocSize());
 
@@ -603,6 +604,17 @@ class Pointer {
  sizeof(InitMapPtr))[I];
   }
 
+  /// Whether this block can be read from at all. This is only true for
+  /// block pointers that point to a valid location inside that block.
+  bool isDereferencable() const {
+if (!isBlockPointer())
+  return false;
+if (isPastEnd())
+  return false;
+
+return true;
+  }
+
   /// Initializes a field.
   void initialize() const;
   /// Activats a field.



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


[clang] f30c09e - [clang][Interp][NFC] Use a templated conversion operator

2024-07-15 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-16T04:49:05+02:00
New Revision: f30c09e2d3107e117faf8311c6d8642fa95680af

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

LOG: [clang][Interp][NFC] Use a templated conversion operator

Added: 


Modified: 
clang/lib/AST/Interp/Boolean.h
clang/lib/AST/Interp/Integral.h

Removed: 




diff  --git a/clang/lib/AST/Interp/Boolean.h b/clang/lib/AST/Interp/Boolean.h
index 336f7941dfc47..1bfb26b1b669f 100644
--- a/clang/lib/AST/Interp/Boolean.h
+++ b/clang/lib/AST/Interp/Boolean.h
@@ -45,15 +45,10 @@ class Boolean final {
   Boolean operator-(const Boolean ) const { return Boolean(V - Other.V); 
}
   Boolean operator~() const { return Boolean(true); }
 
-  explicit operator int8_t() const { return V; }
-  explicit operator uint8_t() const { return V; }
-  explicit operator int16_t() const { return V; }
-  explicit operator uint16_t() const { return V; }
-  explicit operator int32_t() const { return V; }
-  explicit operator uint32_t() const { return V; }
-  explicit operator int64_t() const { return V; }
-  explicit operator uint64_t() const { return V; }
-  explicit operator bool() const { return V; }
+  template >>
+  explicit operator Ty() const {
+return V;
+  }
 
   APSInt toAPSInt() const {
 return APSInt(APInt(1, static_cast(V), false), true);

diff  --git a/clang/lib/AST/Interp/Integral.h b/clang/lib/AST/Interp/Integral.h
index cc1cab8f39fb1..db4cc9ae45b49 100644
--- a/clang/lib/AST/Interp/Integral.h
+++ b/clang/lib/AST/Interp/Integral.h
@@ -98,10 +98,10 @@ template  class Integral final {
 return Integral(V);
   }
 
-  explicit operator unsigned() const { return V; }
-  explicit operator int64_t() const { return V; }
-  explicit operator uint64_t() const { return V; }
-  explicit operator int32_t() const { return V; }
+  template >>
+  explicit operator Ty() const {
+return V;
+  }
 
   APSInt toAPSInt() const {
 return APSInt(APInt(Bits, static_cast(V), Signed), !Signed);



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


[clang] 6484655 - [clang][Interp] Allow initialization of extern variables via ctors

2024-07-15 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-15T13:12:52+02:00
New Revision: 6484655f9dd07c6d5669dd540feef3c80af84827

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

LOG: [clang][Interp] Allow initialization of extern variables via ctors

Added: 


Modified: 
clang/lib/AST/Interp/Interp.cpp
clang/test/AST/Interp/literals.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp
index 7b2c0480f80ae..b673cc27aee21 100644
--- a/clang/lib/AST/Interp/Interp.cpp
+++ b/clang/lib/AST/Interp/Interp.cpp
@@ -248,7 +248,8 @@ bool CheckExtern(InterpState , CodePtr OpPC, const 
Pointer ) {
   if (!Ptr.isExtern())
 return true;
 
-  if (Ptr.isInitialized())
+  if (Ptr.isInitialized() ||
+  (Ptr.getDeclDesc()->asVarDecl() == S.EvaluatingDecl))
 return true;
 
   if (!S.checkingPotentialConstantExpression() && S.getLangOpts().CPlusPlus) {

diff  --git a/clang/test/AST/Interp/literals.cpp 
b/clang/test/AST/Interp/literals.cpp
index 6c214f5a6efa7..9cd65462a0af3 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -1232,6 +1232,13 @@ namespace Extern {
   }
   static_assert(() == , "");
 #endif
+
+  struct A {
+int b;
+  };
+
+  extern constexpr A a{12};
+  static_assert(a.b == 12, "");
 }
 
 #if __cplusplus >= 201402L



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


[clang] 9ac2b89 - [clang][Interp] Diagnose volatile reads

2024-07-15 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-15T09:37:45+02:00
New Revision: 9ac2b8965264a7f20a3e07c913b25c375a080c0f

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

LOG: [clang][Interp] Diagnose volatile reads

Added: 


Modified: 
clang/lib/AST/Interp/Interp.cpp
clang/test/AST/Interp/literals.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp
index 70a470021e7f2..7b2c0480f80ae 100644
--- a/clang/lib/AST/Interp/Interp.cpp
+++ b/clang/lib/AST/Interp/Interp.cpp
@@ -444,6 +444,27 @@ bool CheckMutable(InterpState , CodePtr OpPC, const 
Pointer ) {
   return false;
 }
 
+bool CheckVolatile(InterpState , CodePtr OpPC, const Pointer ,
+   AccessKinds AK) {
+  assert(Ptr.isLive());
+
+  // FIXME: This check here might be kinda expensive. Maybe it would be better
+  // to have another field in InlineDescriptor for this?
+  if (!Ptr.isBlockPointer())
+return true;
+
+  QualType PtrType = Ptr.getType();
+  if (!PtrType.isVolatileQualified())
+return true;
+
+  const SourceInfo  = S.Current->getSource(OpPC);
+  if (S.getLangOpts().CPlusPlus)
+S.FFDiag(Loc, diag::note_constexpr_access_volatile_type) << AK << PtrType;
+  else
+S.FFDiag(Loc);
+  return false;
+}
+
 bool CheckInitialized(InterpState , CodePtr OpPC, const Pointer ,
   AccessKinds AK) {
   assert(Ptr.isLive());
@@ -508,6 +529,8 @@ bool CheckLoad(InterpState , CodePtr OpPC, const Pointer 
,
 return false;
   if (!CheckMutable(S, OpPC, Ptr))
 return false;
+  if (!CheckVolatile(S, OpPC, Ptr, AK))
+return false;
   return true;
 }
 

diff  --git a/clang/test/AST/Interp/literals.cpp 
b/clang/test/AST/Interp/literals.cpp
index af5bcb6d48ae7..6c214f5a6efa7 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -1290,3 +1290,9 @@ namespace UnaryOpError {
   }
 }
 #endif
+
+namespace VolatileReads {
+  const volatile int b = 1;
+  static_assert(b, ""); // both-error {{not an integral constant expression}} \
+// both-note {{read of volatile-qualified type 'const 
volatile int' is not allowed in a constant expression}}
+}



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


[clang] 48d703e - Revert "[clang][Interp] Implement dynamic memory allocation handling (#70306)"

2024-07-14 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-14T21:17:47+02:00
New Revision: 48d703e7f56282ce5d690e45a129a4a7fd040ee6

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

LOG: Revert "[clang][Interp] Implement dynamic memory allocation handling 
(#70306)"

This reverts commit fa133d3151b5e428b1c5819d29b0ad28a90882a2.

It looks like this has some more serious problems:
https://lab.llvm.org/buildbot/#/builders/39/builds/528

As well as build failures on MacOS.

Added: 


Modified: 
clang/lib/AST/CMakeLists.txt
clang/lib/AST/Interp/Compiler.cpp
clang/lib/AST/Interp/Compiler.h
clang/lib/AST/Interp/EvalEmitter.cpp
clang/lib/AST/Interp/EvaluationResult.cpp
clang/lib/AST/Interp/EvaluationResult.h
clang/lib/AST/Interp/Interp.cpp
clang/lib/AST/Interp/Interp.h
clang/lib/AST/Interp/InterpBlock.h
clang/lib/AST/Interp/InterpState.cpp
clang/lib/AST/Interp/InterpState.h
clang/lib/AST/Interp/Opcodes.td
clang/lib/AST/Interp/Pointer.h
clang/test/Rewriter/rewrite-modern-catch.m
clang/test/SemaCXX/delete.cpp
clang/test/SemaCXX/new-delete.cpp

Removed: 
clang/lib/AST/Interp/DynamicAllocator.cpp
clang/lib/AST/Interp/DynamicAllocator.h
clang/test/AST/Interp/new-delete.cpp



diff  --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt
index 70aecb781c2ff..ceaad8d3c5a86 100644
--- a/clang/lib/AST/CMakeLists.txt
+++ b/clang/lib/AST/CMakeLists.txt
@@ -75,7 +75,6 @@ add_clang_library(clangAST
   Interp/InterpBuiltin.cpp
   Interp/Floating.cpp
   Interp/EvaluationResult.cpp
-  Interp/DynamicAllocator.cpp
   Interp/Interp.cpp
   Interp/InterpBlock.cpp
   Interp/InterpFrame.cpp

diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index 1f43f46c399f1..30dc7f5e4840b 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -2771,109 +2771,6 @@ bool Compiler::VisitCXXInheritedCtorInitExpr(
   return this->emitCall(F, 0, E);
 }
 
-template 
-bool Compiler::VisitCXXNewExpr(const CXXNewExpr *E) {
-  assert(classifyPrim(E->getType()) == PT_Ptr);
-  const Expr *Init = E->getInitializer();
-  QualType ElementType = E->getAllocatedType();
-  std::optional ElemT = classify(ElementType);
-  unsigned PlacementArgs = E->getNumPlacementArgs();
-  bool IsNoThrow = false;
-
-  // FIXME: Better diagnostic. diag::note_constexpr_new_placement
-  if (PlacementArgs != 0) {
-// The only new-placement list we support is of the form (std::nothrow).
-//
-// FIXME: There is no restriction on this, but it's not clear that any
-// other form makes any sense. We get here for cases such as:
-//
-//   new (std::align_val_t{N}) X(int)
-//
-// (which should presumably be valid only if N is a multiple of
-// alignof(int), and in any case can't be deallocated unless N is
-// alignof(X) and X has new-extended alignment).
-if (PlacementArgs != 1 || !E->getPlacementArg(0)->getType()->isNothrowT())
-  return this->emitInvalid(E);
-
-if (!this->discard(E->getPlacementArg(0)))
-  return false;
-IsNoThrow = true;
-  }
-
-  const Descriptor *Desc;
-  if (ElemT) {
-if (E->isArray())
-  Desc = nullptr; // We're not going to use it in this case.
-else
-  Desc = P.createDescriptor(E, *ElemT, Descriptor::InlineDescMD,
-/*IsConst=*/false, /*IsTemporary=*/false,
-/*IsMutable=*/false);
-  } else {
-Desc = P.createDescriptor(
-E, ElementType.getTypePtr(),
-E->isArray() ? std::nullopt : Descriptor::InlineDescMD,
-/*IsConst=*/false, /*IsTemporary=*/false, /*IsMutable=*/false, Init);
-  }
-
-  if (E->isArray()) {
-std::optional ArraySizeExpr = E->getArraySize();
-if (!ArraySizeExpr)
-  return false;
-PrimType SizeT = classifyPrim((*ArraySizeExpr)->getType());
-
-if (!this->visit(*ArraySizeExpr))
-  return false;
-
-if (ElemT) {
-  // N primitive elements.
-  if (!this->emitAllocN(SizeT, *ElemT, E, IsNoThrow, E))
-return false;
-} else {
-  // N Composite elements.
-  if (!this->emitAllocCN(SizeT, Desc, IsNoThrow, E))
-return false;
-}
-
-if (Init && !this->visitInitializer(Init))
-  return false;
-
-  } else {
-// Allocate just one element.
-if (!this->emitAlloc(Desc, E))
-  return false;
-
-if (Init) {
-  if (ElemT) {
-if (!this->visit(Init))
-  return false;
-
-if (!this->emitInit(*ElemT, E))
-  return false;
-  } else {
-// Composite.
-if (!this->visitInitializer(Init))
-  return false;
-  }
-}
-  }
-
-  if (DiscardResult)
-return this->emitPopPtr(E);
-
-  return true;
-}
-
-template 
-bool 

[clang] ba3dcec - Revert "[clang][Interp] Fix a build failure on Windows"

2024-07-14 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-14T21:17:39+02:00
New Revision: ba3dcec16b6bb955f2c65a3df157744069441d7f

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

LOG: Revert "[clang][Interp] Fix a build failure on Windows"

This reverts commit 27f5c00c607e08b3cdf37f3bf9f4ccf156de2ab4.

Added: 


Modified: 
clang/lib/AST/Interp/Interp.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp
index 0ec77200c3a79..cafe2175f5cc4 100644
--- a/clang/lib/AST/Interp/Interp.cpp
+++ b/clang/lib/AST/Interp/Interp.cpp
@@ -715,8 +715,8 @@ bool CheckNewDeleteForms(InterpState , CodePtr OpPC, bool 
NewWasArray,
   if (D->isArray()) {
 QualType ElemQT = D->getType()->getPointeeType();
 TypeToDiagnose = S.getCtx().getConstantArrayType(
-ElemQT, APInt(64, static_cast(D->getNumElems()), false),
-nullptr, ArraySizeModifier::Normal, 0);
+ElemQT, APInt(64, D->getNumElems(), false), nullptr,
+ArraySizeModifier::Normal, 0);
   } else
 TypeToDiagnose = D->getType()->getPointeeType();
 



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


[clang] 27f5c00 - [clang][Interp] Fix a build failure on Windows

2024-07-14 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-14T20:15:20+02:00
New Revision: 27f5c00c607e08b3cdf37f3bf9f4ccf156de2ab4

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

LOG: [clang][Interp] Fix a build failure on Windows

The usual ambiguous APInt constructor:

https://lab.llvm.org/buildbot/#/builders/141/builds/764

Added: 


Modified: 
clang/lib/AST/Interp/Interp.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp
index cafe2175f5cc4..0ec77200c3a79 100644
--- a/clang/lib/AST/Interp/Interp.cpp
+++ b/clang/lib/AST/Interp/Interp.cpp
@@ -715,8 +715,8 @@ bool CheckNewDeleteForms(InterpState , CodePtr OpPC, bool 
NewWasArray,
   if (D->isArray()) {
 QualType ElemQT = D->getType()->getPointeeType();
 TypeToDiagnose = S.getCtx().getConstantArrayType(
-ElemQT, APInt(64, D->getNumElems(), false), nullptr,
-ArraySizeModifier::Normal, 0);
+ElemQT, APInt(64, static_cast(D->getNumElems()), false),
+nullptr, ArraySizeModifier::Normal, 0);
   } else
 TypeToDiagnose = D->getType()->getPointeeType();
 



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


[clang] 3aae4ca - [clang][Interp] Improve InterpFrame::describe()

2024-07-14 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-14T18:20:51+02:00
New Revision: 3aae4caffa3134d4edd1811fd2c35cbc95eb7441

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

LOG: [clang][Interp] Improve InterpFrame::describe()

Use getNameForDiagnostic(), like the CallStackFrame of the current
interpreter.

Added: 


Modified: 
clang/lib/AST/Interp/InterpFrame.cpp
clang/test/AST/Interp/literals.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/InterpFrame.cpp 
b/clang/lib/AST/Interp/InterpFrame.cpp
index b33f74dfe99f..383380f485e0 100644
--- a/clang/lib/AST/Interp/InterpFrame.cpp
+++ b/clang/lib/AST/Interp/InterpFrame.cpp
@@ -167,7 +167,10 @@ void InterpFrame::describe(llvm::raw_ostream ) const {
 print(OS, This, S.getCtx(), S.getCtx().getRecordType(M->getParent()));
 OS << "->";
   }
-  OS << *F << "(";
+
+  F->getNameForDiagnostic(OS, S.getCtx().getPrintingPolicy(),
+  /*Qualified=*/false);
+  OS << '(';
   unsigned Off = 0;
 
   Off += Func->hasRVO() ? primSize(PT_Ptr) : 0;

diff  --git a/clang/test/AST/Interp/literals.cpp 
b/clang/test/AST/Interp/literals.cpp
index 93e7e8b52a45..af5bcb6d48ae 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -568,37 +568,27 @@ namespace IncDec {
 return 1;
   }
   static_assert(uninit(), ""); // both-error {{not an 
integral constant expression}} \
-// ref-note {{in call to 
'uninit()'}} \
-// expected-note {{in call to 
'uninit()'}}
+// both-note {{in call to 
'uninit()'}}
   static_assert(uninit(), ""); // both-error {{not an 
integral constant expression}} \
- // ref-note {{in call to 
'uninit()'}} \
- // expected-note {{in call to 
'uninit()'}}
+ // both-note {{in call to 
'uninit()'}}
 
   static_assert(uninit(), ""); // both-error {{not an 
integral constant expression}} \
-  // ref-note {{in call to 
'uninit()'}} \
-  // expected-note {{in call 
to 'uninit()'}}
+  // both-note {{in call to 
'uninit()'}}
   static_assert(uninit(), ""); // both-error {{not an 
integral constant expression}} \
-   // ref-note {{in call to 
'uninit()'}} \
-   // expected-note {{in call 
to 'uninit()'}}
+   // both-note {{in call to 
'uninit()'}}
   static_assert(uninit(), ""); // both-error {{not an 
integral constant expression}} \
-   // ref-note {{in call to 
'uninit()'}} \
-   // expected-note {{in call 
to 'uninit()'}}
+   // both-note {{in call to 
'uninit()'}}
   static_assert(uninit(), ""); // both-error {{not an 
integral constant expression}} \
-// ref-note {{in call to 
'uninit()'}} \
-// expected-note {{in call 
to 'uninit()'}}
+// both-note {{in call to 
'uninit()'}}
 
   static_assert(uninit(), ""); // both-error {{not an 
integral constant expression}} \
- // ref-note {{in call to 
'uninit()'}} \
- // expected-note {{in call to 
'uninit()'}}
+ // both-note {{in call to 
'uninit()'}}
   static_assert(uninit(), ""); // both-error {{not an 
integral constant expression}} \
-  // ref-note {{in call to 
'uninit()'}} \
-  // expected-note {{in call 
to 'uninit()'}}
+  // both-note {{in call to 
'uninit()'}}
   static_assert(uninit(), ""); // both-error {{not an 
integral constant expression}} \
-  // ref-note {{in call to 
'uninit()'}} \
-  // expected-note {{in call 
to 'uninit()'}}
+  // both-note {{in call to 
'uninit()'}}
   static_assert(uninit(), ""); // both-error {{not an 
integral constant expression}} \
-   // ref-note {{in call to 

[clang] 33af112 - [clang][Interp] Fix modifying const objects in functions calls in ctors

2024-07-14 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-14T17:47:11+02:00
New Revision: 33af112f99fe956fb93fb2b797a141ee93956283

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

LOG: [clang][Interp] Fix modifying const objects in functions calls in ctors

The current frame might not be a constructor for the object we're
initializing, but a parent frame might.

Added: 


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

Removed: 




diff  --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp
index 0411fcad88ad0..70a470021e7f2 100644
--- a/clang/lib/AST/Interp/Interp.cpp
+++ b/clang/lib/AST/Interp/Interp.cpp
@@ -405,10 +405,16 @@ bool CheckConst(InterpState , CodePtr OpPC, const 
Pointer ) {
 
   // The This pointer is writable in constructors and destructors,
   // even if isConst() returns true.
-  if (const Function *Func = S.Current->getFunction();
-  Func && (Func->isConstructor() || Func->isDestructor()) &&
-  Ptr.block() == S.Current->getThis().block()) {
-return true;
+  // TODO(perf): We could be hitting this code path quite a lot in complex
+  // constructors. Is there a better way to do this?
+  if (S.Current->getFunction()) {
+for (const InterpFrame *Frame = S.Current; Frame; Frame = Frame->Caller) {
+  if (const Function *Func = Frame->getFunction();
+  Func && (Func->isConstructor() || Func->isDestructor()) &&
+  Ptr.block() == Frame->getThis().block()) {
+return true;
+  }
+}
   }
 
   if (!Ptr.isBlockPointer())

diff  --git a/clang/test/AST/Interp/records.cpp 
b/clang/test/AST/Interp/records.cpp
index 4b06fc7522d45..2fc88a0b1df6a 100644
--- a/clang/test/AST/Interp/records.cpp
+++ b/clang/test/AST/Interp/records.cpp
@@ -1512,3 +1512,28 @@ namespace OnePastEndAndBack {
   constexpr const Base *d = c - 1;
   static_assert(d == , "");
 }
+
+namespace BitSet {
+  class Bitset {
+unsigned Bit = 0;
+
+  public:
+constexpr Bitset() {
+  int Init[2] = {1,2};
+  for (auto I : Init)
+set(I);
+}
+constexpr void set(unsigned I) {
+  this->Bit++;
+  this->Bit = 1u << 1;
+}
+  };
+
+  struct ArchInfo {
+Bitset DefaultExts;
+  };
+
+  constexpr ArchInfo ARMV8A = {
+Bitset()
+  };
+}



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


[clang] 181e4c6 - [clang][Interp] Check for non-primitive types in unary operators

2024-07-14 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-14T10:47:51+02:00
New Revision: 181e4c6291c94a38c0ee89d2128f8d70b15d2d23

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

LOG: [clang][Interp] Check for non-primitive types in unary operators

For invalid cases (non-vector/complex/...), this should only happen
in error cases such as the attached test case.

Added: 


Modified: 
clang/lib/AST/Interp/Compiler.cpp
clang/test/AST/Interp/literals.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index c58eb2eaa477..30dc7f5e4840 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -4706,6 +4706,8 @@ bool Compiler::VisitUnaryOperator(const 
UnaryOperator *E) {
   case UO_PostInc: { // x++
 if (!Ctx.getLangOpts().CPlusPlus14)
   return this->emitInvalid(E);
+if (!T)
+  return this->emitError(E);
 
 if (!this->visit(SubExpr))
   return false;
@@ -4727,6 +4729,8 @@ bool Compiler::VisitUnaryOperator(const 
UnaryOperator *E) {
   case UO_PostDec: { // x--
 if (!Ctx.getLangOpts().CPlusPlus14)
   return this->emitInvalid(E);
+if (!T)
+  return this->emitError(E);
 
 if (!this->visit(SubExpr))
   return false;
@@ -4748,6 +4752,8 @@ bool Compiler::VisitUnaryOperator(const 
UnaryOperator *E) {
   case UO_PreInc: { // ++x
 if (!Ctx.getLangOpts().CPlusPlus14)
   return this->emitInvalid(E);
+if (!T)
+  return this->emitError(E);
 
 if (!this->visit(SubExpr))
   return false;
@@ -4795,6 +4801,8 @@ bool Compiler::VisitUnaryOperator(const 
UnaryOperator *E) {
   case UO_PreDec: { // --x
 if (!Ctx.getLangOpts().CPlusPlus14)
   return this->emitInvalid(E);
+if (!T)
+  return this->emitError(E);
 
 if (!this->visit(SubExpr))
   return false;
@@ -4840,6 +4848,9 @@ bool Compiler::VisitUnaryOperator(const 
UnaryOperator *E) {
 return E->isGLValue() || this->emitLoadPop(*T, E);
   }
   case UO_LNot: // !x
+if (!T)
+  return this->emitError(E);
+
 if (DiscardResult)
   return this->discard(SubExpr);
 
@@ -4853,10 +4864,16 @@ bool Compiler::VisitUnaryOperator(const 
UnaryOperator *E) {
   return this->emitCast(PT_Bool, ET, E);
 return true;
   case UO_Minus: // -x
+if (!T)
+  return this->emitError(E);
+
 if (!this->visit(SubExpr))
   return false;
 return DiscardResult ? this->emitPop(*T, E) : this->emitNeg(*T, E);
   case UO_Plus:// +x
+if (!T)
+  return this->emitError(E);
+
 if (!this->visit(SubExpr)) // noop
   return false;
 return DiscardResult ? this->emitPop(*T, E) : true;
@@ -4873,6 +4890,9 @@ bool Compiler::VisitUnaryOperator(const 
UnaryOperator *E) {
   return this->discard(SubExpr);
 return this->visit(SubExpr);
   case UO_Not: // ~x
+if (!T)
+  return this->emitError(E);
+
 if (!this->visit(SubExpr))
   return false;
 return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E);

diff  --git a/clang/test/AST/Interp/literals.cpp 
b/clang/test/AST/Interp/literals.cpp
index 1f2755e710e3..93e7e8b52a45 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -1290,3 +1290,13 @@ namespace NTTP {
 return size(Chars);
   }
 }
+
+#if __cplusplus >= 201402L
+namespace UnaryOpError {
+  constexpr int foo() {
+int f = 0;
+++g; // both-error {{use of undeclared identifier 'g'}}
+return f;
+  }
+}
+#endif



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


[clang] 9d88990 - [clang][Interp][NFC] Remove visit{Global,Local,This}Initializer

2024-07-14 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-14T10:47:50+02:00
New Revision: 9d889906720c1a4fbdb3b8aaacfeebd62f235b87

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

LOG: [clang][Interp][NFC] Remove visit{Global,Local,This}Initializer

They were only called once, or not at all.

Added: 


Modified: 
clang/lib/AST/Interp/Compiler.cpp
clang/lib/AST/Interp/Compiler.h

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index 0b2a38d02b4a..c58eb2eaa477 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -3583,7 +3583,19 @@ VarCreationState Compiler::visitVarDecl(const 
VarDecl *VD, bool Topleve
 return checkDecl() && this->emitInitGlobal(*VarT, GlobalIndex, VD);
   }
 
-  return checkDecl() && this->visitGlobalInitializer(Init, GlobalIndex);
+  if (!checkDecl())
+return false;
+
+  if (!this->emitGetPtrGlobal(GlobalIndex, Init))
+return false;
+
+  if (!visitInitializer(Init))
+return false;
+
+  if (!this->emitFinishInit(Init))
+return false;
+
+  return this->emitPopPtr(Init);
 };
 
 // We've already seen and initialized this global.
@@ -3627,7 +3639,16 @@ VarCreationState Compiler::visitVarDecl(const 
VarDecl *VD, bool Topleve
 if (!Init)
   return true;
 
-return this->visitLocalInitializer(Init, *Offset);
+if (!this->emitGetPtrLocal(*Offset, Init))
+  return false;
+
+if (!visitInitializer(Init))
+  return false;
+
+if (!this->emitFinishInit(Init))
+  return false;
+
+return this->emitPopPtr(Init);
   }
   return false;
 }

diff  --git a/clang/lib/AST/Interp/Compiler.h b/clang/lib/AST/Interp/Compiler.h
index de873c7e6825..23e7afd767e8 100644
--- a/clang/lib/AST/Interp/Compiler.h
+++ b/clang/lib/AST/Interp/Compiler.h
@@ -278,45 +278,6 @@ class Compiler : public 
ConstStmtVisitor, bool>,
   /// Visits an expression and converts it to a boolean.
   bool visitBool(const Expr *E);
 
-  /// Visits an initializer for a local.
-  bool visitLocalInitializer(const Expr *Init, unsigned I) {
-if (!this->emitGetPtrLocal(I, Init))
-  return false;
-
-if (!visitInitializer(Init))
-  return false;
-
-if (!this->emitFinishInit(Init))
-  return false;
-
-return this->emitPopPtr(Init);
-  }
-
-  /// Visits an initializer for a global.
-  bool visitGlobalInitializer(const Expr *Init, unsigned I) {
-if (!this->emitGetPtrGlobal(I, Init))
-  return false;
-
-if (!visitInitializer(Init))
-  return false;
-
-if (!this->emitFinishInit(Init))
-  return false;
-
-return this->emitPopPtr(Init);
-  }
-
-  /// Visits a delegated initializer.
-  bool visitThisInitializer(const Expr *I) {
-if (!this->emitThis(I))
-  return false;
-
-if (!visitInitializer(I))
-  return false;
-
-return this->emitFinishInitPop(I);
-  }
-
   bool visitInitList(ArrayRef Inits, const Expr *ArrayFiller,
  const Expr *E);
   bool visitArrayElemInit(unsigned ElemIndex, const Expr *Init);



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


[clang] 92fe391 - [clang][Interp] Reject non-pointer typed dummies

2024-07-13 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-14T07:32:42+02:00
New Revision: 92fe3911c3e0f5e76cf60c8b3203002e6e6aa047

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

LOG: [clang][Interp] Reject non-pointer typed dummies

This happens a lot for NonTypeTemplateParm decls.

Added: 


Modified: 
clang/lib/AST/Interp/Compiler.cpp
clang/test/AST/Interp/literals.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index 209fb54ecdcb..0b2a38d02b4a 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -5094,9 +5094,10 @@ bool Compiler::visitDeclRef(const ValueDecl *D, 
const Expr *E) {
 if (E->getType()->isVoidType())
   return true;
 // Convert the dummy pointer to another pointer type if we have to.
-if (PrimType PT = classifyPrim(E); PT != PT_Ptr && isPtrType(PT)) {
-  if (!this->emitDecayPtr(PT_Ptr, PT, E))
-return false;
+if (PrimType PT = classifyPrim(E); PT != PT_Ptr) {
+  if (isPtrType(PT))
+return this->emitDecayPtr(PT_Ptr, PT, E);
+  return false;
 }
 return true;
   }

diff  --git a/clang/test/AST/Interp/literals.cpp 
b/clang/test/AST/Interp/literals.cpp
index 630d9b53cca2..1f2755e710e3 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -1276,3 +1276,17 @@ namespace ComparisonAgainstOnePastEnd {
 
   static_assert( + 1 ==  + 1, ""); // both-error {{static assertion 
failed}}
 };
+
+namespace NTTP {
+  template 
+constexpr unsigned
+size(const _Tp (&)[_Nm]) noexcept
+{ return _Nm; }
+
+  template 
+  static int write_padding() {
+static const char Chars[] = {C};
+
+return size(Chars);
+  }
+}



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


[clang] 77d2283 - [clang][Interp] Diagnose shift overflows

2024-07-13 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-14T07:28:02+02:00
New Revision: 77d2283e5824fb5bf375df65559a88a68159594b

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

LOG: [clang][Interp] Diagnose shift overflows

Added: 


Modified: 
clang/lib/AST/Interp/Interp.h
clang/test/AST/Interp/shifts.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 60e1d78f7405..c7d8604c7dc2 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -147,7 +147,7 @@ bool CheckShift(InterpState , CodePtr OpPC, const LT 
, const RT ,
 const APSInt Val = RHS.toAPSInt();
 QualType Ty = E->getType();
 S.CCEDiag(E, diag::note_constexpr_large_shift) << Val << Ty << Bits;
-return true; // We will do the shift anyway but fix up the shift amount.
+return !(S.getEvalStatus().Diag && !S.getEvalStatus().Diag->empty() && 
S.getLangOpts().CPlusPlus11);
   }
 
   if (LHS.isSigned() && !S.getLangOpts().CPlusPlus20) {

diff  --git a/clang/test/AST/Interp/shifts.cpp 
b/clang/test/AST/Interp/shifts.cpp
index c5abdb7dd8a1..360b87b7ee04 100644
--- a/clang/test/AST/Interp/shifts.cpp
+++ b/clang/test/AST/Interp/shifts.cpp
@@ -200,13 +200,14 @@ namespace LongInt {
 };
 
 enum shiftof {
-X = (1<<-29) // all-error {{expression is not an integral constant 
expression}} \
- // all-note {{negative shift count -29}}
-};
+X = (1<<-29), // all-error {{expression is not an integral constant 
expression}} \
+  // all-note {{negative shift count -29}}
+
+X2 = (-1<<29), // cxx17-error {{expression is not an integral constant 
expression}} \
+   // cxx17-note {{left shift of negative value -1}} \
+   // ref-cxx17-error {{expression is not an integral constant 
expression}} \
+   // ref-cxx17-note {{left shift of negative value -1}}
 
-enum shiftof2 {
-X2 = (-1<<29) // cxx17-error {{expression is not an integral constant 
expression}} \
-  // cxx17-note {{left shift of negative value -1}} \
-  // ref-cxx17-error {{expression is not an integral constant 
expression}} \
-  // ref-cxx17-note {{left shift of negative value -1}}
+X3 = (1<<32) // all-error {{expression is not an integral constant 
expression}} \
+ // all-note {{shift count 32 >= width of type 'int'}}
 };



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


[clang] ed304b6 - [clang][Interp] Diagnose left shifts of negative values

2024-07-13 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-14T07:28:02+02:00
New Revision: ed304b6790ba0391211bffe66856b00d0a949670

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

LOG: [clang][Interp] Diagnose left shifts of negative values

Added: 


Modified: 
clang/lib/AST/Interp/Interp.h
clang/test/AST/Interp/shifts.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 8502b7ca136e..60e1d78f7405 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -2234,6 +2234,20 @@ inline bool DoShift(InterpState , CodePtr OpPC, LT 
, RT ) {
  : ShiftDir::Left > (S, OpPC, LHS, RHS);
   }
 
+  if constexpr (Dir == ShiftDir::Left) {
+if (LHS.isNegative() && !S.getLangOpts().CPlusPlus20) {
+  // C++11 [expr.shift]p2: A signed left shift must have a non-negative
+  // operand, and must not overflow the corresponding unsigned type.
+  // C++2a [expr.shift]p2: E1 << E2 is the unique value congruent to
+  // E1 x 2^E2 module 2^N.
+  const SourceInfo  = S.Current->getSource(OpPC);
+  S.CCEDiag(Loc, diag::note_constexpr_lshift_of_negative) << 
LHS.toAPSInt();
+  if (S.getLangOpts().CPlusPlus11 && S.getEvalStatus().Diag &&
+  !S.getEvalStatus().Diag->empty())
+return false;
+}
+  }
+
   if (!CheckShift(S, OpPC, LHS, RHS, Bits))
 return false;
 

diff  --git a/clang/test/AST/Interp/shifts.cpp 
b/clang/test/AST/Interp/shifts.cpp
index ce17fabc7833..c5abdb7dd8a1 100644
--- a/clang/test/AST/Interp/shifts.cpp
+++ b/clang/test/AST/Interp/shifts.cpp
@@ -203,3 +203,10 @@ enum shiftof {
 X = (1<<-29) // all-error {{expression is not an integral constant 
expression}} \
  // all-note {{negative shift count -29}}
 };
+
+enum shiftof2 {
+X2 = (-1<<29) // cxx17-error {{expression is not an integral constant 
expression}} \
+  // cxx17-note {{left shift of negative value -1}} \
+  // ref-cxx17-error {{expression is not an integral constant 
expression}} \
+  // ref-cxx17-note {{left shift of negative value -1}}
+};



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


[clang] de02994 - [clang][Interp] Handle negative shift amounts correctly

2024-07-13 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-14T07:28:02+02:00
New Revision: de029943cc5ad0028f16e6ecaffa03e32ffd1a6f

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

LOG: [clang][Interp] Handle negative shift amounts correctly

We need to invert them and use the opposite shift.

Added: 


Modified: 
clang/lib/AST/Interp/Interp.h
clang/test/AST/Interp/shifts.cpp
clang/test/Sema/shift-count-negative.c

Removed: 




diff  --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 95f89990a7a18..8502b7ca136ee 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -2209,13 +2209,10 @@ inline bool RVOPtr(InterpState , CodePtr OpPC) {
 
//===--===//
 // Shr, Shl
 
//===--===//
+enum class ShiftDir { Left, Right };
 
-template 
-inline bool Shr(InterpState , CodePtr OpPC) {
-  using LT = typename PrimConv::T;
-  using RT = typename PrimConv::T;
-  auto RHS = S.Stk.pop();
-  const auto  = S.Stk.pop();
+template 
+inline bool DoShift(InterpState , CodePtr OpPC, LT , RT ) {
   const unsigned Bits = LHS.bitWidth();
 
   // OpenCL 6.3j: shift values are effectively % word size of LHS.
@@ -2223,6 +2220,20 @@ inline bool Shr(InterpState , CodePtr OpPC) {
 RT::bitAnd(RHS, RT::from(LHS.bitWidth() - 1, RHS.bitWidth()),
RHS.bitWidth(), );
 
+  if (RHS.isNegative()) {
+// During constant-folding, a negative shift is an opposite shift. Such a
+// shift is not a constant expression.
+const SourceInfo  = S.Current->getSource(OpPC);
+S.CCEDiag(Loc, diag::note_constexpr_negative_shift) << RHS.toAPSInt();
+if (S.getLangOpts().CPlusPlus11 && S.getEvalStatus().Diag &&
+!S.getEvalStatus().Diag->empty())
+  return false;
+RHS = -RHS;
+return DoShift < LT, RT,
+   Dir == ShiftDir::Left ? ShiftDir::Right
+ : ShiftDir::Left > (S, OpPC, LHS, RHS);
+  }
+
   if (!CheckShift(S, OpPC, LHS, RHS, Bits))
 return false;
 
@@ -2230,45 +2241,44 @@ inline bool Shr(InterpState , CodePtr OpPC) {
   // it has already been diagnosed by CheckShift() above,
   // but we still need to handle it.
   typename LT::AsUnsigned R;
-  if (RHS > RT::from(Bits - 1, RHS.bitWidth()))
-LT::AsUnsigned::shiftRight(LT::AsUnsigned::from(LHS),
-   LT::AsUnsigned::from(Bits - 1), Bits, );
-  else
-LT::AsUnsigned::shiftRight(LT::AsUnsigned::from(LHS),
-   LT::AsUnsigned::from(RHS, Bits), Bits, );
+  if constexpr (Dir == ShiftDir::Left) {
+if (RHS > RT::from(Bits - 1, RHS.bitWidth()))
+  LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS),
+LT::AsUnsigned::from(Bits - 1), Bits, );
+else
+  LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS),
+LT::AsUnsigned::from(RHS, Bits), Bits, );
+  } else {
+if (RHS > RT::from(Bits - 1, RHS.bitWidth()))
+  LT::AsUnsigned::shiftRight(LT::AsUnsigned::from(LHS),
+ LT::AsUnsigned::from(Bits - 1), Bits, );
+else
+  LT::AsUnsigned::shiftRight(LT::AsUnsigned::from(LHS),
+ LT::AsUnsigned::from(RHS, Bits), Bits, );
+  }
+
   S.Stk.push(LT::from(R));
   return true;
 }
 
 template 
-inline bool Shl(InterpState , CodePtr OpPC) {
+inline bool Shr(InterpState , CodePtr OpPC) {
   using LT = typename PrimConv::T;
   using RT = typename PrimConv::T;
   auto RHS = S.Stk.pop();
-  const auto  = S.Stk.pop();
-  const unsigned Bits = LHS.bitWidth();
-
-  // OpenCL 6.3j: shift values are effectively % word size of LHS.
-  if (S.getLangOpts().OpenCL)
-RT::bitAnd(RHS, RT::from(LHS.bitWidth() - 1, RHS.bitWidth()),
-   RHS.bitWidth(), );
+  auto LHS = S.Stk.pop();
 
-  if (!CheckShift(S, OpPC, LHS, RHS, Bits))
-return false;
+  return DoShift(S, OpPC, LHS, RHS);
+}
 
-  // Limit the shift amount to Bits - 1. If this happened,
-  // it has already been diagnosed by CheckShift() above,
-  // but we still need to handle it.
-  typename LT::AsUnsigned R;
-  if (RHS > RT::from(Bits - 1, RHS.bitWidth()))
-LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS),
-  LT::AsUnsigned::from(Bits - 1), Bits, );
-  else
-LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS),
-  LT::AsUnsigned::from(RHS, Bits), Bits, );
+template 
+inline bool Shl(InterpState , CodePtr OpPC) {
+  using LT = typename PrimConv::T;
+  using RT = typename PrimConv::T;
+  auto RHS = S.Stk.pop();
+  auto LHS = S.Stk.pop();
 
-  S.Stk.push(LT::from(R));
-  return true;
+  return DoShift(S, OpPC, 

[clang] 7645823 - [clang][Interp] Don't require StmtExpr result to be an expression

2024-07-13 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-14T07:28:02+02:00
New Revision: 7645823564a34db84f0da53e53e38eb0ceb429ec

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

LOG: [clang][Interp] Don't require StmtExpr result to be an expression

It can be a statement containing an expression.

Added: 


Modified: 
clang/lib/AST/Interp/Compiler.cpp
clang/test/CodeGenCXX/cxx1z-constexpr-if.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index 48e7519f8f89d..209fb54ecdcb5 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -3073,13 +3073,13 @@ bool Compiler::VisitStmtExpr(const StmtExpr 
*E) {
 }
 
 assert(S == Result);
-// This better produces a value (i.e. is an expression).
 if (const Expr *ResultExpr = dyn_cast(S)) {
   if (DiscardResult)
 return this->discard(ResultExpr);
   return this->delegate(ResultExpr);
 }
-return false;
+
+return this->visitStmt(S);
   }
 
   return BS.destroyLocals();

diff  --git a/clang/test/CodeGenCXX/cxx1z-constexpr-if.cpp 
b/clang/test/CodeGenCXX/cxx1z-constexpr-if.cpp
index d14e36406a45e..5a11afb8dec40 100644
--- a/clang/test/CodeGenCXX/cxx1z-constexpr-if.cpp
+++ b/clang/test/CodeGenCXX/cxx1z-constexpr-if.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -std=c++1z %s -emit-llvm -fblocks -triple 
x86_64-apple-darwin10 -o - | FileCheck %s 
--implicit-check-not=should_not_be_used
+// RUN: %clang_cc1 -std=c++1z %s -emit-llvm -fblocks -triple 
x86_64-apple-darwin10 -o - -fexperimental-new-constant-interpreter | FileCheck 
%s --implicit-check-not=should_not_be_used
 
 void should_be_used_1();
 void should_be_used_2();



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


[clang] 6b380a8 - [clang][Interp] Fix integral overflow reporting

2024-07-13 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-14T07:28:01+02:00
New Revision: 6b380a810ea57fdb36ef911756bd2e1cbf2fbac0

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

LOG: [clang][Interp] Fix integral overflow reporting

We need to always do the CCEDiag, the report() is optional.

Added: 


Modified: 
clang/lib/AST/Interp/Interp.h
clang/test/SemaCXX/enum.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 1df8d65c80445..95f89990a7a18 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -302,15 +302,16 @@ bool AddSubMulHelper(InterpState , CodePtr OpPC, 
unsigned Bits, const T ,
 auto Loc = E->getExprLoc();
 S.report(Loc, diag::warn_integer_constant_overflow)
 << Trunc << Type << E->getSourceRange();
-return true;
-  } else {
-S.CCEDiag(E, diag::note_constexpr_overflow) << Value << Type;
-if (!S.noteUndefinedBehavior()) {
-  S.Stk.pop();
-  return false;
-}
-return true;
   }
+
+  S.CCEDiag(E, diag::note_constexpr_overflow) << Value << Type;
+
+  if (!S.noteUndefinedBehavior()) {
+S.Stk.pop();
+return false;
+  }
+
+  return true;
 }
 
 template ::T>

diff  --git a/clang/test/SemaCXX/enum.cpp b/clang/test/SemaCXX/enum.cpp
index 7d4a05083b9cd..739d35ec4a06b 100644
--- a/clang/test/SemaCXX/enum.cpp
+++ b/clang/test/SemaCXX/enum.cpp
@@ -1,5 +1,9 @@
 // RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++98 -verify -triple 
x86_64-apple-darwin %s
 // RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++11 -verify -triple 
x86_64-apple-darwin %s
+
+// RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++98 -verify -triple 
x86_64-apple-darwin %s -fexperimental-new-constant-interpreter
+// RUN: %clang_cc1 -fsyntax-only -pedantic -std=c++11 -verify -triple 
x86_64-apple-darwin %s -fexperimental-new-constant-interpreter
+
 enum E { // expected-note{{previous definition is here}}
   Val1,
   Val2



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


[clang] b22adf0 - [clang][Interp] Clear pointers pointing to dead blocks

2024-07-13 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-13T15:55:55+02:00
New Revision: b22adf02a2d2cc290d618fe47bec5aeec47ab992

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

LOG: [clang][Interp] Clear pointers pointing to dead blocks

before free()ing the dead blocks. Otherwise, we might end up with
dangling Pointers to those dead blocks.

Added: 


Modified: 
clang/lib/AST/Interp/InterpState.cpp
clang/lib/AST/Interp/Pointer.h
clang/test/AST/Interp/lifetimes.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/InterpState.cpp 
b/clang/lib/AST/Interp/InterpState.cpp
index 550bc9f1a84b..a8538541f491 100644
--- a/clang/lib/AST/Interp/InterpState.cpp
+++ b/clang/lib/AST/Interp/InterpState.cpp
@@ -33,7 +33,15 @@ InterpState::~InterpState() {
   }
 }
 
-void InterpState::cleanup() {}
+void InterpState::cleanup() {
+  // As a last resort, make sure all pointers still pointing to a dead block
+  // don't point to it anymore.
+  for (DeadBlock *DB = DeadBlocks; DB; DB = DB->Next) {
+for (Pointer *P = DB->B.Pointers; P; P = P->Next) {
+  P->PointeeStorage.BS.Pointee = nullptr;
+}
+  }
+}
 
 Frame *InterpState::getCurrentFrame() {
   if (Current && Current->Caller)

diff  --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/Interp/Pointer.h
index 3515f525a22f..6e9e8675306e 100644
--- a/clang/lib/AST/Interp/Pointer.h
+++ b/clang/lib/AST/Interp/Pointer.h
@@ -635,6 +635,7 @@ class Pointer {
   friend class Block;
   friend class DeadBlock;
   friend class MemberPointer;
+  friend class InterpState;
   friend struct InitMap;
 
   Pointer(Block *Pointee, unsigned Base, uint64_t Offset);

diff  --git a/clang/test/AST/Interp/lifetimes.cpp 
b/clang/test/AST/Interp/lifetimes.cpp
index c544baba6178..d47533ab547b 100644
--- a/clang/test/AST/Interp/lifetimes.cpp
+++ b/clang/test/AST/Interp/lifetimes.cpp
@@ -1,6 +1,8 @@
 // RUN: %clang_cc1 -fexperimental-new-constant-interpreter 
-verify=expected,both %s
 // RUN: %clang_cc1 -verify=ref,both %s
 
+/// FIXME: Slight 
diff erence in diagnostic output here.
+
 struct Foo {
   int a;
 };
@@ -20,3 +22,14 @@ static_assert(dead1() == 1, ""); // both-error {{not an 
integral constant expres
  // both-note {{in call to}}
 
 
+struct S {
+  int & // both-note {{reference member declared here}}
+  int t;
+  constexpr S() : r(0), t(r) {} // both-error {{reference member 'r' binds to 
a temporary object whose lifetime would be shorter than the lifetime of the 
constructed object}} \
+// ref-note {{read of object outside its 
lifetime is not allowed in a constant expression}} \
+// expected-note {{temporary created here}} \
+// expected-note {{read of temporary whose 
lifetime has ended}}
+};
+constexpr int k1 = S().t; // both-error {{must be initialized by a constant 
expression}} \
+  // ref-note {{in call to}} \
+  // expected-note {{in call to}}



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


[clang] 66e6df2 - [clang][Interp] Fix one-past-end pointers going back into the block

2024-07-12 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-13T07:25:47+02:00
New Revision: 66e6df22b5a509c16e50364d72b1a40bacaea91a

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

LOG: [clang][Interp] Fix one-past-end pointers going back into the block

Added: 


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

Removed: 




diff  --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 83c7e98c2dda0..1df8d65c80445 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -1844,6 +1844,15 @@ bool OffsetHelper(InterpState , CodePtr OpPC, const T 
,
   else
 Result = WideIndex - WideOffset;
 
+  // When the pointer is one-past-end, going back to index 0 is the only
+  // useful thing we can do. Any other index has been diagnosed before and
+  // we don't get here.
+  if (Result == 0 && Ptr.isOnePastEnd()) {
+S.Stk.push(Ptr.asBlockPointer().Pointee,
+Ptr.asBlockPointer().Base);
+return true;
+  }
+
   S.Stk.push(Ptr.atIndex(static_cast(Result)));
   return true;
 }

diff  --git a/clang/test/AST/Interp/records.cpp 
b/clang/test/AST/Interp/records.cpp
index adc3799a20ce4..4b06fc7522d45 100644
--- a/clang/test/AST/Interp/records.cpp
+++ b/clang/test/AST/Interp/records.cpp
@@ -1500,3 +1500,15 @@ namespace LocalWithThisPtrInit {
   }
   static_assert(foo() == 2, "");
 }
+
+namespace OnePastEndAndBack {
+  struct Base {
+constexpr Base() {}
+int n = 0;
+  };
+
+  constexpr Base a;
+  constexpr const Base *c =  + 1;
+  constexpr const Base *d = c - 1;
+  static_assert(d == , "");
+}



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


[clang] 634128b - [clang][Interp][NFC] Remove some unused includes

2024-07-12 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-13T07:25:47+02:00
New Revision: 634128be4610a4d85d92935109ed7761f0e06af1

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

LOG: [clang][Interp][NFC] Remove some unused includes

Added: 


Modified: 
clang/lib/AST/Interp/Interp.h

Removed: 




diff  --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index ac87901570ec..83c7e98c2dda 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -27,13 +27,9 @@
 #include "Program.h"
 #include "State.h"
 #include "clang/AST/ASTContext.h"
-#include "clang/AST/ASTDiagnostic.h"
-#include "clang/AST/CXXInheritance.h"
 #include "clang/AST/Expr.h"
 #include "llvm/ADT/APFloat.h"
 #include "llvm/ADT/APSInt.h"
-#include "llvm/Support/Endian.h"
-#include 
 #include 
 
 namespace clang {



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


[clang] 7d59020 - [clang][Interp][NFC] Remove unused include

2024-07-12 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-13T07:25:47+02:00
New Revision: 7d5902025d20e00b1865d02dfe514fb35259ae2a

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

LOG: [clang][Interp][NFC] Remove unused include

Added: 


Modified: 
clang/lib/AST/Interp/Pointer.h

Removed: 




diff  --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/Interp/Pointer.h
index 0ebac1ba04551..3515f525a22fe 100644
--- a/clang/lib/AST/Interp/Pointer.h
+++ b/clang/lib/AST/Interp/Pointer.h
@@ -19,7 +19,6 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/Expr.h"
-#include "llvm/ADT/PointerUnion.h"
 #include "llvm/Support/raw_ostream.h"
 
 namespace clang {



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


[clang] c784abf - [clang][Interp] Delay compiling functions that don't have a body yet

2024-07-12 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-12T17:32:39+02:00
New Revision: c784abf2007a98c5fea64a84b56fa21974983d90

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

LOG: [clang][Interp] Delay compiling functions that don't have a body yet

Sometimes, isDefined() returns true, even though the function doesn't
have a body yet, but will have one later. This is for example the case
when referring to a class member function via a member pointer before
the member function has been fully parsed. Reject them at first and
compile them later.

Added: 


Modified: 
clang/lib/AST/Interp/ByteCodeEmitter.cpp
clang/test/AST/Interp/memberpointers.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/ByteCodeEmitter.cpp 
b/clang/lib/AST/Interp/ByteCodeEmitter.cpp
index 918cd66c9a976..ae777d555e916 100644
--- a/clang/lib/AST/Interp/ByteCodeEmitter.cpp
+++ b/clang/lib/AST/Interp/ByteCodeEmitter.cpp
@@ -147,7 +147,8 @@ Function *ByteCodeEmitter::compileFunc(const FunctionDecl 
*FuncDecl) {
   assert(Func);
   // For not-yet-defined functions, we only create a Function instance and
   // compile their body later.
-  if (!FuncDecl->isDefined()) {
+  if (!FuncDecl->isDefined() ||
+  (FuncDecl->willHaveBody() && !FuncDecl->hasBody())) {
 Func->setDefined(false);
 return Func;
   }

diff  --git a/clang/test/AST/Interp/memberpointers.cpp 
b/clang/test/AST/Interp/memberpointers.cpp
index 178d2e23f1266..f38e948638631 100644
--- a/clang/test/AST/Interp/memberpointers.cpp
+++ b/clang/test/AST/Interp/memberpointers.cpp
@@ -1,5 +1,7 @@
 // RUN: %clang_cc1 -std=c++14 -fexperimental-new-constant-interpreter 
-verify=expected,both %s
+// RUN: %clang_cc1 -std=c++23 -fexperimental-new-constant-interpreter 
-verify=expected,both %s
 // RUN: %clang_cc1 -std=c++14 -verify=ref,both %s
+// RUN: %clang_cc1 -std=c++23 -verify=ref,both %s
 
 namespace MemberPointers {
   struct A {



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


[clang] 840c7c6 - [clang][Interp] Fix Pointer::expand() checking for metadata size

2024-07-12 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-12T17:18:26+02:00
New Revision: 840c7c6e1fba52748e3ceccd2842e5d96f658f2e

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

LOG: [clang][Interp] Fix Pointer::expand() checking for metadata size

The == 0 check here was used before blocks had metadata, but doesn't
work anymore today.

Added: 


Modified: 
clang/lib/AST/Interp/Pointer.h
clang/test/AST/Interp/arrays.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/Interp/Pointer.h
index 7785da1d68f63..0ebac1ba04551 100644
--- a/clang/lib/AST/Interp/Pointer.h
+++ b/clang/lib/AST/Interp/Pointer.h
@@ -211,6 +211,9 @@ class Pointer {
 
   /// Expands a pointer to the containing array, undoing narrowing.
   [[nodiscard]] Pointer expand() const {
+assert(isBlockPointer());
+Block *Pointee = asBlockPointer().Pointee;
+
 if (isElementPastEnd()) {
   // Revert to an outer one-past-end pointer.
   unsigned Adjust;
@@ -218,7 +221,7 @@ class Pointer {
 Adjust = sizeof(InitMapPtr);
   else
 Adjust = sizeof(InlineDescriptor);
-  return Pointer(asBlockPointer().Pointee, asBlockPointer().Base,
+  return Pointer(Pointee, asBlockPointer().Base,
  asBlockPointer().Base + getSize() + Adjust);
 }
 
@@ -228,15 +231,17 @@ class Pointer {
 
 // If at base, point to an array of base types.
 if (isRoot())
-  return Pointer(asBlockPointer().Pointee, RootPtrMark, 0);
+  return Pointer(Pointee, RootPtrMark, 0);
 
 // Step into the containing array, if inside one.
 unsigned Next = asBlockPointer().Base - getInlineDesc()->Offset;
 const Descriptor *Desc =
-Next == 0 ? getDeclDesc() : getDescriptor(Next)->Desc;
+(Next == Pointee->getDescriptor()->getMetadataSize())
+? getDeclDesc()
+: getDescriptor(Next)->Desc;
 if (!Desc->IsArray)
   return *this;
-return Pointer(asBlockPointer().Pointee, Next, Offset);
+return Pointer(Pointee, Next, Offset);
   }
 
   /// Checks if the pointer is null.

diff  --git a/clang/test/AST/Interp/arrays.cpp 
b/clang/test/AST/Interp/arrays.cpp
index 933437c3401c4..612bd552aed48 100644
--- a/clang/test/AST/Interp/arrays.cpp
+++ b/clang/test/AST/Interp/arrays.cpp
@@ -625,3 +625,10 @@ constexpr int *get2() {
   return same_entity_2;
 }
 static_assert(get2() == same_entity_2, "failed to find previous decl");
+
+constexpr int zs[2][2][2][2] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 
14, 15, 16 };
+constexpr int fail(const int ) {
+  return ()[64]; // both-note {{cannot refer to element 64 of array of 2 
elements}}
+}
+static_assert(fail(*(&(&(*(*&([2] - 1)[0] + 2 - 2))[2])[-1][2] - 2)) == 11, 
""); // both-error {{not an integral constant expression}} \
+   
 // both-note {{in call to}}



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


[clang] 1752b7b - [clang][Interp][NFC] Apply some clang-tidy suggestions

2024-07-12 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-12T17:18:26+02:00
New Revision: 1752b7bc521ae878355a1c9e48644b0ad320dbe5

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

LOG: [clang][Interp][NFC] Apply some clang-tidy suggestions

Remove unused includes and don't use an else after a return.

Added: 


Modified: 
clang/lib/AST/Interp/InterpFrame.h

Removed: 




diff  --git a/clang/lib/AST/Interp/InterpFrame.h 
b/clang/lib/AST/Interp/InterpFrame.h
index 1f80a0a5d2c49..4a312a71bcf1c 100644
--- a/clang/lib/AST/Interp/InterpFrame.h
+++ b/clang/lib/AST/Interp/InterpFrame.h
@@ -15,8 +15,6 @@
 
 #include "Frame.h"
 #include "Program.h"
-#include 
-#include 
 
 namespace clang {
 namespace interp {
@@ -85,11 +83,9 @@ class InterpFrame final : public Frame {
   /// Returns the value of an argument.
   template  const T (unsigned Offset) const {
 auto Pt = Params.find(Offset);
-if (Pt == Params.end()) {
+if (Pt == Params.end())
   return stackRef(Offset);
-} else {
-  return Pointer(reinterpret_cast(Pt->second.get())).deref();
-}
+return Pointer(reinterpret_cast(Pt->second.get())).deref();
   }
 
   /// Mutates a local copy of a parameter.



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


[clang] 007e32d - [clang][Interp][NFC] Simplify record creation

2024-07-12 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-12T16:45:18+02:00
New Revision: 007e32d024f31ef157e3e16117a6c000bfaa2754

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

LOG: [clang][Interp][NFC] Simplify record creation

Try to keep the indentation width lower here.

Added: 


Modified: 
clang/lib/AST/Interp/Program.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Program.cpp 
b/clang/lib/AST/Interp/Program.cpp
index d3864d23925c0..5dd59d969853c 100644
--- a/clang/lib/AST/Interp/Program.cpp
+++ b/clang/lib/AST/Interp/Program.cpp
@@ -288,40 +288,41 @@ Record *Program::getOrCreateRecord(const RecordDecl *RD) {
   Record::BaseList Bases;
   Record::VirtualBaseList VirtBases;
   if (const auto *CD = dyn_cast(RD)) {
-
 for (const CXXBaseSpecifier  : CD->bases()) {
   if (Spec.isVirtual())
 continue;
 
   // In error cases, the base might not be a RecordType.
-  if (const auto *RT = Spec.getType()->getAs()) {
-const RecordDecl *BD = RT->getDecl();
-const Record *BR = getOrCreateRecord(BD);
-
-if (const Descriptor *Desc = GetBaseDesc(BD, BR)) {
-  BaseSize += align(sizeof(InlineDescriptor));
-  Bases.push_back({BD, BaseSize, Desc, BR});
-  BaseSize += align(BR->getSize());
-  continue;
-}
-  }
-  return nullptr;
+  const auto *RT = Spec.getType()->getAs();
+  if (!RT)
+return nullptr;
+  const RecordDecl *BD = RT->getDecl();
+  const Record *BR = getOrCreateRecord(BD);
+
+  const Descriptor *Desc = GetBaseDesc(BD, BR);
+  if (!Desc)
+return nullptr;
+
+  BaseSize += align(sizeof(InlineDescriptor));
+  Bases.push_back({BD, BaseSize, Desc, BR});
+  BaseSize += align(BR->getSize());
 }
 
 for (const CXXBaseSpecifier  : CD->vbases()) {
+  const auto *RT = Spec.getType()->getAs();
+  if (!RT)
+return nullptr;
 
-  if (const auto *RT = Spec.getType()->getAs()) {
-const RecordDecl *BD = RT->getDecl();
-const Record *BR = getOrCreateRecord(BD);
+  const RecordDecl *BD = RT->getDecl();
+  const Record *BR = getOrCreateRecord(BD);
 
-if (const Descriptor *Desc = GetBaseDesc(BD, BR)) {
-  VirtSize += align(sizeof(InlineDescriptor));
-  VirtBases.push_back({BD, VirtSize, Desc, BR});
-  VirtSize += align(BR->getSize());
-  continue;
-}
-  }
-  return nullptr;
+  const Descriptor *Desc = GetBaseDesc(BD, BR);
+  if (!Desc)
+return nullptr;
+
+  VirtSize += align(sizeof(InlineDescriptor));
+  VirtBases.push_back({BD, VirtSize, Desc, BR});
+  VirtSize += align(BR->getSize());
 }
   }
 



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


[clang] 98edc0c - [clang][Interp] Fix member pointer temporaries

2024-07-12 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-12T16:37:04+02:00
New Revision: 98edc0cb1f4ca53bd2d490916566ff7d217110f8

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

LOG: [clang][Interp] Fix member pointer temporaries

PT_MemberPtr also needs its ctor/dtor called, so add that.
However, this exposed a problem in initializing virtual bases,
so fix that as well.

Added: 


Modified: 
clang/lib/AST/Interp/Descriptor.cpp
clang/test/AST/Interp/memberpointers.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Descriptor.cpp 
b/clang/lib/AST/Interp/Descriptor.cpp
index afafae088aca0..a3801a01688c8 100644
--- a/clang/lib/AST/Interp/Descriptor.cpp
+++ b/clang/lib/AST/Interp/Descriptor.cpp
@@ -162,8 +162,7 @@ static void initField(Block *B, std::byte *Ptr, bool 
IsConst, bool IsMutable,
 }
 
 static void initBase(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
- bool IsActive, const Descriptor *D, unsigned FieldOffset,
- bool IsVirtualBase) {
+ bool IsActive, const Descriptor *D, unsigned FieldOffset) 
{
   assert(D);
   assert(D->ElemRecord);
 
@@ -179,43 +178,46 @@ static void initBase(Block *B, std::byte *Ptr, bool 
IsConst, bool IsMutable,
 
   for (const auto  : D->ElemRecord->bases())
 initBase(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, V.Desc,
- V.Offset, false);
+ V.Offset);
   for (const auto  : D->ElemRecord->fields())
-initField(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, IsUnion, 
F.Desc,
-  F.Offset);
-
-  // If this is initializing a virtual base, we do NOT want to consider its
-  // virtual bases, those are already flattened into the parent record when
-  // creating it.
-  if (IsVirtualBase)
-return;
-
-  for (const auto  : D->ElemRecord->virtual_bases())
-initBase(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, V.Desc,
- V.Offset, true);
+initField(B, Ptr + FieldOffset, IsConst, IsMutable, IsActive, IsUnion,
+  F.Desc, F.Offset);
 }
 
 static void ctorRecord(Block *B, std::byte *Ptr, bool IsConst, bool IsMutable,
bool IsActive, const Descriptor *D) {
   for (const auto  : D->ElemRecord->bases())
-initBase(B, Ptr, IsConst, IsMutable, IsActive, V.Desc, V.Offset, false);
+initBase(B, Ptr, IsConst, IsMutable, IsActive, V.Desc, V.Offset);
   for (const auto  : D->ElemRecord->fields())
 initField(B, Ptr, IsConst, IsMutable, IsActive, D->ElemRecord->isUnion(), 
F.Desc, F.Offset);
   for (const auto  : D->ElemRecord->virtual_bases())
-initBase(B, Ptr, IsConst, IsMutable, IsActive, V.Desc, V.Offset, true);
+initBase(B, Ptr, IsConst, IsMutable, IsActive, V.Desc, V.Offset);
+}
+
+static void destroyField(Block *B, std::byte *Ptr, const Descriptor *D,
+ unsigned FieldOffset) {
+  if (auto Fn = D->DtorFn)
+Fn(B, Ptr + FieldOffset, D);
+}
+
+static void destroyBase(Block *B, std::byte *Ptr, const Descriptor *D,
+unsigned FieldOffset) {
+  assert(D);
+  assert(D->ElemRecord);
+
+  for (const auto  : D->ElemRecord->bases())
+destroyBase(B, Ptr + FieldOffset, V.Desc, V.Offset);
+  for (const auto  : D->ElemRecord->fields())
+destroyField(B, Ptr + FieldOffset, F.Desc, F.Offset);
 }
 
 static void dtorRecord(Block *B, std::byte *Ptr, const Descriptor *D) {
-  auto DtorSub = [=](unsigned SubOff, const Descriptor *F) {
-if (auto Fn = F->DtorFn)
-  Fn(B, Ptr + SubOff, F);
-  };
   for (const auto  : D->ElemRecord->bases())
-DtorSub(F.Offset, F.Desc);
+destroyBase(B, Ptr, F.Desc, F.Offset);
   for (const auto  : D->ElemRecord->fields())
-DtorSub(F.Offset, F.Desc);
+destroyField(B, Ptr, F.Desc, F.Offset);
   for (const auto  : D->ElemRecord->virtual_bases())
-DtorSub(F.Offset, F.Desc);
+destroyBase(B, Ptr, F.Desc, F.Offset);
 }
 
 static void moveRecord(Block *B, const std::byte *Src, std::byte *Dst,
@@ -238,6 +240,8 @@ static BlockCtorFn getCtorPrim(PrimType Type) {
 return ctorTy::T>;
   if (Type == PT_IntAPS)
 return ctorTy::T>;
+  if (Type == PT_MemberPtr)
+return ctorTy::T>;
 
   COMPOSITE_TYPE_SWITCH(Type, return ctorTy, return nullptr);
 }
@@ -251,6 +255,8 @@ static BlockDtorFn getDtorPrim(PrimType Type) {
 return dtorTy::T>;
   if (Type == PT_IntAPS)
 return dtorTy::T>;
+  if (Type == PT_MemberPtr)
+return dtorTy::T>;
 
   COMPOSITE_TYPE_SWITCH(Type, return dtorTy, return nullptr);
 }

diff  --git a/clang/test/AST/Interp/memberpointers.cpp 
b/clang/test/AST/Interp/memberpointers.cpp
index 54d73fe86ca18..178d2e23f1266 100644
--- a/clang/test/AST/Interp/memberpointers.cpp
+++ b/clang/test/AST/Interp/memberpointers.cpp
@@ -195,3 +195,15 @@ namespace {
 

[clang] 7a93508 - [clang][Interp] Reject calling function pointers if types don't match

2024-07-12 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-12T15:32:40+02:00
New Revision: 7a935089d4593de6767901810594058904412106

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

LOG: [clang][Interp] Reject calling function pointers if types don't match

Added: 


Modified: 
clang/lib/AST/Interp/Interp.h
clang/test/AST/Interp/functions.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 12143fbf50808..ac87901570ec1 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -2569,6 +2569,12 @@ inline bool CallPtr(InterpState , CodePtr OpPC, 
uint32_t ArgSize,
 
   assert(F);
 
+  // This happens when the call expression has been cast to
+  // something else, but we don't support that.
+  if (S.Ctx.classify(F->getDecl()->getReturnType()) !=
+  S.Ctx.classify(CE->getType()))
+return false;
+
   // Check argument nullability state.
   if (F->hasNonNullAttr()) {
 if (!CheckNonNullArgs(S, OpPC, F, CE, ArgSize))

diff  --git a/clang/test/AST/Interp/functions.cpp 
b/clang/test/AST/Interp/functions.cpp
index f43be1d3c0403..fa29e08a30175 100644
--- a/clang/test/AST/Interp/functions.cpp
+++ b/clang/test/AST/Interp/functions.cpp
@@ -1,9 +1,9 @@
-// RUN: %clang_cc1 -fexperimental-new-constant-interpreter 
-verify=expected,both %s
-// RUN: %clang_cc1 -std=c++14 -fexperimental-new-constant-interpreter 
-verify=expected,both %s
-// RUN: %clang_cc1 -std=c++20 -fexperimental-new-constant-interpreter 
-verify=expected,both %s
-// RUN: %clang_cc1 -verify=ref,both %s
-// RUN: %clang_cc1 -std=c++14 -verify=ref,both %s
-// RUN: %clang_cc1 -std=c++20 -verify=ref,both %s
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -pedantic 
-verify=expected,both %s
+// RUN: %clang_cc1 -std=c++14 -fexperimental-new-constant-interpreter 
-pedantic -verify=expected,both %s
+// RUN: %clang_cc1 -std=c++20 -fexperimental-new-constant-interpreter 
-pedantic -verify=expected,both %s
+// RUN: %clang_cc1 -pedantic -verify=ref,both %s
+// RUN: %clang_cc1 -pedantic -std=c++14 -verify=ref,both %s
+// RUN: %clang_cc1 -pedantic -std=c++20 -verify=ref,both %s
 
 constexpr void doNothing() {}
 constexpr int gimme5() {
@@ -471,7 +471,7 @@ namespace AddressOf {
   constexpr int foo() {return 1;}
   static_assert(__builtin_addressof(foo) == foo, "");
 
-  constexpr _Complex float F = {3, 4};
+  constexpr _Complex float F = {3, 4}; // both-warning {{'_Complex' is a C99 
extension}}
   static_assert(__builtin_addressof(F) == , "");
 
   void testAddressof(int x) {
@@ -633,3 +633,14 @@ namespace {
   void ()() = f;
   void ()() = r;
 }
+
+namespace FunctionCast {
+  // When folding, we allow functions to be cast to 
diff erent types. Such
+  // cast functions cannot be called, even if they're constexpr.
+  constexpr int f() { return 1; }
+  typedef double (*DoubleFn)();
+  typedef int (*IntFn)();
+  int a[(int)DoubleFn(f)()]; // both-error {{variable length array}} \
+ // both-warning {{are a Clang extension}}
+  int b[(int)IntFn(f)()];// ok
+}



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


[clang] 369d3a7 - [clang][Interp][NFC] Remove ExprScope

2024-07-09 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-09T11:52:40+02:00
New Revision: 369d3a738082a2fac1a98aae8a8cfded9a010e10

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

LOG: [clang][Interp][NFC] Remove ExprScope

It's been nothing but a LocalScope for a while.

Added: 


Modified: 
clang/lib/AST/Interp/Compiler.cpp
clang/lib/AST/Interp/Compiler.h

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index 1d39d7bb9e15f..5fad24a0930ac 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -2204,7 +2204,7 @@ bool Compiler::VisitCompoundAssignOperator(
 
 template 
 bool Compiler::VisitExprWithCleanups(const ExprWithCleanups *E) {
-  ExprScope ES(this);
+  LocalScope ES(this);
   const Expr *SubExpr = E->getSubExpr();
 
   assert(E->getNumObjects() == 0 && "TODO: Implement cleanups");
@@ -3425,7 +3425,7 @@ const Function *Compiler::getFunction(const 
FunctionDecl *FD) {
 }
 
 template  bool Compiler::visitExpr(const Expr *E) {
-  ExprScope RootScope(this);
+  LocalScope RootScope(this);
   // Void expressions.
   if (E->getType()->isVoidType()) {
 if (!visit(E))
@@ -3610,10 +3610,10 @@ VarCreationState Compiler::visitVarDecl(const 
VarDecl *VD, bool Topleve
 // If this is a toplevel declaration, create a scope for the
 // initializer.
 if (Toplevel) {
-  ExprScope Scope(this);
+  LocalScope Scope(this);
   if (!this->visit(Init))
 return false;
-  return this->emitSetLocal(*VarT, Offset, VD);
+  return this->emitSetLocal(*VarT, Offset, VD) && 
Scope.destroyLocals();
 } else {
   if (!this->visit(Init))
 return false;
@@ -4120,7 +4120,7 @@ bool Compiler::visitReturnStmt(const ReturnStmt 
*RS) {
 return this->emitUnsupported(RS);
 
   if (const Expr *RE = RS->getRetValue()) {
-ExprScope RetScope(this);
+LocalScope RetScope(this);
 if (ReturnType) {
   // Primitive types are simply returned.
   if (!this->visit(RE))

diff  --git a/clang/lib/AST/Interp/Compiler.h b/clang/lib/AST/Interp/Compiler.h
index fbeda8a0b7a4f..246ff25347067 100644
--- a/clang/lib/AST/Interp/Compiler.h
+++ b/clang/lib/AST/Interp/Compiler.h
@@ -612,11 +612,6 @@ template  class BlockScope final : public 
AutoScope {
   }
 };
 
-template  class ExprScope final : public AutoScope {
-public:
-  ExprScope(Compiler *Ctx) : AutoScope(Ctx) {}
-};
-
 template  class ArrayIndexScope final {
 public:
   ArrayIndexScope(Compiler *Ctx, uint64_t Index) : Ctx(Ctx) {



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


[clang] f6712d2 - [clang][Interp][NFC] Get rid of AutoScope

2024-07-09 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-09T11:52:41+02:00
New Revision: f6712d27874004835170e6eb8ff5f348a8866057

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

LOG: [clang][Interp][NFC] Get rid of AutoScope

Added: 


Modified: 
clang/lib/AST/Interp/Compiler.cpp
clang/lib/AST/Interp/Compiler.h

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index 5fad24a0930ac..48e7519f8f89d 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -1794,6 +1794,8 @@ bool Compiler::VisitArrayInitLoopExpr(const 
ArrayInitLoopExpr *E) {
 
 if (!this->visitArrayElemInit(I, SubExpr))
   return false;
+if (!BS.destroyLocals())
+  return false;
   }
   return true;
 }
@@ -3080,7 +3082,7 @@ bool Compiler::VisitStmtExpr(const StmtExpr *E) {
 return false;
   }
 
-  return true;
+  return BS.destroyLocals();
 }
 
 template  bool Compiler::discard(const Expr *E) {
@@ -4190,7 +4192,7 @@ template  bool 
Compiler::visitIfStmt(const IfStmt *IS) {
 this->emitLabel(LabelEnd);
   }
 
-  return true;
+  return IfScope.destroyLocals();
 }
 
 template 
@@ -4656,6 +4658,9 @@ bool Compiler::visitFunc(const FunctionDecl *F) {
 if (!this->emitPopPtr(InitExpr))
   return false;
   }
+
+  if (!Scope.destroyLocals())
+return false;
 }
   }
 

diff  --git a/clang/lib/AST/Interp/Compiler.h b/clang/lib/AST/Interp/Compiler.h
index 246ff25347067..de873c7e6825f 100644
--- a/clang/lib/AST/Interp/Compiler.h
+++ b/clang/lib/AST/Interp/Compiler.h
@@ -589,20 +589,10 @@ template  class DestructorScope final {
   LocalScope 
 };
 
-/// Like a regular LocalScope, except that the destructors of all local
-/// variables are automatically emitted when the AutoScope is destroyed.
-template  class AutoScope : public LocalScope {
-public:
-  AutoScope(Compiler *Ctx) : LocalScope(Ctx), DS(*this) {}
-
-private:
-  DestructorScope DS;
-};
-
 /// Scope for storage declared in a compound statement.
-template  class BlockScope final : public AutoScope {
+template  class BlockScope final : public LocalScope {
 public:
-  BlockScope(Compiler *Ctx) : AutoScope(Ctx) {}
+  BlockScope(Compiler *Ctx) : LocalScope(Ctx) {}
 
   void addExtended(const Scope::Local ) override {
 // If we to this point, just add the variable as a normal local



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


[clang] dd2bf3b - [clang][Interp] Redo variable (re)visiting

2024-07-09 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-09T10:43:35+02:00
New Revision: dd2bf3b840df260d794e37cc96d4498372aa08f6

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

LOG: [clang][Interp] Redo variable (re)visiting

Depending on the circumstances we visit variables in, we need to
be careful about when to destroy their temporaries and whether to
emit a Ret op at all or not.

Added: 


Modified: 
clang/lib/AST/Interp/ByteCodeEmitter.h
clang/lib/AST/Interp/Compiler.cpp
clang/lib/AST/Interp/Compiler.h
clang/lib/AST/Interp/EvalEmitter.cpp
clang/lib/AST/Interp/EvalEmitter.h
clang/test/C/C23/n3017.c
clang/test/CodeGenCXX/no-const-init-cxx2a.cpp
clang/test/SemaCXX/warn-unused-variables.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/ByteCodeEmitter.h 
b/clang/lib/AST/Interp/ByteCodeEmitter.h
index 9a329e969f339..a19a25c2f9e8e 100644
--- a/clang/lib/AST/Interp/ByteCodeEmitter.h
+++ b/clang/lib/AST/Interp/ByteCodeEmitter.h
@@ -46,7 +46,7 @@ class ByteCodeEmitter {
   /// Methods implemented by the compiler.
   virtual bool visitFunc(const FunctionDecl *E) = 0;
   virtual bool visitExpr(const Expr *E) = 0;
-  virtual bool visitDecl(const VarDecl *E, bool ConstantContext) = 0;
+  virtual bool visitDeclAndReturn(const VarDecl *E, bool ConstantContext) = 0;
 
   /// Emits jumps.
   bool jumpTrue(const LabelTy );

diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index 613bf4af137b6..1d39d7bb9e15f 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -25,10 +25,10 @@ namespace clang {
 namespace interp {
 
 /// Scope used to handle temporaries in toplevel variable declarations.
-template  class DeclScope final : public VariableScope 
{
+template  class DeclScope final : public LocalScope {
 public:
   DeclScope(Compiler *Ctx, const ValueDecl *VD)
-  : VariableScope(Ctx, nullptr), Scope(Ctx->P, VD),
+  : LocalScope(Ctx, VD), Scope(Ctx->P, VD),
 OldGlobalDecl(Ctx->GlobalDecl),
 OldInitializingDecl(Ctx->InitializingDecl) {
 Ctx->GlobalDecl = Context::shouldBeGloballyIndexed(VD);
@@ -3462,40 +3462,52 @@ template  bool 
Compiler::visitExpr(const Expr *E) {
   return false;
 }
 
-/// Toplevel visitDecl().
+template 
+VarCreationState Compiler::visitDecl(const VarDecl *VD) {
+
+  auto R = this->visitVarDecl(VD, /*Toplevel=*/true);
+
+  if (R.notCreated())
+return R;
+
+  if (R)
+return true;
+
+  if (!R && Context::shouldBeGloballyIndexed(VD)) {
+if (auto GlobalIndex = P.getGlobal(VD)) {
+  Block *GlobalBlock = P.getGlobal(*GlobalIndex);
+  GlobalInlineDescriptor  =
+  *reinterpret_cast(GlobalBlock->rawData());
+
+  GD.InitState = GlobalInitState::InitializerFailed;
+  GlobalBlock->invokeDtor();
+}
+  }
+
+  return R;
+}
+
+/// Toplevel visitDeclAndReturn().
 /// We get here from evaluateAsInitializer().
 /// We need to evaluate the initializer and return its value.
 template 
-bool Compiler::visitDecl(const VarDecl *VD, bool ConstantContext) {
-  assert(!VD->isInvalidDecl() && "Trying to constant evaluate an invalid 
decl");
-
+bool Compiler::visitDeclAndReturn(const VarDecl *VD,
+   bool ConstantContext) {
   std::optional VarT = classify(VD->getType());
 
   // We only create variables if we're evaluating in a constant context.
   // Otherwise, just evaluate the initializer and return it.
   if (!ConstantContext) {
-DeclScope LocalScope(this, VD);
+DeclScope LS(this, VD);
 if (!this->visit(VD->getAnyInitializer()))
   return false;
-return this->emitRet(VarT.value_or(PT_Ptr), VD);
-  }
-
-  // If we've seen the global variable already and the initializer failed,
-  // just return false immediately.
-  if (std::optional Index = P.getGlobal(VD)) {
-const Pointer  = P.getPtrGlobal(*Index);
-const GlobalInlineDescriptor  =
-*reinterpret_cast(
-Ptr.block()->rawData());
-if (GD.InitState == GlobalInitState::InitializerFailed)
-  return false;
+return this->emitRet(VarT.value_or(PT_Ptr), VD) && LS.destroyLocals();
   }
 
-  // Create and initialize the variable.
+  LocalScope VDScope(this, VD);
   if (!this->visitVarDecl(VD, /*Toplevel=*/true))
 return false;
 
-  // Get a pointer to the variable
   if (Context::shouldBeGloballyIndexed(VD)) {
 auto GlobalIndex = P.getGlobal(VD);
 assert(GlobalIndex); // visitVarDecl() didn't return false.
@@ -3535,7 +3547,7 @@ bool Compiler::visitDecl(const VarDecl *VD, bool 
ConstantContext) {
 return false;
   }
 
-  return true;
+  return VDScope.destroyLocals();
 }
 
 template 
@@ -3589,26 +3601,34 @@ VarCreationState Compiler::visitVarDecl(const 
VarDecl *VD, bool Topleve
 
 return !Init 

[clang] ad82d1c - [clang][Interp][NFC] Move a lambda declaration into its closest scope

2024-07-09 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-09T10:12:53+02:00
New Revision: ad82d1c53f089937c05af11ff45798ceb5ca894e

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

LOG: [clang][Interp][NFC] Move a lambda declaration into its closest scope

Added: 


Modified: 
clang/lib/AST/Interp/Compiler.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index 3d9a0358c5487..613bf4af137b6 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -3552,12 +3552,12 @@ VarCreationState Compiler::visitVarDecl(const 
VarDecl *VD, bool Topleve
   const Expr *Init = VD->getInit();
   std::optional VarT = classify(VD->getType());
 
-  auto checkDecl = [&]() -> bool {
-bool NeedsOp = !Toplevel && VD->isLocalVarDecl() && VD->isStaticLocal();
-return !NeedsOp || this->emitCheckDecl(VD, VD);
-  };
-
   if (Context::shouldBeGloballyIndexed(VD)) {
+auto checkDecl = [&]() -> bool {
+  bool NeedsOp = !Toplevel && VD->isLocalVarDecl() && VD->isStaticLocal();
+  return !NeedsOp || this->emitCheckDecl(VD, VD);
+};
+
 auto initGlobal = [&](unsigned GlobalIndex) -> bool {
   assert(Init);
   DeclScope LocalScope(this, VD);



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


[clang] 4f68d20 - [clang][Interp][NFC] Simplify Pointer Block accessing code

2024-07-09 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-09T10:12:53+02:00
New Revision: 4f68d20d87b5a4c06c4ec954c93069cebeb6dfee

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

LOG: [clang][Interp][NFC] Simplify Pointer Block accessing code

Try to get PointeeStorage.BS.Pointee only once and reuse that.

Added: 


Modified: 
clang/lib/AST/Interp/Pointer.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Pointer.cpp 
b/clang/lib/AST/Interp/Pointer.cpp
index 157892ea492f6..b2e3a7ff70881 100644
--- a/clang/lib/AST/Interp/Pointer.cpp
+++ b/clang/lib/AST/Interp/Pointer.cpp
@@ -57,9 +57,9 @@ Pointer::~Pointer() {
   if (isIntegralPointer())
 return;
 
-  if (PointeeStorage.BS.Pointee) {
-PointeeStorage.BS.Pointee->removePointer(this);
-PointeeStorage.BS.Pointee->cleanup();
+  if (Block *Pointee = PointeeStorage.BS.Pointee) {
+Pointee->removePointer(this);
+Pointee->cleanup();
   }
 }
 
@@ -188,6 +188,7 @@ APValue Pointer::toAPValue() const {
 void Pointer::print(llvm::raw_ostream ) const {
   OS << PointeeStorage.BS.Pointee << " (";
   if (isBlockPointer()) {
+const Block *B = PointeeStorage.BS.Pointee;
 OS << "Block) {";
 
 if (isRoot())
@@ -200,8 +201,8 @@ void Pointer::print(llvm::raw_ostream ) const {
 else
   OS << Offset << ", ";
 
-if (PointeeStorage.BS.Pointee)
-  OS << PointeeStorage.BS.Pointee->getSize();
+if (B)
+  OS << B->getSize();
 else
   OS << "nullptr";
   } else {



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


[clang] efc5a6a - [clang][Interp][NFC] Print Block descriptor in ::dump()

2024-07-09 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-09T09:59:52+02:00
New Revision: efc5a6aa82081aaa002f90baa21fc16655af0729

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

LOG: [clang][Interp][NFC] Print Block descriptor in ::dump()

Added: 


Modified: 
clang/lib/AST/Interp/Disasm.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Disasm.cpp b/clang/lib/AST/Interp/Disasm.cpp
index d946a10c22dc3..c6c6275593007 100644
--- a/clang/lib/AST/Interp/Disasm.cpp
+++ b/clang/lib/AST/Interp/Disasm.cpp
@@ -325,8 +325,11 @@ LLVM_DUMP_METHOD void Record::dump(llvm::raw_ostream , 
unsigned Indentation,
 LLVM_DUMP_METHOD void Block::dump(llvm::raw_ostream ) const {
   {
 ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_BLUE, true});
-OS << "Block " << (const void *)this << "\n";
+OS << "Block " << (const void *)this;
   }
+  OS << " (";
+  Desc->dump(OS);
+  OS << ")\n";
   unsigned NPointers = 0;
   for (const Pointer *P = Pointers; P; P = P->Next) {
 ++NPointers;



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


[clang] 3655de7 - [clang][Interp] Avoid a dangling pointer

2024-07-09 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-09T09:59:51+02:00
New Revision: 3655de73809b0f8f100040c4b9c9ad889dca2225

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

LOG: [clang][Interp] Avoid a dangling pointer

We've just moved all the pointers from the Block to the DeadBlock,
so make sure the old Block doesn't point to a linked list of Pointers
that don't even point to it anymore.

Added: 


Modified: 
clang/lib/AST/Interp/InterpBlock.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/InterpBlock.cpp 
b/clang/lib/AST/Interp/InterpBlock.cpp
index c34ea7634b4a9..7bef5e678c074 100644
--- a/clang/lib/AST/Interp/InterpBlock.cpp
+++ b/clang/lib/AST/Interp/InterpBlock.cpp
@@ -106,6 +106,7 @@ DeadBlock::DeadBlock(DeadBlock *, Block *Blk)
   B.Pointers = Blk->Pointers;
   for (Pointer *P = Blk->Pointers; P; P = P->Next)
 P->PointeeStorage.BS.Pointee = 
+  Blk->Pointers = nullptr;
 }
 
 void DeadBlock::free() {



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


[clang] 93869df - [clang][Interp][NFC] Simplify a test case

2024-07-09 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-09T09:23:14+02:00
New Revision: 93869dfd89387844bf8b605ebcd1abc0cc81bde8

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

LOG: [clang][Interp][NFC] Simplify a test case

Added: 


Modified: 
clang/test/AST/Interp/lifetimes.cpp

Removed: 




diff  --git a/clang/test/AST/Interp/lifetimes.cpp 
b/clang/test/AST/Interp/lifetimes.cpp
index c1046e5689207..c544baba6178c 100644
--- a/clang/test/AST/Interp/lifetimes.cpp
+++ b/clang/test/AST/Interp/lifetimes.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify %s
-// RUN: %clang_cc1 -verify=ref %s
+// RUN: %clang_cc1 -fexperimental-new-constant-interpreter 
-verify=expected,both %s
+// RUN: %clang_cc1 -verify=ref,both %s
 
 struct Foo {
   int a;
@@ -16,9 +16,7 @@ constexpr int dead1() { // expected-error {{never produces a 
constant expression
   return F2->a; // expected-note 2{{read of variable whose lifetime has 
ended}} \
 // ref-note {{read of object outside its lifetime is not 
allowed in a constant expression}}
 }
-static_assert(dead1() == 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}} \
+static_assert(dead1() == 1, ""); // both-error {{not an integral constant 
expression}} \
+ // both-note {{in call to}}
 
 



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


[clang] eee9efb - [clang][Interp][NFC] Add empty initializer list to test decl

2024-07-09 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-09T09:23:14+02:00
New Revision: eee9efb09c1a3cbbb1ad5471713f3da218c8b00e

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

LOG: [clang][Interp][NFC] Add empty initializer list to test decl

This was missing in the test.

Added: 


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

Removed: 




diff  --git a/clang/test/AST/Interp/records.cpp 
b/clang/test/AST/Interp/records.cpp
index f27c895e89948..adc3799a20ce4 100644
--- a/clang/test/AST/Interp/records.cpp
+++ b/clang/test/AST/Interp/records.cpp
@@ -495,7 +495,7 @@ namespace DeclRefs {
   static_assert(b.a.m == 100, "");
   static_assert(b.a.f == 100, "");
 
-  constexpr B b2;
+  constexpr B b2{};
   static_assert(b2.a.m == 100, "");
   static_assert(b2.a.f == 100, "");
   static_assert(b2.a.f == 101, ""); // both-error {{failed}} \



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


[clang] 00c622e - [clang][Interp][Test] Add test for #97302

2024-07-05 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-05T12:44:32+02:00
New Revision: 00c622e596f918d9d83674b58097c8982ae1af95

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

LOG: [clang][Interp][Test] Add test for #97302

Fixes #97302

Added: 


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

Removed: 




diff  --git a/clang/test/AST/Interp/records.cpp 
b/clang/test/AST/Interp/records.cpp
index 1554e54275598a..f27c895e899486 100644
--- a/clang/test/AST/Interp/records.cpp
+++ b/clang/test/AST/Interp/records.cpp
@@ -494,6 +494,12 @@ namespace DeclRefs {
   constexpr B b;
   static_assert(b.a.m == 100, "");
   static_assert(b.a.f == 100, "");
+
+  constexpr B b2;
+  static_assert(b2.a.m == 100, "");
+  static_assert(b2.a.f == 100, "");
+  static_assert(b2.a.f == 101, ""); // both-error {{failed}} \
+// both-note {{evaluates to '100 == 101'}}
 }
 
 namespace PointerArith {



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


[clang] 2f0700a - [clang][Interp] Add a missing template keyword

2024-07-05 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-05T12:28:17+02:00
New Revision: 2f0700a84311d1a8b0fc12499fe9480ccbd188e9

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

LOG: [clang][Interp] Add a missing template keyword

This broke a buildbot:
https://lab.llvm.org/buildbot/#/builders/190/builds/1326

Added: 


Modified: 
clang/lib/AST/Interp/Compiler.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index 2ada68f6bc756..3d9a0358c5487 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -3995,7 +3995,7 @@ bool Compiler::VisitCXXThisExpr(const 
CXXThisExpr *E) {
 }
 
 for (unsigned I = StartIndex, N = InitStack.size(); I != N; ++I) {
-  if (!InitStack[I].emit(this, E))
+  if (!InitStack[I].template emit(this, E))
 return false;
 }
 return true;



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


[clang] f926e19 - Reapply "[clang][Interp] Fix init chain in local initializers"

2024-07-05 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-05T12:16:18+02:00
New Revision: f926e19aa9c0bdca3f05322e1b62562a9a3a05e2

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

LOG: Reapply "[clang][Interp] Fix init chain in local initializers"

This reverts commit 2dda8a2650927e4b0fbb459507684455e196d9a9.

Added: 


Modified: 
clang/lib/AST/Interp/Compiler.cpp
clang/lib/AST/Interp/Compiler.h
clang/lib/AST/Interp/EvalEmitter.cpp
clang/lib/AST/Interp/Pointer.h
clang/test/AST/Interp/records.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index 2fd20d8022126..2ada68f6bc756 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -85,8 +85,12 @@ bool InitLink::emit(Compiler *Ctx, const Expr *E) 
const {
   case K_Field:
 // We're assuming there's a base pointer on the stack already.
 return Ctx->emitGetPtrFieldPop(Offset, E);
+  case K_Temp:
+return Ctx->emitGetPtrLocal(Offset, E);
   case K_Decl:
 return Ctx->visitDeclRef(D, E);
+  default:
+llvm_unreachable("Unhandled InitLink kind");
   }
   return true;
 }
@@ -1330,6 +1334,7 @@ bool Compiler::visitInitList(ArrayRef Inits,
 
 auto initCompositeField = [=](const Record::Field *FieldToInit,
   const Expr *Init) -> bool {
+  InitLinkScope ILS(this, InitLink::Field(FieldToInit->Offset));
   // Non-primitive case. Get a pointer to the field-to-initialize
   // on the stack and recurse into visitInitializer().
   if (!this->emitGetPtrField(FieldToInit->Offset, Init))
@@ -2271,6 +2276,7 @@ bool Compiler::VisitMaterializeTemporaryExpr(
 const Expr *Inner = E->getSubExpr()->skipRValueSubobjectAdjustments();
 if (std::optional LocalIndex =
 allocateLocal(Inner, E->getExtendingDecl())) {
+  InitLinkScope ILS(this, InitLink::Temp(*LocalIndex));
   if (!this->emitGetPtrLocal(*LocalIndex, E))
 return false;
   return this->visitInitializer(SubExpr);
@@ -2449,6 +2455,7 @@ bool Compiler::VisitCXXConstructExpr(const 
CXXConstructExpr *E) {
 
 // Trivial copy/move constructor. Avoid copy.
 if (Ctor->isDefaulted() && Ctor->isCopyOrMoveConstructor() &&
+Ctor->isTrivial() &&
 E->getArg(0)->isTemporaryObject(Ctx.getASTContext(),
 T->getAsCXXRecordDecl()))
   return this->visitInitializer(E->getArg(0));
@@ -3583,6 +3590,7 @@ VarCreationState Compiler::visitVarDecl(const 
VarDecl *VD, bool Topleve
 return !Init || (checkDecl() && initGlobal(*GlobalIndex));
   } else {
 VariableScope LocalScope(this, VD);
+InitLinkScope ILS(this, InitLink::Decl(VD));
 
 if (VarT) {
   unsigned Offset = this->allocateLocalPrimitive(
@@ -3917,7 +3925,8 @@ bool Compiler::VisitCXXDefaultInitExpr(const 
CXXDefaultInitExpr *E) {
   SourceLocScope SLS(this, E);
 
   bool Old = InitStackActive;
-  InitStackActive = !isa(E->getUsedContext());
+  InitStackActive =
+  !(E->getUsedContext()->getDeclKind() == Decl::CXXConstructor);
   bool Result = this->delegate(E->getExpr());
   InitStackActive = Old;
   return Result;
@@ -3979,8 +3988,14 @@ bool Compiler::VisitCXXThisExpr(const 
CXXThisExpr *E) {
   // currently being initialized. Here we emit the necessary instruction(s) for
   // this scenario.
   if (InitStackActive && !InitStack.empty()) {
-for (const InitLink  : InitStack) {
-  if (!IL.emit(this, E))
+unsigned StartIndex = 0;
+for (StartIndex = InitStack.size() - 1; StartIndex > 0; --StartIndex) {
+  if (InitStack[StartIndex].Kind != InitLink::K_Field)
+break;
+}
+
+for (unsigned I = StartIndex, N = InitStack.size(); I != N; ++I) {
+  if (!InitStack[I].emit(this, E))
 return false;
 }
 return true;

diff  --git a/clang/lib/AST/Interp/Compiler.h b/clang/lib/AST/Interp/Compiler.h
index d28526c76fe13..1405abfc1a1e2 100644
--- a/clang/lib/AST/Interp/Compiler.h
+++ b/clang/lib/AST/Interp/Compiler.h
@@ -47,7 +47,8 @@ struct InitLink {
   enum {
 K_This = 0,
 K_Field = 1,
-K_Decl = 2,
+K_Temp = 2,
+K_Decl = 3,
   };
 
   static InitLink This() { return InitLink{K_This}; }
@@ -56,6 +57,11 @@ struct InitLink {
 IL.Offset = Offset;
 return IL;
   }
+  static InitLink Temp(unsigned Offset) {
+InitLink IL{K_Temp};
+IL.Offset = Offset;
+return IL;
+  }
   static InitLink Decl(const ValueDecl *D) {
 InitLink IL{K_Decl};
 IL.D = D;
@@ -66,7 +72,6 @@ struct InitLink {
   template 
   bool emit(Compiler *Ctx, const Expr *E) const;
 
-private:
   uint32_t Kind;
   union {
 unsigned Offset;

diff  --git a/clang/lib/AST/Interp/EvalEmitter.cpp 
b/clang/lib/AST/Interp/EvalEmitter.cpp
index 

[clang] 6fbd26b - [clang][Interp] Add QualType parameter to Pointer::toRValue

2024-07-05 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-05T11:58:04+02:00
New Revision: 6fbd26b147ab93da4d0689ea2f6ff73cc9859cb8

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

LOG: [clang][Interp] Add QualType parameter to Pointer::toRValue

This fixes the crash from #97302, but exposes an underlying problem.

Added: 


Modified: 
clang/lib/AST/Interp/EvalEmitter.cpp
clang/lib/AST/Interp/EvaluationResult.cpp
clang/lib/AST/Interp/EvaluationResult.h
clang/lib/AST/Interp/Interp.h
clang/lib/AST/Interp/Pointer.cpp
clang/lib/AST/Interp/Pointer.h

Removed: 




diff  --git a/clang/lib/AST/Interp/EvalEmitter.cpp 
b/clang/lib/AST/Interp/EvalEmitter.cpp
index d17151416b44b..5d20a0b8182a9 100644
--- a/clang/lib/AST/Interp/EvalEmitter.cpp
+++ b/clang/lib/AST/Interp/EvalEmitter.cpp
@@ -156,7 +156,8 @@ template <> bool EvalEmitter::emitRet(const 
SourceInfo ) {
 if (!Ptr.isConst() && Ptr.block()->getEvalID() != Ctx.getEvalID())
   return false;
 
-if (std::optional V = Ptr.toRValue(Ctx)) {
+if (std::optional V =
+Ptr.toRValue(Ctx, EvalResult.getSourceType())) {
   EvalResult.setValue(*V);
 } else {
   return false;
@@ -186,7 +187,8 @@ bool EvalEmitter::emitRetValue(const SourceInfo ) {
   if (CheckFullyInitialized && !EvalResult.checkFullyInitialized(S, Ptr))
 return false;
 
-  if (std::optional APV = Ptr.toRValue(S.getCtx())) {
+  if (std::optional APV =
+  Ptr.toRValue(S.getCtx(), EvalResult.getSourceType())) {
 EvalResult.setValue(*APV);
 return true;
   }
@@ -257,7 +259,8 @@ void EvalEmitter::updateGlobalTemporaries() {
   if (std::optional T = Ctx.classify(E->getType())) {
 TYPE_SWITCH(*T, { *Cached = Ptr.deref().toAPValue(); });
   } else {
-if (std::optional APV = Ptr.toRValue(Ctx))
+if (std::optional APV =
+Ptr.toRValue(Ctx, Temp->getTemporaryExpr()->getType()))
   *Cached = *APV;
   }
 }

diff  --git a/clang/lib/AST/Interp/EvaluationResult.cpp 
b/clang/lib/AST/Interp/EvaluationResult.cpp
index a62f3f635e6e0..d0d68f75dd803 100644
--- a/clang/lib/AST/Interp/EvaluationResult.cpp
+++ b/clang/lib/AST/Interp/EvaluationResult.cpp
@@ -43,7 +43,7 @@ std::optional EvaluationResult::toRValue() const {
 
   // We have a pointer and want an RValue.
   if (const auto *P = std::get_if())
-return P->toRValue(*Ctx);
+return P->toRValue(*Ctx, getSourceType());
   else if (const auto *FP = std::get_if()) // Nope
 return FP->toAPValue();
   llvm_unreachable("Unhandled lvalue kind");

diff  --git a/clang/lib/AST/Interp/EvaluationResult.h 
b/clang/lib/AST/Interp/EvaluationResult.h
index ecf2250074cc9..378f1ccdb0af4 100644
--- a/clang/lib/AST/Interp/EvaluationResult.h
+++ b/clang/lib/AST/Interp/EvaluationResult.h
@@ -100,6 +100,15 @@ class EvaluationResult final {
 
   bool checkFullyInitialized(InterpState , const Pointer ) const;
 
+  QualType getSourceType() const {
+if (const auto *D =
+dyn_cast_if_present(Source.dyn_cast()))
+  return D->getType();
+else if (const auto *E = Source.dyn_cast())
+  return E->getType();
+return QualType();
+  }
+
   /// Dump to stderr.
   void dump() const;
 

diff  --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 5d8362b4fa881..12143fbf50808 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -1309,7 +1309,8 @@ inline bool InitGlobalTempComp(InterpState , CodePtr 
OpPC,
   S.SeenGlobalTemporaries.push_back(
   std::make_pair(P.getDeclDesc()->asExpr(), Temp));
 
-  if (std::optional APV = P.toRValue(S.getCtx())) {
+  if (std::optional APV =
+  P.toRValue(S.getCtx(), Temp->getTemporaryExpr()->getType())) {
 *Cached = *APV;
 return true;
   }

diff  --git a/clang/lib/AST/Interp/Pointer.cpp 
b/clang/lib/AST/Interp/Pointer.cpp
index d6603f91fb127..157892ea492f6 100644
--- a/clang/lib/AST/Interp/Pointer.cpp
+++ b/clang/lib/AST/Interp/Pointer.cpp
@@ -340,7 +340,9 @@ bool Pointer::hasSameArray(const Pointer , const Pointer 
) {
  A.getFieldDesc()->IsArray;
 }
 
-std::optional Pointer::toRValue(const Context ) const {
+std::optional Pointer::toRValue(const Context ,
+ QualType ResultType) const {
+  assert(!ResultType.isNull());
   // Method to recursively traverse composites.
   std::function Composite;
   Composite = [, ](QualType Ty, const Pointer , APValue ) {
@@ -483,13 +485,19 @@ std::optional Pointer::toRValue(const Context 
) const {
 llvm_unreachable("invalid value to return");
   };
 
-  if (isZero())
-return APValue(static_cast(nullptr), CharUnits::Zero(), {}, false,
-   true);
-
-  if (isDummy() || !isLive())
+  // Invalid to read from.
+  if (isDummy() 

[clang] fbd7360 - [clang][Interp] Short-cirtuit Move/Copy constructors if we can

2024-07-05 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-05T11:29:32+02:00
New Revision: fbd736062e043d34cddd6031b4ee93954d4bf199

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

LOG: [clang][Interp] Short-cirtuit Move/Copy constructors if we can

Added: 


Modified: 
clang/lib/AST/Interp/Compiler.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index 775cabf7f8c59..2fd20d8022126 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -2447,6 +2447,12 @@ bool Compiler::VisitCXXConstructExpr(const 
CXXConstructExpr *E) {
   if (T->isRecordType()) {
 const CXXConstructorDecl *Ctor = E->getConstructor();
 
+// Trivial copy/move constructor. Avoid copy.
+if (Ctor->isDefaulted() && Ctor->isCopyOrMoveConstructor() &&
+E->getArg(0)->isTemporaryObject(Ctx.getASTContext(),
+T->getAsCXXRecordDecl()))
+  return this->visitInitializer(E->getArg(0));
+
 // If we're discarding a construct expression, we still need
 // to allocate a variable and call the constructor and destructor.
 if (DiscardResult) {



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


[clang] 2dda8a2 - Revert "[clang][Interp] Fix init chain in local initializers"

2024-07-04 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-04T08:50:14+02:00
New Revision: 2dda8a2650927e4b0fbb459507684455e196d9a9

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

LOG: Revert "[clang][Interp] Fix init chain in local initializers"

This reverts commit 86187ed2998e43be62176c2c4a7b204cc52f6ce6.

Seems like this breaks buildbots:
https://lab.llvm.org/buildbot/#/builders/56/builds/1638

Added: 


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

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index 2af4c38c5ac3d..775cabf7f8c59 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -3577,7 +3577,6 @@ VarCreationState Compiler::visitVarDecl(const 
VarDecl *VD, bool Topleve
 return !Init || (checkDecl() && initGlobal(*GlobalIndex));
   } else {
 VariableScope LocalScope(this, VD);
-InitLinkScope ILS(this, InitLink::Decl(VD));
 
 if (VarT) {
   unsigned Offset = this->allocateLocalPrimitive(
@@ -3912,8 +3911,7 @@ bool Compiler::VisitCXXDefaultInitExpr(const 
CXXDefaultInitExpr *E) {
   SourceLocScope SLS(this, E);
 
   bool Old = InitStackActive;
-  InitStackActive =
-  !(E->getUsedContext()->getDeclKind() == Decl::CXXConstructor);
+  InitStackActive = !isa(E->getUsedContext());
   bool Result = this->delegate(E->getExpr());
   InitStackActive = Old;
   return Result;

diff  --git a/clang/test/AST/Interp/records.cpp 
b/clang/test/AST/Interp/records.cpp
index 1554e54275598..9f341f5bc6d1d 100644
--- a/clang/test/AST/Interp/records.cpp
+++ b/clang/test/AST/Interp/records.cpp
@@ -1482,15 +1482,3 @@ namespace FloatAPValue {
   ClassTemplateArgRefTemplate ClassTemplateArgRefObj;
 }
 #endif
-
-namespace LocalWithThisPtrInit {
-  struct S {
-int i;
-int *p = 
-  };
-  constexpr int foo() {
-S s{2};
-return *s.p;
-  }
-  static_assert(foo() == 2, "");
-}



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


[clang] 86187ed - [clang][Interp] Fix init chain in local initializers

2024-07-04 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-04T08:41:09+02:00
New Revision: 86187ed2998e43be62176c2c4a7b204cc52f6ce6

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

LOG: [clang][Interp] Fix init chain in local initializers

Added: 


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

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index 775cabf7f8c59..2af4c38c5ac3d 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -3577,6 +3577,7 @@ VarCreationState Compiler::visitVarDecl(const 
VarDecl *VD, bool Topleve
 return !Init || (checkDecl() && initGlobal(*GlobalIndex));
   } else {
 VariableScope LocalScope(this, VD);
+InitLinkScope ILS(this, InitLink::Decl(VD));
 
 if (VarT) {
   unsigned Offset = this->allocateLocalPrimitive(
@@ -3911,7 +3912,8 @@ bool Compiler::VisitCXXDefaultInitExpr(const 
CXXDefaultInitExpr *E) {
   SourceLocScope SLS(this, E);
 
   bool Old = InitStackActive;
-  InitStackActive = !isa(E->getUsedContext());
+  InitStackActive =
+  !(E->getUsedContext()->getDeclKind() == Decl::CXXConstructor);
   bool Result = this->delegate(E->getExpr());
   InitStackActive = Old;
   return Result;

diff  --git a/clang/test/AST/Interp/records.cpp 
b/clang/test/AST/Interp/records.cpp
index 9f341f5bc6d1d..1554e54275598 100644
--- a/clang/test/AST/Interp/records.cpp
+++ b/clang/test/AST/Interp/records.cpp
@@ -1482,3 +1482,15 @@ namespace FloatAPValue {
   ClassTemplateArgRefTemplate ClassTemplateArgRefObj;
 }
 #endif
+
+namespace LocalWithThisPtrInit {
+  struct S {
+int i;
+int *p = 
+  };
+  constexpr int foo() {
+S s{2};
+return *s.p;
+  }
+  static_assert(foo() == 2, "");
+}



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


[clang] 54aa1d2 - [clang][Interp] Fix initializing atomic record types

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

Author: Timm Bäder
Date: 2024-07-03T16:38:09+02:00
New Revision: 54aa1d28b6a26b4980df4d5448fb64d19dc1a100

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

LOG: [clang][Interp] Fix initializing atomic record types

Remove the atomic type when visiting InitListExprs.

Added: 


Modified: 
clang/lib/AST/Interp/Compiler.cpp
clang/test/CodeGenCXX/atomicinit.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index 9ca71e0496989..775cabf7f8c59 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -1285,7 +1285,13 @@ bool Compiler::VisitArraySubscriptExpr(const 
ArraySubscriptExpr *E) {
 template 
 bool Compiler::visitInitList(ArrayRef Inits,
   const Expr *ArrayFiller, const Expr *E) {
-  if (E->getType()->isVoidType())
+
+  QualType QT = E->getType();
+
+  if (const auto *AT = QT->getAs())
+QT = AT->getValueType();
+
+  if (QT->isVoidType())
 return this->emitInvalid(E);
 
   // Handle discarding first.
@@ -1298,17 +1304,16 @@ bool Compiler::visitInitList(ArrayRef Inits,
   }
 
   // Primitive values.
-  if (std::optional T = classify(E->getType())) {
+  if (std::optional T = classify(QT)) {
 assert(!DiscardResult);
 if (Inits.size() == 0)
-  return this->visitZeroInitializer(*T, E->getType(), E);
+  return this->visitZeroInitializer(*T, QT, E);
 assert(Inits.size() == 1);
 return this->delegate(Inits[0]);
   }
 
-  QualType T = E->getType();
-  if (T->isRecordType()) {
-const Record *R = getRecord(E->getType());
+  if (QT->isRecordType()) {
+const Record *R = getRecord(QT);
 
 if (Inits.size() == 1 && E->getType() == Inits[0]->getType())
   return this->delegate(Inits[0]);
@@ -1405,8 +1410,8 @@ bool Compiler::visitInitList(ArrayRef Inits,
 return this->emitFinishInit(E);
   }
 
-  if (T->isArrayType()) {
-if (Inits.size() == 1 && E->getType() == Inits[0]->getType())
+  if (QT->isArrayType()) {
+if (Inits.size() == 1 && QT == Inits[0]->getType())
   return this->delegate(Inits[0]);
 
 unsigned ElementIndex = 0;
@@ -1438,7 +1443,7 @@ bool Compiler::visitInitList(ArrayRef Inits,
 // FIXME: This should go away.
 if (ArrayFiller) {
   const ConstantArrayType *CAT =
-  Ctx.getASTContext().getAsConstantArrayType(E->getType());
+  Ctx.getASTContext().getAsConstantArrayType(QT);
   uint64_t NumElems = CAT->getZExtSize();
 
   for (; ElementIndex != NumElems; ++ElementIndex) {
@@ -1450,7 +1455,7 @@ bool Compiler::visitInitList(ArrayRef Inits,
 return this->emitFinishInit(E);
   }
 
-  if (const auto *ComplexTy = E->getType()->getAs()) {
+  if (const auto *ComplexTy = QT->getAs()) {
 unsigned NumInits = Inits.size();
 
 if (NumInits == 1)
@@ -1480,7 +1485,7 @@ bool Compiler::visitInitList(ArrayRef Inits,
 return true;
   }
 
-  if (const auto *VecT = E->getType()->getAs()) {
+  if (const auto *VecT = QT->getAs()) {
 unsigned NumVecElements = VecT->getNumElements();
 assert(NumVecElements >= Inits.size());
 

diff  --git a/clang/test/CodeGenCXX/atomicinit.cpp 
b/clang/test/CodeGenCXX/atomicinit.cpp
index a568f17b90d0c..b507a22e84bc1 100644
--- a/clang/test/CodeGenCXX/atomicinit.cpp
+++ b/clang/test/CodeGenCXX/atomicinit.cpp
@@ -1,4 +1,5 @@
 // RUN: %clang_cc1 -fno-inline-functions %s -emit-llvm -O1 -o - 
-triple=i686-apple-darwin9 -std=c++11 | FileCheck %s
+// RUN: %clang_cc1 -fno-inline-functions %s -emit-llvm -O1 -o - 
-triple=i686-apple-darwin9 -std=c++11 -fexperimental-new-constant-interpreter | 
FileCheck %s
 
 // CHECK-DAG: @PR22043 ={{.*}} local_unnamed_addr global i32 0, align 4
 typedef _Atomic(int) AtomicInt;



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


[clang] c1af97d - [clang][Interp] Diagnose comparisons against one-past-end pointers

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

Author: Timm Bäder
Date: 2024-07-03T14:07:28+02:00
New Revision: c1af97db1e3846db1188149afe86cee6585dfc9a

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

LOG: [clang][Interp] Diagnose comparisons against one-past-end pointers

Added: 


Modified: 
clang/lib/AST/Interp/Interp.h
clang/lib/AST/Interp/Pointer.cpp
clang/lib/AST/Interp/Pointer.h
clang/test/AST/Interp/literals.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 328db219ca628..5d8362b4fa881 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -922,6 +922,7 @@ inline bool CmpHelperEQ(InterpState , CodePtr 
OpPC, CompareFn Fn) {
 return true;
   }
 
+  // Reject comparisons to weak pointers.
   for (const auto  : {LHS, RHS}) {
 if (P.isZero())
   continue;
@@ -934,6 +935,20 @@ inline bool CmpHelperEQ(InterpState , CodePtr 
OpPC, CompareFn Fn) {
   }
 
   if (!Pointer::hasSameBase(LHS, RHS)) {
+if (LHS.isOnePastEnd() && !RHS.isOnePastEnd() && !RHS.isZero() &&
+RHS.getOffset() == 0) {
+  const SourceInfo  = S.Current->getSource(OpPC);
+  S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_past_end)
+  << LHS.toDiagnosticString(S.getCtx());
+  return false;
+} else if (RHS.isOnePastEnd() && !LHS.isOnePastEnd() && !LHS.isZero() &&
+   LHS.getOffset() == 0) {
+  const SourceInfo  = S.Current->getSource(OpPC);
+  S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_past_end)
+  << RHS.toDiagnosticString(S.getCtx());
+  return false;
+}
+
 S.Stk.push(BoolT::from(Fn(ComparisonCategoryResult::Unordered)));
 return true;
   } else {

diff  --git a/clang/lib/AST/Interp/Pointer.cpp 
b/clang/lib/AST/Interp/Pointer.cpp
index 4070d0c54225d..d6603f91fb127 100644
--- a/clang/lib/AST/Interp/Pointer.cpp
+++ b/clang/lib/AST/Interp/Pointer.cpp
@@ -143,7 +143,7 @@ APValue Pointer::toAPValue() const {
 
   if (isDummy() || isUnknownSizeArray() || Desc->asExpr())
 return APValue(Base, CharUnits::Zero(), Path,
-   /*IsOnePastEnd=*/false, /*IsNullPtr=*/false);
+   /*IsOnePastEnd=*/isOnePastEnd(), /*IsNullPtr=*/false);
 
   // TODO: compute the offset into the object.
   CharUnits Offset = CharUnits::Zero();
@@ -181,7 +181,8 @@ APValue Pointer::toAPValue() const {
   // Just invert the order of the elements.
   std::reverse(Path.begin(), Path.end());
 
-  return APValue(Base, Offset, Path, /*IsOnePastEnd=*/false, 
/*IsNullPtr=*/false);
+  return APValue(Base, Offset, Path, /*IsOnePastEnd=*/isOnePastEnd(),
+ /*IsNullPtr=*/false);
 }
 
 void Pointer::print(llvm::raw_ostream ) const {
@@ -348,7 +349,7 @@ std::optional Pointer::toRValue(const Context 
) const {
 
 // Invalid pointers.
 if (Ptr.isDummy() || !Ptr.isLive() || !Ptr.isBlockPointer() ||
-(!Ptr.isUnknownSizeArray() && Ptr.isOnePastEnd()))
+Ptr.isPastEnd())
   return false;
 
 // Primitive values.

diff  --git a/clang/lib/AST/Interp/Pointer.h b/clang/lib/AST/Interp/Pointer.h
index 5faec75cc3ec5..4f277eb7d9e58 100644
--- a/clang/lib/AST/Interp/Pointer.h
+++ b/clang/lib/AST/Interp/Pointer.h
@@ -556,10 +556,18 @@ class Pointer {
 if (isUnknownSizeArray())
   return false;
 
-return isElementPastEnd() ||
+return isElementPastEnd() || isPastEnd() ||
(getSize() == getOffset() && !isZeroSizeArray());
   }
 
+  /// Checks if the pointer points past the end of the object.
+  bool isPastEnd() const {
+if (isIntegralPointer())
+  return false;
+
+return !isZero() && Offset > PointeeStorage.BS.Pointee->getSize();
+  }
+
   /// Checks if the pointer is an out-of-bounds element pointer.
   bool isElementPastEnd() const { return Offset == PastEndMark; }
 

diff  --git a/clang/test/AST/Interp/literals.cpp 
b/clang/test/AST/Interp/literals.cpp
index f70ca79e216da..630d9b53cca25 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -1266,3 +1266,13 @@ static_assert(ReturnInStmtExpr() == 1, ""); // 
both-error {{not an integral cons
 // both-note {{in call to}}
 
 #endif
+
+namespace ComparisonAgainstOnePastEnd {
+  int a, b;
+  static_assert( + 1 == , ""); // both-error {{not an integral constant 
expression}} \
+   // both-note {{comparison against pointer 
' + 1' that points past the end of a complete object has unspecified value}}
+  static_assert( ==  + 1, ""); // both-error {{not an integral constant 
expression}} \
+   // both-note {{comparison against pointer 
' + 1' that points past the end of a complete object has unspecified value}}
+
+  

[clang] c5f7f38 - [clang][Interp][NFC] Make some local pointers const

2024-07-02 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-02T13:17:06+02:00
New Revision: c5f7f380314c7d290e039e9c35562e1cedc01268

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

LOG: [clang][Interp][NFC] Make some local pointers const

Added: 


Modified: 
clang/lib/AST/Interp/Compiler.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index 739a65070b21d..9ca71e0496989 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -4033,7 +4033,7 @@ template  bool 
Compiler::visitLoopBody(const Stmt *S) {
 return true;
 
   if (const auto *CS = dyn_cast(S)) {
-for (auto *InnerStmt : CS->body())
+for (const auto *InnerStmt : CS->body())
   if (!visitStmt(InnerStmt))
 return false;
 return true;
@@ -4045,7 +4045,7 @@ template  bool 
Compiler::visitLoopBody(const Stmt *S) {
 template 
 bool Compiler::visitCompoundStmt(const CompoundStmt *S) {
   BlockScope Scope(this);
-  for (auto *InnerStmt : S->body())
+  for (const auto *InnerStmt : S->body())
 if (!visitStmt(InnerStmt))
   return false;
   return true;



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


[clang] c49c386 - [clang][Interp] Reject StmtExprs containing return statements

2024-07-02 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-02T12:15:24+02:00
New Revision: c49c386caaf7132908995749fed4894cfa1b62d1

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

LOG: [clang][Interp] Reject StmtExprs containing return statements

Added: 


Modified: 
clang/lib/AST/Interp/Compiler.cpp
clang/lib/AST/Interp/Compiler.h
clang/lib/AST/Interp/Interp.h
clang/lib/AST/Interp/Opcodes.td
clang/test/AST/Interp/literals.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index 3d9c72e2b6dee..739a65070b21d 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -154,6 +154,19 @@ template  class SwitchScope final : public 
LabelScope {
   CaseMap OldCaseLabels;
 };
 
+template  class StmtExprScope final {
+public:
+  StmtExprScope(Compiler *Ctx) : Ctx(Ctx), OldFlag(Ctx->InStmtExpr) {
+Ctx->InStmtExpr = true;
+  }
+
+  ~StmtExprScope() { Ctx->InStmtExpr = OldFlag; }
+
+private:
+  Compiler *Ctx;
+  bool OldFlag;
+};
+
 } // namespace interp
 } // namespace clang
 
@@ -3028,6 +3041,7 @@ bool Compiler::VisitCXXStdInitializerListExpr(
 template 
 bool Compiler::VisitStmtExpr(const StmtExpr *E) {
   BlockScope BS(this);
+  StmtExprScope SS(this);
 
   const CompoundStmt *CS = E->getSubStmt();
   const Stmt *Result = CS->getStmtExprResult();
@@ -4056,6 +4070,9 @@ bool Compiler::visitDeclStmt(const DeclStmt *DS) 
{
 
 template 
 bool Compiler::visitReturnStmt(const ReturnStmt *RS) {
+  if (this->InStmtExpr)
+return this->emitUnsupported(RS);
+
   if (const Expr *RE = RS->getRetValue()) {
 ExprScope RetScope(this);
 if (ReturnType) {

diff  --git a/clang/lib/AST/Interp/Compiler.h b/clang/lib/AST/Interp/Compiler.h
index 67bd7efb3b091..d28526c76fe13 100644
--- a/clang/lib/AST/Interp/Compiler.h
+++ b/clang/lib/AST/Interp/Compiler.h
@@ -39,6 +39,7 @@ template  class SourceLocScope;
 template  class LoopScope;
 template  class LabelScope;
 template  class SwitchScope;
+template  class StmtExprScope;
 
 template  class Compiler;
 struct InitLink {
@@ -334,6 +335,7 @@ class Compiler : public ConstStmtVisitor, 
bool>,
   friend class LoopScope;
   friend class LabelScope;
   friend class SwitchScope;
+  friend class StmtExprScope;
 
   /// Emits a zero initializer.
   bool visitZeroInitializer(PrimType T, QualType QT, const Expr *E);
@@ -398,6 +400,8 @@ class Compiler : public ConstStmtVisitor, 
bool>,
   /// Flag indicating if return value is to be discarded.
   bool DiscardResult = false;
 
+  bool InStmtExpr = false;
+
   /// Flag inidicating if we're initializing an already created
   /// variable. This is set in visitInitializer().
   bool Initializing = false;

diff  --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index ff6d50ab9b6f8..328db219ca628 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -2618,6 +2618,13 @@ inline bool Invalid(InterpState , CodePtr OpPC) {
   return false;
 }
 
+inline bool Unsupported(InterpState , CodePtr OpPC) {
+  const SourceLocation  = S.Current->getLocation(OpPC);
+  S.FFDiag(Loc, diag::note_constexpr_stmt_expr_unsupported)
+  << S.Current->getRange(OpPC);
+  return false;
+}
+
 /// Do nothing and just abort execution.
 inline bool Error(InterpState , CodePtr OpPC) { return false; }
 

diff  --git a/clang/lib/AST/Interp/Opcodes.td b/clang/lib/AST/Interp/Opcodes.td
index 81e7b812da237..8d01fe1ac2bd1 100644
--- a/clang/lib/AST/Interp/Opcodes.td
+++ b/clang/lib/AST/Interp/Opcodes.td
@@ -714,6 +714,7 @@ def Dup : Opcode {
 
 // [] -> []
 def Invalid : Opcode {}
+def Unsupported : Opcode {}
 def Error : Opcode {}
 def InvalidCast : Opcode {
   let Args = [ArgCastKind];

diff  --git a/clang/test/AST/Interp/literals.cpp 
b/clang/test/AST/Interp/literals.cpp
index 3abaf89e8bd01..f70ca79e216da 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -1255,4 +1255,14 @@ constexpr int StmtExprEval() {
   return 1;
 }
 static_assert(StmtExprEval() == 2, "");
+
+constexpr int ReturnInStmtExpr() { // both-error {{never produces a constant 
expression}}
+  return ({
+  return 1; // both-note 2{{this use of statement expressions is not 
supported in a constant expression}}
+  2;
+  });
+}
+static_assert(ReturnInStmtExpr() == 1, ""); // both-error {{not an integral 
constant expression}} \
+// both-note {{in call to}}
+
 #endif



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


[clang] 62e6255 - [clang][Interp] Add missing fallthrough in loops

2024-07-02 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-02T11:51:07+02:00
New Revision: 62e6255a58eb0e9bb31e366a9e30d5c1eaadd004

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

LOG: [clang][Interp] Add missing fallthrough in loops

Added: 


Modified: 
clang/lib/AST/Interp/Compiler.cpp
clang/test/AST/Interp/literals.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index 77c7e20632881..3d9c72e2b6dee 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -4139,6 +4139,7 @@ bool Compiler::visitWhileStmt(const WhileStmt 
*S) {
   LabelTy EndLabel = this->getLabel();  // Label after the loop.
   LoopScope LS(this, EndLabel, CondLabel);
 
+  this->fallthrough(CondLabel);
   this->emitLabel(CondLabel);
 
   if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt())
@@ -4174,12 +4175,14 @@ template  bool 
Compiler::visitDoStmt(const DoStmt *S) {
   LoopScope LS(this, EndLabel, CondLabel);
   LocalScope Scope(this);
 
+  this->fallthrough(StartLabel);
   this->emitLabel(StartLabel);
   {
 DestructorScope DS(Scope);
 
 if (!this->visitLoopBody(Body))
   return false;
+this->fallthrough(CondLabel);
 this->emitLabel(CondLabel);
 if (!this->visitBool(Cond))
   return false;
@@ -4187,6 +4190,7 @@ template  bool 
Compiler::visitDoStmt(const DoStmt *S) {
   if (!this->jumpTrue(StartLabel))
 return false;
 
+  this->fallthrough(EndLabel);
   this->emitLabel(EndLabel);
   return true;
 }
@@ -4207,6 +4211,7 @@ bool Compiler::visitForStmt(const ForStmt *S) {
 
   if (Init && !this->visitStmt(Init))
 return false;
+  this->fallthrough(CondLabel);
   this->emitLabel(CondLabel);
 
   if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt())
@@ -4225,6 +4230,7 @@ bool Compiler::visitForStmt(const ForStmt *S) {
 
 if (Body && !this->visitLoopBody(Body))
   return false;
+this->fallthrough(IncLabel);
 this->emitLabel(IncLabel);
 if (Inc && !this->discard(Inc))
   return false;
@@ -4232,6 +4238,7 @@ bool Compiler::visitForStmt(const ForStmt *S) {
 
   if (!this->jump(CondLabel))
 return false;
+  this->fallthrough(EndLabel);
   this->emitLabel(EndLabel);
   return true;
 }
@@ -4263,6 +4270,7 @@ bool Compiler::visitCXXForRangeStmt(const 
CXXForRangeStmt *S) {
 return false;
 
   // Now the condition as well as the loop variable assignment.
+  this->fallthrough(CondLabel);
   this->emitLabel(CondLabel);
   if (!this->visitBool(Cond))
 return false;
@@ -4279,13 +4287,16 @@ bool Compiler::visitCXXForRangeStmt(const 
CXXForRangeStmt *S) {
 
 if (!this->visitLoopBody(Body))
   return false;
+  this->fallthrough(IncLabel);
 this->emitLabel(IncLabel);
 if (!this->discard(Inc))
   return false;
   }
+
   if (!this->jump(CondLabel))
 return false;
 
+  this->fallthrough(EndLabel);
   this->emitLabel(EndLabel);
   return true;
 }

diff  --git a/clang/test/AST/Interp/literals.cpp 
b/clang/test/AST/Interp/literals.cpp
index a7a602ec355d5..3abaf89e8bd01 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -1243,3 +1243,16 @@ namespace Extern {
   static_assert(() == , "");
 #endif
 }
+
+#if __cplusplus >= 201402L
+constexpr int StmtExprEval() {
+  if (({
+while (0);
+true;
+  })) {
+return 2;
+  }
+  return 1;
+}
+static_assert(StmtExprEval() == 2, "");
+#endif



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


[clang] 030ea6d - [clang][Interp] Only check toplevel declarations

2024-07-02 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-02T11:50:41+02:00
New Revision: 030ea6d38b7c6afc191bc721be9d59e89bbf7631

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

LOG: [clang][Interp] Only check toplevel declarations

Added: 


Modified: 
clang/lib/AST/Interp/Compiler.cpp
clang/lib/AST/Interp/Compiler.h
clang/test/AST/Interp/c.c

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index 5ae36dae6557d..77c7e20632881 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -3460,7 +3460,7 @@ bool Compiler::visitDecl(const VarDecl *VD, bool 
ConstantContext) {
   }
 
   // Create and initialize the variable.
-  if (!this->visitVarDecl(VD))
+  if (!this->visitVarDecl(VD, /*Toplevel=*/true))
 return false;
 
   // Get a pointer to the variable
@@ -3507,7 +3507,7 @@ bool Compiler::visitDecl(const VarDecl *VD, bool 
ConstantContext) {
 }
 
 template 
-VarCreationState Compiler::visitVarDecl(const VarDecl *VD) {
+VarCreationState Compiler::visitVarDecl(const VarDecl *VD, bool 
Toplevel) {
   // We don't know what to do with these, so just return false.
   if (VD->getType().isNull())
 return false;
@@ -3521,7 +3521,7 @@ VarCreationState Compiler::visitVarDecl(const 
VarDecl *VD) {
   std::optional VarT = classify(VD->getType());
 
   auto checkDecl = [&]() -> bool {
-bool NeedsOp = VD->isLocalVarDecl() && VD->isStaticLocal();
+bool NeedsOp = !Toplevel && VD->isLocalVarDecl() && VD->isStaticLocal();
 return !NeedsOp || this->emitCheckDecl(VD, VD);
   };
 
@@ -4991,7 +4991,7 @@ bool Compiler::visitDeclRef(const ValueDecl *D, 
const Expr *E) {
 if ((VD->hasGlobalStorage() || VD->isLocalVarDecl() ||
  VD->isStaticDataMember()) &&
 typeShouldBeVisited(VD->getType())) {
-  auto VarState = this->visitVarDecl(VD);
+  auto VarState = this->visitVarDecl(VD, true);
   if (VarState.notCreated())
 return true;
   if (!VarState)
@@ -5004,7 +5004,7 @@ bool Compiler::visitDeclRef(const ValueDecl *D, 
const Expr *E) {
   if (const auto *VD = dyn_cast(D);
   VD && VD->getAnyInitializer() &&
   VD->getType().isConstant(Ctx.getASTContext()) && !VD->isWeak()) {
-auto VarState = this->visitVarDecl(VD);
+auto VarState = this->visitVarDecl(VD, true);
 if (VarState.notCreated())
   return true;
 if (!VarState)

diff  --git a/clang/lib/AST/Interp/Compiler.h b/clang/lib/AST/Interp/Compiler.h
index d188ce2200664..67bd7efb3b091 100644
--- a/clang/lib/AST/Interp/Compiler.h
+++ b/clang/lib/AST/Interp/Compiler.h
@@ -260,7 +260,7 @@ class Compiler : public ConstStmtVisitor, 
bool>,
   /// intact.
   bool delegate(const Expr *E);
   /// Creates and initializes a variable from the given decl.
-  VarCreationState visitVarDecl(const VarDecl *VD);
+  VarCreationState visitVarDecl(const VarDecl *VD, bool Toplevel = false);
   /// Visit an APValue.
   bool visitAPValue(const APValue , PrimType ValType, const Expr *E);
   bool visitAPValueInitializer(const APValue , const Expr *E);

diff  --git a/clang/test/AST/Interp/c.c b/clang/test/AST/Interp/c.c
index 684658da26a0e..9ec305d59c68c 100644
--- a/clang/test/AST/Interp/c.c
+++ b/clang/test/AST/Interp/c.c
@@ -293,3 +293,11 @@ void SuperSpecialFunc(void) {
 const int SuperSpecialCase = 10;
 _Static_assert((sizeof(SuperSpecialCase) == 12 && SuperSpecialCase == 3) || 
SuperSpecialCase == 10, ""); // pedantic-warning {{GNU extension}}
 }
+
+
+void T1(void) {
+  static int *y[1] = {({ static int _x = 20; (void*)0;})}; // all-error 
{{initializer element is not a compile-time constant}} \
+   // pedantic-warning 
{{use of GNU statement expression extension}}
+}
+
+



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


[clang] 42fc93d - [clang][Interp][NFC] Make a local pointer const

2024-07-01 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-01T11:59:56+02:00
New Revision: 42fc93d3ffb35ec1ff5c6584e1b15d5118db7311

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

LOG: [clang][Interp][NFC] Make a local pointer const

Added: 


Modified: 
clang/lib/AST/Interp/Compiler.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index ff755d503f871..5ae36dae6557d 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -4039,7 +4039,7 @@ bool Compiler::visitCompoundStmt(const 
CompoundStmt *S) {
 
 template 
 bool Compiler::visitDeclStmt(const DeclStmt *DS) {
-  for (auto *D : DS->decls()) {
+  for (const auto *D : DS->decls()) {
 if (isa(D))
   continue;



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


[clang] 7f1d672 - [clang][Interp] Diagnose static declarations in constexpr functions

2024-07-01 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-07-01T11:58:56+02:00
New Revision: 7f1d672d70eabe010567fcd8c365d27549736c6d

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

LOG: [clang][Interp] Diagnose static declarations in constexpr functions

Added: 


Modified: 
clang/lib/AST/Interp/Compiler.cpp
clang/lib/AST/Interp/Interp.h
clang/lib/AST/Interp/Opcodes.td
clang/test/AST/Interp/cxx23.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index 424f4f84a0167..ff755d503f871 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -3520,6 +3520,11 @@ VarCreationState Compiler::visitVarDecl(const 
VarDecl *VD) {
   const Expr *Init = VD->getInit();
   std::optional VarT = classify(VD->getType());
 
+  auto checkDecl = [&]() -> bool {
+bool NeedsOp = VD->isLocalVarDecl() && VD->isStaticLocal();
+return !NeedsOp || this->emitCheckDecl(VD, VD);
+  };
+
   if (Context::shouldBeGloballyIndexed(VD)) {
 auto initGlobal = [&](unsigned GlobalIndex) -> bool {
   assert(Init);
@@ -3527,20 +3532,22 @@ VarCreationState Compiler::visitVarDecl(const 
VarDecl *VD) {
 
   if (VarT) {
 if (!this->visit(Init))
-  return false;
-return this->emitInitGlobal(*VarT, GlobalIndex, VD);
+  return checkDecl() && false;
+
+return checkDecl() && this->emitInitGlobal(*VarT, GlobalIndex, VD);
   }
-  return this->visitGlobalInitializer(Init, GlobalIndex);
+
+  return checkDecl() && this->visitGlobalInitializer(Init, GlobalIndex);
 };
 
 // We've already seen and initialized this global.
 if (std::optional GlobalIndex = P.getGlobal(VD)) {
   if (P.getPtrGlobal(*GlobalIndex).isInitialized())
-return true;
+return checkDecl();
 
   // The previous attempt at initialization might've been unsuccessful,
   // so let's try this one.
-  return Init && initGlobal(*GlobalIndex);
+  return Init && checkDecl() && initGlobal(*GlobalIndex);
 }
 
 std::optional GlobalIndex = P.createGlobal(VD, Init);
@@ -3548,9 +3555,10 @@ VarCreationState Compiler::visitVarDecl(const 
VarDecl *VD) {
 if (!GlobalIndex)
   return false;
 
-return !Init || initGlobal(*GlobalIndex);
+return !Init || (checkDecl() && initGlobal(*GlobalIndex));
   } else {
 VariableScope LocalScope(this, VD);
+
 if (VarT) {
   unsigned Offset = this->allocateLocalPrimitive(
   VD, *VarT, VD->getType().isConstQualified());

diff  --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 866593b9af094..ff6d50ab9b6f8 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -2689,6 +2689,25 @@ inline bool DecayPtr(InterpState , CodePtr OpPC) {
   return true;
 }
 
+inline bool CheckDecl(InterpState , CodePtr OpPC, const VarDecl *VD) {
+  // An expression E is a core constant expression unless the evaluation of E
+  // would evaluate one of the following: [C++23] - a control flow that passes
+  // through a declaration of a variable with static or thread storage duration
+  // unless that variable is usable in constant expressions.
+  assert(VD->isLocalVarDecl() &&
+ VD->isStaticLocal()); // Checked before emitting this.
+
+  if (VD == S.EvaluatingDecl)
+return true;
+
+  if (!VD->isUsableInConstantExpressions(S.getCtx())) {
+S.CCEDiag(VD->getLocation(), diag::note_constexpr_static_local)
+<< (VD->getTSCSpec() == TSCS_unspecified ? 0 : 1) << VD;
+return false;
+  }
+  return true;
+}
+
 
//===--===//
 // Read opcode arguments
 
//===--===//

diff  --git a/clang/lib/AST/Interp/Opcodes.td b/clang/lib/AST/Interp/Opcodes.td
index ddd955fc4cfa4..81e7b812da237 100644
--- a/clang/lib/AST/Interp/Opcodes.td
+++ b/clang/lib/AST/Interp/Opcodes.td
@@ -63,6 +63,7 @@ def ArgDeclRef : ArgType { let Name = "const DeclRefExpr *"; }
 def ArgDesc : ArgType { let Name = "const Descriptor *"; }
 def ArgCCI : ArgType { let Name = "const ComparisonCategoryInfo *"; }
 def ArgDecl : ArgType { let Name = "const Decl*"; }
+def ArgVarDecl : ArgType { let Name = "const VarDecl*"; }
 
 
//===--===//
 // Classes of types instructions operate on.
@@ -382,6 +383,10 @@ def GetLocal : AccessOpcode { let HasCustomEval = 1; }
 // [] -> [Pointer]
 def SetLocal : AccessOpcode { let HasCustomEval = 1; }
 
+def CheckDecl : Opcode {
+  let Args = [ArgVarDecl];
+}
+
 // [] -> [Value]
 def GetGlobal : AccessOpcode;
 def GetGlobalUnchecked : AccessOpcode;

diff  --git a/clang/test/AST/Interp/cxx23.cpp 

[clang] 56a636f - [clang][Interp] Implement StmtExprs

2024-06-30 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-06-30T09:28:56+02:00
New Revision: 56a636f2d22890cc71f358ddc50d3e0f2b60bd9c

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

LOG: [clang][Interp] Implement StmtExprs

Added: 


Modified: 
clang/lib/AST/Interp/Compiler.cpp
clang/lib/AST/Interp/Compiler.h
clang/test/AST/Interp/literals.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index 8b6f7f644a778..424f4f84a0167 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -3025,6 +3025,32 @@ bool Compiler::VisitCXXStdInitializerListExpr(
   return this->emitInitFieldPtr(R->getField(1u)->Offset, E);
 }
 
+template 
+bool Compiler::VisitStmtExpr(const StmtExpr *E) {
+  BlockScope BS(this);
+
+  const CompoundStmt *CS = E->getSubStmt();
+  const Stmt *Result = CS->getStmtExprResult();
+  for (const Stmt *S : CS->body()) {
+if (S != Result) {
+  if (!this->visitStmt(S))
+return false;
+  continue;
+}
+
+assert(S == Result);
+// This better produces a value (i.e. is an expression).
+if (const Expr *ResultExpr = dyn_cast(S)) {
+  if (DiscardResult)
+return this->discard(ResultExpr);
+  return this->delegate(ResultExpr);
+}
+return false;
+  }
+
+  return true;
+}
+
 template  bool Compiler::discard(const Expr *E) {
   OptionScope Scope(this, /*NewDiscardResult=*/true,
  /*NewInitializing=*/false);

diff  --git a/clang/lib/AST/Interp/Compiler.h b/clang/lib/AST/Interp/Compiler.h
index 89e36f9201a41..d188ce2200664 100644
--- a/clang/lib/AST/Interp/Compiler.h
+++ b/clang/lib/AST/Interp/Compiler.h
@@ -183,6 +183,7 @@ class Compiler : public ConstStmtVisitor, 
bool>,
   bool VisitExtVectorElementExpr(const ExtVectorElementExpr *E);
   bool VisitObjCBoxedExpr(const ObjCBoxedExpr *E);
   bool VisitCXXStdInitializerListExpr(const CXXStdInitializerListExpr *E);
+  bool VisitStmtExpr(const StmtExpr *E);
 
   // Statements.
   bool visitCompoundStmt(const CompoundStmt *S);

diff  --git a/clang/test/AST/Interp/literals.cpp 
b/clang/test/AST/Interp/literals.cpp
index ef98b4947e64f..a7a602ec355d5 100644
--- a/clang/test/AST/Interp/literals.cpp
+++ b/clang/test/AST/Interp/literals.cpp
@@ -1213,6 +1213,18 @@ constexpr int externvar1() { // both-error {{never 
produces a constant expressio
return arr[0]; // ref-note {{read of non-constexpr variable 'arr'}} \
   // expected-note {{indexing of array without known bound}}
 }
+
+namespace StmtExprs {
+  constexpr int foo() {
+ ({
+   int i;
+   for (i = 0; i < 76; i++) {}
+   i; // both-warning {{expression result unused}}
+});
+return 76;
+  }
+  static_assert(foo() == 76, "");
+}
 #endif
 
 namespace Extern {



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


[clang] 5a8c4b5 - [clang][Interp] Don't allow reading from non-const blocks when returning

2024-06-29 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-06-29T21:10:25+02:00
New Revision: 5a8c4b597beed38e392f221042d29f475a3d1626

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

LOG: [clang][Interp] Don't allow reading from non-const blocks when returning

Added: 


Modified: 
clang/lib/AST/Interp/EvalEmitter.cpp
clang/test/AST/Interp/const-temporaries.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/EvalEmitter.cpp 
b/clang/lib/AST/Interp/EvalEmitter.cpp
index f4854adba9348..d17151416b44b 100644
--- a/clang/lib/AST/Interp/EvalEmitter.cpp
+++ b/clang/lib/AST/Interp/EvalEmitter.cpp
@@ -151,6 +151,11 @@ template <> bool EvalEmitter::emitRet(const 
SourceInfo ) {
 
   // Implicitly convert lvalue to rvalue, if requested.
   if (ConvertResultToRValue) {
+// Never allow reading from a non-const pointer, unless the memory
+// has been created in this evaluation.
+if (!Ptr.isConst() && Ptr.block()->getEvalID() != Ctx.getEvalID())
+  return false;
+
 if (std::optional V = Ptr.toRValue(Ctx)) {
   EvalResult.setValue(*V);
 } else {

diff  --git a/clang/test/AST/Interp/const-temporaries.cpp 
b/clang/test/AST/Interp/const-temporaries.cpp
index bbb95b3c3dff7..1dc16ef63a846 100644
--- a/clang/test/AST/Interp/const-temporaries.cpp
+++ b/clang/test/AST/Interp/const-temporaries.cpp
@@ -90,3 +90,12 @@ struct R { mutable long x; };
 struct Z2 { const R , y; };
 Z2 z2 = { R{1}, z2.x.x = 10 };
 
+// CHECK: __cxa_atexit({{.*}} @_ZN1BD1Ev, {{.*}} @b
+
+// CHECK: define
+// CHECK-NOT: @_ZGRN21ModifyStaticTemporary1cE_
+// CHECK: store {{.*}} @_ZGRN21ModifyStaticTemporary1cE_, {{.*}} 
@_ZN21ModifyStaticTemporary1cE
+// CHECK: add
+// CHECK: store
+// CHECK: load {{.*}} @_ZN21ModifyStaticTemporary1bE
+// CHECK: store {{.*}} @_ZN21ModifyStaticTemporary1cE



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


[clang] 40f4bd1 - [clang][Interp] Allow reading mutable members if they were created...

2024-06-29 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-06-29T21:10:24+02:00
New Revision: 40f4bd18f2fb01731fa7891fb7349e05dc98aeec

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

LOG: [clang][Interp] Allow reading mutable members if they were created...

... in this evaluation.

Added: 
clang/test/AST/Interp/mutable.cpp

Modified: 
clang/lib/AST/Interp/Context.cpp
clang/lib/AST/Interp/Context.h
clang/lib/AST/Interp/EvalEmitter.cpp
clang/lib/AST/Interp/Interp.cpp
clang/lib/AST/Interp/InterpBlock.cpp
clang/lib/AST/Interp/InterpBlock.h
clang/lib/AST/Interp/InterpFrame.cpp
clang/lib/AST/Interp/Program.cpp
clang/test/AST/Interp/const-temporaries.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Context.cpp 
b/clang/lib/AST/Interp/Context.cpp
index 22ccae4fa30f8..913e8d514282a 100644
--- a/clang/lib/AST/Interp/Context.cpp
+++ b/clang/lib/AST/Interp/Context.cpp
@@ -39,6 +39,7 @@ bool Context::isPotentialConstantExpr(State , const 
FunctionDecl *FD) {
 }
 
 bool Context::evaluateAsRValue(State , const Expr *E, APValue ) {
+  ++EvalID;
   bool Recursing = !Stk.empty();
   Compiler C(*this, *P, Parent, Stk);
 
@@ -65,6 +66,7 @@ bool Context::evaluateAsRValue(State , const Expr *E, 
APValue ) {
 }
 
 bool Context::evaluate(State , const Expr *E, APValue ) {
+  ++EvalID;
   bool Recursing = !Stk.empty();
   Compiler C(*this, *P, Parent, Stk);
 
@@ -90,6 +92,7 @@ bool Context::evaluate(State , const Expr *E, APValue 
) {
 
 bool Context::evaluateAsInitializer(State , const VarDecl *VD,
 APValue ) {
+  ++EvalID;
   bool Recursing = !Stk.empty();
   Compiler C(*this, *P, Parent, Stk);
 

diff  --git a/clang/lib/AST/Interp/Context.h b/clang/lib/AST/Interp/Context.h
index c78dc9a2a471e..b8ea4ad6b3b44 100644
--- a/clang/lib/AST/Interp/Context.h
+++ b/clang/lib/AST/Interp/Context.h
@@ -109,6 +109,8 @@ class Context final {
 
   const Record *getRecord(const RecordDecl *D) const;
 
+  unsigned getEvalID() const { return EvalID; }
+
 private:
   /// Runs a function.
   bool Run(State , const Function *Func, APValue );
@@ -119,6 +121,8 @@ class Context final {
   InterpStack Stk;
   /// Constexpr program.
   std::unique_ptr P;
+  /// ID identifying an evaluation.
+  unsigned EvalID = 0;
 };
 
 } // namespace interp

diff  --git a/clang/lib/AST/Interp/EvalEmitter.cpp 
b/clang/lib/AST/Interp/EvalEmitter.cpp
index 6748b305d5c8e..f4854adba9348 100644
--- a/clang/lib/AST/Interp/EvalEmitter.cpp
+++ b/clang/lib/AST/Interp/EvalEmitter.cpp
@@ -84,7 +84,7 @@ EvalEmitter::LabelTy EvalEmitter::getLabel() { return 
NextLabel++; }
 Scope::Local EvalEmitter::createLocal(Descriptor *D) {
   // Allocate memory for a local.
   auto Memory = std::make_unique(sizeof(Block) + D->getAllocSize());
-  auto *B = new (Memory.get()) Block(D, /*isStatic=*/false);
+  auto *B = new (Memory.get()) Block(Ctx.getEvalID(), D, /*isStatic=*/false);
   B->invokeCtor();
 
   // Initialize local variable inline descriptor.

diff  --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp
index 2fe8ab7d0df4b..0411fcad88ad0 100644
--- a/clang/lib/AST/Interp/Interp.cpp
+++ b/clang/lib/AST/Interp/Interp.cpp
@@ -400,7 +400,7 @@ bool CheckDowncast(InterpState , CodePtr OpPC, const 
Pointer ,
 
 bool CheckConst(InterpState , CodePtr OpPC, const Pointer ) {
   assert(Ptr.isLive() && "Pointer is not live");
-  if (!Ptr.isConst())
+  if (!Ptr.isConst() || Ptr.isMutable())
 return true;
 
   // The This pointer is writable in constructors and destructors,
@@ -422,9 +422,14 @@ bool CheckConst(InterpState , CodePtr OpPC, const 
Pointer ) {
 
 bool CheckMutable(InterpState , CodePtr OpPC, const Pointer ) {
   assert(Ptr.isLive() && "Pointer is not live");
-  if (!Ptr.isMutable()) {
+  if (!Ptr.isMutable())
+return true;
+
+  // In C++14 onwards, it is permitted to read a mutable member whose
+  // lifetime began within the evaluation.
+  if (S.getLangOpts().CPlusPlus14 &&
+  Ptr.block()->getEvalID() == S.Ctx.getEvalID())
 return true;
-  }
 
   const SourceInfo  = S.Current->getSource(OpPC);
   const FieldDecl *Field = Ptr.getField();

diff  --git a/clang/lib/AST/Interp/InterpBlock.cpp 
b/clang/lib/AST/Interp/InterpBlock.cpp
index 9b33d1b778fb2..c34ea7634b4a9 100644
--- a/clang/lib/AST/Interp/InterpBlock.cpp
+++ b/clang/lib/AST/Interp/InterpBlock.cpp
@@ -92,7 +92,8 @@ bool Block::hasPointer(const Pointer *P) const {
 #endif
 
 DeadBlock::DeadBlock(DeadBlock *, Block *Blk)
-: Root(Root), B(Blk->Desc, Blk->IsStatic, Blk->IsExtern, /*isDead=*/true) {
+: Root(Root),
+  B(~0u, Blk->Desc, Blk->IsStatic, Blk->IsExtern, /*isDead=*/true) {
   // Add the block to the chain of dead blocks.
   if (Root)
 Root->Prev = this;

diff  --git 

[clang] 37698d9 - [clang][Interp][NFC] Use CheckLoad() in Inc/Dec ops

2024-06-29 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-06-29T21:10:24+02:00
New Revision: 37698d924840a229e5a1bece8f5e845e0f5c80a6

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

LOG: [clang][Interp][NFC] Use CheckLoad() in Inc/Dec ops

CheckLoad checks more things than we did before.

Added: 


Modified: 
clang/lib/AST/Interp/Interp.cpp
clang/lib/AST/Interp/Interp.h

Removed: 




diff  --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp
index 76a0751a006e4..2fe8ab7d0df4b 100644
--- a/clang/lib/AST/Interp/Interp.cpp
+++ b/clang/lib/AST/Interp/Interp.cpp
@@ -476,23 +476,24 @@ bool CheckGlobalInitialized(InterpState , CodePtr OpPC, 
const Pointer ) {
   return false;
 }
 
-bool CheckLoad(InterpState , CodePtr OpPC, const Pointer ) {
-  if (!CheckLive(S, OpPC, Ptr, AK_Read))
+bool CheckLoad(InterpState , CodePtr OpPC, const Pointer ,
+   AccessKinds AK) {
+  if (!CheckLive(S, OpPC, Ptr, AK))
 return false;
   if (!CheckConstant(S, OpPC, Ptr))
 return false;
 
-  if (!CheckDummy(S, OpPC, Ptr, AK_Read))
+  if (!CheckDummy(S, OpPC, Ptr, AK))
 return false;
   if (!CheckExtern(S, OpPC, Ptr))
 return false;
-  if (!CheckRange(S, OpPC, Ptr, AK_Read))
+  if (!CheckRange(S, OpPC, Ptr, AK))
 return false;
-  if (!CheckActive(S, OpPC, Ptr, AK_Read))
+  if (!CheckActive(S, OpPC, Ptr, AK))
 return false;
-  if (!CheckInitialized(S, OpPC, Ptr, AK_Read))
+  if (!CheckInitialized(S, OpPC, Ptr, AK))
 return false;
-  if (!CheckTemporary(S, OpPC, Ptr, AK_Read))
+  if (!CheckTemporary(S, OpPC, Ptr, AK))
 return false;
   if (!CheckMutable(S, OpPC, Ptr))
 return false;

diff  --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 75a8f66cc5d50..866593b9af094 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -92,7 +92,8 @@ bool CheckConstant(InterpState , CodePtr OpPC, const 
Descriptor *Desc);
 bool CheckMutable(InterpState , CodePtr OpPC, const Pointer );
 
 /// Checks if a value can be loaded from a block.
-bool CheckLoad(InterpState , CodePtr OpPC, const Pointer );
+bool CheckLoad(InterpState , CodePtr OpPC, const Pointer ,
+   AccessKinds AK = AK_Read);
 
 bool CheckInitialized(InterpState , CodePtr OpPC, const Pointer ,
   AccessKinds AK);
@@ -724,9 +725,7 @@ bool IncDecHelper(InterpState , CodePtr OpPC, const 
Pointer ) {
 template ::T>
 bool Inc(InterpState , CodePtr OpPC) {
   const Pointer  = S.Stk.pop();
-  if (!CheckDummy(S, OpPC, Ptr, AK_Increment))
-return false;
-  if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
+  if (!CheckLoad(S, OpPC, Ptr, AK_Increment))
 return false;
 
   return IncDecHelper(S, OpPC, Ptr);
@@ -738,9 +737,7 @@ bool Inc(InterpState , CodePtr OpPC) {
 template ::T>
 bool IncPop(InterpState , CodePtr OpPC) {
   const Pointer  = S.Stk.pop();
-  if (!CheckDummy(S, OpPC, Ptr, AK_Increment))
-return false;
-  if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
+  if (!CheckLoad(S, OpPC, Ptr, AK_Increment))
 return false;
 
   return IncDecHelper(S, OpPC, Ptr);
@@ -753,9 +750,7 @@ bool IncPop(InterpState , CodePtr OpPC) {
 template ::T>
 bool Dec(InterpState , CodePtr OpPC) {
   const Pointer  = S.Stk.pop();
-  if (!CheckDummy(S, OpPC, Ptr, AK_Decrement))
-return false;
-  if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
+  if (!CheckLoad(S, OpPC, Ptr, AK_Decrement))
 return false;
 
   return IncDecHelper(S, OpPC, Ptr);
@@ -767,9 +762,7 @@ bool Dec(InterpState , CodePtr OpPC) {
 template ::T>
 bool DecPop(InterpState , CodePtr OpPC) {
   const Pointer  = S.Stk.pop();
-  if (!CheckDummy(S, OpPC, Ptr, AK_Decrement))
-return false;
-  if (!CheckInitialized(S, OpPC, Ptr, AK_Decrement))
+  if (!CheckLoad(S, OpPC, Ptr, AK_Decrement))
 return false;
 
   return IncDecHelper(S, OpPC, Ptr);
@@ -797,9 +790,7 @@ bool IncDecFloatHelper(InterpState , CodePtr OpPC, const 
Pointer ,
 
 inline bool Incf(InterpState , CodePtr OpPC, llvm::RoundingMode RM) {
   const Pointer  = S.Stk.pop();
-  if (Ptr.isDummy())
-return false;
-  if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
+  if (!CheckLoad(S, OpPC, Ptr, AK_Increment))
 return false;
 
   return IncDecFloatHelper(S, OpPC, Ptr, RM);
@@ -807,9 +798,7 @@ inline bool Incf(InterpState , CodePtr OpPC, 
llvm::RoundingMode RM) {
 
 inline bool IncfPop(InterpState , CodePtr OpPC, llvm::RoundingMode RM) {
   const Pointer  = S.Stk.pop();
-  if (Ptr.isDummy())
-return false;
-  if (!CheckInitialized(S, OpPC, Ptr, AK_Increment))
+  if (!CheckLoad(S, OpPC, Ptr, AK_Increment))
 return false;
 
   return IncDecFloatHelper(S, OpPC, Ptr, RM);
@@ -817,11 +806,7 @@ inline bool IncfPop(InterpState , CodePtr OpPC, 
llvm::RoundingMode RM) {
 
 inline bool 

[clang] 8d4aa1f - [clang][Interp] Update global temporaries at the end of a declaration

2024-06-29 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-06-29T21:10:24+02:00
New Revision: 8d4aa1f22ea08b12a7958b681e8a265f78cb349f

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

LOG: [clang][Interp] Update global temporaries at the end of a declaration

When we create a global temporary variable via a
LifetimeExtendedTemporaryDecl, we have an expression to initialize it
with, so we evaluate that expression, convert it to an APValue and set
it on the LETD. However, when the value is updated after the
initialization, we don't propagate the new value to the LETD, which
means we will see an outdated value set on the LETD.

Fix this by keeping a list of seen LETDs and update them from the
global variable at the end of evaluation a declaration.

Added: 
clang/test/AST/Interp/const-temporaries.cpp

Modified: 
clang/lib/AST/Interp/EvalEmitter.cpp
clang/lib/AST/Interp/EvalEmitter.h
clang/lib/AST/Interp/Interp.h
clang/lib/AST/Interp/InterpState.h

Removed: 




diff  --git a/clang/lib/AST/Interp/EvalEmitter.cpp 
b/clang/lib/AST/Interp/EvalEmitter.cpp
index a13cd94b0ba1c..6748b305d5c8e 100644
--- a/clang/lib/AST/Interp/EvalEmitter.cpp
+++ b/clang/lib/AST/Interp/EvalEmitter.cpp
@@ -71,6 +71,7 @@ EvaluationResult EvalEmitter::interpretDecl(const VarDecl *VD,
 EvalResult.setInvalid();
 
   S.EvaluatingDecl = nullptr;
+  updateGlobalTemporaries();
   return std::move(this->EvalResult);
 }
 
@@ -237,6 +238,28 @@ bool EvalEmitter::emitDestroy(uint32_t I, const SourceInfo 
) {
   return true;
 }
 
+/// Global temporaries (LifetimeExtendedTemporary) carry their value
+/// around as an APValue, which codegen accesses.
+/// We set their value once when creating them, but we don't update it
+/// afterwards when code changes it later.
+/// This is what we do here.
+void EvalEmitter::updateGlobalTemporaries() {
+  for (const auto &[E, Temp] : S.SeenGlobalTemporaries) {
+if (std::optional GlobalIndex = P.getGlobal(E)) {
+  const Pointer  = P.getPtrGlobal(*GlobalIndex);
+  APValue *Cached = Temp->getOrCreateValue(true);
+
+  if (std::optional T = Ctx.classify(E->getType())) {
+TYPE_SWITCH(*T, { *Cached = Ptr.deref().toAPValue(); });
+  } else {
+if (std::optional APV = Ptr.toRValue(Ctx))
+  *Cached = *APV;
+  }
+}
+  }
+  S.SeenGlobalTemporaries.clear();
+}
+
 
//===--===//
 // Opcode evaluators
 
//===--===//

diff  --git a/clang/lib/AST/Interp/EvalEmitter.h 
b/clang/lib/AST/Interp/EvalEmitter.h
index 109e6e0bc0d76..d1e125cae9594 100644
--- a/clang/lib/AST/Interp/EvalEmitter.h
+++ b/clang/lib/AST/Interp/EvalEmitter.h
@@ -109,6 +109,8 @@ class EvalEmitter : public SourceMapper {
 return reinterpret_cast(It->second.get());
   }
 
+  void updateGlobalTemporaries();
+
   // The emitter always tracks the current instruction and sets OpPC to a token
   // value which is mapped to the location of the opcode being evaluated.
   CodePtr OpPC;

diff  --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 6c9246f692204..75a8f66cc5d50 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -1283,16 +1283,20 @@ bool InitGlobal(InterpState , CodePtr OpPC, uint32_t 
I) {
 template ::T>
 bool InitGlobalTemp(InterpState , CodePtr OpPC, uint32_t I,
 const LifetimeExtendedTemporaryDecl *Temp) {
-  assert(Temp);
+  const Pointer  = S.P.getGlobal(I);
+
   const T Value = S.Stk.peek();
   APValue APV = Value.toAPValue();
   APValue *Cached = Temp->getOrCreateValue(true);
   *Cached = APV;
 
-  const Pointer  = S.P.getGlobal(I);
-  P.deref() = S.Stk.pop();
-  P.initialize();
+  assert(Ptr.getDeclDesc()->asExpr());
+
+  S.SeenGlobalTemporaries.push_back(
+  std::make_pair(Ptr.getDeclDesc()->asExpr(), Temp));
 
+  Ptr.deref() = S.Stk.pop();
+  Ptr.initialize();
   return true;
 }
 
@@ -1305,6 +1309,9 @@ inline bool InitGlobalTempComp(InterpState , CodePtr 
OpPC,
   const Pointer  = S.Stk.peek();
   APValue *Cached = Temp->getOrCreateValue(true);
 
+  S.SeenGlobalTemporaries.push_back(
+  std::make_pair(P.getDeclDesc()->asExpr(), Temp));
+
   if (std::optional APV = P.toRValue(S.getCtx())) {
 *Cached = *APV;
 return true;

diff  --git a/clang/lib/AST/Interp/InterpState.h 
b/clang/lib/AST/Interp/InterpState.h
index 925395b6eba0c..138e1d7ac95d5 100644
--- a/clang/lib/AST/Interp/InterpState.h
+++ b/clang/lib/AST/Interp/InterpState.h
@@ -123,6 +123,10 @@ class InterpState final : public State, public 
SourceMapper {
   SourceLocation EvalLocation;
   /// Declaration we're initializing/evaluting, if any.
   const VarDecl *EvaluatingDecl = nullptr;
+
+  

[clang] deb039e - [clang][Interp][NFC] Provide Program accessor for global temporaries

2024-06-29 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-06-29T19:55:30+02:00
New Revision: deb039e69ed7efc94ef517809f36298f40359c21

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

LOG: [clang][Interp][NFC] Provide Program accessor for global temporaries

Just like the one we have taking a ValueDecl*, provide a getGlobal()
version taking an expression.

Added: 


Modified: 
clang/lib/AST/Interp/Program.cpp
clang/lib/AST/Interp/Program.h

Removed: 




diff  --git a/clang/lib/AST/Interp/Program.cpp 
b/clang/lib/AST/Interp/Program.cpp
index caff9d01cdfee..2a1ad4d4eb850 100644
--- a/clang/lib/AST/Interp/Program.cpp
+++ b/clang/lib/AST/Interp/Program.cpp
@@ -126,6 +126,12 @@ std::optional Program::getGlobal(const ValueDecl 
*VD) {
   return std::nullopt;
 }
 
+std::optional Program::getGlobal(const Expr *E) {
+  if (auto It = GlobalIndices.find(E); It != GlobalIndices.end())
+return It->second;
+  return std::nullopt;
+}
+
 std::optional Program::getOrCreateGlobal(const ValueDecl *VD,
const Expr *Init) {
   if (auto Idx = getGlobal(VD))
@@ -195,7 +201,14 @@ std::optional Program::createGlobal(const 
ValueDecl *VD,
 }
 
 std::optional Program::createGlobal(const Expr *E) {
-  return createGlobal(E, E->getType(), /*isStatic=*/true, /*isExtern=*/false);
+  if (auto Idx = getGlobal(E))
+return Idx;
+  if (auto Idx = createGlobal(E, E->getType(), /*isStatic=*/true,
+  /*isExtern=*/false)) {
+GlobalIndices[E] = *Idx;
+return *Idx;
+  }
+  return std::nullopt;
 }
 
 std::optional Program::createGlobal(const DeclTy , QualType Ty,

diff  --git a/clang/lib/AST/Interp/Program.h b/clang/lib/AST/Interp/Program.h
index ec7c0744b8856..1cabc5212180f 100644
--- a/clang/lib/AST/Interp/Program.h
+++ b/clang/lib/AST/Interp/Program.h
@@ -77,6 +77,7 @@ class Program final {
 
   /// Finds a global's index.
   std::optional getGlobal(const ValueDecl *VD);
+  std::optional getGlobal(const Expr *E);
 
   /// Returns or creates a global an creates an index to it.
   std::optional getOrCreateGlobal(const ValueDecl *VD,



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


[clang] d957da8 - [clang][Interp] Allow taking the address of a non-const global reference

2024-06-29 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-06-29T19:55:29+02:00
New Revision: d957da83791930a3c23f4f936ca7c7644c4b07a4

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

LOG: [clang][Interp] Allow taking the address of a non-const global reference

This is not a read, but the GetGlobal op before failed if the reference
we were taking a pointer of was non-const. Use GetGlobalUnchecked
instead.

Added: 


Modified: 
clang/lib/AST/Interp/Compiler.cpp
clang/lib/AST/Interp/Interp.h
clang/test/AST/Interp/references.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Compiler.cpp 
b/clang/lib/AST/Interp/Compiler.cpp
index e21e2c0eb8b6a..8b6f7f644a778 100644
--- a/clang/lib/AST/Interp/Compiler.cpp
+++ b/clang/lib/AST/Interp/Compiler.cpp
@@ -4906,8 +4906,11 @@ bool Compiler::visitDeclRef(const ValueDecl *D, 
const Expr *E) {
   return this->emitGetLocal(PT_Ptr, Offset, E);
 return this->emitGetPtrLocal(Offset, E);
   } else if (auto GlobalIndex = P.getGlobal(D)) {
-if (IsReference)
-  return this->emitGetGlobal(classifyPrim(E), *GlobalIndex, E);
+if (IsReference) {
+  if (!Ctx.getLangOpts().CPlusPlus11)
+return this->emitGetGlobal(classifyPrim(E), *GlobalIndex, E);
+  return this->emitGetGlobalUnchecked(classifyPrim(E), *GlobalIndex, E);
+}
 
 return this->emitGetPtrGlobal(*GlobalIndex, E);
   } else if (const auto *PVD = dyn_cast(D)) {

diff  --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 916d268aa4f09..6c9246f692204 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -1255,7 +1255,10 @@ bool GetGlobal(InterpState , CodePtr OpPC, uint32_t I) 
{
 /// Same as GetGlobal, but without the checks.
 template ::T>
 bool GetGlobalUnchecked(InterpState , CodePtr OpPC, uint32_t I) {
-  auto *B = S.P.getGlobal(I);
+  const Pointer  = S.P.getPtrGlobal(I);
+  if (!Ptr.isInitialized())
+return false;
+  const Block *B = S.P.getGlobal(I);
   S.Stk.push(B->deref());
   return true;
 }

diff  --git a/clang/test/AST/Interp/references.cpp 
b/clang/test/AST/Interp/references.cpp
index efb756545b4aa..9a790dc75d730 100644
--- a/clang/test/AST/Interp/references.cpp
+++ b/clang/test/AST/Interp/references.cpp
@@ -130,3 +130,8 @@ const char (_string_ref)[3] = {"hi"};
 static_assert(nonextended_string_ref[0] == 'h', "");
 static_assert(nonextended_string_ref[1] == 'i', "");
 static_assert(nonextended_string_ref[2] == '\0', "");
+
+/// This isa non-constant context. Reading A is not allowed,
+/// but taking its address is.
+int & = 12;
+int arr[!];



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


[clang] df067e5 - [clang][Interp][NFC] Pretty-print global temporary APValues

2024-06-29 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-06-29T18:29:02+02:00
New Revision: df067e567f7793a7c82096df0387a6e6dd31a828

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

LOG: [clang][Interp][NFC] Pretty-print global temporary APValues

Added: 


Modified: 
clang/lib/AST/Interp/Disasm.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Disasm.cpp b/clang/lib/AST/Interp/Disasm.cpp
index 56c2b7032f6d5..d946a10c22dc3 100644
--- a/clang/lib/AST/Interp/Disasm.cpp
+++ b/clang/lib/AST/Interp/Disasm.cpp
@@ -156,15 +156,28 @@ LLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream 
) const {
 }
 Desc->dump(OS);
 
-if (Desc->IsTemporary) {
+if (GP.isInitialized() && Desc->IsTemporary) {
   if (const auto *MTE =
   dyn_cast_if_present(Desc->asExpr());
   MTE && MTE->getLifetimeExtendedTemporaryDecl()) {
-const APValue *V = MTE->getLifetimeExtendedTemporaryDecl()->getValue();
-if (V->isInt())
-  OS << " (global temporary value: " << V->getInt() << ")";
-else
-  OS << " (huh?)";
+if (const APValue *V =
+MTE->getLifetimeExtendedTemporaryDecl()->getValue()) {
+  OS << " (global temporary value: ";
+  {
+ColorScope SC(OS, true, {llvm::raw_ostream::BRIGHT_MAGENTA, true});
+std::string VStr;
+llvm::raw_string_ostream SS(VStr);
+V->dump(SS, Ctx.getASTContext());
+
+for (unsigned I = 0; I != VStr.size(); ++I) {
+  if (VStr[I] == '\n')
+VStr[I] = ' ';
+}
+VStr.pop_back(); // Remove the newline (or now space) at the end.
+OS << VStr;
+  }
+  OS << ')';
+}
   }
 }
 



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


[clang] 58160e7 - [clang][Interp][NFC] Use const pointers in Descriptor::getType()

2024-06-29 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-06-29T09:42:37+02:00
New Revision: 58160e78e5ed82bdcc1dcbda4d57442aa4e1dd9e

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

LOG: [clang][Interp][NFC] Use const pointers in Descriptor::getType()

Added: 


Modified: 
clang/lib/AST/Interp/Descriptor.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Descriptor.cpp 
b/clang/lib/AST/Interp/Descriptor.cpp
index fea8a7b1d14a9..afafae088aca0 100644
--- a/clang/lib/AST/Interp/Descriptor.cpp
+++ b/clang/lib/AST/Interp/Descriptor.cpp
@@ -355,11 +355,11 @@ Descriptor::Descriptor(const DeclTy )
 }
 
 QualType Descriptor::getType() const {
-  if (auto *E = asExpr())
+  if (const auto *E = asExpr())
 return E->getType();
-  if (auto *D = asValueDecl())
+  if (const auto *D = asValueDecl())
 return D->getType();
-  if (auto *T = dyn_cast(asDecl()))
+  if (const auto *T = dyn_cast(asDecl()))
 return QualType(T->getTypeForDecl(), 0);
   llvm_unreachable("Invalid descriptor type");
 }



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


[clang] 99ff5d5 - [clang][Interp][NFC] Simplify test

2024-06-29 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-06-29T09:42:37+02:00
New Revision: 99ff5d5c963b8bd9ccae99fbb17b8fc537fe8095

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

LOG: [clang][Interp][NFC] Simplify test

Added: 


Modified: 
clang/test/AST/Interp/arrays.cpp

Removed: 




diff  --git a/clang/test/AST/Interp/arrays.cpp 
b/clang/test/AST/Interp/arrays.cpp
index 26ec39e9cca65..933437c3401c4 100644
--- a/clang/test/AST/Interp/arrays.cpp
+++ b/clang/test/AST/Interp/arrays.cpp
@@ -513,11 +513,9 @@ namespace NonConstReads {
 // both-note {{read of non-const variable 'z'}}
 #else
   void *p = nullptr;
-  int arr[!p]; // ref-error {{not allowed at file scope}} \
-   // expected-error {{not allowed at file scope}}
+  int arr[!p]; // both-error {{not allowed at file scope}}
   int z;
-  int a[z]; // ref-error {{not allowed at file scope}} \
-// expected-error {{not allowed at file scope}}
+  int a[z]; // both-error {{not allowed at file scope}}
 #endif
 
   const int y = 0;



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


[clang] 8d3abc9 - [clang][Interp][NFC] Dump expression address

2024-06-29 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-06-29T09:42:36+02:00
New Revision: 8d3abc92d663552b97de083e77d2cc76164d0dd4

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

LOG: [clang][Interp][NFC] Dump expression address

Added: 


Modified: 
clang/lib/AST/Interp/Disasm.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Disasm.cpp b/clang/lib/AST/Interp/Disasm.cpp
index 8204fd1bc040c..56c2b7032f6d5 100644
--- a/clang/lib/AST/Interp/Disasm.cpp
+++ b/clang/lib/AST/Interp/Disasm.cpp
@@ -205,7 +205,7 @@ LLVM_DUMP_METHOD void Descriptor::dump(llvm::raw_ostream 
) const {
 if (const auto *ND = dyn_cast_if_present(asDecl()))
   ND->printQualifiedName(OS);
 else if (asExpr())
-  OS << "expr (TODO)";
+  OS << "Expr " << (const void *)asExpr();
   }
 
   // Print a few interesting bits about the descriptor.



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


[clang] e379629 - [clang][NFC] Use provided stream in APValue::dump()

2024-06-28 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-06-28T10:41:25+02:00
New Revision: e3796291abd83012762c832ec37ac4ecd9aba5ad

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

LOG: [clang][NFC] Use provided stream in APValue::dump()

I assume this is a copy/paste error.

Added: 


Modified: 
clang/lib/AST/ASTDumper.cpp

Removed: 




diff  --git a/clang/lib/AST/ASTDumper.cpp b/clang/lib/AST/ASTDumper.cpp
index f0603880c32dd..864d0393f9a78 100644
--- a/clang/lib/AST/ASTDumper.cpp
+++ b/clang/lib/AST/ASTDumper.cpp
@@ -342,8 +342,7 @@ LLVM_DUMP_METHOD void APValue::dump() const {
 
 LLVM_DUMP_METHOD void APValue::dump(raw_ostream ,
 const ASTContext ) const {
-  ASTDumper Dumper(llvm::errs(), Context,
-   Context.getDiagnostics().getShowColors());
+  ASTDumper Dumper(OS, Context, Context.getDiagnostics().getShowColors());
   Dumper.Visit(*this, /*Ty=*/Context.getPointerType(Context.CharTy));
 }
 



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


[clang] 61975cd - [clang][Interp][NFC] Print global temporary value in Program::dump()

2024-06-27 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-06-27T19:24:35+02:00
New Revision: 61975cdf44a75917a738ca7fa9971b03f6d4fad8

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

LOG: [clang][Interp][NFC] Print global temporary value in Program::dump()

There is quite a problem here, so print both the value we have in
Program as well as the value from the LifetimeExtendedTemporaryDecl.

Added: 


Modified: 
clang/lib/AST/Interp/Disasm.cpp

Removed: 




diff  --git a/clang/lib/AST/Interp/Disasm.cpp b/clang/lib/AST/Interp/Disasm.cpp
index 0ab84d159c58b..8204fd1bc040c 100644
--- a/clang/lib/AST/Interp/Disasm.cpp
+++ b/clang/lib/AST/Interp/Disasm.cpp
@@ -25,6 +25,7 @@
 #include "Program.h"
 #include "clang/AST/ASTDumperUtils.h"
 #include "clang/AST/DeclCXX.h"
+#include "clang/AST/ExprCXX.h"
 #include "llvm/Support/Compiler.h"
 #include "llvm/Support/Format.h"
 
@@ -154,6 +155,19 @@ LLVM_DUMP_METHOD void Program::dump(llvm::raw_ostream ) 
const {
   OS << (GP.isInitialized() ? "initialized " : "uninitialized ");
 }
 Desc->dump(OS);
+
+if (Desc->IsTemporary) {
+  if (const auto *MTE =
+  dyn_cast_if_present(Desc->asExpr());
+  MTE && MTE->getLifetimeExtendedTemporaryDecl()) {
+const APValue *V = MTE->getLifetimeExtendedTemporaryDecl()->getValue();
+if (V->isInt())
+  OS << " (global temporary value: " << V->getInt() << ")";
+else
+  OS << " (huh?)";
+  }
+}
+
 OS << "\n";
 if (GP.isInitialized() && Desc->isPrimitive() && !Desc->isDummy()) {
   OS << "   ";



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


[clang] 50b1534 - [clang][Interp] Don't diagnose non-const reads from the evaluating decl

2024-06-27 Thread Timm Bäder via cfe-commits

Author: Timm Bäder
Date: 2024-06-27T18:01:11+02:00
New Revision: 50b15341182e0a5f53dd6e9b4a00fef56f31147c

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

LOG: [clang][Interp] Don't diagnose non-const reads from the evaluating decl

Added: 


Modified: 
clang/lib/AST/Interp/EvalEmitter.cpp
clang/lib/AST/Interp/Interp.cpp
clang/lib/AST/Interp/InterpState.h

Removed: 




diff  --git a/clang/lib/AST/Interp/EvalEmitter.cpp 
b/clang/lib/AST/Interp/EvalEmitter.cpp
index 77ff901634a46..a13cd94b0ba1c 100644
--- a/clang/lib/AST/Interp/EvalEmitter.cpp
+++ b/clang/lib/AST/Interp/EvalEmitter.cpp
@@ -56,6 +56,7 @@ EvaluationResult EvalEmitter::interpretExpr(const Expr *E,
 EvaluationResult EvalEmitter::interpretDecl(const VarDecl *VD,
 bool CheckFullyInitialized) {
   this->CheckFullyInitialized = CheckFullyInitialized;
+  S.EvaluatingDecl = VD;
 
   if (const Expr *Init = VD->getAnyInitializer()) {
 QualType T = VD->getType();
@@ -69,6 +70,7 @@ EvaluationResult EvalEmitter::interpretDecl(const VarDecl *VD,
   if (!this->visitDecl(VD, S.inConstantContext()) && EvalResult.empty())
 EvalResult.setInvalid();
 
+  S.EvaluatingDecl = nullptr;
   return std::move(this->EvalResult);
 }
 

diff  --git a/clang/lib/AST/Interp/Interp.cpp b/clang/lib/AST/Interp/Interp.cpp
index fc4c0058fbda4..76a0751a006e4 100644
--- a/clang/lib/AST/Interp/Interp.cpp
+++ b/clang/lib/AST/Interp/Interp.cpp
@@ -322,7 +322,7 @@ bool CheckConstant(InterpState , CodePtr OpPC, const 
Descriptor *Desc) {
   };
 
   if (const auto *D = Desc->asVarDecl();
-  D && D->hasGlobalStorage() && !IsConstType(D)) {
+  D && D->hasGlobalStorage() && D != S.EvaluatingDecl && !IsConstType(D)) {
 diagnoseNonConstVariable(S, OpPC, D);
 return S.inConstantContext();
   }

diff  --git a/clang/lib/AST/Interp/InterpState.h 
b/clang/lib/AST/Interp/InterpState.h
index 0938a723a76d0..925395b6eba0c 100644
--- a/clang/lib/AST/Interp/InterpState.h
+++ b/clang/lib/AST/Interp/InterpState.h
@@ -121,6 +121,8 @@ class InterpState final : public State, public SourceMapper 
{
   InterpFrame *Current = nullptr;
   /// Source location of the evaluating expression
   SourceLocation EvalLocation;
+  /// Declaration we're initializing/evaluting, if any.
+  const VarDecl *EvaluatingDecl = nullptr;
 };
 
 } // namespace interp



___
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   >