================ @@ -3058,6 +3058,141 @@ void Sema::NoteAllFoundTemplates(TemplateName Name) { } } +static std::optional<QualType> commonTypeImpl(Sema &S, + TemplateName BaseTemplate, + SourceLocation TemplateLoc, + ArrayRef<TemplateArgument> Ts) { + auto lookUpCommonType = [&](TemplateArgument T1, + TemplateArgument T2) -> std::optional<QualType> { + // Don't bother looking for other specializations if both types are + // builtins - users aren't allowed to specialize for them + if (T1.getAsType()->isBuiltinType() && T2.getAsType()->isBuiltinType()) + return commonTypeImpl(S, BaseTemplate, TemplateLoc, {T1, T2}); + + TemplateArgumentListInfo Args; + Args.addArgument(TemplateArgumentLoc( + T1, S.Context.getTrivialTypeSourceInfo(T1.getAsType()))); + Args.addArgument(TemplateArgumentLoc( + T2, S.Context.getTrivialTypeSourceInfo(T2.getAsType()))); + QualType BaseTemplateInst = + S.CheckTemplateIdType(BaseTemplate, TemplateLoc, Args); + if (S.RequireCompleteType(TemplateLoc, BaseTemplateInst, + diag::err_incomplete_type)) + return std::nullopt; + if (QualType Type = S.getTypeMember("type", BaseTemplateInst); + !Type.isNull()) { + return Type; + } + return std::nullopt; + }; + + // Note A: For the common_type trait applied to a template parameter pack T of + // types, the member type shall be either defined or not present as follows: + switch (Ts.size()) { + + // If sizeof...(T) is zero, there shall be no member type. + case 0: + return std::nullopt; + + // If sizeof...(T) is one, let T0 denote the sole type constituting the + // pack T. The member typedef-name type shall denote the same type, if any, as + // common_type_t<T0, T0>; otherwise there shall be no member type. + case 1: + return lookUpCommonType(Ts[0], Ts[0]); + + // If sizeof...(T) is two, let the first and second types constituting T be + // denoted by T1 and T2, respectively, and let D1 and D2 denote the same types + // as decay_t<T1> and decay_t<T2>, respectively. + case 2: { + QualType T1 = Ts[0].getAsType(); + QualType T2 = Ts[1].getAsType(); + QualType D1 = S.BuiltinDecay(T1, {}); + QualType D2 = S.BuiltinDecay(T2, {}); + + // If is_same_v<T1, D1> is false or is_same_v<T2, D2> is false, let C denote + // the same type, if any, as common_type_t<D1, D2>. + if (!S.Context.hasSameType(T1, D1) || !S.Context.hasSameType(T2, D2)) { + return lookUpCommonType(D1, D2); + } ---------------- Sirraide wrote:
```suggestion if (!S.Context.hasSameType(T1, D1) || !S.Context.hasSameType(T2, D2)) return lookUpCommonType(D1, D2); ``` nit: no braces around single-statement `if`s (unless that single statement is egregiously big) https://github.com/llvm/llvm-project/pull/99473 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits