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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits