llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Krystian Stasiowski (sdkrystian) <details> <summary>Changes</summary> Clang crashes when diagnosing the following invalid redeclaration in C++11: ```cpp struct A { void f(); }; constexpr void A::f() { } // crash here ``` This happens because `DiagnoseInvalidRedeclaration` tries to create a fix-it to remove `const` from the out-of-line declaration of `f`, but there is no `SourceLocation` for the `const` qualifier (it's implicitly `const` due to `constexpr`) and an assert in `FunctionTypeInfo::getConstQualifierLoc` fails. This patch changes the accessors for _cv-qualifier-seq_ `SourceLocations` in `FunctionTypeInfo` to return an invalid `SourceLocation` if no _cv-qualifier-seq_ is present, and changes `DiagnoseInvalidRedeclaration` to only suggest the removal of the `const` qualifier when it was explicitly specified. --- Full diff: https://github.com/llvm/llvm-project/pull/92452.diff 4 Files Affected: - (modified) clang/docs/ReleaseNotes.rst (+2) - (modified) clang/include/clang/Sema/DeclSpec.h (+6-6) - (modified) clang/lib/Sema/SemaDecl.cpp (+9-9) - (modified) clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp (+11) ``````````diff diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 2d2928e418623..411a5f752899d 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -724,6 +724,8 @@ Bug Fixes to C++ Support templates during partial ordering when deducing template arguments from a function declaration or when taking the address of a function template. - Fix a bug with checking constrained non-type template parameters for equivalence. Fixes (#GH77377). +- Fix a C++11 crash when a non-const non-static member function is defined out-of-line with + the ``constexpr`` specifier. Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Sema/DeclSpec.h b/clang/include/clang/Sema/DeclSpec.h index 23bc780e04979..44d96db54b5f0 100644 --- a/clang/include/clang/Sema/DeclSpec.h +++ b/clang/include/clang/Sema/DeclSpec.h @@ -1527,20 +1527,20 @@ struct DeclaratorChunk { /// Retrieve the location of the 'const' qualifier. SourceLocation getConstQualifierLoc() const { - assert(MethodQualifiers); - return MethodQualifiers->getConstSpecLoc(); + return MethodQualifiers ? MethodQualifiers->getConstSpecLoc() + : SourceLocation(); } /// Retrieve the location of the 'volatile' qualifier. SourceLocation getVolatileQualifierLoc() const { - assert(MethodQualifiers); - return MethodQualifiers->getVolatileSpecLoc(); + return MethodQualifiers ? MethodQualifiers->getVolatileSpecLoc() + : SourceLocation(); } /// Retrieve the location of the 'restrict' qualifier. SourceLocation getRestrictQualifierLoc() const { - assert(MethodQualifiers); - return MethodQualifiers->getRestrictSpecLoc(); + return MethodQualifiers ? MethodQualifiers->getRestrictSpecLoc() + : SourceLocation(); } /// Retrieve the location of the 'mutable' qualifier, if any. diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 0dbdf923df95a..22749dc4799bc 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -9203,15 +9203,15 @@ static NamedDecl *DiagnoseInvalidRedeclaration( << Idx << FDParam->getType() << NewFD->getParamDecl(Idx - 1)->getType(); } else if (FDisConst != NewFDisConst) { - SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_const_match) - << NewFDisConst << FD->getSourceRange().getEnd() - << (NewFDisConst - ? FixItHint::CreateRemoval(ExtraArgs.D.getFunctionTypeInfo() - .getConstQualifierLoc()) - : FixItHint::CreateInsertion(ExtraArgs.D.getFunctionTypeInfo() - .getRParenLoc() - .getLocWithOffset(1), - " const")); + auto DB = SemaRef.Diag(FD->getLocation(), + diag::note_member_def_close_const_match) + << NewFDisConst << FD->getSourceRange().getEnd(); + if (const auto &FTI = ExtraArgs.D.getFunctionTypeInfo(); !NewFDisConst) + DB << FixItHint::CreateInsertion(FTI.getRParenLoc().getLocWithOffset(1), + " const"); + else if (SourceLocation ConstLoc = FTI.getConstQualifierLoc(); + ConstLoc.isValid()) + DB << FixItHint::CreateRemoval(ConstLoc); } else SemaRef.Diag(FD->getLocation(), IsMember ? diag::note_member_def_close_match diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp index a28a5f91c4775..788e93b56bb38 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp @@ -154,3 +154,14 @@ namespace { // FIXME: We should diagnose this prior to C++17. const int &r = A::n; } + +#if __cplusplus < 201402L +namespace ImplicitConstexprDef { + struct A { + void f(); // expected-note {{member declaration does not match because it is not const qualified}} + }; + + constexpr void A::f() { } // expected-warning {{'constexpr' non-static member function will not be implicitly 'const' in C++14; add 'const' to avoid a change in behavior}} + // expected-error@-1 {{out-of-line definition of 'f' does not match any declaration in 'ImplicitConstexprDef::A'}} +} +#endif `````````` </details> https://github.com/llvm/llvm-project/pull/92452 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits