mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-28 08:02:08 +00:00
[SemaCXX] Validate destructor is valid for dependent classes
We didn't check that a destructor's name matches the directly enclosing class if the class was dependent. I enabled the check we already had for non-dependent types, which seems to work. Added appropriate tests. Fixes GitHub issue #56772 Reviewed By: erichkeane Differential Revision: https://reviews.llvm.org/D130936
This commit is contained in:
parent
92c1bc6158
commit
508c431ed9
@ -52,6 +52,8 @@ Bug Fixes
|
||||
- Fixes an accepts-invalid bug in C when using a ``_Noreturn`` function
|
||||
specifier on something other than a function declaration. This fixes
|
||||
`Issue 56800 <https://github.com/llvm/llvm-project/issues/56800>`_.
|
||||
- Fix `#56772 <https://github.com/llvm/llvm-project/issues/56772>`_ - invalid
|
||||
destructor names were incorrectly accepted on template classes.
|
||||
|
||||
Improvements to Clang's diagnostics
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -11496,17 +11496,12 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD,
|
||||
CXXRecordDecl *Record = Destructor->getParent();
|
||||
QualType ClassType = Context.getTypeDeclType(Record);
|
||||
|
||||
// FIXME: Shouldn't we be able to perform this check even when the class
|
||||
// type is dependent? Both gcc and edg can handle that.
|
||||
if (!ClassType->isDependentType()) {
|
||||
DeclarationName Name
|
||||
= Context.DeclarationNames.getCXXDestructorName(
|
||||
Context.getCanonicalType(ClassType));
|
||||
if (NewFD->getDeclName() != Name) {
|
||||
Diag(NewFD->getLocation(), diag::err_destructor_name);
|
||||
NewFD->setInvalidDecl();
|
||||
return Redeclaration;
|
||||
}
|
||||
DeclarationName Name = Context.DeclarationNames.getCXXDestructorName(
|
||||
Context.getCanonicalType(ClassType));
|
||||
if (NewFD->getDeclName() != Name) {
|
||||
Diag(NewFD->getLocation(), diag::err_destructor_name);
|
||||
NewFD->setInvalidDecl();
|
||||
return Redeclaration;
|
||||
}
|
||||
} else if (auto *Guide = dyn_cast<CXXDeductionGuideDecl>(NewFD)) {
|
||||
if (auto *TD = Guide->getDescribedFunctionTemplate())
|
||||
|
@ -1,4 +1,6 @@
|
||||
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
|
||||
// RUN: %clang_cc1 -std=c++17 -fsyntax-only -verify %s
|
||||
// RUN: %clang_cc1 -std=c++20 -fsyntax-only -verify %s
|
||||
|
||||
struct rdar9677163 {
|
||||
struct Y { ~Y(); };
|
||||
@ -6,3 +8,22 @@ struct rdar9677163 {
|
||||
Y::~Y() { } // expected-error{{non-friend class member '~Y' cannot have a qualified name}}
|
||||
~Z(); // expected-error{{expected the class name after '~' to name the enclosing class}}
|
||||
};
|
||||
|
||||
namespace GH56772 {
|
||||
|
||||
template<class T>
|
||||
struct A {
|
||||
~A<T>();
|
||||
};
|
||||
#if __cplusplus >= 202002L
|
||||
// FIXME: This isn't valid in C++20 and later.
|
||||
#endif
|
||||
|
||||
struct B;
|
||||
|
||||
template<class T>
|
||||
struct C {
|
||||
~B(); // expected-error {{expected the class name after '~' to name the enclosing class}}
|
||||
};
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user