@@ -17748,6 +17748,47 @@ Sema::PushExpressionEvaluationContext(
1774817748 PushExpressionEvaluationContext(NewContext, ClosureContextDecl, ExprContext);
1774917749}
1775017750
17751+ void Sema::PushExpressionEvaluationContextForFunction(
17752+ ExpressionEvaluationContext NewContext, FunctionDecl *FD) {
17753+ // [expr.const]/p14.1
17754+ // An expression or conversion is in an immediate function context if it is
17755+ // potentially evaluated and either: its innermost enclosing non-block scope
17756+ // is a function parameter scope of an immediate function.
17757+ PushExpressionEvaluationContext(
17758+ FD && FD->isConsteval()
17759+ ? ExpressionEvaluationContext::ImmediateFunctionContext
17760+ : NewContext);
17761+ const Sema::ExpressionEvaluationContextRecord &Parent =
17762+ parentEvaluationContext();
17763+ Sema::ExpressionEvaluationContextRecord &Current = currentEvaluationContext();
17764+
17765+ Current.InDiscardedStatement = false;
17766+
17767+ if (FD) {
17768+
17769+ // Each ExpressionEvaluationContextRecord also keeps track of whether the
17770+ // context is nested in an immediate function context, so smaller contexts
17771+ // that appear inside immediate functions (like variable initializers) are
17772+ // considered to be inside an immediate function context even though by
17773+ // themselves they are not immediate function contexts. But when a new
17774+ // function is entered, we need to reset this tracking, since the entered
17775+ // function might be not an immediate function.
17776+
17777+ Current.InImmediateEscalatingFunctionContext =
17778+ getLangOpts().CPlusPlus20 && FD->isImmediateEscalating();
17779+
17780+ if (isLambdaMethod(FD)) {
17781+ Current.InDiscardedStatement = Parent.isDiscardedStatementContext();
17782+ Current.InImmediateFunctionContext =
17783+ FD->isConsteval() ||
17784+ (isLambdaMethod(FD) && (Parent.isConstantEvaluated() ||
17785+ Parent.isImmediateFunctionContext()));
17786+ } else {
17787+ Current.InImmediateFunctionContext = FD->isConsteval();
17788+ }
17789+ }
17790+ }
17791+
1775117792namespace {
1775217793
1775317794const DeclRefExpr *CheckPossibleDeref(Sema &S, const Expr *PossibleDeref) {
@@ -18360,35 +18401,23 @@ enum class OdrUseContext {
1836018401/// Are we within a context in which references to resolved functions or to
1836118402/// variables result in odr-use?
1836218403static OdrUseContext isOdrUseContext(Sema &SemaRef) {
18363- OdrUseContext Result;
18364-
18365- switch (SemaRef.ExprEvalContexts.back().Context) {
18366- case Sema::ExpressionEvaluationContext::Unevaluated:
18367- case Sema::ExpressionEvaluationContext::UnevaluatedList:
18368- case Sema::ExpressionEvaluationContext::UnevaluatedAbstract:
18369- return OdrUseContext::None;
18370-
18371- case Sema::ExpressionEvaluationContext::ConstantEvaluated:
18372- case Sema::ExpressionEvaluationContext::ImmediateFunctionContext:
18373- case Sema::ExpressionEvaluationContext::PotentiallyEvaluated:
18374- Result = OdrUseContext::Used;
18375- break;
18404+ const Sema::ExpressionEvaluationContextRecord &Context =
18405+ SemaRef.currentEvaluationContext();
1837618406
18377- case Sema::ExpressionEvaluationContext::DiscardedStatement:
18378- Result = OdrUseContext::FormallyOdrUsed;
18379- break;
18380-
18381- case Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed:
18382- // A default argument formally results in odr-use, but doesn't actually
18383- // result in a use in any real sense until it itself is used.
18384- Result = OdrUseContext::FormallyOdrUsed;
18385- break;
18386- }
18407+ if (Context.isUnevaluated())
18408+ return OdrUseContext::None;
1838718409
1838818410 if (SemaRef.CurContext->isDependentContext())
1838918411 return OdrUseContext::Dependent;
1839018412
18391- return Result;
18413+ if (Context.isDiscardedStatementContext())
18414+ return OdrUseContext::FormallyOdrUsed;
18415+
18416+ else if (Context.Context ==
18417+ Sema::ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed)
18418+ return OdrUseContext::FormallyOdrUsed;
18419+
18420+ return OdrUseContext::Used;
1839218421}
1839318422
1839418423static bool isImplicitlyDefinableConstexprFunction(FunctionDecl *Func) {
@@ -20355,9 +20384,11 @@ MarkExprReferenced(Sema &SemaRef, SourceLocation Loc, Decl *D, Expr *E,
2035520384}
2035620385
2035720386void Sema::MarkDeclRefReferenced(DeclRefExpr *E, const Expr *Base) {
20358- // TODO: update this with DR# once a defect report is filed.
20359- // C++11 defect. The address of a pure member should not be an ODR use, even
20360- // if it's a qualified reference.
20387+ // [basic.def.odr] (CWG 1614)
20388+ // A function is named by an expression or conversion [...]
20389+ // unless it is a pure virtual function and either the expression is not an
20390+ // id-expression naming the function with an explicitly qualified name or
20391+ // the expression forms a pointer to member
2036120392 bool OdrUse = true;
2036220393 if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(E->getDecl()))
2036320394 if (Method->isVirtual() &&
0 commit comments