diff --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp --- a/clang/lib/Sema/SemaTemplateDeduction.cpp +++ b/clang/lib/Sema/SemaTemplateDeduction.cpp @@ -4346,7 +4346,7 @@ HasDeducedReturnType = true; } - if (!ArgFunctionType.isNull()) { + if (!ArgFunctionType.isNull() && !FunctionType.isNull()) { unsigned TDF = TDF_TopLevelParameterTypeList | TDF_AllowCompatibleFunctionType; // Deduce template arguments from the function type. diff --git a/clang/test/SemaCXX/pr51171-crash.cpp b/clang/test/SemaCXX/pr51171-crash.cpp new file mode 100644 --- /dev/null +++ b/clang/test/SemaCXX/pr51171-crash.cpp @@ -0,0 +1,33 @@ +// RUN: %clang_cc1 -fsyntax-only -verify -std=c++17 %s + +// Ensure that we don't crash if errors are suppressed by an error limit. +// RUN: not %clang_cc1 -fsyntax-only -std=c++17 -ferror-limit 1 %s + +template +struct tv_val { +}; + +template +auto &val(const tv_val &val) { return val.val(); } // expected-note {{possible target for call}} + +struct Class { + template + struct Entry { + tv_val val; + }; +}; + +enum Types : int { + Class = 1, // expected-note 2 {{struct 'Class' is hidden}} +}; + +struct Record { + Class *val_; // expected-error {{must use 'struct' tag}} + void setClass(Class *); // expected-error {{must use 'struct' tag}} +}; + +void Record::setClass(Class *val) { // expected-error {{variable has incomplete type 'void'}} \ + // expected-error {{reference to overloaded function}} \ + // expected-error {{expected ';' after top level declarator}} + val_ = val; +}