mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-17 08:21:13 +00:00
[Clang] Support MSPropertyRefExpr as placement arg to new-expression (#75883)
It seems we were forgetting to call `checkArgsForPlaceholders` on the placement arguments of new-expressions in Sema. I don't think that was intended—at least doing so doesn't seem to break anything—so this pr adds that. This also fixes #65053 --------- Co-authored-by: Erich Keane <ekeane@nvidia.com>
This commit is contained in:
parent
04a69a10f6
commit
af0ee617fc
@ -572,6 +572,30 @@ Improvements to Clang's diagnostics
|
||||
enclosing template must be a definition.
|
||||
- Clang now diagnoses function/variable templates that shadow their own template parameters, e.g. ``template<class T> void T();``.
|
||||
|
||||
- Clang now emits more descriptive diagnostics for 'unusual' expressions (e.g. incomplete index
|
||||
expressions on matrix types or builtin functions without an argument list) as placement-args
|
||||
to new-expressions.
|
||||
|
||||
Before:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
error: no matching function for call to 'operator new'
|
||||
13 | new (__builtin_memset) S {};
|
||||
| ^ ~~~~~~~~~~~~~~~~~~
|
||||
|
||||
note: candidate function not viable: no known conversion from '<builtin fn type>' to 'int' for 2nd argument
|
||||
5 | void* operator new(__SIZE_TYPE__, int);
|
||||
| ^
|
||||
|
||||
After:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
error: builtin functions must be directly called
|
||||
13 | new (__builtin_memset) S {};
|
||||
| ^
|
||||
|
||||
|
||||
Improvements to Clang's time-trace
|
||||
----------------------------------
|
||||
@ -774,6 +798,12 @@ Bug Fixes in This Version
|
||||
- Fix assertion failure when call noreturn-attribute function with musttail
|
||||
attribute.
|
||||
Fixes (`#76631 <https://github.com/llvm/llvm-project/issues/76631>`_)
|
||||
- The MS ``__noop`` builtin without an argument list is now accepted
|
||||
in the placement-args of new-expressions, matching MSVC's behaviour.
|
||||
- Fix an issue that caused MS ``__decspec(property)`` accesses as well as
|
||||
Objective-C++ property accesses to not be converted to a function call
|
||||
to the getter in the placement-args of new-expressions.
|
||||
Fixes (`#65053 <https://github.com/llvm/llvm-project/issues/65053>`_)
|
||||
|
||||
Bug Fixes to Compiler Builtins
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -2112,6 +2112,10 @@ public:
|
||||
|
||||
bool CheckFunctionReturnType(QualType T, SourceLocation Loc);
|
||||
|
||||
/// Check an argument list for placeholders that we won't try to
|
||||
/// handle later.
|
||||
bool CheckArgsForPlaceholders(MultiExprArg args);
|
||||
|
||||
/// Build a function type.
|
||||
///
|
||||
/// This routine checks the function type according to C++ rules and
|
||||
|
@ -5058,8 +5058,6 @@ static QualType getDependentArraySubscriptType(Expr *LHS, Expr *RHS,
|
||||
return Result->isDependentType() ? Result : Ctx.DependentTy;
|
||||
}
|
||||
|
||||
static bool checkArgsForPlaceholders(Sema &S, MultiExprArg args);
|
||||
|
||||
ExprResult Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base,
|
||||
SourceLocation lbLoc,
|
||||
MultiExprArg ArgExprs,
|
||||
@ -5163,7 +5161,7 @@ ExprResult Sema::ActOnArraySubscriptExpr(Scope *S, Expr *base,
|
||||
return ExprError();
|
||||
ArgExprs[0] = result.get();
|
||||
} else {
|
||||
if (checkArgsForPlaceholders(*this, ArgExprs))
|
||||
if (CheckArgsForPlaceholders(ArgExprs))
|
||||
return ExprError();
|
||||
}
|
||||
|
||||
@ -6912,15 +6910,13 @@ static bool isPlaceholderToRemoveAsArg(QualType type) {
|
||||
llvm_unreachable("bad builtin type kind");
|
||||
}
|
||||
|
||||
/// Check an argument list for placeholders that we won't try to
|
||||
/// handle later.
|
||||
static bool checkArgsForPlaceholders(Sema &S, MultiExprArg args) {
|
||||
bool Sema::CheckArgsForPlaceholders(MultiExprArg args) {
|
||||
// Apply this processing to all the arguments at once instead of
|
||||
// dying at the first failure.
|
||||
bool hasInvalid = false;
|
||||
for (size_t i = 0, e = args.size(); i != e; i++) {
|
||||
if (isPlaceholderToRemoveAsArg(args[i]->getType())) {
|
||||
ExprResult result = S.CheckPlaceholderExpr(args[i]);
|
||||
ExprResult result = CheckPlaceholderExpr(args[i]);
|
||||
if (result.isInvalid()) hasInvalid = true;
|
||||
else args[i] = result.get();
|
||||
}
|
||||
@ -7194,7 +7190,7 @@ ExprResult Sema::BuildCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
|
||||
if (Result.isInvalid()) return ExprError();
|
||||
Fn = Result.get();
|
||||
|
||||
if (checkArgsForPlaceholders(*this, ArgExprs))
|
||||
if (CheckArgsForPlaceholders(ArgExprs))
|
||||
return ExprError();
|
||||
|
||||
if (getLangOpts().CPlusPlus) {
|
||||
|
@ -2286,6 +2286,9 @@ ExprResult Sema::BuildCXXNew(SourceRange Range, bool UseGlobal,
|
||||
bool PassAlignment = getLangOpts().AlignedAllocation &&
|
||||
Alignment > NewAlignment;
|
||||
|
||||
if (CheckArgsForPlaceholders(PlacementArgs))
|
||||
return ExprError();
|
||||
|
||||
AllocationFunctionScope Scope = UseGlobal ? AFS_Global : AFS_Both;
|
||||
if (!AllocType->isDependentType() &&
|
||||
!Expr::hasAnyTypeDependentArguments(PlacementArgs) &&
|
||||
|
52
clang/test/CodeGenCXX/ms-property-new.cpp
Normal file
52
clang/test/CodeGenCXX/ms-property-new.cpp
Normal file
@ -0,0 +1,52 @@
|
||||
// RUN: %clang_cc1 -emit-llvm -triple=x86_64-pc-win32 -fms-compatibility %s -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fms-compatibility -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 -emit-llvm -triple=x86_64-pc-win32 -fms-compatibility -include-pch %t -verify %s -o - | FileCheck %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
#ifndef HEADER
|
||||
#define HEADER
|
||||
|
||||
struct S {
|
||||
int GetX() { return 42; }
|
||||
__declspec(property(get=GetX)) int x;
|
||||
|
||||
int GetY(int i, int j) { return i+j; }
|
||||
__declspec(property(get=GetY)) int y[];
|
||||
|
||||
void* operator new(__SIZE_TYPE__, int);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct TS {
|
||||
T GetT() { return T(); }
|
||||
__declspec(property(get=GetT)) T t;
|
||||
|
||||
T GetR(T i, T j) { return i+j; }
|
||||
__declspec(property(get=GetR)) T r[];
|
||||
};
|
||||
|
||||
// CHECK-LABEL: main
|
||||
int main(int argc, char **argv) {
|
||||
S *s;
|
||||
TS<double> *ts;
|
||||
|
||||
// CHECK: [[X:%.+]] = call noundef i32 @"?GetX@S@@QEAAHXZ"(ptr {{[^,]*}} %{{.+}})
|
||||
// CHECK-NEXT: call noundef ptr @"??2S@@SAPEAX_KH@Z"(i64 noundef 1, i32 noundef [[X]])
|
||||
new (s->x) S;
|
||||
|
||||
// CHECK: [[Y:%.+]] = call noundef i32 @"?GetY@S@@QEAAHHH@Z"(ptr {{[^,]*}} %{{.+}}, i32 noundef 1, i32 noundef 2)
|
||||
// CHECK-NEXT: call noundef ptr @"??2S@@SAPEAX_KH@Z"(i64 noundef 1, i32 noundef [[Y]])
|
||||
new ((s->y)[1][2]) S;
|
||||
|
||||
// CHECK: [[T:%.+]] = call noundef double @"?GetT@?$TS@N@@QEAANXZ"(ptr {{[^,]*}} %{{.+}})
|
||||
// CHECK-NEXT: [[TI:%.+]] = fptosi double [[T]] to i32
|
||||
// CHECK-NEXT: call noundef ptr @"??2S@@SAPEAX_KH@Z"(i64 noundef 1, i32 noundef [[TI]])
|
||||
new (ts->t) S;
|
||||
|
||||
// CHECK: [[R:%.+]] = call noundef double @"?GetR@?$TS@N@@QEAANNN@Z"(ptr {{[^,]*}} %{{.+}}, double {{[^,]*}}, double {{[^,]*}})
|
||||
// CHECK-NEXT: [[RI:%.+]] = fptosi double [[R]] to i32
|
||||
// CHECK-NEXT: call noundef ptr @"??2S@@SAPEAX_KH@Z"(i64 noundef 1, i32 noundef [[RI]])
|
||||
new ((ts->r)[1][2]) S;
|
||||
}
|
||||
|
||||
#endif
|
12
clang/test/CodeGenCXX/placement-new-ms-__noop.cpp
Normal file
12
clang/test/CodeGenCXX/placement-new-ms-__noop.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
// RUN: %clang_cc1 -triple x86_64-windows-msvc -fms-extensions -std=c++11 -emit-llvm -o - %s | FileCheck %s
|
||||
|
||||
struct S {
|
||||
void* operator new(__SIZE_TYPE__, int);
|
||||
};
|
||||
|
||||
int main() {
|
||||
// CHECK: call {{.*}} ptr @"??2S@@SAPEAX_KH@Z"(i64 {{.*}} 1, i32 {{.*}} 0)
|
||||
// CHECK: call {{.*}} ptr @"??2S@@SAPEAX_KH@Z"(i64 {{.*}} 1, i32 {{.*}} 0)
|
||||
new (__noop) S;
|
||||
new ((__noop)) S;
|
||||
}
|
46
clang/test/CodeGenObjCXX/property-placement-new.mm
Normal file
46
clang/test/CodeGenObjCXX/property-placement-new.mm
Normal file
@ -0,0 +1,46 @@
|
||||
// RUN: %clang_cc1 -x objective-c++ -std=c++11 %s -triple x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
|
||||
|
||||
// CHECK: [[NAME:@.*]] = private unnamed_addr constant [9 x i8] c"position\00"
|
||||
// CHECK: [[SEL:@.*]] = internal externally_initialized global ptr [[NAME]]
|
||||
|
||||
@interface I {
|
||||
int position;
|
||||
}
|
||||
@property(nonatomic) int position;
|
||||
@end
|
||||
|
||||
struct S {
|
||||
void *operator new(__SIZE_TYPE__, int);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct TS {
|
||||
void *operator new(__SIZE_TYPE__, T);
|
||||
};
|
||||
|
||||
I *GetI();
|
||||
|
||||
int main() {
|
||||
@autoreleasepool {
|
||||
// CHECK: [[I:%.+]] = alloca ptr
|
||||
auto* i = GetI();
|
||||
i.position = 42;
|
||||
|
||||
// This is so we can find the next line more easily.
|
||||
// CHECK: store double
|
||||
double d = 42.0;
|
||||
|
||||
// CHECK: [[I1:%.+]] = load ptr, ptr [[I]]
|
||||
// CHECK-NEXT: [[SEL1:%.+]] = load ptr, ptr [[SEL]]
|
||||
// CHECK-NEXT: [[POS1:%.+]] = call {{.*}} i32 @objc_msgSend(ptr {{.*}} [[I1]], ptr {{.*}} [[SEL1]])
|
||||
// CHECK-NEXT: call {{.*}} ptr @_ZN1SnwEmi(i64 {{.*}} 1, i32 {{.*}} [[POS1]])
|
||||
new (i.position) S;
|
||||
|
||||
// CHECK: [[I2:%.+]] = load ptr, ptr [[I]]
|
||||
// CHECK-NEXT: [[SEL2:%.+]] = load ptr, ptr [[SEL]]
|
||||
// CHECK-NEXT: [[POS2:%.+]] = call {{.*}} i32 @objc_msgSend(ptr {{.*}} [[I2]], ptr {{.*}} [[SEL2]])
|
||||
// CHECK-NEXT: [[DBL:%.+]] = sitofp i32 [[POS2]] to double
|
||||
// CHECK-NEXT: call {{.*}} ptr @_ZN2TSIdEnwEmd(i64 {{.*}} 1, double {{.*}} [[DBL]])
|
||||
new (i.position) TS<double>;
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
// RUN: %clang_cc1 -std=c++17 -verify %s
|
||||
// RUN: %clang_cc1 -std=c++17 -verify %s -DNO_CONSTEXPR
|
||||
// RUN: %clang_cc1 -std=c++20 -verify %s
|
||||
// RUN: %clang_cc1 -std=c++17 -verify=cxx17,expected %s
|
||||
// RUN: %clang_cc1 -std=c++17 -verify=cxx17,expected %s -DNO_CONSTEXPR
|
||||
// RUN: %clang_cc1 -std=c++20 -verify=cxx20,expected %s
|
||||
|
||||
namespace std {
|
||||
#ifndef NO_CONSTEXPR
|
||||
@ -12,6 +12,7 @@ namespace std {
|
||||
template<typename T> CONSTEXPR T &&move(T &x) {
|
||||
static_assert(T::moveable, "instantiated move"); // expected-error {{no member named 'moveable' in 'B'}}
|
||||
// expected-error@-1 {{no member named 'moveable' in 'C'}}
|
||||
// expected-error@-2 {{no member named 'moveable' in 'D'}}
|
||||
return static_cast<T&&>(x);
|
||||
}
|
||||
|
||||
@ -23,6 +24,7 @@ namespace std {
|
||||
|
||||
template<typename T> CONSTEXPR auto move_if_noexcept(T &x) -> typename ref<T, noexcept(T(static_cast<T&&>(x)))>::type {
|
||||
static_assert(T::moveable, "instantiated move_if_noexcept"); // expected-error {{no member named 'moveable' in 'B'}}
|
||||
// expected-error@-1 {{no member named 'moveable' in 'D'}}
|
||||
return static_cast<typename ref<T, noexcept(T(static_cast<T&&>(x)))>::type>(x);
|
||||
}
|
||||
|
||||
@ -36,6 +38,7 @@ namespace std {
|
||||
template<typename T> CONSTEXPR T &&forward(typename remove_reference<T>::type &x) {
|
||||
static_assert(T::moveable, "instantiated forward"); // expected-error {{no member named 'moveable' in 'B'}}
|
||||
// expected-error@-1 {{no member named 'moveable' in 'C'}}
|
||||
// expected-error@-2 {{no member named 'moveable' in 'D'}}
|
||||
return static_cast<T&&>(x);
|
||||
}
|
||||
template<typename T> CONSTEXPR T &&forward(typename remove_reference<T>::type &&x) {
|
||||
@ -67,21 +70,25 @@ namespace std {
|
||||
CONSTEXPR auto forward_like(T &&t) -> ForwardLikeRetType<U, T> {
|
||||
using TT = typename remove_reference<T>::type;
|
||||
static_assert(TT::moveable, "instantiated as_const"); // expected-error {{no member named 'moveable' in 'B'}}
|
||||
// expected-error@-1 {{no member named 'moveable' in 'D'}}
|
||||
return static_cast<ForwardLikeRetType<U, T>>(t);
|
||||
}
|
||||
|
||||
template<typename T> CONSTEXPR const T &as_const(T &x) {
|
||||
static_assert(T::moveable, "instantiated as_const"); // expected-error {{no member named 'moveable' in 'B'}}
|
||||
// expected-error@-1 {{no member named 'moveable' in 'D'}}
|
||||
return x;
|
||||
}
|
||||
|
||||
template<typename T> CONSTEXPR T *addressof(T &x) {
|
||||
static_assert(T::moveable, "instantiated addressof"); // expected-error {{no member named 'moveable' in 'B'}}
|
||||
// expected-error@-1 {{no member named 'moveable' in 'D'}}
|
||||
return __builtin_addressof(x);
|
||||
}
|
||||
|
||||
template<typename T> CONSTEXPR T *__addressof(T &x) {
|
||||
static_assert(T::moveable, "instantiated __addressof"); // expected-error {{no member named 'moveable' in 'B'}}
|
||||
// expected-error@-1 {{no member named 'moveable' in 'D'}}
|
||||
return __builtin_addressof(x);
|
||||
}
|
||||
}
|
||||
@ -116,42 +123,20 @@ A &forward_rval_as_lval() {
|
||||
}
|
||||
|
||||
struct B {};
|
||||
B &&(*pMove)(B&) = std::move; // #1 expected-note {{instantiation of}}
|
||||
B &&(*pMoveIfNoexcept)(B&) = &std::move_if_noexcept; // #2 expected-note {{instantiation of}}
|
||||
B &&(*pForward)(B&) = &std::forward<B>; // #3 expected-note {{instantiation of}}
|
||||
B &&(*pForwardLike)(B&) = &std::forward_like<int&&, B&>; // #4 expected-note {{instantiation of}}
|
||||
const B &(*pAsConst)(B&) = &std::as_const; // #5 expected-note {{instantiation of}}
|
||||
B *(*pAddressof)(B&) = &std::addressof; // #6 expected-note {{instantiation of}}
|
||||
B *(*pUnderUnderAddressof)(B&) = &std::__addressof; // #7 expected-note {{instantiation of}}
|
||||
B &&(*pMove)(B&) = std::move; // cxx17-warning {{non-addressable}} cxx20-error {{non-addressable}} expected-note {{instantiation of}}
|
||||
B &&(*pMoveIfNoexcept)(B&) = &std::move_if_noexcept; // cxx17-warning {{non-addressable}} cxx20-error {{non-addressable}} expected-note {{instantiation of}}
|
||||
B &&(*pForward)(B&) = &std::forward<B>; // cxx17-warning {{non-addressable}} cxx20-error {{non-addressable}} expected-note {{instantiation of}}
|
||||
B &&(*pForwardLike)(B&) = &std::forward_like<int&&, B&>; // cxx17-warning {{non-addressable}} cxx20-error {{non-addressable}} expected-note {{instantiation of}}
|
||||
const B &(*pAsConst)(B&) = &std::as_const; // cxx17-warning {{non-addressable}} cxx20-error {{non-addressable}} expected-note {{instantiation of}}
|
||||
B *(*pAddressof)(B&) = &std::addressof; // cxx17-warning {{non-addressable}} cxx20-error {{non-addressable}} expected-note {{instantiation of}}
|
||||
B *(*pUnderUnderAddressof)(B&) = &std::__addressof; // cxx17-warning {{non-addressable}} cxx20-error {{non-addressable}} expected-note {{instantiation of}}
|
||||
int (*pUnrelatedMove)(B, B) = std::move;
|
||||
|
||||
struct C {};
|
||||
C &&(&rMove)(C&) = std::move; // #8 expected-note {{instantiation of}}
|
||||
C &&(&rForward)(C&) = std::forward<C>; // #9 expected-note {{instantiation of}}
|
||||
C &&(&rMove)(C&) = std::move; // cxx17-warning {{non-addressable}} cxx20-error {{non-addressable}} expected-note {{instantiation of}}
|
||||
C &&(&rForward)(C&) = std::forward<C>; // cxx17-warning {{non-addressable}} cxx20-error {{non-addressable}} expected-note {{instantiation of}}
|
||||
int (&rUnrelatedMove)(B, B) = std::move;
|
||||
|
||||
#if __cplusplus <= 201703L
|
||||
// expected-warning@#1 {{non-addressable}}
|
||||
// expected-warning@#2 {{non-addressable}}
|
||||
// expected-warning@#3 {{non-addressable}}
|
||||
// expected-warning@#4 {{non-addressable}}
|
||||
// expected-warning@#5 {{non-addressable}}
|
||||
// expected-warning@#6 {{non-addressable}}
|
||||
// expected-warning@#7 {{non-addressable}}
|
||||
// expected-warning@#8 {{non-addressable}}
|
||||
// expected-warning@#9 {{non-addressable}}
|
||||
#else
|
||||
// expected-error@#1 {{non-addressable}}
|
||||
// expected-error@#2 {{non-addressable}}
|
||||
// expected-error@#3 {{non-addressable}}
|
||||
// expected-error@#4 {{non-addressable}}
|
||||
// expected-error@#5 {{non-addressable}}
|
||||
// expected-error@#6 {{non-addressable}}
|
||||
// expected-error@#7 {{non-addressable}}
|
||||
// expected-error@#8 {{non-addressable}}
|
||||
// expected-error@#9 {{non-addressable}}
|
||||
#endif
|
||||
|
||||
void attribute_const() {
|
||||
int n;
|
||||
std::move(n); // expected-warning {{ignoring return value}}
|
||||
@ -163,6 +148,22 @@ void attribute_const() {
|
||||
std::as_const(n); // expected-warning {{ignoring return value}}
|
||||
}
|
||||
|
||||
struct D {
|
||||
void* operator new(__SIZE_TYPE__, D&&(*)(D&));
|
||||
void* operator new(__SIZE_TYPE__, D*(*)(D&));
|
||||
void* operator new(__SIZE_TYPE__, const D&(*)(D&));
|
||||
};
|
||||
|
||||
void placement_new() {
|
||||
new (std::move<D>) D; // cxx17-warning {{non-addressable}} cxx20-error {{non-addressable}} expected-note {{instantiation of}}
|
||||
new (std::move_if_noexcept<D>) D; // cxx17-warning {{non-addressable}} cxx20-error {{non-addressable}} expected-note {{instantiation of}}
|
||||
new (std::forward<D>) D; // cxx17-warning {{non-addressable}} cxx20-error {{non-addressable}} expected-note {{instantiation of}}
|
||||
new (std::forward_like<D>) D; // cxx17-warning {{non-addressable}} cxx20-error {{non-addressable}} expected-note {{instantiation of}}
|
||||
new (std::addressof<D>) D; // cxx17-warning {{non-addressable}} cxx20-error {{non-addressable}} expected-note {{instantiation of}}
|
||||
new (std::__addressof<D>) D; // cxx17-warning {{non-addressable}} cxx20-error {{non-addressable}} expected-note {{instantiation of}}
|
||||
new (std::as_const<D>) D; // cxx17-warning {{non-addressable}} cxx20-error {{non-addressable}} expected-note {{instantiation of}}
|
||||
}
|
||||
|
||||
namespace std {
|
||||
template<typename T> int &move(T);
|
||||
}
|
||||
|
44
clang/test/SemaCXX/ms-property-new.cpp
Normal file
44
clang/test/SemaCXX/ms-property-new.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
// RUN: %clang_cc1 -ast-print -verify -triple=x86_64-pc-win32 -fms-compatibility %s -o - | FileCheck %s
|
||||
// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fms-compatibility -emit-pch -o %t %s
|
||||
// RUN: %clang_cc1 -triple=x86_64-pc-win32 -fms-compatibility -include-pch %t -verify %s -ast-print -o - | FileCheck %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
#ifndef HEADER
|
||||
#define HEADER
|
||||
|
||||
struct S {
|
||||
int GetX() { return 42; }
|
||||
__declspec(property(get=GetX)) int x;
|
||||
|
||||
int GetY(int i, int j) { return i+j; }
|
||||
__declspec(property(get=GetY)) int y[];
|
||||
|
||||
void* operator new(__SIZE_TYPE__, int);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct TS {
|
||||
T GetT() { return T(); }
|
||||
__declspec(property(get=GetT)) T t;
|
||||
|
||||
T GetR(T i, T j) { return i+j; }
|
||||
__declspec(property(get=GetR)) T r[];
|
||||
};
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
// CHECK: S *s;
|
||||
// CHECK-NEXT: new (s->x) S;
|
||||
// CHECK-NEXT: new ((s->y)[1][2]) S;
|
||||
S *s;
|
||||
new (s->x) S;
|
||||
new ((s->y)[1][2]) S;
|
||||
|
||||
// CHECK-NEXT: TS<double> *ts;
|
||||
// CHECK-NEXT: new (ts->t) S;
|
||||
// CHECK-NEXT: new ((ts->r)[1][2]) S;
|
||||
TS<double> *ts;
|
||||
new (ts->t) S;
|
||||
new ((ts->r)[1][2]) S;
|
||||
}
|
||||
|
||||
#endif
|
68
clang/test/SemaCXX/placement-new-bound-member-function.cpp
Normal file
68
clang/test/SemaCXX/placement-new-bound-member-function.cpp
Normal file
@ -0,0 +1,68 @@
|
||||
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
|
||||
|
||||
struct S {
|
||||
int NoArgs();
|
||||
int OneArg(int);
|
||||
|
||||
template <typename T>
|
||||
T TemplNoArgs(); // expected-note {{possible target for call}} // expected-note {{possible target for call}}
|
||||
|
||||
template <typename T>
|
||||
T TemplOneArg(T); // expected-note {{possible target for call}} // expected-note {{possible target for call}}
|
||||
|
||||
void* operator new(__SIZE_TYPE__, int);
|
||||
};
|
||||
|
||||
S* GetS();
|
||||
|
||||
int test() {
|
||||
S s, *ps = GetS();
|
||||
int (S::*pNoArgs)() = &S::NoArgs;
|
||||
int (S::*pOneArg)(int) = &S::OneArg;
|
||||
int (S::*pTemplNoArgs)() = &S::TemplNoArgs<int>;
|
||||
int (S::*pTemplOneArg)(int) = &S::TemplOneArg<int>;
|
||||
|
||||
new (s.NoArgs()) S;
|
||||
new (s.OneArg(1)) S;
|
||||
new (ps->NoArgs()) S;
|
||||
new (ps->OneArg(1)) S;
|
||||
new ((s.*pNoArgs)()) S;
|
||||
new ((s.*pOneArg)(1)) S;
|
||||
new ((ps->*pNoArgs)()) S;
|
||||
new ((ps->*pOneArg)(1)) S;
|
||||
|
||||
new (s.TemplNoArgs<int>()) S;
|
||||
new (s.TemplOneArg<int>(1)) S;
|
||||
new (ps->TemplNoArgs<int>()) S;
|
||||
new (ps->TemplOneArg<int>(1)) S;
|
||||
new ((s.*pTemplNoArgs)()) S;
|
||||
new ((s.*pTemplOneArg)(1)) S;
|
||||
new ((ps->*pTemplNoArgs)()) S;
|
||||
new ((ps->*pTemplOneArg)(1)) S;
|
||||
|
||||
new (s.NoArgs) S; // expected-error {{reference to non-static member function must be called; did you mean to call it with no arguments?}}
|
||||
new (s.OneArg) S; // expected-error {{reference to non-static member function must be called}}
|
||||
new (ps->NoArgs) S; // expected-error {{reference to non-static member function must be called; did you mean to call it with no arguments?}}
|
||||
new (ps->OneArg) S; // expected-error {{reference to non-static member function must be called}}
|
||||
new (s.*pNoArgs) S; // expected-error {{reference to non-static member function must be called; did you mean to call it with no arguments?}}
|
||||
new (s.*pOneArg) S; // expected-error {{reference to non-static member function must be called}}
|
||||
new (ps->*pNoArgs) S; // expected-error {{reference to non-static member function must be called; did you mean to call it with no arguments?}}
|
||||
new (ps->*pOneArg) S; // expected-error {{reference to non-static member function must be called}}
|
||||
new ((s.*pNoArgs)) S; // expected-error {{reference to non-static member function must be called; did you mean to call it with no arguments?}}
|
||||
new ((s.*pOneArg)) S; // expected-error {{reference to non-static member function must be called}}
|
||||
new ((ps->*pNoArgs)) S; // expected-error {{reference to non-static member function must be called; did you mean to call it with no arguments?}}
|
||||
new ((ps->*pOneArg)) S; // expected-error {{reference to non-static member function must be called}}
|
||||
|
||||
new (s.TemplNoArgs<int>) S; // expected-error {{reference to non-static member function must be called; did you mean to call it with no arguments?}}
|
||||
new (s.TemplOneArg<int>) S; // expected-error {{reference to non-static member function must be called}}
|
||||
new (ps->TemplNoArgs<int>) S; // expected-error {{reference to non-static member function must be called; did you mean to call it with no arguments?}}
|
||||
new (ps->TemplOneArg<int>) S; // expected-error {{reference to non-static member function must be called}}
|
||||
new (s.*pTemplNoArgs) S; // expected-error {{reference to non-static member function must be called; did you mean to call it with no arguments?}}
|
||||
new (s.*pTemplOneArg) S; // expected-error {{reference to non-static member function must be called}}
|
||||
new (ps->*pTemplNoArgs) S; // expected-error {{reference to non-static member function must be called; did you mean to call it with no arguments?}}
|
||||
new (ps->*pTemplOneArg) S; // expected-error {{reference to non-static member function must be called}}
|
||||
new ((s.*pTemplNoArgs)) S; // expected-error {{reference to non-static member function must be called; did you mean to call it with no arguments?}}
|
||||
new ((s.*pTemplOneArg)) S; // expected-error {{reference to non-static member function must be called}}
|
||||
new ((ps->*pTemplNoArgs)) S; // expected-error {{reference to non-static member function must be called; did you mean to call it with no arguments?}}
|
||||
new ((ps->*pTemplOneArg)) S; // expected-error {{reference to non-static member function must be called}}
|
||||
}
|
11
clang/test/SemaCXX/placement-new-builtin.cpp
Normal file
11
clang/test/SemaCXX/placement-new-builtin.cpp
Normal file
@ -0,0 +1,11 @@
|
||||
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
|
||||
|
||||
struct S {
|
||||
void* operator new(__SIZE_TYPE__, char*);
|
||||
void* operator new(__SIZE_TYPE__, __SIZE_TYPE__);
|
||||
};
|
||||
|
||||
int main() {
|
||||
new (__builtin_strchr) S; // expected-error {{builtin functions must be directly called}}
|
||||
new ((__builtin_strlen)) S; // expected-error {{builtin functions must be directly called}}
|
||||
}
|
26
clang/test/SemaCXX/placement-new-matrix.cpp
Normal file
26
clang/test/SemaCXX/placement-new-matrix.cpp
Normal file
@ -0,0 +1,26 @@
|
||||
// RUN: %clang_cc1 -fenable-matrix -fsyntax-only -verify %s -std=c++11
|
||||
|
||||
using Matrix = int __attribute__((matrix_type(4, 3)));
|
||||
|
||||
template <__SIZE_TYPE__ a, __SIZE_TYPE__ b>
|
||||
using TMatrix = int __attribute__((matrix_type(a, b)));
|
||||
|
||||
struct S {
|
||||
void* operator new(__SIZE_TYPE__, int);
|
||||
void* operator new(__SIZE_TYPE__, Matrix);
|
||||
void* operator new(__SIZE_TYPE__, TMatrix<2, 2>);
|
||||
};
|
||||
|
||||
int main() {
|
||||
Matrix m;
|
||||
TMatrix<2, 2> tm;
|
||||
|
||||
new (m) S {};
|
||||
new (tm) S {};
|
||||
|
||||
new (m[1][1]) S {};
|
||||
new (tm[1][1]) S {};
|
||||
|
||||
new (m[1]) S {}; // expected-error {{single subscript expressions are not allowed for matrix values}}
|
||||
new (tm[1]) S {}; // expected-error {{single subscript expressions are not allowed for matrix values}}
|
||||
}
|
12
clang/test/SemaCXX/placement-new-ms-__noop.cpp
Normal file
12
clang/test/SemaCXX/placement-new-ms-__noop.cpp
Normal file
@ -0,0 +1,12 @@
|
||||
// RUN: %clang_cc1 -fsyntax-only -fms-extensions -verify %s -std=c++11
|
||||
// expected-no-diagnostics
|
||||
|
||||
struct S {
|
||||
void* operator new(__SIZE_TYPE__, int);
|
||||
};
|
||||
|
||||
int main() {
|
||||
// MSVC supports __noop with no arguments or (), so we do as well.
|
||||
new (__noop) S;
|
||||
new ((__noop)) S;
|
||||
}
|
28
clang/test/SemaObjCXX/property-placement-new.mm
Normal file
28
clang/test/SemaObjCXX/property-placement-new.mm
Normal file
@ -0,0 +1,28 @@
|
||||
// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify -Wno-objc-root-class %s
|
||||
// expected-no-diagnostics
|
||||
|
||||
@interface I {
|
||||
int position;
|
||||
}
|
||||
@property(nonatomic) int position;
|
||||
@end
|
||||
|
||||
struct S {
|
||||
void *operator new(__SIZE_TYPE__, int);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct TS {
|
||||
void *operator new(__SIZE_TYPE__, T);
|
||||
};
|
||||
|
||||
I *GetI();
|
||||
|
||||
int main() {
|
||||
@autoreleasepool {
|
||||
auto* i = GetI();
|
||||
i.position = 42;
|
||||
new (i.position) S;
|
||||
new (i.position) TS<double>;
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user