forked from OSchip/llvm-project
[MS] Add frontend support for __declspec(allocator)
The intention is to add metadata to direct call sites of functions marked with __declspec(allocator), which will ultimately result in some S_HEAPALLOCSITE debug info records when emitting codeview. This is a piece of PR38491 llvm-svn: 356964
This commit is contained in:
parent
1e5d569c8c
commit
1181c9f45d
|
@ -2757,6 +2757,12 @@ def : IgnoredAttr {
|
|||
let Spellings = [Declspec<"property">];
|
||||
}
|
||||
|
||||
def MSAllocator : InheritableAttr {
|
||||
let Spellings = [Declspec<"allocator">];
|
||||
let Subjects = SubjectList<[Function]>;
|
||||
let Documentation = [MSAllocatorDocs];
|
||||
}
|
||||
|
||||
def MSStruct : InheritableAttr {
|
||||
let Spellings = [GCC<"ms_struct">];
|
||||
let Subjects = SubjectList<[Record]>;
|
||||
|
|
|
@ -4089,3 +4089,20 @@ it will be automatically applied to overrides if the method is virtual. The
|
|||
attribute can also be written using C++11 syntax: ``[[mig::server_routine]]``.
|
||||
}];
|
||||
}
|
||||
|
||||
def MSAllocatorDocs : Documentation {
|
||||
let Category = DocCatType;
|
||||
let Content = [{
|
||||
The ``__declspec(allocator)`` attribute is applied to functions that allocate
|
||||
memory, such as operator new in C++. When CodeView debug information is emitted
|
||||
(enabled by ``clang -gcodeview`` or ``clang-cl /Z7``), Clang will attempt to
|
||||
record the code offset of heap allocation call sites in the debug info. It will
|
||||
also record the type being allocated using some local heuristics. The Visual
|
||||
Studio debugger uses this information to `profile memory usage`_.
|
||||
|
||||
.. _profile memory usage: https://docs.microsoft.com/en-us/visualstudio/profiling/memory-usage
|
||||
|
||||
This attribute does not affect optimizations in any way, unlike GCC's
|
||||
``__attribute__((malloc))``.
|
||||
}];
|
||||
}
|
||||
|
|
|
@ -2956,6 +2956,9 @@ def err_base_specifier_attribute : Error<
|
|||
"%0 attribute cannot be applied to a base specifier">;
|
||||
def err_invalid_attribute_on_virtual_function : Error<
|
||||
"%0 attribute cannot be applied to virtual functions">;
|
||||
def warn_declspec_allocator_nonpointer : Warning<
|
||||
"ignoring __declspec(allocator) because the function return type %0 is not "
|
||||
"a pointer or reference type">, InGroup<IgnoredAttributes>;
|
||||
|
||||
def ext_cannot_use_trivial_abi : ExtWarn<
|
||||
"'trivial_abi' cannot be applied to %0">, InGroup<IgnoredAttributes>;
|
||||
|
|
|
@ -6548,6 +6548,20 @@ static void handleMIGServerRoutineAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
|
|||
handleSimpleAttribute<MIGServerRoutineAttr>(S, D, AL);
|
||||
}
|
||||
|
||||
static void handleMSAllocatorAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
|
||||
// Warn if the return type is not a pointer or reference type.
|
||||
if (auto *FD = dyn_cast<FunctionDecl>(D)) {
|
||||
QualType RetTy = FD->getReturnType();
|
||||
if (!RetTy->isPointerType() && !RetTy->isReferenceType()) {
|
||||
S.Diag(AL.getLoc(), diag::warn_declspec_allocator_nonpointer)
|
||||
<< AL.getRange() << RetTy;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
handleSimpleAttribute<MSAllocatorAttr>(S, D, AL);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Top Level Sema Entry Points
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
@ -7281,6 +7295,10 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
|
|||
case ParsedAttr::AT_MIGServerRoutine:
|
||||
handleMIGServerRoutineAttr(S, D, AL);
|
||||
break;
|
||||
|
||||
case ParsedAttr::AT_MSAllocator:
|
||||
handleMSAllocatorAttr(S, D, AL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
// RUN: %clang_cc1 -fms-compatibility -triple x86_64-windows-msvc -std=c++14 -fms-extensions -fms-compatibility-version=19.00 -verify %s
|
||||
|
||||
__declspec(allocator) int err_on_data; // expected-warning {{'allocator' attribute only applies to functions}}
|
||||
__declspec(allocator) struct ErrOnStruct1; // expected-warning {{place it after "struct" to apply attribute}}
|
||||
struct __declspec(allocator) ErrOnStruct2 {}; // expected-warning {{'allocator' attribute only applies to functions}}
|
||||
__declspec(allocator) void err_on_ret_void(); // expected-warning {{not a pointer or reference type}}
|
||||
__declspec(allocator) int err_on_ret_int(); // expected-warning {{not a pointer or reference type}}
|
||||
__declspec(allocator) void *accept_on_ptr1();
|
||||
__declspec(allocator) void *accept_on_ptr2(size_t);
|
||||
void * __declspec(allocator) accept_on_ptr3(size_t); // expected-error {{expected unqualified-id}}
|
||||
|
||||
struct Foo { int x; };
|
||||
__declspec(allocator) Foo *accept_nonvoid_ptr(size_t);
|
Loading…
Reference in New Issue