aaron.ballman created this revision. aaron.ballman added reviewers: rsmith, erichkeane, rjmccall, arthur.j.odwyer. aaron.ballman requested review of this revision. Herald added a project: clang.
When parsing the following construct, we parse it as an erroneous deduction guide declaration and correctly diagnose the issues with it. template<class> struct B; struct A { B() noexcept(false); }; However, we then go on to finish late parsing the declaration and this expects that what we've parsed is a `CXXMethodDecl`. A `CXXDeductionGuideDecl` is not a `CXXMethodDecl` (it's a `FunctionDecl`), and so we assert on the cast. This fixes the crash by switching from `cast<>` to `dyn_cast<>` and not setting up a "this" scope when the declaration is not a `CXXMethodDecl`. This fixes PR49735. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D112616 Files: clang/lib/Parse/ParseCXXInlineMethods.cpp clang/test/Parser/cxx1z-class-template-argument-deduction.cpp Index: clang/test/Parser/cxx1z-class-template-argument-deduction.cpp =================================================================== --- clang/test/Parser/cxx1z-class-template-argument-deduction.cpp +++ clang/test/Parser/cxx1z-class-template-argument-deduction.cpp @@ -230,3 +230,21 @@ template<int ...N> struct Z { Y<X(N)...> y; }; } + +namespace PR49735 { +// Ensure that we do not crash when parsing code which looks like an invalid +// deduction guide declaration. +template<class> struct B; // expected-note 2{{template is declared here}} +struct A1 { + B() noexcept(false); // expected-error {{deduction guide must be declared in the same scope as template 'PR49735::B'}} \ + // expected-error {{deduction guide declaration without trailing return type}} +}; + +struct A2 { + template <typename Ty> // expected-note {{non-deducible template parameter 'Ty'}} + B() noexcept(false); // expected-error {{deduction guide must be declared in the same scope as template 'PR49735::B'}} \ + // expected-error {{deduction guide template contains a template parameter that cannot be deduced}} \ + // expected-error {{deduction guide declaration without trailing return type}} +}; + +} Index: clang/lib/Parse/ParseCXXInlineMethods.cpp =================================================================== --- clang/lib/Parse/ParseCXXInlineMethods.cpp +++ clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -452,13 +452,14 @@ CXXMethodDecl *Method; if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(LM.Method)) - Method = cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl()); + Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl()); else - Method = cast<CXXMethodDecl>(LM.Method); + Method = dyn_cast<CXXMethodDecl>(LM.Method); - Sema::CXXThisScopeRAII ThisScope(Actions, Method->getParent(), - Method->getMethodQualifiers(), - getLangOpts().CPlusPlus11); + Sema::CXXThisScopeRAII ThisScope( + Actions, Method ? Method->getParent() : nullptr, + Method ? Method->getMethodQualifiers() : Qualifiers{}, + Method && getLangOpts().CPlusPlus11); // Parse the exception-specification. SourceRange SpecificationRange;
Index: clang/test/Parser/cxx1z-class-template-argument-deduction.cpp =================================================================== --- clang/test/Parser/cxx1z-class-template-argument-deduction.cpp +++ clang/test/Parser/cxx1z-class-template-argument-deduction.cpp @@ -230,3 +230,21 @@ template<int ...N> struct Z { Y<X(N)...> y; }; } + +namespace PR49735 { +// Ensure that we do not crash when parsing code which looks like an invalid +// deduction guide declaration. +template<class> struct B; // expected-note 2{{template is declared here}} +struct A1 { + B() noexcept(false); // expected-error {{deduction guide must be declared in the same scope as template 'PR49735::B'}} \ + // expected-error {{deduction guide declaration without trailing return type}} +}; + +struct A2 { + template <typename Ty> // expected-note {{non-deducible template parameter 'Ty'}} + B() noexcept(false); // expected-error {{deduction guide must be declared in the same scope as template 'PR49735::B'}} \ + // expected-error {{deduction guide template contains a template parameter that cannot be deduced}} \ + // expected-error {{deduction guide declaration without trailing return type}} +}; + +} Index: clang/lib/Parse/ParseCXXInlineMethods.cpp =================================================================== --- clang/lib/Parse/ParseCXXInlineMethods.cpp +++ clang/lib/Parse/ParseCXXInlineMethods.cpp @@ -452,13 +452,14 @@ CXXMethodDecl *Method; if (FunctionTemplateDecl *FunTmpl = dyn_cast<FunctionTemplateDecl>(LM.Method)) - Method = cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl()); + Method = dyn_cast<CXXMethodDecl>(FunTmpl->getTemplatedDecl()); else - Method = cast<CXXMethodDecl>(LM.Method); + Method = dyn_cast<CXXMethodDecl>(LM.Method); - Sema::CXXThisScopeRAII ThisScope(Actions, Method->getParent(), - Method->getMethodQualifiers(), - getLangOpts().CPlusPlus11); + Sema::CXXThisScopeRAII ThisScope( + Actions, Method ? Method->getParent() : nullptr, + Method ? Method->getMethodQualifiers() : Qualifiers{}, + Method && getLangOpts().CPlusPlus11); // Parse the exception-specification. SourceRange SpecificationRange;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits