Skip to content

Commit

Permalink
[clang][Interp] Fix compiling undefined templated functions (#67232)
Browse files Browse the repository at this point in the history
  • Loading branch information
tbaederr committed Sep 25, 2023
1 parent 029c9c3 commit 364757d
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 3 deletions.
6 changes: 5 additions & 1 deletion clang/lib/AST/Interp/ByteCodeEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/Interp/Context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
5 changes: 5 additions & 0 deletions clang/lib/AST/Interp/Function.h
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
Expand Down Expand Up @@ -204,6 +207,7 @@ class Function final {
}

void setIsFullyCompiled(bool FC) { IsFullyCompiled = FC; }
void setDefined(bool D) { Defined = D; }

private:
friend class Program;
Expand Down Expand Up @@ -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().
Expand Down
11 changes: 11 additions & 0 deletions clang/test/AST/Interp/functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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, "");
}

0 comments on commit 364757d

Please sign in to comment.