Skip to content

Commit 2b3aa56

Browse files
authored
[MS][clang] Error about ambiguous operator delete[] only when required (#135041)
And issue was reported in #133950 (comment) . Since we don't always emit vector deleting dtors, only error out about ambiguous operator delete[] when it will be required for vector deleting dtor emission.
1 parent f7617f7 commit 2b3aa56

File tree

3 files changed

+74
-14
lines changed

3 files changed

+74
-14
lines changed

Diff for: clang/lib/Sema/SemaDeclCXX.cpp

+17-9
Original file line numberDiff line numberDiff line change
@@ -11045,15 +11045,23 @@ bool Sema::CheckDestructor(CXXDestructorDecl *Destructor) {
1104511045
DiagnoseUseOfDecl(OperatorDelete, Loc);
1104611046
MarkFunctionReferenced(Loc, OperatorDelete);
1104711047
Destructor->setOperatorDelete(OperatorDelete, ThisArg);
11048-
// Lookup delete[] too in case we have to emit a vector deleting dtor;
11049-
DeclarationName VDeleteName =
11050-
Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete);
11051-
FunctionDecl *ArrOperatorDelete = FindDeallocationFunctionForDestructor(
11052-
Loc, RD, VDeleteName, /*Diagnose=*/false);
11053-
// delete[] in the TU will make sure the operator is referenced and its
11054-
// uses diagnosed, otherwise vector deleting dtor won't be called anyway,
11055-
// so just record it in the destructor.
11056-
Destructor->setOperatorArrayDelete(ArrOperatorDelete);
11048+
if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
11049+
// Lookup delete[] too in case we have to emit a vector deleting dtor;
11050+
DeclarationName VDeleteName =
11051+
Context.DeclarationNames.getCXXOperatorName(OO_Array_Delete);
11052+
// Diagnose if there is no available operator delete[] found and the
11053+
// destructor is exported. Vector deleting dtor body emission requires
11054+
// operator delete[] to be present. Whenever the destructor is exported,
11055+
// we just always emit vector deleting dtor body, because we don't know
11056+
// if new[] will be used with the type outside of the library. Otherwise
11057+
// when the dtor is not exported then new[]/delete[] in the TU will make
11058+
// sure the operator is referenced and its uses diagnosed.
11059+
bool Diagnose =
11060+
Destructor->hasAttr<DLLExportAttr>() && Destructor->isDefined();
11061+
FunctionDecl *ArrOperatorDelete = FindDeallocationFunctionForDestructor(
11062+
Loc, RD, VDeleteName, Diagnose);
11063+
Destructor->setOperatorArrayDelete(ArrOperatorDelete);
11064+
}
1105711065
}
1105811066
}
1105911067

Diff for: clang/lib/Sema/SemaExprCXX.cpp

+16-2
Original file line numberDiff line numberDiff line change
@@ -2789,8 +2789,19 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range,
27892789
return true;
27902790
}
27912791

2792+
// new[] will force emission of vector deleting dtor which needs delete[].
2793+
bool MaybeVectorDeletingDtor = false;
2794+
if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
2795+
if (AllocElemType->isRecordType() && IsArray) {
2796+
auto *RD =
2797+
cast<CXXRecordDecl>(AllocElemType->castAs<RecordType>()->getDecl());
2798+
CXXDestructorDecl *DD = RD->getDestructor();
2799+
MaybeVectorDeletingDtor = DD && DD->isVirtual() && !DD->isDeleted();
2800+
}
2801+
}
2802+
27922803
// We don't need an operator delete if we're running under -fno-exceptions.
2793-
if (!getLangOpts().Exceptions) {
2804+
if (!getLangOpts().Exceptions && !MaybeVectorDeletingDtor) {
27942805
OperatorDelete = nullptr;
27952806
return false;
27962807
}
@@ -3290,8 +3301,11 @@ bool Sema::FindDeallocationFunction(SourceLocation StartLoc, CXXRecordDecl *RD,
32903301
// Try to find operator delete/operator delete[] in class scope.
32913302
LookupQualifiedName(Found, RD);
32923303

3293-
if (Found.isAmbiguous())
3304+
if (Found.isAmbiguous()) {
3305+
if (!Diagnose)
3306+
Found.suppressDiagnostics();
32943307
return true;
3308+
}
32953309

32963310
Found.suppressDiagnostics();
32973311

Diff for: clang/test/SemaCXX/gh134265.cpp

+41-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
// RUN: %clang_cc1 %s -verify -fsyntax-only
1+
// RUN: %clang_cc1 %s -verify=expected -fsyntax-only -triple=x86_64-unknown-linux-gnu
2+
// RUN: %clang_cc1 %s -verify=expected -fsyntax-only -triple=x86_64-unknown-linux-gnu -std=c++20
3+
// RUN: %clang_cc1 %s -verify=expected,ms -fms-extensions -fms-compatibility -triple=x86_64-pc-windows-msvc -DMS
24

35
struct Foo {
46
virtual ~Foo() {} // expected-error {{attempt to use a deleted function}}
@@ -13,10 +15,46 @@ struct Bar {
1315

1416
struct Baz {
1517
virtual ~Baz() {}
16-
static void operator delete[](void* ptr) = delete; // expected-note {{explicitly marked deleted here}}
18+
static void operator delete[](void* ptr) = delete; // expected-note {{explicitly marked deleted here}}\
19+
ms-note{{explicitly marked deleted here}}}
20+
};
21+
22+
struct BarBaz {
23+
~BarBaz() {}
24+
static void operator delete[](void* ptr) = delete;
1725
};
1826

1927
void foobar() {
20-
Baz *B = new Baz[10]();
28+
Baz *B = new Baz[10](); // ms-error {{attempt to use a deleted function}}
2129
delete [] B; // expected-error {{attempt to use a deleted function}}
30+
BarBaz *BB = new BarBaz[10]();
31+
}
32+
33+
struct BaseDelete1 {
34+
void operator delete[](void *); //ms-note 3{{member found by ambiguous name lookup}}
35+
};
36+
struct BaseDelete2 {
37+
void operator delete[](void *); //ms-note 3{{member found by ambiguous name lookup}}
38+
};
39+
struct BaseDestructor {
40+
BaseDestructor() {}
41+
virtual ~BaseDestructor() = default;
42+
};
43+
struct Final : BaseDelete1, BaseDelete2, BaseDestructor {
44+
Final() {}
45+
};
46+
struct FinalExplicit : BaseDelete1, BaseDelete2, BaseDestructor {
47+
FinalExplicit() {}
48+
inline ~FinalExplicit() {}
49+
};
50+
51+
#ifdef MS
52+
struct Final1 : BaseDelete1, BaseDelete2, BaseDestructor {
53+
__declspec(dllexport) ~Final1() {} // ms-error {{member 'operator delete[]' found in multiple base classes of different types}}
54+
};
55+
#endif // MS
56+
57+
void foo() {
58+
Final* a = new Final[10](); // ms-error {{member 'operator delete[]' found in multiple base classes of different types}}
59+
FinalExplicit* b = new FinalExplicit[10](); // ms-error {{member 'operator delete[]' found in multiple base classes of different types}}
2260
}

0 commit comments

Comments
 (0)