diff --git a/clang/lib/Sema/SemaChecking.cpp b/clang/lib/Sema/SemaChecking.cpp --- a/clang/lib/Sema/SemaChecking.cpp +++ b/clang/lib/Sema/SemaChecking.cpp @@ -4540,8 +4540,7 @@ // Find expected alignment, and the actual alignment of the passed object. // getTypeAlignInChars requires complete types - if (ParamTy->isIncompleteType() || ArgTy->isIncompleteType() || - ParamTy->isUndeducedType() || ArgTy->isUndeducedType()) + if (ParamTy->isIncompleteType() || ArgTy->isIncompleteType()) return; CharUnits ParamAlign = Context.getTypeAlignInChars(ParamTy); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -19661,8 +19661,10 @@ if (isSFINAEContext()) return ExprError(); - if (T.isNull() || !Context.getLangOpts().RecoveryASTType) + if (T.isNull() || T->isUndeducedType() || + !Context.getLangOpts().RecoveryASTType) // We don't know the concrete type, fallback to dependent type. T = Context.DependentTy; + return RecoveryExpr::Create(Context, T, Begin, End, SubExprs); } diff --git a/clang/test/SemaCXX/recovery-expr-type.cpp b/clang/test/SemaCXX/recovery-expr-type.cpp --- a/clang/test/SemaCXX/recovery-expr-type.cpp +++ b/clang/test/SemaCXX/recovery-expr-type.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -triple=x86_64-unknown-unknown -frecovery-ast -frecovery-ast-type -o - %s -fsyntax-only -verify +// RUN: %clang_cc1 -triple=x86_64-unknown-unknown -frecovery-ast -frecovery-ast-type -o - %s -std=c++17 -fsyntax-only -verify namespace test0 { struct Indestructible { @@ -26,7 +26,10 @@ void foo(); // expected-note 3{{requires 0 arguments}} void func() { // verify that "field has incomplete type" diagnostic is suppressed. - typeof(foo(42)) var; // expected-error {{no matching function}} + typeof(foo(42)) var; // expected-error {{no matching function}} \ + // expected-error {{use of undeclared identifier 'typeof'}} \ + // expected-error {{expected ';' after expression}} \ + // expected-error {{use of undeclared identifier 'var'}} // FIXME: suppress the "cannot initialize a variable" diagnostic. int a = foo(1); // expected-error {{no matching function}} \ @@ -116,3 +119,23 @@ template const int k = f(T()); // expected-error {{no matching function}} static_assert(k == 1, ""); // expected-note {{instantiation of}} } + +namespace test11 { +// Verify we do not assert()-fail here. +template void foo(T &t); +template +void bar(T t) { + foo(t); +} + +template +struct S { // expected-note {{candidate}} + S(T t); // expected-note {{candidate}} + ~S(); +}; +template S(T t) -> S; + +void baz() { + bar(S(123)); // expected-error {{no matching conversion}} +} +} // namespace test11