[clang] [Clang][Sema] Fix exception specification comparison for functions with different template depths (PR #111561)
via cfe-commits
cfe-commits at lists.llvm.org
Wed Jan 22 02:01:15 PST 2025
================
@@ -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
More information about the cfe-commits
mailing list