tbaeder updated this revision to Diff 456281.

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

https://reviews.llvm.org/D132832

Files:
  clang/lib/AST/Interp/ByteCodeEmitter.cpp
  clang/lib/AST/Interp/ByteCodeExprGen.cpp
  clang/lib/AST/Interp/ByteCodeStmtGen.cpp
  clang/lib/AST/Interp/Function.h
  clang/test/AST/Interp/cxx20.cpp

Index: clang/test/AST/Interp/cxx20.cpp
===================================================================
--- clang/test/AST/Interp/cxx20.cpp
+++ clang/test/AST/Interp/cxx20.cpp
@@ -2,8 +2,6 @@
 // RUN: %clang_cc1 -std=c++20 -verify=ref %s
 
 
-// expected-no-diagnostics
-// ref-no-diagnostics
 constexpr int getMinus5() {
   int a = 10;
   a = -5;
@@ -53,3 +51,12 @@
   return v;
 }
 //static_assert(pointerAssign2() == 12, ""); TODO
+
+
+constexpr int unInitLocal() {
+  int a;
+  return a; // ref-note{{read of uninitialized object}}
+}
+static_assert(unInitLocal() == 0, ""); // expected-error {{not an integral constant expression}} \
+                                       // ref-error {{not an integral constant expression}} \
+                                       // ref-note {{in call to 'unInitLocal()'}}
Index: clang/lib/AST/Interp/Function.h
===================================================================
--- clang/lib/AST/Interp/Function.h
+++ clang/lib/AST/Interp/Function.h
@@ -112,6 +112,9 @@
   /// Checks if the function is a constructor.
   bool isConstructor() const { return isa<CXXConstructorDecl>(F); }
 
+  /// Checks if the function is fully done compiling.
+  bool isFullyCompiled() const { return IsFullyCompiled; }
+
 private:
   /// Construct a function representing an actual function.
   Function(Program &P, const FunctionDecl *F, unsigned ArgSize,
@@ -128,6 +131,8 @@
     IsValid = true;
   }
 
+  void setIsFullyCompiled(bool FC) { IsFullyCompiled = FC; }
+
 private:
   friend class Program;
   friend class ByteCodeEmitter;
@@ -154,6 +159,9 @@
   llvm::DenseMap<unsigned, ParamDescriptor> Params;
   /// Flag to indicate if the function is valid.
   bool IsValid = false;
+  /// Flag to indicate if the function is done being
+  /// compile to bytecode.
+  bool IsFullyCompiled = false;
 
 public:
   /// Dumps the disassembled bytecode to \c llvm::errs().
Index: clang/lib/AST/Interp/ByteCodeStmtGen.cpp
===================================================================
--- clang/lib/AST/Interp/ByteCodeStmtGen.cpp
+++ clang/lib/AST/Interp/ByteCodeStmtGen.cpp
@@ -238,12 +238,17 @@
 
   // Integers, pointers, primitives.
   if (Optional<PrimType> T = this->classify(VD->getType())) {
+    const Expr *Init = VD->getInit();
     auto Offset =
         this->allocateLocalPrimitive(VD, *T, VD->getType().isConstQualified());
+
+    if (!Init)
+      return false;
+
     // Compile the initialiser in its own scope.
-    {
+    if (Init) {
       ExprScope<Emitter> Scope(this);
-      if (!this->visit(VD->getInit()))
+      if (!this->visit(Init))
         return false;
     }
     // Set the value.
Index: clang/lib/AST/Interp/ByteCodeExprGen.cpp
===================================================================
--- clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -699,6 +699,14 @@
     }
     assert(Func);
 
+    // If the function is being compiled right now, this is a recursive call.
+    // In that case, the function can't be valid yet, even though it will be
+    // later.
+    // If the function is already fully compiled but not constexpr, it was
+    // found to be faulty earlier on, so bail out.
+    if (Func->isFullyCompiled() && !Func->isConstexpr())
+      return false;
+
     QualType ReturnType = E->getCallReturnType(Ctx.getASTContext());
     Optional<PrimType> T = classify(ReturnType);
 
Index: clang/lib/AST/Interp/ByteCodeEmitter.cpp
===================================================================
--- clang/lib/AST/Interp/ByteCodeEmitter.cpp
+++ clang/lib/AST/Interp/ByteCodeEmitter.cpp
@@ -62,8 +62,10 @@
     // Return a dummy function if compilation failed.
     if (BailLocation)
       return llvm::make_error<ByteCodeGenError>(*BailLocation);
-    else
+    else {
+      Func->setIsFullyCompiled(true);
       return Func;
+    }
   } else {
     // Create scopes from descriptors.
     llvm::SmallVector<Scope, 2> Scopes;
@@ -74,6 +76,7 @@
     // Set the function's code.
     Func->setCode(NextLocalOffset, std::move(Code), std::move(SrcMap),
                   std::move(Scopes));
+    Func->setIsFullyCompiled(true);
     return Func;
   }
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to