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
This commit is contained in:
Aaron Ballman 2013-05-30 01:55:39 +00:00
parent 543bdd1237
commit 324fbeeba7
3 changed files with 62 additions and 0 deletions

View File

@ -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

View File

@ -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*
}
}

View File

@ -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];
}