Skip to content

Commit 9e923b1

Browse files
committed
[MS][clang] Error about ambigous operator delete[] only when required
And issue was reported in llvm#133950 . Since we don't always emit vector deleting dtors, only error out about ambigous operator delete[] when it will be required for vector delering dtor emission.
1 parent 53fa92d commit 9e923b1

File tree

3 files changed

+64
-14
lines changed

3 files changed

+64
-14
lines changed

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11045,15 +11045,18 @@ 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+
FunctionDecl *ArrOperatorDelete = FindDeallocationFunctionForDestructor(
11053+
Loc, RD, VDeleteName,
11054+
Destructor->hasAttr<DLLExportAttr>() && Destructor->isDefined());
11055+
// delete[] in the TU will make sure the operator is referenced and its
11056+
// uses diagnosed, otherwise vector deleting dtor won't be called
11057+
// anyway, so just record it in the destructor.
11058+
Destructor->setOperatorArrayDelete(ArrOperatorDelete);
11059+
}
1105711060
}
1105811061
}
1105911062

clang/lib/Sema/SemaExprCXX.cpp

Lines changed: 16 additions & 2 deletions
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

clang/test/SemaCXX/gh134265.cpp

Lines changed: 36 additions & 3 deletions
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
2+
// RUN: %clang_cc1 %s -verify=expected -fsyntax-only -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,41 @@ 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 2{{member found by ambiguous name lookup}}
35+
};
36+
struct BaseDelete2 {
37+
void operator delete[](void *); //ms-note 2{{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+
47+
#ifdef MS
48+
struct Final1 : BaseDelete1, BaseDelete2, BaseDestructor {
49+
__declspec(dllexport) ~Final1() {} // ms-error {{member 'operator delete[]' found in multiple base classes of different types}}
50+
};
51+
#endif // MS
52+
53+
void foo() {
54+
Final* a = new Final[10](); // ms-error {{member 'operator delete[]' found in multiple base classes of different types}}
2255
}

0 commit comments

Comments
 (0)