rsmith added inline comments. Herald added a subscriber: carlosgalvezp.
================ Comment at: clang/include/clang/AST/Type.h:4968 QualType getDeducedType() const { - return !isCanonicalUnqualified() ? getCanonicalTypeInternal() : QualType(); + return DeducedAsType.isNull() ? QualType() : DeducedAsType; } ---------------- ================ Comment at: clang/lib/AST/ASTImporter.cpp:3275 + !DeducedT.isNull() + ? dyn_cast<RecordType>(DeducedT->getCanonicalTypeInternal()) + : nullptr) { ---------------- ================ Comment at: clang/lib/AST/ASTImporter.cpp:3285 } - if (const TypedefType *TypedefT = - dyn_cast<TypedefType>(FromFPT->getReturnType())) { - TypedefNameDecl *TD = TypedefT->getDecl(); + if (const auto *TypedefT = dyn_cast<TypedefType>(FromFPT->getReturnType())) { + const TypedefNameDecl *TD = TypedefT->getDecl(); ---------------- (Preparing for D112374) ================ Comment at: clang/lib/Sema/SemaTemplateDeduction.cpp:1154 if (!ParamFunction || !ArgFunction) return Param == Arg; ---------------- The `==` comparisons here and below should presumably be `hasSameType` comparisons now that we're preserving sugar. ================ Comment at: clang/lib/Sema/SemaTemplateDeduction.cpp:1234-1250 llvm::SmallPtrSet<const RecordType *, 8> Visited; SmallVector<const RecordType *, 8> ToVisit; // We iterate over this later, so we have to use MapVector to ensure // determinism. llvm::MapVector<const RecordType *, SmallVector<DeducedTemplateArgument, 8>> Matches; ---------------- I think we should: * track `ToVisit` as a vector of `QualType`, so we preserve the type sugar as written in base specifier lists * track `Visited` as a set of (canonical) `const CXXRecordDecl*`s rather than relying on `RecordType`s always being canonical (they currently are, but I don't think that's intended to be guaranteed) ================ Comment at: clang/lib/Sema/SemaTemplateDeduction.cpp:1385-1388 + P = P.getUnqualifiedType(); // - If A is a cv-qualified type, A is replaced by the cv-unqualified // version of A. + A = A.getUnqualifiedType(); ---------------- Do we need to use `Context.getUnqualifiedArrayType` here, for cases like: ``` typedef const int CInt; // Partial ordering should deduce `T = int` from both parameters here, // even though `T = const int` might make more sense for the first one. template<int N> void f(CInt (&)[N], int*); template<int N, typename T> void f(T (&)[N], T*); CInt arr[5]; void g() { f(arr, arr); } ``` ? I think `getUnqualifiedType()` on `CInt[N]` will not remove the indirect `const` qualifier. ================ Comment at: clang/lib/Sema/SemaTemplateDeduction.cpp:1437 // top level, so they can be matched with the qualifiers on the parameter. - if (isa<ArrayType>(Arg)) { + if (isa<ArrayType>(A)) { Qualifiers Quals; ---------------- `A` could be sugar for an array type here. ================ Comment at: clang/lib/Sema/SemaTemplateDeduction.cpp:1546-1568 + QualType CanP = P.getCanonicalType(); + // If the parameter type is not dependent, there is nothing to deduce. + if (!P->isDependentType()) { + if (TDF & TDF_SkipNonDependent) return Sema::TDK_Success; + + QualType CanA = A.getCanonicalType(); ---------------- I think we can excise `CanA` and `CanP` entirely here so people aren't tempted to use them and lose sugar. ================ Comment at: clang/lib/Sema/SemaTemplateDeduction.cpp:1643 - return Param == Arg? Sema::TDK_Success : Sema::TDK_NonDeducedMismatch; + return ParDesug == ArgDesug ? Sema::TDK_Success + : Sema::TDK_NonDeducedMismatch; ---------------- mizvekov wrote: > mizvekov wrote: > > rsmith wrote: > > > This looks wrong to me: we should be comparing the types, not how they're > > > written. `Context.hasSameType(Param, Arg)` (or > > > `Context.hasSameUnqualifiedType(Param, Arg)` in the > > > `TDF_IgnoreQualifiers` case) would be appropriate here. > > You are right, but the reason we don't get into any troubles here is > > because this is dead code anyway, the non-dependent case will always be > > handled above :) > > > > Although perhaps, I wonder if we should dig down into non-dependent types > > anyway, in case the types are too complex and it's not immediately obvious > > what does not match, we could perhaps improve the diagnostic? > > > > I will experiment a little bit with this idea. > Here are the results of this experiment: > ``` > error: 'note' diagnostics expected but not seen: > File SemaCXX\cxx1z-noexcept-function-type.cpp Line 21: could not match > 'void (I) noexcept(false)' (aka 'void (int) noexcept(false)') against 'void > (int) noexcept' > error: 'note' diagnostics seen but not expected: > File SemaCXX\cxx1z-noexcept-function-type.cpp Line 21: candidate template > ignored: failed template argument deduction > > error: 'note' diagnostics expected but not seen: > File SemaCXX\deduced-return-type-cxx14.cpp Line 146: candidate template > ignored: could not match 'auto ()' against 'int ()' > File SemaCXX\deduced-return-type-cxx14.cpp Line 161: candidate template > ignored: could not match 'auto ()' against 'void ()' > error: 'note' diagnostics seen but not expected: > File SemaCXX\deduced-return-type-cxx14.cpp Line 146: candidate template > ignored: could not match 'auto' against 'int' > File SemaCXX\deduced-return-type-cxx14.cpp Line 161: candidate template > ignored: could not match 'auto' against 'void' > > error: 'note' diagnostics expected but not seen: > File SemaCXX\pass-object-size.cpp Line 62 (directive at > SemaCXX\pass-object-size.cpp:69): candidate address cannot be taken because > parameter 1 has pass_object_size attribute > File SemaCXX\pass-object-size.cpp Line 56 (directive at > SemaCXX\pass-object-size.cpp:74): candidate address cannot be taken because > parameter 1 has pass_object_size attribute > File SemaCXX\pass-object-size.cpp Line 62 (directive at > SemaCXX\pass-object-size.cpp:75): candidate address cannot be taken because > parameter 1 has pass_object_size attribute > error: 'note' diagnostics seen but not expected: > File SemaCXX\pass-object-size.cpp Line 56: candidate template ignored: > failed template argument deduction > File SemaCXX\pass-object-size.cpp Line 62: candidate template ignored: > failed template argument deduction > File SemaCXX\pass-object-size.cpp Line 62: candidate template ignored: > failed template argument deduction > > error: 'note' diagnostics expected but not seen: > File SemaTemplate\deduction.cpp Line 316: deduced non-type template > argument does not have the same type as the corresponding template parameter > ('std::nullptr_t' vs 'int *') > File SemaTemplate\deduction.cpp Line 323: values of conflicting types > error: 'note' diagnostics seen but not expected: > File SemaTemplate\deduction.cpp Line 275: candidate template ignored: could > not match 'const int' against 'int' > File SemaTemplate\deduction.cpp Line 316: candidate template ignored: could > not match 'int *' against 'std::nullptr_t' > File SemaTemplate\deduction.cpp Line 323: candidate template ignored: could > not match 'int *' against 'std::nullptr_t' > > error: 'note' diagnostics expected but not seen: > File SemaTemplate\explicit-instantiation.cpp Line 64: candidate template > ignored: could not match 'void ()' against 'void (float *)' > File SemaTemplate\explicit-instantiation.cpp Line 70: candidate template > ignored: could not match 'void (int *)' against 'void (float *)' > error: 'note' diagnostics seen but not expected: > File SemaTemplate\explicit-instantiation.cpp Line 70: candidate template > ignored: could not match 'int' against 'float' > File SemaTemplate\explicit-instantiation.cpp Line 64: candidate template > ignored: failed template argument deduction > ``` > > It's interesting to note that it reveals several cases we give too generic > 'failed template argument deduction' errors, like the different noexcept > specifications, function prototypes with different amount of parameters, and > the 'pass_object_size attribute' case. Hm, this doesn't seem to be an improvement; I think it's better to present the larger non-matching types and use `%diff` in the diagnostic to highlight the part that differs. Especially because we don't provide a source location for (eg) where in the type we found a `float`, providing the more complete context of (eg) `void (float*)` seems more useful. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D110216/new/ https://reviews.llvm.org/D110216 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits