From 324fbeeba700668f4091d8ce1345d4a2aebee976 Mon Sep 17 00:00:00 2001 From: Aaron Ballman Date: Thu, 30 May 2013 01:55:39 +0000 Subject: [PATCH] Add support to fallback on operator new when a placement operator new[] is called for which there is no valid declaration. This fallback only happens in Microsoft compatibility mode. This patch addresses PR13164, and improves support for the WDK. llvm-svn: 182905 --- clang/lib/Sema/SemaExprCXX.cpp | 15 +++++++++ clang/test/CodeGenCXX/microsoft-new.cpp | 37 +++++++++++++++++++++ clang/test/SemaCXX/microsoft-new-delete.cpp | 10 ++++++ 3 files changed, 62 insertions(+) create mode 100644 clang/test/CodeGenCXX/microsoft-new.cpp create mode 100644 clang/test/SemaCXX/microsoft-new-delete.cpp diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp index 21f00b22fc24..439fc1636f50 100644 --- a/clang/lib/Sema/SemaExprCXX.cpp +++ b/clang/lib/Sema/SemaExprCXX.cpp @@ -1554,13 +1554,28 @@ bool Sema::FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, /*AllowMissing=*/true, OperatorNew)) return true; } + if (!OperatorNew) { // Didn't find a member overload. Look for a global one. DeclareGlobalNewDelete(); DeclContext *TUDecl = Context.getTranslationUnitDecl(); + bool FallbackEnabled = IsArray && Context.getLangOpts().MicrosoftMode; if (FindAllocationOverload(StartLoc, Range, NewName, AllocArgs, TUDecl, + /*AllowMissing=*/FallbackEnabled, OperatorNew, + /*Diagnose=*/!FallbackEnabled)) { + if (!FallbackEnabled) + return true; + + // MSVC will fall back on trying to find a matching global operator new + // if operator new[] cannot be found. Also, MSVC will leak by not + // generating a call to operator delete or operator delete[], but we + // will not replicate that bug. + NewName = Context.DeclarationNames.getCXXOperatorName(OO_New); + DeleteName = Context.DeclarationNames.getCXXOperatorName(OO_Delete); + if (FindAllocationOverload(StartLoc, Range, NewName, AllocArgs, TUDecl, /*AllowMissing=*/false, OperatorNew)) return true; + } } // We don't need an operator delete if we're running under diff --git a/clang/test/CodeGenCXX/microsoft-new.cpp b/clang/test/CodeGenCXX/microsoft-new.cpp new file mode 100644 index 000000000000..80a5019fd48e --- /dev/null +++ b/clang/test/CodeGenCXX/microsoft-new.cpp @@ -0,0 +1,37 @@ +// RUN: %clang_cc1 -triple i686-pc-win32 -fms-compatibility %s -emit-llvm -o - | FileCheck %s + +struct arbitrary_t {} arbitrary; +void *operator new(unsigned int size, arbitrary_t); + +struct arbitrary2_t {} arbitrary2; +void *operator new[](unsigned int size, arbitrary2_t); + +namespace PR13164 { + void f() { + // MSVC will fall back on the non-array operator new. + void *a; + int *p = new(arbitrary) int[4]; + // CHECK: call i8* @_Znwj11arbitrary_t(i32 16, %struct.arbitrary_t* + } + + struct S { + void *operator new[](unsigned int size, arbitrary_t); + }; + + void g() { + S *s = new(arbitrary) S[2]; + // CHECK: call i8* @_ZN7PR131641SnaEj11arbitrary_t(i32 2, %struct.arbitrary_t* + S *s1 = new(arbitrary) S; + // CHECK: call i8* @_Znwj11arbitrary_t(i32 1, %struct.arbitrary_t* + } + + struct T { + void *operator new(unsigned int size, arbitrary2_t); + }; + + void h() { + // This should still call the global operator new[]. + T *t = new(arbitrary2) T[2]; + // CHECK: call i8* @_Znaj12arbitrary2_t(i32 2, %struct.arbitrary2_t* + } +} diff --git a/clang/test/SemaCXX/microsoft-new-delete.cpp b/clang/test/SemaCXX/microsoft-new-delete.cpp new file mode 100644 index 000000000000..90b42edb18f9 --- /dev/null +++ b/clang/test/SemaCXX/microsoft-new-delete.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fms-compatibility -fsyntax-only -verify %s +// expected-no-diagnostics + +struct arbitrary_t {} arbitrary; +void *operator new(unsigned int size, arbitrary_t); + +void f() { + // Expect no error in MSVC compatibility mode + int *p = new(arbitrary) int[4]; +}