Skip to content

Commit 3efaf9c

Browse files
authored
[Clang][Sema] Fix crash when diagnosing near-match for 'constexpr' redeclaration in C++11 (#92452)
Clang crashes when diagnosing the following invalid redeclaration in C++11: ``` 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 `DiagnoseInvalidRedeclaration` to only suggest the removal of the `const` qualifier when it was explicitly specified in the _cv-qualifier-seq_ of the declaration.
1 parent e33db24 commit 3efaf9c

File tree

3 files changed

+24
-10
lines changed

3 files changed

+24
-10
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,8 @@ Bug Fixes to C++ Support
742742
- Fix a bug with checking constrained non-type template parameters for equivalence. Fixes (#GH77377).
743743
- Fix a bug where the last argument was not considered when considering the most viable function for
744744
explicit object argument member functions. Fixes (#GH92188).
745+
- Fix a C++11 crash when a non-const non-static member function is defined out-of-line with
746+
the ``constexpr`` specifier. Fixes (#GH61004).
745747

746748
Bug Fixes to AST Handling
747749
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/lib/Sema/SemaDecl.cpp

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9217,19 +9217,20 @@ static NamedDecl *DiagnoseInvalidRedeclaration(
92179217
<< Idx << FDParam->getType()
92189218
<< NewFD->getParamDecl(Idx - 1)->getType();
92199219
} else if (FDisConst != NewFDisConst) {
9220-
SemaRef.Diag(FD->getLocation(), diag::note_member_def_close_const_match)
9221-
<< NewFDisConst << FD->getSourceRange().getEnd()
9222-
<< (NewFDisConst
9223-
? FixItHint::CreateRemoval(ExtraArgs.D.getFunctionTypeInfo()
9224-
.getConstQualifierLoc())
9225-
: FixItHint::CreateInsertion(ExtraArgs.D.getFunctionTypeInfo()
9226-
.getRParenLoc()
9227-
.getLocWithOffset(1),
9228-
" const"));
9229-
} else
9220+
auto DB = SemaRef.Diag(FD->getLocation(),
9221+
diag::note_member_def_close_const_match)
9222+
<< NewFDisConst << FD->getSourceRange().getEnd();
9223+
if (const auto &FTI = ExtraArgs.D.getFunctionTypeInfo(); !NewFDisConst)
9224+
DB << FixItHint::CreateInsertion(FTI.getRParenLoc().getLocWithOffset(1),
9225+
" const");
9226+
else if (FTI.hasMethodTypeQualifiers() &&
9227+
FTI.getConstQualifierLoc().isValid())
9228+
DB << FixItHint::CreateRemoval(FTI.getConstQualifierLoc());
9229+
} else {
92309230
SemaRef.Diag(FD->getLocation(),
92319231
IsMember ? diag::note_member_def_close_match
92329232
: diag::note_local_decl_close_match);
9233+
}
92339234
}
92349235
return nullptr;
92359236
}

clang/test/CXX/dcl.dcl/dcl.spec/dcl.constexpr/p1.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,3 +154,14 @@ namespace {
154154
// FIXME: We should diagnose this prior to C++17.
155155
const int &r = A::n;
156156
}
157+
158+
#if __cplusplus < 201402L
159+
namespace ImplicitConstexprDef {
160+
struct A {
161+
void f(); // expected-note {{member declaration does not match because it is not const qualified}}
162+
};
163+
164+
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}}
165+
// expected-error@-1 {{out-of-line definition of 'f' does not match any declaration in 'ImplicitConstexprDef::A'}}
166+
}
167+
#endif

0 commit comments

Comments
 (0)