https://github.com/tbaederr created https://github.com/llvm/llvm-project/pull/67232
None >From ed30d89a3c8f0ec5296561e128b2af8b05ade5ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timm=20B=C3=A4der?= <tbae...@redhat.com> Date: Fri, 22 Sep 2023 21:26:51 +0200 Subject: [PATCH] [clang][Interp] Fix compiling undefined templated functions --- clang/lib/AST/Interp/ByteCodeEmitter.cpp | 6 +++++- clang/lib/AST/Interp/Context.cpp | 4 ++-- clang/lib/AST/Interp/Function.h | 5 +++++ clang/test/AST/Interp/functions.cpp | 11 +++++++++++ 4 files changed, 23 insertions(+), 3 deletions(-) diff --git a/clang/lib/AST/Interp/ByteCodeEmitter.cpp b/clang/lib/AST/Interp/ByteCodeEmitter.cpp index 9b6adcc29bac5f1..f33a151037fd130 100644 --- a/clang/lib/AST/Interp/ByteCodeEmitter.cpp +++ b/clang/lib/AST/Interp/ByteCodeEmitter.cpp @@ -94,8 +94,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 1a732b6c1a092ac..f2f4a5cadc47a4c 100644 --- a/clang/lib/AST/Interp/Context.cpp +++ b/clang/lib/AST/Interp/Context.cpp @@ -214,8 +214,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, ""); +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits