================ @@ -501,6 +519,110 @@ bool Sema::CheckEquivalentExceptionSpec( return Result; } +static const Expr *SubstituteExceptionSpecWithoutEvaluation( + Sema &S, const Sema::TemplateCompareNewDeclInfo &DeclInfo, + const Expr *ExceptionSpec) { + MultiLevelTemplateArgumentList MLTAL = S.getTemplateInstantiationArgs( + DeclInfo.getDecl(), DeclInfo.getLexicalDeclContext(), /*Final=*/false, + /*Innermost=*/std::nullopt, + /*RelativeToPrimary=*/true, + /*ForConstraintInstantiation=*/true); + + if (MLTAL.getNumSubstitutedLevels() == 0) + return ExceptionSpec; + + Sema::SFINAETrap SFINAE(S, /*AccessCheckingSFINAE=*/false); + + auto *FD = const_cast<FunctionDecl *>(DeclInfo.getDecl()->getAsFunction()); + Sema::InstantiatingTemplate Inst( + S, DeclInfo.getLocation(), FD, + Sema::InstantiatingTemplate::ExceptionSpecification()); + if (Inst.isInvalid()) + return nullptr; + + // Set up a dummy 'instantiation' scope in the case of reference to function + // parameters that the surrounding function hasn't been instantiated yet. Note + // this may happen while we're comparing two templates' constraint + // equivalence. + LocalInstantiationScope ScopeForParameters(S); + + for (auto *PVD : FD->parameters()) { + if (!PVD->isParameterPack()) { + ScopeForParameters.InstantiatedLocal(PVD, PVD); + continue; + } + // This is hacky: we're mapping the parameter pack to a size-of-1 argument + // to avoid building SubstTemplateTypeParmPackTypes for + // PackExpansionTypes. The SubstTemplateTypeParmPackType node would + // otherwise reference the AssociatedDecl of the template arguments, which + // is, in this case, the template declaration. + // + // However, as we are in the process of comparing potential + // re-declarations, the canonical declaration is the declaration itself at + // this point. So if we didn't expand these packs, we would end up with an + // incorrect profile difference because we will be profiling the + // canonical types! + // + // FIXME: Improve the "no-transform" machinery in FindInstantiatedDecl so + // that we can eliminate the Scope in the cases where the declarations are + // not necessarily instantiated. It would also benefit the noexcept + // specifier comparison. + ScopeForParameters.MakeInstantiatedLocalArgPack(PVD); + ScopeForParameters.InstantiatedLocalPackArg(PVD, PVD); + } + + // See TreeTransform::RebuildTemplateSpecializationType. A context scope is + // essential for having an injected class as the canonical type for a template + // specialization type at the rebuilding stage. This guarantees that, for + // out-of-line definitions, injected class name types and their equivalent + // template specializations can be profiled to the same value, which makes it + // possible that e.g. constraints involving C<Class<T>> and C<Class> are + // perceived identical. + Sema::ContextRAII ContextScope(S, FD); + + auto *MD = dyn_cast<CXXMethodDecl>(FD); + Sema::CXXThisScopeRAII ThisScope( + S, MD ? MD->getParent() : nullptr, + MD ? MD->getMethodQualifiers() : Qualifiers{}, MD != nullptr); + + EnterExpressionEvaluationContext ConstantEvaluated( + S, Sema::ExpressionEvaluationContext::ConstantEvaluated); ---------------- cor3ntin wrote:
Should that not be be Unevaluated? https://eel.is/c++draft/expr.unary.noexcept#1 https://github.com/llvm/llvm-project/pull/111561 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits