[clang] [Clang] Instantiate constexpr function when they are needed. (PR #173537)
Corentin Jabot via cfe-commits
cfe-commits at lists.llvm.org
Mon Feb 16 11:14:50 PST 2026
https://github.com/cor3ntin updated https://github.com/llvm/llvm-project/pull/173537
>From 9eed555bd86be4accc2096cc40e5de30c809afda Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Wed, 24 Dec 2025 14:30:29 +0100
Subject: [PATCH 1/5] [Clang] Instantiate constexpr function when they are
needed.
This is a rework of #115168, with the sole aim of fixing #73232.
The scaffolding is introduced here is necessary - but not sufficient
for reflection.
Reading the comments on #115168, I think we need to separate multiple
concerns:
- Do we have access to Sema (which this PR provides)
- Can we mutate the AST - which is something individual callers
will have to figure out.
This does **not** fix #59966, as the change is complicated enough
that i want to explore it in a separate PR.
Fixes #73232
---
clang/docs/ReleaseNotes.rst | 155 ++++++++++++++++++
clang/include/clang/AST/ASTContext.h | 17 ++
clang/include/clang/Sema/Sema.h | 3 +
clang/lib/AST/ASTContext.cpp | 7 +
clang/lib/AST/ByteCode/Interp.cpp | 30 +++-
clang/lib/AST/ByteCode/InterpState.cpp | 2 +
clang/lib/AST/ByteCode/State.h | 2 +
clang/lib/AST/ExprConstant.cpp | 42 ++++-
clang/lib/Interpreter/IncrementalParser.cpp | 6 +-
clang/lib/Parse/ParseAST.cpp | 6 +
clang/lib/Sema/Sema.cpp | 30 ++++
.../SemaCXX/constexpr-late-instantiation.cpp | 84 +++++++++-
.../constexpr-subobj-initialization.cpp | 5 +-
.../SemaCXX/cxx2b-consteval-propagate.cpp | 5 +-
14 files changed, 374 insertions(+), 20 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5ac5ae4a7d37e..009a09819f359 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -140,9 +140,97 @@ Non-comprehensive list of changes in this release
Usable in constant expressions. Implicit conversion is supported for
class/struct types with conversion operators.
+<<<<<<< HEAD
- A new generic bit-reverse builtin function ``__builtin_bitreverseg`` that
extends bit-reversal support to all standard integers type, including
``_BitInt``
+=======
+- Added ``__builtin_elementwise_ldexp``.
+
+- Added ``__builtin_elementwise_fshl`` and ``__builtin_elementwise_fshr``.
+
+- ``__builtin_elementwise_abs`` can now be used in constant expression.
+
+- Added ``__builtin_elementwise_minnumnum`` and ``__builtin_elementwise_maxnumnum``.
+
+- Trapping UBSan (e.g. ``-fsanitize=undefined -fsanitize-trap=undefined``) now
+ emits a string describing the reason for trapping into the generated debug
+ info. This feature allows debuggers (e.g. LLDB) to display the reason for
+ trapping if the trap is reached. The string is currently encoded in the debug
+ info as an artificial frame that claims to be inlined at the trap location.
+ The function used for the artificial frame is an artificial function whose
+ name encodes the reason for trapping. The encoding used is currently the same
+ as ``__builtin_verbose_trap`` but might change in the future. This feature is
+ enabled by default but can be disabled by compiling with
+ ``-fno-sanitize-debug-trap-reasons``. The feature has a ``basic`` and
+ ``detailed`` mode (the default). The ``basic`` mode emits a hard-coded string
+ per trap kind (e.g. ``Integer addition overflowed``) and the ``detailed`` mode
+ emits a more descriptive string describing each individual trap (e.g. ``signed
+ integer addition overflow in 'a + b'``). The ``detailed`` mode produces larger
+ debug info than ``basic`` but is more helpful for debugging. The
+ ``-fsanitize-debug-trap-reasons=`` flag can be used to switch between the
+ different modes or disable the feature entirely. Note due to trap merging in
+ optimized builds (i.e. in each function all traps of the same kind get merged
+ into the same trap instruction) the trap reasons might be removed. To prevent
+ this build without optimizations (i.e. use `-O0` or use the `optnone` function
+ attribute) or use the `fno-sanitize-merge=` flag in optimized builds.
+
+- ``__builtin_elementwise_max`` and ``__builtin_elementwise_min`` functions for integer types can
+ now be used in constant expressions.
+
+- A vector of booleans is now a valid condition for the ternary ``?:`` operator.
+ This binds to a simple vector select operation.
+
+- Added ``__builtin_masked_load``, ``__builtin_masked_expand_load``,
+ ``__builtin_masked_store``, ``__builtin_masked_compress_store`` for
+ conditional memory loads from vectors. Binds to the LLVM intrinsics of the
+ same name.
+
+- Added ``__builtin_masked_gather`` and ``__builtin_masked_scatter`` for
+ conditional gathering and scattering operations on vectors. Binds to the LLVM
+ intrinsics of the same name.
+
+- The ``__builtin_popcountg``, ``__builtin_ctzg``, and ``__builtin_clzg``
+ functions now accept fixed-size boolean vectors.
+
+- Use of ``__has_feature`` to detect the ``ptrauth_qualifier`` and ``ptrauth_intrinsics``
+ features has been deprecated, and is restricted to the arm64e target only. The
+ correct method to check for these features is to test for the ``__PTRAUTH__``
+ macro.
+
+- Added a new builtin, ``__builtin_dedup_pack``, to remove duplicate types from a parameter pack.
+ This feature is particularly useful in template metaprogramming for normalizing type lists.
+ The builtin produces a new, unexpanded parameter pack that can be used in contexts like template
+ argument lists or base specifiers.
+
+ .. code-block:: c++
+
+ template <typename...> struct TypeList;
+
+ // The resulting type is TypeList<int, double, char>
+ using MyTypeList = TypeList<__builtin_dedup_pack<int, double, int, char, double>...>;
+
+ Currently, the use of ``__builtin_dedup_pack`` is limited to template arguments and base
+ specifiers, it also must be used within a template context.
+
+- ``__builtin_assume_dereferenceable`` now accepts non-constant size operands.
+
+- Fixed a crash when the second argument to ``__builtin_assume_aligned`` was not constant (#GH161314)
+
+- Introduce support for :doc:`allocation tokens <AllocToken>` to enable
+ allocator-level heap organization strategies. A feature to instrument all
+ allocation functions with a token ID can be enabled via the
+ ``-fsanitize=alloc-token`` flag.
+
+- A new generic byte swap builtin function ``__builtin_bswapg`` that extends the existing
+ __builtin_bswap{16,32,64} function family to support all standard integer types.
+
+- A builtin ``__builtin_infer_alloc_token(<args>, ...)`` is provided to allow
+ compile-time querying of allocation token IDs, where the builtin arguments
+ mirror those normally passed to an allocation function.
+
+- Clang now rejects the invalid use of ``constexpr`` with ``auto`` and an explicit type in C. (#GH163090)
+>>>>>>> 3f06fd997749 ([Clang] Instantiate constexpr function when they are needed.)
New Compiler Flags
------------------
@@ -230,6 +318,7 @@ Improvements to Clang's diagnostics
.. code-block:: c++
+<<<<<<< HEAD
struct DanglingView {
std::string_view view;
DanglingView(std::string s) : view(s) {} // warning: address of stack memory escapes to a field
@@ -246,6 +335,14 @@ Improvements to Clang's diagnostics
- The ``-Wloop-analysis`` warning has been extended to catch more cases of
variable modification inside lambda expressions (#GH132038).
+=======
+- Fixed a crash when enabling ``-fdiagnostics-format=sarif`` and the output
+ carries messages like 'In file included from ...' or 'In module ...'.
+ Now the include/import locations are written into `sarif.run.result.relatedLocations`.
+
+- Clang now generates a fix-it for C++20 designated initializers when the
+ initializers do not match the declaration order in the structure.
+>>>>>>> 3f06fd997749 ([Clang] Instantiate constexpr function when they are needed.)
Improvements to Clang's time-trace
----------------------------------
@@ -280,10 +377,68 @@ Bug Fixes to Attribute Support
Bug Fixes to C++ Support
^^^^^^^^^^^^^^^^^^^^^^^^
+<<<<<<< HEAD
- Fixed a crash when instantiating ``requires`` expressions involving substitution failures in C++ concepts. (#GH176402)
- Fixed a crash when a default argument is passed to an explicit object parameter. (#GH176639)
- Fixed a crash when diagnosing an invalid static member function with an explicit object parameter (#GH177741)
- Fixed a crash when evaluating uninitialized GCC vector/ext_vector_type vectors in ``constexpr``. (#GH180044)
+=======
+- Diagnose binding a reference to ``*nullptr`` during constant evaluation. (#GH48665)
+- Suppress ``-Wdeprecated-declarations`` in implicitly generated functions. (#GH147293)
+- Fix a crash when deleting a pointer to an incomplete array (#GH150359).
+- Fixed a mismatched lambda scope bug when propagating up ``consteval`` within nested lambdas. (#GH145776)
+- Disallow immediate escalation in destructors. (#GH109096)
+- Fix an assertion failure when expression in assumption attribute
+ (``[[assume(expr)]]``) creates temporary objects.
+- Fix the dynamic_cast to final class optimization to correctly handle
+ casts that are guaranteed to fail (#GH137518).
+- Fix bug rejecting partial specialization of variable templates with auto NTTPs (#GH118190).
+- Fix a crash if errors "member of anonymous [...] redeclares" and
+ "initializing multiple members of union" coincide (#GH149985).
+- Fix a crash when using ``explicit(bool)`` in pre-C++11 language modes. (#GH152729)
+- Fix the parsing of variadic member functions when the ellipis immediately follows a default argument.(#GH153445)
+- Fix a crash when using an explicit object parameter in a non-member function with an invalid return type.(#GH173943)
+- Fixed a bug that caused ``this`` captured by value in a lambda with a dependent explicit object parameter to not be
+ instantiated properly. (#GH154054)
+- Fixed a bug where our ``member-like constrained friend`` checking caused an incorrect analysis of lambda captures. (#GH156225)
+- Fixed a crash when implicit conversions from initialize list to arrays of
+ unknown bound during constant evaluation. (#GH151716)
+- Instantiate constexpr functions as needed before they are evaluated. (#GH73232)
+- Support the dynamic_cast to final class optimization with pointer
+ authentication enabled. (#GH152601)
+- Fix the check for narrowing int-to-float conversions, so that they are detected in
+ cases where converting the float back to an integer is undefined behaviour (#GH157067).
+- Stop rejecting C++11-style attributes on the first argument of constructors in older
+ standards. (#GH156809).
+- Fix a crash when applying binary or ternary operators to two same function types with different spellings,
+ where at least one of the function parameters has an attribute which affects
+ the function type.
+- Fix an assertion failure when a ``constexpr`` variable is only referenced through
+ ``__builtin_addressof``, and related issues with builtin arguments. (#GH154034)
+- Fix an assertion failure when taking the address on a non-type template parameter argument of
+ object type. (#GH151531)
+- Suppress ``-Wdouble-promotion`` when explicitly asked for with C++ list initialization (#GH33409).
+- Fix the result of `__builtin_is_implicit_lifetime` for types with a user-provided constructor. (#GH160610)
+- Correctly deduce return types in ``decltype`` expressions. (#GH160497) (#GH56652) (#GH116319) (#GH161196)
+- Fixed a crash in the pre-C++23 warning for attributes before a lambda declarator (#GH161070).
+- Fix a crash when attempting to deduce a deduction guide from a non deducible template template parameter. (#130604)
+- Fix for clang incorrectly rejecting the default construction of a union with
+ nontrivial member when another member has an initializer. (#GH81774)
+- Fixed a template depth issue when parsing lambdas inside a type constraint. (#GH162092)
+- Fix the support of zero-length arrays in SFINAE context. (#GH170040)
+- Diagnose unresolved overload sets in non-dependent compound requirements. (#GH51246) (#GH97753)
+- Fix a crash when extracting unavailable member type from alias in template deduction. (#GH165560)
+- Fix incorrect diagnostics for lambdas with init-captures inside braced initializers. (#GH163498)
+- Fixed an issue where templates prevented nested anonymous records from checking the deletion of special members. (#GH167217)
+- Fixed serialization of pack indexing types, where we failed to expand those packs from a PCH/module. (#GH172464)
+- Fixed spurious diagnoses of certain nested lambda expressions. (#GH149121) (#GH156579)
+- Fix the result of ``__is_pointer_interconvertible_base_of`` when arguments are qualified and passed via template parameters. (#GH135273)
+- Fixed a crash when evaluating nested requirements in requires-expressions that reference invented parameters. (#GH166325)
+- Fixed a crash when standard comparison categories (e.g. ``std::partial_ordering``) are defined with incorrect static member types. (#GH170015) (#GH56571)
+- Fixed a crash when parsing the ``enable_if`` attribute on C function declarations with identifier-list parameters. (#GH173826)
+- Fixed an assertion failure triggered by nested lambdas during capture handling. (#GH172814)
+- Fixed an assertion failure in vector conversions involving instantiation-dependent template expressions. (#GH173347)
+>>>>>>> 3f06fd997749 ([Clang] Instantiate constexpr function when they are needed.)
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index 6b819de2fb36d..bf75813922c6e 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -44,6 +44,7 @@
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Support/TypeSize.h"
+#include <memory>
#include <optional>
namespace llvm {
@@ -215,6 +216,16 @@ struct TypeInfoChars {
}
};
+/// Interface that allows constant evaluator to call Sema
+/// and mutate the AST.
+struct SemaProxy {
+ virtual ~SemaProxy() = default;
+
+ virtual void
+ InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
+ FunctionDecl *Function) = 0;
+};
+
/// Holds long-lived AST nodes (such as types and decls) that can be
/// referred to throughout the semantic analysis of a file.
class ASTContext : public RefCountedBase<ASTContext> {
@@ -786,6 +797,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// Keeps track of the deallocated DeclListNodes for future reuse.
DeclListNode *ListNodeFreeList = nullptr;
+ std::unique_ptr<SemaProxy> SemaProxyPtr;
+
public:
IdentifierTable &Idents;
SelectorTable &Selectors;
@@ -1409,6 +1422,10 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// with this AST context, if any.
ASTMutationListener *getASTMutationListener() const { return Listener; }
+ SemaProxy *getSemaProxy();
+
+ void setSemaProxy(std::unique_ptr<SemaProxy> Proxy);
+
void PrintStats() const;
const SmallVectorImpl<Type *>& getTypes() const { return Types; }
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 9424b80d5cdb6..fa8a54a3730ac 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -910,6 +910,9 @@ class Sema final : public SemaBase {
/// initialized but before it parses anything.
void Initialize();
+ void RegisterSemaProxy();
+ void UnregisterSemaProxy();
+
/// This virtual key function only exists to limit the emission of debug info
/// describing the Sema class. GCC and Clang only emit debug info for a class
/// with a vtable when the vtable is emitted. Sema is final and not
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 3f63420cae91e..eb70a9d91cc0c 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -926,6 +926,13 @@ ASTContext::setExternalSource(IntrusiveRefCntPtr<ExternalASTSource> Source) {
ExternalSource = std::move(Source);
}
+SemaProxy *ASTContext::getSemaProxy() { return SemaProxyPtr.get(); }
+
+void ASTContext::setSemaProxy(std::unique_ptr<SemaProxy> Proxy) {
+ assert((!SemaProxyPtr || !Proxy) && "SemaProxy already set");
+ SemaProxyPtr = std::move(Proxy);
+}
+
void ASTContext::PrintStats() const {
llvm::errs() << "\n*** AST Context Stats:\n";
llvm::errs() << " " << Types.size() << " types total.\n";
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index bb259822c3dfe..11f629d0d97c5 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "Interp.h"
+#include "ByteCode/Source.h"
#include "Compiler.h"
#include "Function.h"
#include "InterpFrame.h"
@@ -1624,13 +1625,30 @@ bool CheckBitCast(InterpState &S, CodePtr OpPC, const Type *TargetType,
return true;
}
-static void compileFunction(InterpState &S, const Function *Func) {
- const FunctionDecl *Definition = Func->getDecl()->getDefinition();
- if (!Definition)
+static void compileFunction(InterpState &S, const Function *Func,
+ SourceLocation Loc) {
+
+ const FunctionDecl *Fn = Func->getDecl();
+
+ // [C++26] [temp.inst] p5
+ // [...] the function template specialization is implicitly instantiated
+ // when the specialization is referenced in a context that requires a function
+ // definition to exist or if the existence of the definition affects the
+ // semantics of the program.
+ if (!Fn->isDefined() && Fn->isImplicitlyInstantiable() && Fn->isConstexpr() &&
+ S.inConstantContext() && !S.TryConstantInitialization &&
+ !S.checkingPotentialConstantExpression()) {
+ SemaProxy *SP = S.getASTContext().getSemaProxy();
+ if (!SP)
+ return;
+ SP->InstantiateFunctionDefinition(Loc, const_cast<FunctionDecl *>(Fn));
+ }
+ Fn = Fn->getDefinition();
+ if (!Fn)
return;
Compiler<ByteCodeEmitter>(S.getContext(), S.P)
- .compileFunc(Definition, const_cast<Function *>(Func));
+ .compileFunc(Fn, const_cast<Function *>(Func));
}
bool CallVar(InterpState &S, CodePtr OpPC, const Function *Func,
@@ -1656,7 +1674,7 @@ bool CallVar(InterpState &S, CodePtr OpPC, const Function *Func,
}
if (!Func->isFullyCompiled())
- compileFunction(S, Func);
+ compileFunction(S, Func, S.Current->getLocation(OpPC));
if (!CheckCallable(S, OpPC, Func))
return false;
@@ -1733,7 +1751,7 @@ bool Call(InterpState &S, CodePtr OpPC, const Function *Func,
}
if (!Func->isFullyCompiled())
- compileFunction(S, Func);
+ compileFunction(S, Func, S.Current->getLocation(OpPC));
if (!CheckCallable(S, OpPC, Func))
return cleanup();
diff --git a/clang/lib/AST/ByteCode/InterpState.cpp b/clang/lib/AST/ByteCode/InterpState.cpp
index df507bd5507c3..d8a8d76b9f06d 100644
--- a/clang/lib/AST/ByteCode/InterpState.cpp
+++ b/clang/lib/AST/ByteCode/InterpState.cpp
@@ -24,6 +24,7 @@ InterpState::InterpState(const State &Parent, Program &P, InterpStack &Stk,
StepsLeft(Ctx.getLangOpts().ConstexprStepLimit),
InfiniteSteps(StepsLeft == 0) {
InConstantContext = Parent.InConstantContext;
+ TryConstantInitialization = Parent.TryConstantInitialization;
CheckingPotentialConstantExpression =
Parent.CheckingPotentialConstantExpression;
CheckingForUndefinedBehavior = Parent.CheckingForUndefinedBehavior;
@@ -38,6 +39,7 @@ InterpState::InterpState(const State &Parent, Program &P, InterpStack &Stk,
Current(&BottomFrame), StepsLeft(Ctx.getLangOpts().ConstexprStepLimit),
InfiniteSteps(StepsLeft == 0) {
InConstantContext = Parent.InConstantContext;
+ TryConstantInitialization = Parent.TryConstantInitialization;
CheckingPotentialConstantExpression =
Parent.CheckingPotentialConstantExpression;
CheckingForUndefinedBehavior = Parent.CheckingForUndefinedBehavior;
diff --git a/clang/lib/AST/ByteCode/State.h b/clang/lib/AST/ByteCode/State.h
index a720033c7914b..841da0836516d 100644
--- a/clang/lib/AST/ByteCode/State.h
+++ b/clang/lib/AST/ByteCode/State.h
@@ -187,6 +187,8 @@ class State {
/// is set; this is used when evaluating ICEs in C.
bool CheckingForUndefinedBehavior = false;
+ bool TryConstantInitialization = false;
+
EvaluationMode EvalMode;
ASTContext &Ctx;
Expr::EvalStatus &EvalStatus;
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 2c13befec02f2..7ceea521640f2 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -43,6 +43,7 @@
#include "clang/AST/CXXInheritance.h"
#include "clang/AST/CharUnits.h"
#include "clang/AST/CurrentSourceLocExprScope.h"
+#include "clang/AST/Decl.h"
#include "clang/AST/Expr.h"
#include "clang/AST/InferAlloc.h"
#include "clang/AST/OSLog.h"
@@ -53,6 +54,7 @@
#include "clang/AST/TypeLoc.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/DiagnosticSema.h"
+#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/TargetBuiltins.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/APFixedPoint.h"
@@ -6961,6 +6963,28 @@ static bool handleTrivialCopy(EvalInfo &Info, const ParmVarDecl *Param,
CopyObjectRepresentation);
}
+static void InstantiateFunctionBeforeCall(const FunctionDecl *FD,
+ EvalInfo &Info, SourceLocation Loc) {
+
+ // [C++26] [temp.inst] p5
+ // [...] the function template specialization is implicitly instantiated
+ // when the specialization is referenced in a context that requires a function
+ // definition to exist or if the existence of the definition affects the
+ // semantics of the program.
+
+ if (!FD->isDefined() && FD->isImplicitlyInstantiable() && FD->isConstexpr() &&
+ Info.InConstantContext && !Info.TryConstantInitialization &&
+ !Info.checkingPotentialConstantExpression()) {
+
+ SemaProxy *SP = Info.getASTContext().getSemaProxy();
+ // Try to instantiate the definition if Sema is available
+ // (i.e during the initial parse of the TU).
+ if (SP) {
+ SP->InstantiateFunctionDefinition(Loc, const_cast<FunctionDecl *>(FD));
+ }
+ }
+}
+
/// Evaluate a function call.
static bool HandleFunctionCall(SourceLocation CallLoc,
const FunctionDecl *Callee,
@@ -7354,6 +7378,8 @@ static bool HandleDestructionImpl(EvalInfo &Info, SourceRange CallRange,
if (!Info.CheckCallLimit(CallRange.getBegin()))
return false;
+ InstantiateFunctionBeforeCall(DD, Info, CallRange.getBegin());
+
const FunctionDecl *Definition = nullptr;
const Stmt *Body = DD->getBody(Definition);
@@ -8819,10 +8845,13 @@ class ExprEvaluatorBase
CallScope.destroy();
}
- const FunctionDecl *Definition = nullptr;
- Stmt *Body = FD->getBody(Definition);
SourceLocation Loc = E->getExprLoc();
+ InstantiateFunctionBeforeCall(FD, Info, Loc);
+
+ const FunctionDecl *Definition = nullptr;
+ const Stmt *Body = FD->getBody(Definition);
+
// Treat the object argument as `this` when evaluating defaulted
// special menmber functions
if (FD->hasCXXExplicitFunctionObjectParameter())
@@ -11340,8 +11369,10 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E,
return handleDefaultInitValue(T, Result);
}
+ InstantiateFunctionBeforeCall(FD, Info, E->getBeginLoc());
+
const FunctionDecl *Definition = nullptr;
- auto Body = FD->getBody(Definition);
+ const Stmt *Body = FD->getBody(Definition);
if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body))
return false;
@@ -11381,8 +11412,9 @@ bool RecordExprEvaluator::VisitCXXInheritedCtorInitExpr(
if (FD->isInvalidDecl() || FD->getParent()->isInvalidDecl())
return false;
+ InstantiateFunctionBeforeCall(FD, Info, E->getBeginLoc());
const FunctionDecl *Definition = nullptr;
- auto Body = FD->getBody(Definition);
+ const Stmt *Body = FD->getBody(Definition);
if (!CheckConstexprFunction(Info, E->getExprLoc(), FD, Definition, Body))
return false;
@@ -20796,6 +20828,8 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx,
: EvaluationMode::ConstantFold);
Info.setEvaluatingDecl(VD, Value);
Info.InConstantContext = IsConstantInitialization;
+ Info.TryConstantInitialization =
+ !VD->isConstexpr() && !VD->hasAttr<ConstInitAttr>();
SourceLocation DeclLoc = VD->getLocation();
QualType DeclTy = VD->getType();
diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp
index bf08911e23533..5a24342e73ca4 100644
--- a/clang/lib/Interpreter/IncrementalParser.cpp
+++ b/clang/lib/Interpreter/IncrementalParser.cpp
@@ -42,9 +42,13 @@ IncrementalParser::IncrementalParser(CompilerInstance &Instance,
External->StartTranslationUnit(Consumer);
P->Initialize();
+ S.RegisterSemaProxy();
}
-IncrementalParser::~IncrementalParser() { P.reset(); }
+IncrementalParser::~IncrementalParser() {
+ S.UnregisterSemaProxy();
+ P.reset();
+}
llvm::Expected<TranslationUnitDecl *>
IncrementalParser::ParseOrWrapTopLevelDecl() {
diff --git a/clang/lib/Parse/ParseAST.cpp b/clang/lib/Parse/ParseAST.cpp
index c8ee625eb57ad..1cea282f13a00 100644
--- a/clang/lib/Parse/ParseAST.cpp
+++ b/clang/lib/Parse/ParseAST.cpp
@@ -21,6 +21,7 @@
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaConsumer.h"
#include "clang/Sema/TemplateInstCallback.h"
+#include "llvm/ADT/ScopeExit.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include "llvm/Support/TimeProfiler.h"
#include <cstdio>
@@ -161,6 +162,11 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) {
return M;
});
P.Initialize();
+
+ auto Unregister =
+ llvm::make_scope_exit([&S]() { S.UnregisterSemaProxy(); });
+ S.RegisterSemaProxy();
+
Parser::DeclGroupPtrTy ADecl;
Sema::ModuleImportState ImportState;
EnterExpressionEvaluationContext PotentiallyEvaluated(
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index d53527af38653..90b919974586b 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -75,11 +75,14 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/TimeProfiler.h"
+#include <memory>
#include <optional>
using namespace clang;
using namespace sema;
+static std::unique_ptr<SemaProxy> getSemaProxyImplementation(Sema &SemaRef);
+
SourceLocation Sema::getLocForEndOfToken(SourceLocation Loc, unsigned Offset) {
return Lexer::getLocForEndOfToken(Loc, Offset, SourceMgr, LangOpts);
}
@@ -622,6 +625,15 @@ Sema::~Sema() {
SemaPPCallbackHandler->reset();
}
+void Sema::RegisterSemaProxy() {
+ // Let the AST context relies on Sema for
+ // ast mutations features that require semantic analysis
+ // (lazy instantiation, reflection, etc).
+ Context.setSemaProxy(getSemaProxyImplementation(*this));
+}
+
+void Sema::UnregisterSemaProxy() { Context.setSemaProxy({}); }
+
void Sema::runWithSufficientStackSpace(SourceLocation Loc,
llvm::function_ref<void()> Fn) {
StackHandler.runWithSufficientStackSpace(Loc, Fn);
@@ -2964,3 +2976,21 @@ Attr *Sema::CreateAnnotationAttr(const ParsedAttr &AL) {
return CreateAnnotationAttr(AL, Str, Args);
}
+
+class SemaProxyImplementation final : public SemaProxy {
+private:
+ Sema &SemaRef;
+
+public:
+ SemaProxyImplementation(Sema &SemaRef) : SemaRef(SemaRef) {}
+ void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
+ FunctionDecl *Function) override {
+ SemaRef.InstantiateFunctionDefinition(
+ PointOfInstantiation, Function, /*Recursive=*/true,
+ /*DefinitionRequired=*/true, /*AtEndOfTU=*/false);
+ }
+};
+
+std::unique_ptr<SemaProxy> getSemaProxyImplementation(Sema &SemaRef) {
+ return std::make_unique<SemaProxyImplementation>(SemaRef);
+}
diff --git a/clang/test/SemaCXX/constexpr-late-instantiation.cpp b/clang/test/SemaCXX/constexpr-late-instantiation.cpp
index 9aec0c90e61dc..59cfbfdff0e03 100644
--- a/clang/test/SemaCXX/constexpr-late-instantiation.cpp
+++ b/clang/test/SemaCXX/constexpr-late-instantiation.cpp
@@ -1,16 +1,90 @@
-// RUN: %clang_cc1 %s -fsyntax-only -verify
-// RUN: %clang_cc1 %s -fexperimental-new-constant-interpreter -fsyntax-only -verify
+// RUN: %clang_cc1 %s -std=c++14 -fsyntax-only -verify
+// RUN: %clang_cc1 %s -std=c++20 -fsyntax-only -verify
+// RUN: %clang_cc1 %s -std=c++2c -fsyntax-only -verify
+
+// RUN: %clang_cc1 %s -std=c++14 -fsyntax-only -fexperimental-new-constant-interpreter -verify
+// RUN: %clang_cc1 %s -std=c++20 -fsyntax-only -fexperimental-new-constant-interpreter -verify
+// RUN: %clang_cc1 %s -std=c++2c -fsyntax-only -fexperimental-new-constant-interpreter -verify
template <typename T>
-constexpr T foo(T a); // expected-note {{declared here}}
+constexpr T foo(T a); // expected-note {{explicit instantiation refers here}}
int main() {
int k = foo<int>(5); // Ok
- constexpr int j = // expected-error {{constexpr variable 'j' must be initialized by a constant expression}}
- foo<int>(5); // expected-note {{undefined function 'foo<int>' cannot be used in a constant expression}}
+ constexpr int j =
+ foo<int>(5); // expected-error {{explicit instantiation of undefined function template 'foo'}} \
+ // expected-error {{constexpr variable 'j' must be initialized by a constant expression}}
}
template <typename T>
constexpr T foo(T a) {
return a;
}
+
+
+namespace GH73232 {
+namespace ex1 {
+template <typename T>
+constexpr void g(T);
+
+constexpr int f() {
+ g(0);
+ return 0;
+}
+
+template <typename T>
+constexpr void g(T) {}
+
+constexpr auto z = f();
+}
+
+namespace ex2 {
+template <typename> constexpr static void fromType();
+
+void registerConverter() { fromType<int>(); }
+template <typename> struct QMetaTypeId {};
+template <typename T> constexpr void fromType() {
+ (void)QMetaTypeId<T>{};
+}
+template <> struct QMetaTypeId<int> {};
+} // namespace ex2
+
+namespace ex3 {
+
+#if __cplusplus > 202302L
+struct A {
+ consteval A(int i) {
+ chk(i);
+ }
+ constexpr void chk(auto) {}
+};
+A a{1};
+
+#endif
+
+}
+
+} // namespace GH73232
+
+
+namespace GH156255 {
+
+class X
+{
+public:
+ constexpr int f( int x ) const
+ {
+ return g( x );
+ }
+
+private:
+
+ template<class T>
+ constexpr T g( T x ) const
+ {
+ return x;
+ }
+};
+
+constexpr int x = X().f( 1 );
+}
diff --git a/clang/test/SemaCXX/constexpr-subobj-initialization.cpp b/clang/test/SemaCXX/constexpr-subobj-initialization.cpp
index f0252df1e2ce1..c2e51d3920f6a 100644
--- a/clang/test/SemaCXX/constexpr-subobj-initialization.cpp
+++ b/clang/test/SemaCXX/constexpr-subobj-initialization.cpp
@@ -47,12 +47,13 @@ constexpr Bar bb; // expected-error {{must be initialized by a constant expressi
template <typename Ty>
struct Baz {
- constexpr Baz(); // expected-note {{declared here}}
+ constexpr Baz(); // expected-note {{explicit instantiation refers here}}
};
struct Quux : Baz<Foo>, private Bar {
int i;
- constexpr Quux() : i(12) {} // expected-note {{undefined constructor 'Baz' cannot be used in a constant expression}}
+ constexpr Quux() : i(12) {} // expected-error {{explicit instantiation of undefined member function 'Baz' of class template 'Baz<Foo>'}} \
+ // expected-note {{subexpression not valid in a constant expression}}
};
constexpr Quux qx; // expected-error {{must be initialized by a constant expression}} \
diff --git a/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp b/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
index 39097d17441f7..a2c5b583904f2 100644
--- a/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
+++ b/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
@@ -75,10 +75,11 @@ struct a {
a aa(fdupe<int>((f<int>(7))));
template <typename T>
-constexpr int foo(T t); // expected-note {{declared here}}
+constexpr int foo(T t); // expected-note {{explicit instantiation refers here}}
a bb(f<int>(foo<int>(7))); // expected-error{{call to immediate function 'f<int>' is not a constant expression}} \
- // expected-note{{undefined function 'foo<int>' cannot be used in a constant expression}}
+ // expected-error{{explicit instantiation of undefined function template 'foo'}} \
+ // expected-note{{subexpression not valid in a constant expression}}
}
>From 3a3ad6cb7cb21df5fb9757770dfb7ffe1be1f071 Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Fri, 2 Jan 2026 10:11:38 +0100
Subject: [PATCH 2/5] Address some review comments
---
clang/docs/ReleaseNotes.rst | 2 +-
clang/lib/AST/ByteCode/Interp.cpp | 12 ++---
clang/lib/AST/ByteCode/InterpState.cpp | 4 +-
clang/lib/AST/ByteCode/State.h | 4 +-
clang/lib/AST/ExprConstant.cpp | 4 +-
clang/lib/Sema/Sema.cpp | 5 +-
.../SemaCXX/constexpr-late-instantiation.cpp | 49 +++++++++++++++++++
7 files changed, 65 insertions(+), 15 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 009a09819f359..e0b69dac70baa 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -403,7 +403,7 @@ Bug Fixes to C++ Support
- Fixed a bug where our ``member-like constrained friend`` checking caused an incorrect analysis of lambda captures. (#GH156225)
- Fixed a crash when implicit conversions from initialize list to arrays of
unknown bound during constant evaluation. (#GH151716)
-- Instantiate constexpr functions as needed before they are evaluated. (#GH73232)
+- Instantiate constexpr functions as needed before they are evaluated. (#GH73232) (#GH35052) (#GH100897)
- Support the dynamic_cast to final class optimization with pointer
authentication enabled. (#GH152601)
- Fix the check for narrowing int-to-float conversions, so that they are detected in
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index 11f629d0d97c5..b725ccc6a1a20 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -7,7 +7,6 @@
//===----------------------------------------------------------------------===//
#include "Interp.h"
-#include "ByteCode/Source.h"
#include "Compiler.h"
#include "Function.h"
#include "InterpFrame.h"
@@ -1626,7 +1625,7 @@ bool CheckBitCast(InterpState &S, CodePtr OpPC, const Type *TargetType,
}
static void compileFunction(InterpState &S, const Function *Func,
- SourceLocation Loc) {
+ CodePtr OpPC) {
const FunctionDecl *Fn = Func->getDecl();
@@ -1636,12 +1635,13 @@ static void compileFunction(InterpState &S, const Function *Func,
// definition to exist or if the existence of the definition affects the
// semantics of the program.
if (!Fn->isDefined() && Fn->isImplicitlyInstantiable() && Fn->isConstexpr() &&
- S.inConstantContext() && !S.TryConstantInitialization &&
+ S.inConstantContext() && !S.PerformingTrialEvaluation &&
!S.checkingPotentialConstantExpression()) {
SemaProxy *SP = S.getASTContext().getSemaProxy();
if (!SP)
return;
- SP->InstantiateFunctionDefinition(Loc, const_cast<FunctionDecl *>(Fn));
+ SP->InstantiateFunctionDefinition(S.Current->getLocation(OpPC),
+ const_cast<FunctionDecl *>(Fn));
}
Fn = Fn->getDefinition();
if (!Fn)
@@ -1674,7 +1674,7 @@ bool CallVar(InterpState &S, CodePtr OpPC, const Function *Func,
}
if (!Func->isFullyCompiled())
- compileFunction(S, Func, S.Current->getLocation(OpPC));
+ compileFunction(S, Func, OpPC);
if (!CheckCallable(S, OpPC, Func))
return false;
@@ -1751,7 +1751,7 @@ bool Call(InterpState &S, CodePtr OpPC, const Function *Func,
}
if (!Func->isFullyCompiled())
- compileFunction(S, Func, S.Current->getLocation(OpPC));
+ compileFunction(S, Func, OpPC);
if (!CheckCallable(S, OpPC, Func))
return cleanup();
diff --git a/clang/lib/AST/ByteCode/InterpState.cpp b/clang/lib/AST/ByteCode/InterpState.cpp
index d8a8d76b9f06d..4d6c182392e1c 100644
--- a/clang/lib/AST/ByteCode/InterpState.cpp
+++ b/clang/lib/AST/ByteCode/InterpState.cpp
@@ -24,7 +24,7 @@ InterpState::InterpState(const State &Parent, Program &P, InterpStack &Stk,
StepsLeft(Ctx.getLangOpts().ConstexprStepLimit),
InfiniteSteps(StepsLeft == 0) {
InConstantContext = Parent.InConstantContext;
- TryConstantInitialization = Parent.TryConstantInitialization;
+ PerformingTrialEvaluation = Parent.PerformingTrialEvaluation;
CheckingPotentialConstantExpression =
Parent.CheckingPotentialConstantExpression;
CheckingForUndefinedBehavior = Parent.CheckingForUndefinedBehavior;
@@ -39,7 +39,7 @@ InterpState::InterpState(const State &Parent, Program &P, InterpStack &Stk,
Current(&BottomFrame), StepsLeft(Ctx.getLangOpts().ConstexprStepLimit),
InfiniteSteps(StepsLeft == 0) {
InConstantContext = Parent.InConstantContext;
- TryConstantInitialization = Parent.TryConstantInitialization;
+ PerformingTrialEvaluation = Parent.PerformingTrialEvaluation;
CheckingPotentialConstantExpression =
Parent.CheckingPotentialConstantExpression;
CheckingForUndefinedBehavior = Parent.CheckingForUndefinedBehavior;
diff --git a/clang/lib/AST/ByteCode/State.h b/clang/lib/AST/ByteCode/State.h
index 841da0836516d..c4a4071f6f359 100644
--- a/clang/lib/AST/ByteCode/State.h
+++ b/clang/lib/AST/ByteCode/State.h
@@ -187,7 +187,9 @@ class State {
/// is set; this is used when evaluating ICEs in C.
bool CheckingForUndefinedBehavior = false;
- bool TryConstantInitialization = false;
+ /// Whether we are performing trial evaluation, i.e when evaluating the
+ /// initializer of a constant-initialized variable.
+ bool PerformingTrialEvaluation = false;
EvaluationMode EvalMode;
ASTContext &Ctx;
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 7ceea521640f2..d2026108e9de1 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -6973,7 +6973,7 @@ static void InstantiateFunctionBeforeCall(const FunctionDecl *FD,
// semantics of the program.
if (!FD->isDefined() && FD->isImplicitlyInstantiable() && FD->isConstexpr() &&
- Info.InConstantContext && !Info.TryConstantInitialization &&
+ Info.InConstantContext && !Info.PerformingTrialEvaluation &&
!Info.checkingPotentialConstantExpression()) {
SemaProxy *SP = Info.getASTContext().getSemaProxy();
@@ -20828,7 +20828,7 @@ bool Expr::EvaluateAsInitializer(APValue &Value, const ASTContext &Ctx,
: EvaluationMode::ConstantFold);
Info.setEvaluatingDecl(VD, Value);
Info.InConstantContext = IsConstantInitialization;
- Info.TryConstantInitialization =
+ Info.PerformingTrialEvaluation =
!VD->isConstexpr() && !VD->hasAttr<ConstInitAttr>();
SourceLocation DeclLoc = VD->getLocation();
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index 90b919974586b..bdc5155214730 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -75,7 +75,6 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/Support/TimeProfiler.h"
-#include <memory>
#include <optional>
using namespace clang;
@@ -626,8 +625,8 @@ Sema::~Sema() {
}
void Sema::RegisterSemaProxy() {
- // Let the AST context relies on Sema for
- // ast mutations features that require semantic analysis
+ // Let the AST context rely on Sema for
+ // AST mutation features that require semantic analysis
// (lazy instantiation, reflection, etc).
Context.setSemaProxy(getSemaProxyImplementation(*this));
}
diff --git a/clang/test/SemaCXX/constexpr-late-instantiation.cpp b/clang/test/SemaCXX/constexpr-late-instantiation.cpp
index 59cfbfdff0e03..cbfd26587c128 100644
--- a/clang/test/SemaCXX/constexpr-late-instantiation.cpp
+++ b/clang/test/SemaCXX/constexpr-late-instantiation.cpp
@@ -88,3 +88,52 @@ class X
constexpr int x = X().f( 1 );
}
+
+
+namespace GH35052 {
+
+template <typename F>
+constexpr int func(F f) {
+ if constexpr (f(1UL)) {
+ return 1;
+ }
+ return 0;
+}
+
+int test() {
+ auto predicate = [](auto v) constexpr -> bool { return v == 1; };
+ return func(predicate);
+}
+
+} // namespace GH35052
+
+namespace GH115118 {
+
+struct foo {
+ foo(const foo&) = default;
+ foo(auto)
+ requires([]<int = 0>() -> bool { return true; }())
+ {}
+};
+
+struct bar {
+ foo x;
+};
+
+} // namespace GH115118
+
+namespace GH100897 {
+
+template <typename>
+constexpr auto foo() noexcept {
+ constexpr auto extract_size = []<typename argument_t>() constexpr -> int {
+ return 1;
+ };
+
+ constexpr int result = extract_size.template operator()<int>();
+ return result;
+}
+
+void test() { foo<void>(); }
+
+} // namespace GH100897
>From 1b7302264724fbb9b7c68457ad5b679a809e87bd Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Fri, 2 Jan 2026 13:15:57 +0100
Subject: [PATCH 3/5] fix tests
---
clang/test/SemaCXX/constexpr-late-instantiation.cpp | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/clang/test/SemaCXX/constexpr-late-instantiation.cpp b/clang/test/SemaCXX/constexpr-late-instantiation.cpp
index cbfd26587c128..24df761cf0a52 100644
--- a/clang/test/SemaCXX/constexpr-late-instantiation.cpp
+++ b/clang/test/SemaCXX/constexpr-late-instantiation.cpp
@@ -89,6 +89,7 @@ class X
constexpr int x = X().f( 1 );
}
+#if __cplusplus > 202002L
namespace GH35052 {
@@ -105,6 +106,7 @@ int test() {
return func(predicate);
}
+
} // namespace GH35052
namespace GH115118 {
@@ -122,6 +124,7 @@ struct bar {
} // namespace GH115118
+
namespace GH100897 {
template <typename>
@@ -137,3 +140,5 @@ constexpr auto foo() noexcept {
void test() { foo<void>(); }
} // namespace GH100897
+
+#endif
>From 693f142b0900fc2df9cfa22b638dc97f2e450955 Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Fri, 9 Jan 2026 10:50:19 +0100
Subject: [PATCH 4/5] address more feedback
---
clang/docs/ReleaseNotes.rst | 13 ++++++++--
clang/include/clang/AST/ASTContext.h | 2 +-
clang/include/clang/Sema/Sema.h | 4 +--
clang/lib/AST/ByteCode/Interp.cpp | 4 +--
clang/lib/AST/ExprConstShared.h | 4 +++
clang/lib/AST/ExprConstant.cpp | 27 ++++++++++++---------
clang/lib/Interpreter/IncrementalParser.cpp | 4 +--
clang/lib/Parse/ParseAST.cpp | 24 ++++++++++--------
clang/lib/Sema/Sema.cpp | 6 ++---
9 files changed, 55 insertions(+), 33 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index e0b69dac70baa..3af3f81b4f53c 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -221,8 +221,8 @@ Non-comprehensive list of changes in this release
allocator-level heap organization strategies. A feature to instrument all
allocation functions with a token ID can be enabled via the
``-fsanitize=alloc-token`` flag.
-
-- A new generic byte swap builtin function ``__builtin_bswapg`` that extends the existing
+
+- A new generic byte swap builtin function ``__builtin_bswapg`` that extends the existing
__builtin_bswap{16,32,64} function family to support all standard integer types.
- A builtin ``__builtin_infer_alloc_token(<args>, ...)`` is provided to allow
@@ -318,6 +318,7 @@ Improvements to Clang's diagnostics
.. code-block:: c++
+<<<<<<< HEAD
<<<<<<< HEAD
struct DanglingView {
std::string_view view;
@@ -343,6 +344,14 @@ Improvements to Clang's diagnostics
- Clang now generates a fix-it for C++20 designated initializers when the
initializers do not match the declaration order in the structure.
>>>>>>> 3f06fd997749 ([Clang] Instantiate constexpr function when they are needed.)
+=======
+- Fixed a crash when enabling ``-fdiagnostics-format=sarif`` and the output
+ carries messages like 'In file included from ...' or 'In module ...'.
+ Now the include/import locations are written into `sarif.run.result.relatedLocations`.
+
+- Clang now generates a fix-it for C++20 designated initializers when the
+ initializers do not match the declaration order in the structure.
+>>>>>>> ea6211a89115 (address more feedback)
Improvements to Clang's time-trace
----------------------------------
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index bf75813922c6e..7ba0cde3aba8e 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -222,7 +222,7 @@ struct SemaProxy {
virtual ~SemaProxy() = default;
virtual void
- InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
+ instantiateFunctionDefinition(SourceLocation PointOfInstantiation,
FunctionDecl *Function) = 0;
};
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index fa8a54a3730ac..45f236034bb0e 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -910,8 +910,8 @@ class Sema final : public SemaBase {
/// initialized but before it parses anything.
void Initialize();
- void RegisterSemaProxy();
- void UnregisterSemaProxy();
+ void registerSemaProxy();
+ void unregisterSemaProxy();
/// This virtual key function only exists to limit the emission of debug info
/// describing the Sema class. GCC and Clang only emit debug info for a class
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index b725ccc6a1a20..a7729741cbc5c 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -1634,13 +1634,13 @@ static void compileFunction(InterpState &S, const Function *Func,
// when the specialization is referenced in a context that requires a function
// definition to exist or if the existence of the definition affects the
// semantics of the program.
- if (!Fn->isDefined() && Fn->isImplicitlyInstantiable() && Fn->isConstexpr() &&
+ if (FunctionDefinitionCanBeLazilyInstantiated(Func->getDecl()) &&
S.inConstantContext() && !S.PerformingTrialEvaluation &&
!S.checkingPotentialConstantExpression()) {
SemaProxy *SP = S.getASTContext().getSemaProxy();
if (!SP)
return;
- SP->InstantiateFunctionDefinition(S.Current->getLocation(OpPC),
+ SP->instantiateFunctionDefinition(S.Current->getLocation(OpPC),
const_cast<FunctionDecl *>(Fn));
}
Fn = Fn->getDefinition();
diff --git a/clang/lib/AST/ExprConstShared.h b/clang/lib/AST/ExprConstShared.h
index 550b36c232161..a88e8fc4fa96e 100644
--- a/clang/lib/AST/ExprConstShared.h
+++ b/clang/lib/AST/ExprConstShared.h
@@ -28,6 +28,7 @@ class LangOptions;
class ASTContext;
class CharUnits;
class Expr;
+class FunctionDecl;
} // namespace clang
using namespace clang;
/// Values returned by __builtin_classify_type, chosen to match the values
@@ -84,4 +85,7 @@ uint8_t GFNIAffine(uint8_t XByte, const llvm::APInt &AQword,
llvm::APSInt NormalizeRotateAmount(const llvm::APSInt &Value,
const llvm::APSInt &Amount);
+/// Whether we can instantiate FD during constant evaluation
+bool FunctionDefinitionCanBeLazilyInstantiated(const FunctionDecl *FD);
+
#endif
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index d2026108e9de1..d67cd76a7f407 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -6963,8 +6963,14 @@ static bool handleTrivialCopy(EvalInfo &Info, const ParmVarDecl *Param,
CopyObjectRepresentation);
}
-static void InstantiateFunctionBeforeCall(const FunctionDecl *FD,
- EvalInfo &Info, SourceLocation Loc) {
+bool FunctionDefinitionCanBeLazilyInstantiated(const FunctionDecl *FD) {
+ return !FD->isDefined() && FD->isImplicitlyInstantiable() &&
+ FD->isConstexpr();
+}
+
+static void TryInstantiateFunctionBeforeCall(const FunctionDecl *FD,
+ EvalInfo &Info,
+ SourceLocation Loc) {
// [C++26] [temp.inst] p5
// [...] the function template specialization is implicitly instantiated
@@ -6972,16 +6978,15 @@ static void InstantiateFunctionBeforeCall(const FunctionDecl *FD,
// definition to exist or if the existence of the definition affects the
// semantics of the program.
- if (!FD->isDefined() && FD->isImplicitlyInstantiable() && FD->isConstexpr() &&
- Info.InConstantContext && !Info.PerformingTrialEvaluation &&
+ if (FunctionDefinitionCanBeLazilyInstantiated(FD) && Info.InConstantContext &&
+ !Info.PerformingTrialEvaluation &&
!Info.checkingPotentialConstantExpression()) {
SemaProxy *SP = Info.getASTContext().getSemaProxy();
// Try to instantiate the definition if Sema is available
// (i.e during the initial parse of the TU).
- if (SP) {
- SP->InstantiateFunctionDefinition(Loc, const_cast<FunctionDecl *>(FD));
- }
+ if (SP)
+ SP->instantiateFunctionDefinition(Loc, const_cast<FunctionDecl *>(FD));
}
}
@@ -7378,7 +7383,7 @@ static bool HandleDestructionImpl(EvalInfo &Info, SourceRange CallRange,
if (!Info.CheckCallLimit(CallRange.getBegin()))
return false;
- InstantiateFunctionBeforeCall(DD, Info, CallRange.getBegin());
+ TryInstantiateFunctionBeforeCall(DD, Info, CallRange.getBegin());
const FunctionDecl *Definition = nullptr;
const Stmt *Body = DD->getBody(Definition);
@@ -8847,7 +8852,7 @@ class ExprEvaluatorBase
SourceLocation Loc = E->getExprLoc();
- InstantiateFunctionBeforeCall(FD, Info, Loc);
+ TryInstantiateFunctionBeforeCall(FD, Info, Loc);
const FunctionDecl *Definition = nullptr;
const Stmt *Body = FD->getBody(Definition);
@@ -11369,7 +11374,7 @@ bool RecordExprEvaluator::VisitCXXConstructExpr(const CXXConstructExpr *E,
return handleDefaultInitValue(T, Result);
}
- InstantiateFunctionBeforeCall(FD, Info, E->getBeginLoc());
+ TryInstantiateFunctionBeforeCall(FD, Info, E->getBeginLoc());
const FunctionDecl *Definition = nullptr;
const Stmt *Body = FD->getBody(Definition);
@@ -11412,7 +11417,7 @@ bool RecordExprEvaluator::VisitCXXInheritedCtorInitExpr(
if (FD->isInvalidDecl() || FD->getParent()->isInvalidDecl())
return false;
- InstantiateFunctionBeforeCall(FD, Info, E->getBeginLoc());
+ TryInstantiateFunctionBeforeCall(FD, Info, E->getBeginLoc());
const FunctionDecl *Definition = nullptr;
const Stmt *Body = FD->getBody(Definition);
diff --git a/clang/lib/Interpreter/IncrementalParser.cpp b/clang/lib/Interpreter/IncrementalParser.cpp
index 5a24342e73ca4..5630b96927c38 100644
--- a/clang/lib/Interpreter/IncrementalParser.cpp
+++ b/clang/lib/Interpreter/IncrementalParser.cpp
@@ -42,11 +42,11 @@ IncrementalParser::IncrementalParser(CompilerInstance &Instance,
External->StartTranslationUnit(Consumer);
P->Initialize();
- S.RegisterSemaProxy();
+ S.registerSemaProxy();
}
IncrementalParser::~IncrementalParser() {
- S.UnregisterSemaProxy();
+ S.unregisterSemaProxy();
P.reset();
}
diff --git a/clang/lib/Parse/ParseAST.cpp b/clang/lib/Parse/ParseAST.cpp
index 1cea282f13a00..01e17a563838a 100644
--- a/clang/lib/Parse/ParseAST.cpp
+++ b/clang/lib/Parse/ParseAST.cpp
@@ -163,22 +163,26 @@ void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) {
});
P.Initialize();
- auto Unregister =
- llvm::make_scope_exit([&S]() { S.UnregisterSemaProxy(); });
- S.RegisterSemaProxy();
+ S.registerSemaProxy();
Parser::DeclGroupPtrTy ADecl;
Sema::ModuleImportState ImportState;
EnterExpressionEvaluationContext PotentiallyEvaluated(
S, Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
- for (bool AtEOF = P.ParseFirstTopLevelDecl(ADecl, ImportState); !AtEOF;
- AtEOF = P.ParseTopLevelDecl(ADecl, ImportState)) {
- // If we got a null return and something *was* parsed, ignore it. This
- // is due to a top-level semicolon, an action override, or a parse error
- // skipping something.
- if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get()))
- return;
+ {
+ // Remove the sema proxy after the initial parse.
+ llvm::scope_exit SemaProxyScope([&S]() { S.unregisterSemaProxy(); });
+
+ for (bool AtEOF = P.ParseFirstTopLevelDecl(ADecl, ImportState); !AtEOF;
+ AtEOF = P.ParseTopLevelDecl(ADecl, ImportState)) {
+
+ // If we got a null return and something *was* parsed, ignore it. This
+ // is due to a top-level semicolon, an action override, or a parse error
+ // skipping something.
+ if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get()))
+ return;
+ }
}
}
diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp
index bdc5155214730..d562c8dc95374 100644
--- a/clang/lib/Sema/Sema.cpp
+++ b/clang/lib/Sema/Sema.cpp
@@ -624,14 +624,14 @@ Sema::~Sema() {
SemaPPCallbackHandler->reset();
}
-void Sema::RegisterSemaProxy() {
+void Sema::registerSemaProxy() {
// Let the AST context rely on Sema for
// AST mutation features that require semantic analysis
// (lazy instantiation, reflection, etc).
Context.setSemaProxy(getSemaProxyImplementation(*this));
}
-void Sema::UnregisterSemaProxy() { Context.setSemaProxy({}); }
+void Sema::unregisterSemaProxy() { Context.setSemaProxy({}); }
void Sema::runWithSufficientStackSpace(SourceLocation Loc,
llvm::function_ref<void()> Fn) {
@@ -2982,7 +2982,7 @@ class SemaProxyImplementation final : public SemaProxy {
public:
SemaProxyImplementation(Sema &SemaRef) : SemaRef(SemaRef) {}
- void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation,
+ void instantiateFunctionDefinition(SourceLocation PointOfInstantiation,
FunctionDecl *Function) override {
SemaRef.InstantiateFunctionDefinition(
PointOfInstantiation, Function, /*Recursive=*/true,
>From 8daac7ba06c7c8e1c3413c4bc524ad055cc6597f Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinjabot at gmail.com>
Date: Mon, 16 Feb 2026 19:53:16 +0100
Subject: [PATCH 5/5] fix rebase
---
clang/docs/ReleaseNotes.rst | 173 +-----------------------------
clang/lib/AST/ByteCode/Interp.cpp | 2 +-
2 files changed, 6 insertions(+), 169 deletions(-)
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 3af3f81b4f53c..68400853e36fc 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -140,97 +140,9 @@ Non-comprehensive list of changes in this release
Usable in constant expressions. Implicit conversion is supported for
class/struct types with conversion operators.
-<<<<<<< HEAD
- A new generic bit-reverse builtin function ``__builtin_bitreverseg`` that
extends bit-reversal support to all standard integers type, including
``_BitInt``
-=======
-- Added ``__builtin_elementwise_ldexp``.
-
-- Added ``__builtin_elementwise_fshl`` and ``__builtin_elementwise_fshr``.
-
-- ``__builtin_elementwise_abs`` can now be used in constant expression.
-
-- Added ``__builtin_elementwise_minnumnum`` and ``__builtin_elementwise_maxnumnum``.
-
-- Trapping UBSan (e.g. ``-fsanitize=undefined -fsanitize-trap=undefined``) now
- emits a string describing the reason for trapping into the generated debug
- info. This feature allows debuggers (e.g. LLDB) to display the reason for
- trapping if the trap is reached. The string is currently encoded in the debug
- info as an artificial frame that claims to be inlined at the trap location.
- The function used for the artificial frame is an artificial function whose
- name encodes the reason for trapping. The encoding used is currently the same
- as ``__builtin_verbose_trap`` but might change in the future. This feature is
- enabled by default but can be disabled by compiling with
- ``-fno-sanitize-debug-trap-reasons``. The feature has a ``basic`` and
- ``detailed`` mode (the default). The ``basic`` mode emits a hard-coded string
- per trap kind (e.g. ``Integer addition overflowed``) and the ``detailed`` mode
- emits a more descriptive string describing each individual trap (e.g. ``signed
- integer addition overflow in 'a + b'``). The ``detailed`` mode produces larger
- debug info than ``basic`` but is more helpful for debugging. The
- ``-fsanitize-debug-trap-reasons=`` flag can be used to switch between the
- different modes or disable the feature entirely. Note due to trap merging in
- optimized builds (i.e. in each function all traps of the same kind get merged
- into the same trap instruction) the trap reasons might be removed. To prevent
- this build without optimizations (i.e. use `-O0` or use the `optnone` function
- attribute) or use the `fno-sanitize-merge=` flag in optimized builds.
-
-- ``__builtin_elementwise_max`` and ``__builtin_elementwise_min`` functions for integer types can
- now be used in constant expressions.
-
-- A vector of booleans is now a valid condition for the ternary ``?:`` operator.
- This binds to a simple vector select operation.
-
-- Added ``__builtin_masked_load``, ``__builtin_masked_expand_load``,
- ``__builtin_masked_store``, ``__builtin_masked_compress_store`` for
- conditional memory loads from vectors. Binds to the LLVM intrinsics of the
- same name.
-
-- Added ``__builtin_masked_gather`` and ``__builtin_masked_scatter`` for
- conditional gathering and scattering operations on vectors. Binds to the LLVM
- intrinsics of the same name.
-
-- The ``__builtin_popcountg``, ``__builtin_ctzg``, and ``__builtin_clzg``
- functions now accept fixed-size boolean vectors.
-
-- Use of ``__has_feature`` to detect the ``ptrauth_qualifier`` and ``ptrauth_intrinsics``
- features has been deprecated, and is restricted to the arm64e target only. The
- correct method to check for these features is to test for the ``__PTRAUTH__``
- macro.
-
-- Added a new builtin, ``__builtin_dedup_pack``, to remove duplicate types from a parameter pack.
- This feature is particularly useful in template metaprogramming for normalizing type lists.
- The builtin produces a new, unexpanded parameter pack that can be used in contexts like template
- argument lists or base specifiers.
-
- .. code-block:: c++
-
- template <typename...> struct TypeList;
-
- // The resulting type is TypeList<int, double, char>
- using MyTypeList = TypeList<__builtin_dedup_pack<int, double, int, char, double>...>;
-
- Currently, the use of ``__builtin_dedup_pack`` is limited to template arguments and base
- specifiers, it also must be used within a template context.
-
-- ``__builtin_assume_dereferenceable`` now accepts non-constant size operands.
-
-- Fixed a crash when the second argument to ``__builtin_assume_aligned`` was not constant (#GH161314)
-
-- Introduce support for :doc:`allocation tokens <AllocToken>` to enable
- allocator-level heap organization strategies. A feature to instrument all
- allocation functions with a token ID can be enabled via the
- ``-fsanitize=alloc-token`` flag.
-
-- A new generic byte swap builtin function ``__builtin_bswapg`` that extends the existing
- __builtin_bswap{16,32,64} function family to support all standard integer types.
-
-- A builtin ``__builtin_infer_alloc_token(<args>, ...)`` is provided to allow
- compile-time querying of allocation token IDs, where the builtin arguments
- mirror those normally passed to an allocation function.
-
-- Clang now rejects the invalid use of ``constexpr`` with ``auto`` and an explicit type in C. (#GH163090)
->>>>>>> 3f06fd997749 ([Clang] Instantiate constexpr function when they are needed.)
New Compiler Flags
------------------
@@ -318,8 +230,6 @@ Improvements to Clang's diagnostics
.. code-block:: c++
-<<<<<<< HEAD
-<<<<<<< HEAD
struct DanglingView {
std::string_view view;
DanglingView(std::string s) : view(s) {} // warning: address of stack memory escapes to a field
@@ -331,27 +241,11 @@ Improvements to Clang's diagnostics
when accessing a member function on a past-the-end array element.
(#GH179128)
-- Added a missing space to the FixIt for the ``implicit-int`` group of diagnostics and
+- Added a missing space to the FixIt for the ``implicit-int`` group of diagnostics and
made sure that only one such diagnostic and FixIt is emitted per declaration group. (#GH179354)
- The ``-Wloop-analysis`` warning has been extended to catch more cases of
variable modification inside lambda expressions (#GH132038).
-=======
-- Fixed a crash when enabling ``-fdiagnostics-format=sarif`` and the output
- carries messages like 'In file included from ...' or 'In module ...'.
- Now the include/import locations are written into `sarif.run.result.relatedLocations`.
-
-- Clang now generates a fix-it for C++20 designated initializers when the
- initializers do not match the declaration order in the structure.
->>>>>>> 3f06fd997749 ([Clang] Instantiate constexpr function when they are needed.)
-=======
-- Fixed a crash when enabling ``-fdiagnostics-format=sarif`` and the output
- carries messages like 'In file included from ...' or 'In module ...'.
- Now the include/import locations are written into `sarif.run.result.relatedLocations`.
-
-- Clang now generates a fix-it for C++20 designated initializers when the
- initializers do not match the declaration order in the structure.
->>>>>>> ea6211a89115 (address more feedback)
Improvements to Clang's time-trace
----------------------------------
@@ -386,68 +280,11 @@ Bug Fixes to Attribute Support
Bug Fixes to C++ Support
^^^^^^^^^^^^^^^^^^^^^^^^
-<<<<<<< HEAD
- Fixed a crash when instantiating ``requires`` expressions involving substitution failures in C++ concepts. (#GH176402)
- Fixed a crash when a default argument is passed to an explicit object parameter. (#GH176639)
- Fixed a crash when diagnosing an invalid static member function with an explicit object parameter (#GH177741)
-- Fixed a crash when evaluating uninitialized GCC vector/ext_vector_type vectors in ``constexpr``. (#GH180044)
-=======
-- Diagnose binding a reference to ``*nullptr`` during constant evaluation. (#GH48665)
-- Suppress ``-Wdeprecated-declarations`` in implicitly generated functions. (#GH147293)
-- Fix a crash when deleting a pointer to an incomplete array (#GH150359).
-- Fixed a mismatched lambda scope bug when propagating up ``consteval`` within nested lambdas. (#GH145776)
-- Disallow immediate escalation in destructors. (#GH109096)
-- Fix an assertion failure when expression in assumption attribute
- (``[[assume(expr)]]``) creates temporary objects.
-- Fix the dynamic_cast to final class optimization to correctly handle
- casts that are guaranteed to fail (#GH137518).
-- Fix bug rejecting partial specialization of variable templates with auto NTTPs (#GH118190).
-- Fix a crash if errors "member of anonymous [...] redeclares" and
- "initializing multiple members of union" coincide (#GH149985).
-- Fix a crash when using ``explicit(bool)`` in pre-C++11 language modes. (#GH152729)
-- Fix the parsing of variadic member functions when the ellipis immediately follows a default argument.(#GH153445)
-- Fix a crash when using an explicit object parameter in a non-member function with an invalid return type.(#GH173943)
-- Fixed a bug that caused ``this`` captured by value in a lambda with a dependent explicit object parameter to not be
- instantiated properly. (#GH154054)
-- Fixed a bug where our ``member-like constrained friend`` checking caused an incorrect analysis of lambda captures. (#GH156225)
-- Fixed a crash when implicit conversions from initialize list to arrays of
- unknown bound during constant evaluation. (#GH151716)
- Instantiate constexpr functions as needed before they are evaluated. (#GH73232) (#GH35052) (#GH100897)
-- Support the dynamic_cast to final class optimization with pointer
- authentication enabled. (#GH152601)
-- Fix the check for narrowing int-to-float conversions, so that they are detected in
- cases where converting the float back to an integer is undefined behaviour (#GH157067).
-- Stop rejecting C++11-style attributes on the first argument of constructors in older
- standards. (#GH156809).
-- Fix a crash when applying binary or ternary operators to two same function types with different spellings,
- where at least one of the function parameters has an attribute which affects
- the function type.
-- Fix an assertion failure when a ``constexpr`` variable is only referenced through
- ``__builtin_addressof``, and related issues with builtin arguments. (#GH154034)
-- Fix an assertion failure when taking the address on a non-type template parameter argument of
- object type. (#GH151531)
-- Suppress ``-Wdouble-promotion`` when explicitly asked for with C++ list initialization (#GH33409).
-- Fix the result of `__builtin_is_implicit_lifetime` for types with a user-provided constructor. (#GH160610)
-- Correctly deduce return types in ``decltype`` expressions. (#GH160497) (#GH56652) (#GH116319) (#GH161196)
-- Fixed a crash in the pre-C++23 warning for attributes before a lambda declarator (#GH161070).
-- Fix a crash when attempting to deduce a deduction guide from a non deducible template template parameter. (#130604)
-- Fix for clang incorrectly rejecting the default construction of a union with
- nontrivial member when another member has an initializer. (#GH81774)
-- Fixed a template depth issue when parsing lambdas inside a type constraint. (#GH162092)
-- Fix the support of zero-length arrays in SFINAE context. (#GH170040)
-- Diagnose unresolved overload sets in non-dependent compound requirements. (#GH51246) (#GH97753)
-- Fix a crash when extracting unavailable member type from alias in template deduction. (#GH165560)
-- Fix incorrect diagnostics for lambdas with init-captures inside braced initializers. (#GH163498)
-- Fixed an issue where templates prevented nested anonymous records from checking the deletion of special members. (#GH167217)
-- Fixed serialization of pack indexing types, where we failed to expand those packs from a PCH/module. (#GH172464)
-- Fixed spurious diagnoses of certain nested lambda expressions. (#GH149121) (#GH156579)
-- Fix the result of ``__is_pointer_interconvertible_base_of`` when arguments are qualified and passed via template parameters. (#GH135273)
-- Fixed a crash when evaluating nested requirements in requires-expressions that reference invented parameters. (#GH166325)
-- Fixed a crash when standard comparison categories (e.g. ``std::partial_ordering``) are defined with incorrect static member types. (#GH170015) (#GH56571)
-- Fixed a crash when parsing the ``enable_if`` attribute on C function declarations with identifier-list parameters. (#GH173826)
-- Fixed an assertion failure triggered by nested lambdas during capture handling. (#GH172814)
-- Fixed an assertion failure in vector conversions involving instantiation-dependent template expressions. (#GH173347)
->>>>>>> 3f06fd997749 ([Clang] Instantiate constexpr function when they are needed.)
+- Fixed a crash when evaluating uninitialized GCC vector/ext_vector_type vectors in ``constexpr``. (#GH180044)
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -548,7 +385,7 @@ AST Matchers
clang-format
------------
-- Add ``ObjCSpaceAfterMethodDeclarationPrefix`` option to control space between the
+- Add ``ObjCSpaceAfterMethodDeclarationPrefix`` option to control space between the
'-'/'+' and the return type in Objective-C method declarations
libclang
@@ -586,8 +423,8 @@ Python Binding Changes
Affected methods: ``isKindOptional``, ``isKindTypedText``, ``isKindPlaceHolder``,
``isKindInformative`` and ``isKindResultType``.
- Add a deprecation warning to ``CodeCompletionResults.results``.
- This property will become an implementation detail with changed behavior in a
- future release and should not be used directly.. Existing uses of
+ This property will become an implementation detail with changed behavior in a
+ future release and should not be used directly.. Existing uses of
``CodeCompletionResults.results`` should be changed to directly use
``CodeCompletionResults``: it nows supports ``__len__`` and ``__getitem__``,
so it can be used the same as ``CodeCompletionResults.results``.
diff --git a/clang/lib/AST/ByteCode/Interp.cpp b/clang/lib/AST/ByteCode/Interp.cpp
index a7729741cbc5c..2b750cfb4e0d7 100644
--- a/clang/lib/AST/ByteCode/Interp.cpp
+++ b/clang/lib/AST/ByteCode/Interp.cpp
@@ -1960,7 +1960,7 @@ bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize,
// because the Call/CallVirt below might access the instance pointer
// but the Function's information about them is wrong.
if (!F->isFullyCompiled())
- compileFunction(S, F);
+ compileFunction(S, F, OpPC);
if (!CheckCallable(S, OpPC, F))
return false;
More information about the cfe-commits
mailing list