diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 4d34346460561..4270f3ec5d6ab 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1972,6 +1972,16 @@ def TrivialABI : InheritableAttr { let SimpleHandler = 1; } +def ValueType : InheritableAttr { + // This attribute does not have a C [[]] spelling because it requires the + // CPlusPlus language option. + let Spellings = [Clang<"value_type", 0>]; + let Subjects = SubjectList<[CXXRecord]>; + let Documentation = [TrivialABIDocs]; + let LangOpts = [CPlusPlus]; + let SimpleHandler = 1; +} + def MaxFieldAlignment : InheritableAttr { // This attribute has no spellings as it is only ever created implicitly. let Spellings = []; diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td index 34e7ff9612859..4228bc1f7d888 100644 --- a/clang/include/clang/Basic/AttrDocs.td +++ b/clang/include/clang/Basic/AttrDocs.td @@ -9242,3 +9242,15 @@ Declares that a function potentially allocates heap memory, and prevents any pot of ``nonallocating`` by the compiler. }]; } + +def ValueTypeDocs : Documentation { + let Category = DocCatDecl; + let Content = [{ +The ``value_type`` attribute can be used to mark user-defined types as 'value +types'. When objects of value types are passed value to functions, the objects +are always considered to be formally copied into a new object. This means the +argument itself must be the only value referencing the passed object. This +allows the optimizer to assume that no other pointers may alias the object when +it is passed indirectly to a function.. + }]; +} diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 7aa77e55dbfcc..fb4154eef303d 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -2797,9 +2797,10 @@ void CodeGenModule::ConstructAttributeList(StringRef Name, Attrs.addByValAttr(getTypes().ConvertTypeForMem(ParamType)); auto *Decl = ParamType->getAsRecordDecl(); - if (CodeGenOpts.PassByValueIsNoAlias && Decl && - Decl->getArgPassingRestrictions() == - RecordArgPassingKind::CanPassInRegs) + if (Decl && ((CodeGenOpts.PassByValueIsNoAlias && + Decl->getArgPassingRestrictions() == + RecordArgPassingKind::CanPassInRegs) || + Decl->hasAttr())) // When calling the function, the pointer passed in will be the only // reference to the underlying object. Mark it accordingly. Attrs.addAttribute(llvm::Attribute::NoAlias); diff --git a/clang/test/CodeGenCXX/value-type-attr.cpp b/clang/test/CodeGenCXX/value-type-attr.cpp new file mode 100644 index 0000000000000..46938dd7d271a --- /dev/null +++ b/clang/test/CodeGenCXX/value-type-attr.cpp @@ -0,0 +1,40 @@ +// NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py UTC_ARGS: --version 5 +// RUN: %clang_cc1 -triple arm64-apple-ios11 -std=c++11 -fcxx-exceptions -fexceptions -emit-llvm -o - %s | FileCheck %s + +struct Small { + int *p; + Small(); + ~Small(); + Small(const Small &) noexcept; + Small &operator=(const Small &); +}; + + +struct __attribute__((value_type)) SmallVT { + int *p; + SmallVT(); + ~SmallVT(); + SmallVT(const SmallVT &) noexcept; + SmallVT &operator=(const SmallVT &); +}; + +struct Large { + int *p; + int a[128]; + Large(); + ~Large(); + Large(const Large &) noexcept; + Large &operator=(const Large &); +}; + +struct __attribute__((value_type)) LargeVT { + int *p; + int a[128]; + LargeVT(); + ~LargeVT(); + LargeVT(const LargeVT &) noexcept; + LargeVT &operator=(const LargeVT &); +}; + +void foo(Small a, SmallVT b, Large c, LargeVT d) {} +// CHECK: define void @_Z3foo5Small7SmallVT5Large7LargeVT(ptr noundef %a, ptr noalias noundef %b, ptr noundef %c, ptr noalias noundef %d) diff --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test b/clang/test/Misc/pragma-attribute-supported-attributes-list.test index 55f196625770a..2bc34802c5f5b 100644 --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test @@ -209,6 +209,7 @@ // CHECK-NEXT: UnsafeBufferUsage (SubjectMatchRule_function, SubjectMatchRule_field) // CHECK-NEXT: UseHandle (SubjectMatchRule_variable_is_parameter) // CHECK-NEXT: VTablePointerAuthentication (SubjectMatchRule_record) +// CHECK-NEXT: ValueType (SubjectMatchRule_record) // CHECK-NEXT: VecReturn (SubjectMatchRule_record) // CHECK-NEXT: VecTypeHint (SubjectMatchRule_function) // CHECK-NEXT: WarnUnused (SubjectMatchRule_record)