[clang] 364757d - [clang][Interp] Fix compiling undefined templated functions (#67232)

via cfe-commits cfe-commits at lists.llvm.org
Mon Sep 25 08:28:49 PDT 2023


Author: Timm Baeder
Date: 2023-09-25T17:28:44+02:00
New Revision: 364757d2d5e1498239566941f8ba334e9846c53b

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

LOG: [clang][Interp] Fix compiling undefined templated functions (#67232)

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/clang/lib/AST/Interp/ByteCodeEmitter.cpp b/clang/lib/AST/Interp/ByteCodeEmitter.cpp
index 14593fbffa0e99d..23c28b430d81c22 100644
--- a/clang/lib/AST/Interp/ByteCodeEmitter.cpp
+++ b/clang/lib/AST/Interp/ByteCodeEmitter.cpp
@@ -92,8 +92,12 @@ 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()) {
+    Func->setDefined(false);
     return Func;
+  }
+
+  Func->setDefined(true);
 
   // Lambda static invokers are a special case that we emit custom code for.
   bool IsEligibleForCompilation = false;

diff  --git a/clang/lib/AST/Interp/Context.cpp b/clang/lib/AST/Interp/Context.cpp
index 1c1aacbc8bb9e7d..e84c0f6aae7ee93 100644
--- a/clang/lib/AST/Interp/Context.cpp
+++ b/clang/lib/AST/Interp/Context.cpp
@@ -215,8 +215,8 @@ Context::getOverridingFunction(const CXXRecordDecl *DynamicDecl,
 const Function *Context::getOrCreateFunction(const FunctionDecl *FD) {
   assert(FD);
   const Function *Func = P->getFunction(FD);
-  bool IsBeingCompiled = Func && !Func->isFullyCompiled();
-  bool WasNotDefined = Func && !Func->isConstexpr() && !Func->hasBody();
+  bool IsBeingCompiled = Func && Func->isDefined() && !Func->isFullyCompiled();
+  bool WasNotDefined = Func && !Func->isConstexpr() && !Func->isDefined();
 
   if (IsBeingCompiled)
     return Func;

diff  --git a/clang/lib/AST/Interp/Function.h b/clang/lib/AST/Interp/Function.h
index 5444c9f59cda7ea..0bae314e97701d9 100644
--- a/clang/lib/AST/Interp/Function.h
+++ b/clang/lib/AST/Interp/Function.h
@@ -169,6 +169,9 @@ class Function final {
   /// Checks if the function already has a body attached.
   bool hasBody() const { return HasBody; }
 
+  /// Checks if the function is defined.
+  bool isDefined() const { return Defined; }
+
   unsigned getBuiltinID() const { return F->getBuiltinID(); }
 
   bool isBuiltin() const { return F->getBuiltinID() != 0; }
@@ -204,6 +207,7 @@ class Function final {
   }
 
   void setIsFullyCompiled(bool FC) { IsFullyCompiled = FC; }
+  void setDefined(bool D) { Defined = D; }
 
 private:
   friend class Program;
@@ -245,6 +249,7 @@ class Function final {
   bool HasRVO = false;
   /// If we've already compiled the function's body.
   bool HasBody = false;
+  bool Defined = false;
 
 public:
   /// Dumps the disassembled bytecode to \c llvm::errs().

diff  --git a/clang/test/AST/Interp/functions.cpp b/clang/test/AST/Interp/functions.cpp
index 331df74d50b3d62..5cdecbff1e9d3d4 100644
--- a/clang/test/AST/Interp/functions.cpp
+++ b/clang/test/AST/Interp/functions.cpp
@@ -332,3 +332,14 @@ namespace InvalidReclRefs {
   }
 #endif
 }
+
+namespace TemplateUndefined {
+  template<typename T> constexpr int consume(T);
+  // ok, not a constant expression.
+  const int k = consume(0);
+
+  template<typename T> constexpr int consume(T) { return 0; }
+  // ok, constant expression.
+  constexpr int l = consume(0);
+  static_assert(l == 0, "");
+}


        


More information about the cfe-commits mailing list