[clang] [clang][Interp] Fix compiling undefined templated functions (PR #67232)
Timm Baeder via cfe-commits
cfe-commits at lists.llvm.org
Sat Sep 23 03:47:38 PDT 2023
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?= <tbaeder at 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, "");
+}
More information about the cfe-commits
mailing list