From 94e164144c64ea7596221cb98dfa6f06c123e14f Mon Sep 17 00:00:00 2001 From: Telgome <2657726985@qq.com> Date: Thu, 18 Sep 2025 21:44:18 +0800 Subject: [PATCH] Add support for '~auto' pseudo-destructor --- .../clang/Basic/DiagnosticParseKinds.td | 5 +++++ clang/lib/Parse/ParseExprCXX.cpp | 18 +++++++++++++++ clang/lib/Sema/SemaExprCXX.cpp | 4 +++- clang/test/SemaCXX/auto-dtor.cpp | 22 +++++++++++++++++++ 4 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 clang/test/SemaCXX/auto-dtor.cpp diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td index 12aab09f2855..e22712871465 100644 --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -389,6 +389,11 @@ def warn_cxx11_compat_decltype_auto_type_specifier : Warning< def ext_auto_type : Extension< "'__auto_type' is a GNU extension">, InGroup; +def warn_cxx11_compat_pseudo_destructor_auto : Warning< + "'~auto' only available with '-std=c++14 or -std=gnu++14'">, + InGroup, DefaultIgnore; +def err_requires_gnu_compatibility_for_auto_dtor : Error< + "'~auto' pseudo-destructor requires -fGNU-compatibility flag">; def ext_for_range : ExtWarn< "range-based for loop is a C++11 extension">, InGroup; def warn_cxx98_compat_for_range : Warning< diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 1d364f77a814..01e1190c7ebd 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -1884,6 +1884,24 @@ Parser::ParseCXXPseudoDestructor(Expr *Base, SourceLocation OpLoc, assert(Tok.is(tok::tilde) && "ParseOptionalCXXScopeSpecifier fail"); SourceLocation TildeLoc = ConsumeToken(); + if (Tok.is(tok::kw_auto) && !FirstTypeName.isValid()) { + if (!getLangOpts().GccCompatible) { + Diag(Tok, diag::err_requires_gnu_compatibility_for_auto_dtor); + return ExprError(); + } else { + if (!getLangOpts().CPlusPlus14) + Diag(Tok, diag::warn_cxx11_compat_pseudo_destructor_auto); + } + + ConsumeToken(); + UnqualifiedId SecondTypeName; + SecondTypeName.setIdentifier(nullptr, SourceLocation()); + + return Actions.ActOnPseudoDestructorExpr(getCurScope(), Base, OpLoc, OpKind, + SS, FirstTypeName, CCLoc, TildeLoc, + SecondTypeName); + } + if (Tok.is(tok::kw_decltype) && !FirstTypeName.isValid()) { DeclSpec DS(AttrFactory); ParseDecltypeSpecifier(DS); diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index de50786f4d6c..3348abea6950 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -8195,7 +8195,9 @@ ExprResult Sema::ActOnPseudoDestructorExpr(Scope *S, Expr *Base, QualType DestructedType; TypeSourceInfo *DestructedTypeInfo = nullptr; PseudoDestructorTypeStorage Destructed; - if (SecondTypeName.getKind() == UnqualifiedIdKind::IK_Identifier) { + if (!SecondTypeName.Identifier) { + DestructedType = ObjectType; + } else if (SecondTypeName.getKind() == UnqualifiedIdKind::IK_Identifier) { ParsedType T = getTypeName(*SecondTypeName.Identifier, SecondTypeName.StartLocation, S, &SS, true, false, ObjectTypePtrForLookup, diff --git a/clang/test/SemaCXX/auto-dtor.cpp b/clang/test/SemaCXX/auto-dtor.cpp new file mode 100644 index 000000000000..3375208b0cb1 --- /dev/null +++ b/clang/test/SemaCXX/auto-dtor.cpp @@ -0,0 +1,22 @@ +// RUN: %clang_cc1 -std=c++14 -Werror -Wno-error=c++14-extensions -fsyntax-only %s -fGNU-compatibility +// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11 -Wc++11-compat -fGNU-compatibility + +template +void f (T* p) +{ + p->~auto(); // expected-warning {{'~auto' only available with '-std=c++14 or -std=gnu++14'}} +} + +int d; +struct A { ~A() { ++d; } }; + +int g (int x) +{ + f(new int(x)); + f(new A); + if (d != 1) { + return 1; + } + (new int)->~auto(); // expected-warning {{'~auto' only available with '-std=c++14 or -std=gnu++14'}} + return 0; +} -- Gitee