Yup, I didn't follow up to this email but we talked on gchat and sorted it out.
On Tue, Oct 29, 2019 at 2:20 PM Vitaly Buka <vitalyb...@google.com> wrote: > Ignoring "slave lost exception" bots are green for a while > http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast?numbuilds=100 > > http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-bootstrap?numbuilds=100 > > Vlads report was done when bots were on staging master :8014 for github > migration. Now they are on primary master :8011, so old links are stale. > > > > On Tue, Oct 29, 2019 at 5:33 AM Guillaume Chatelet via cfe-commits < > cfe-commits@lists.llvm.org> wrote: > >> hi Vlad, >> >> I've spend a big part of my day digging into this and I'm less and less >> convinced that my patch broke the builds. >> IIUC the built bots are still failing although my patch has been >> reverted for quite some time now. >> >> Am I missing something? >> >> On Mon, Oct 28, 2019 at 11:24 PM Vlad Tsyrklevich <v...@tsyrklevich.net> >> wrote: >> >>> I've reverted this change as it was causing ASan/MSan failures in >>> check-clang, e.g. take a look at the bottom 2 failures here: >>> http://lab.llvm.org:8014/builders/sanitizer-x86_64-linux-bootstrap/builds/124/steps/check-clang%20asan/logs/stdio >>> or >>> here >>> http://lab.llvm.org:8014/builders/sanitizer-x86_64-linux-fast/builds/126/steps/check-clang%20msan/logs/stdio >>> >>> On Mon, Oct 28, 2019 at 9:30 AM Guillaume Chatelet via cfe-commits < >>> cfe-commits@lists.llvm.org> wrote: >>> >>>> >>>> Author: Guillaume Chatelet >>>> Date: 2019-10-28T17:30:11+01:00 >>>> New Revision: bd87916109483d33455cbf20da2309197b983cdd >>>> >>>> URL: >>>> https://github.com/llvm/llvm-project/commit/bd87916109483d33455cbf20da2309197b983cdd >>>> DIFF: >>>> https://github.com/llvm/llvm-project/commit/bd87916109483d33455cbf20da2309197b983cdd.diff >>>> >>>> LOG: [clang] Add no_builtin attribute >>>> >>>> Summary: >>>> This is a follow up on https://reviews.llvm.org/D61634 >>>> This patch is simpler and only adds the no_builtin attribute. >>>> >>>> Reviewers: tejohnson, courbet, theraven, t.p.northover, jdoerfert >>>> >>>> Subscribers: mgrang, cfe-commits >>>> >>>> Tags: #clang >>>> >>>> Differential Revision: https://reviews.llvm.org/D68028 >>>> >>>> Added: >>>> clang/test/CodeGen/no-builtin.cpp >>>> clang/test/Sema/no-builtin.cpp >>>> >>>> Modified: >>>> clang/include/clang/AST/Decl.h >>>> clang/include/clang/Basic/Attr.td >>>> clang/include/clang/Basic/AttrDocs.td >>>> clang/include/clang/Basic/DiagnosticSemaKinds.td >>>> clang/lib/CodeGen/CGCall.cpp >>>> clang/lib/Sema/SemaDecl.cpp >>>> clang/lib/Sema/SemaDeclAttr.cpp >>>> clang/test/Misc/pragma-attribute-supported-attributes-list.test >>>> >>>> Removed: >>>> >>>> >>>> >>>> >>>> ################################################################################ >>>> diff --git a/clang/include/clang/AST/Decl.h >>>> b/clang/include/clang/AST/Decl.h >>>> index b3e7a570fd6d..16094c0988fa 100644 >>>> --- a/clang/include/clang/AST/Decl.h >>>> +++ b/clang/include/clang/AST/Decl.h >>>> @@ -2031,6 +2031,10 @@ class FunctionDecl : public DeclaratorDecl, >>>> /// >>>> /// This does not determine whether the function has been defined >>>> (e.g., in a >>>> /// previous definition); for that information, use isDefined. >>>> + /// >>>> + /// Note: the function declaration does not become a definition >>>> until the >>>> + /// parser reaches the definition, if called before, this function >>>> will return >>>> + /// `false`. >>>> bool isThisDeclarationADefinition() const { >>>> return isDeletedAsWritten() || isDefaulted() || Body || >>>> hasSkippedBody() || >>>> isLateTemplateParsed() || willHaveBody() || >>>> hasDefiningAttr(); >>>> >>>> diff --git a/clang/include/clang/Basic/Attr.td >>>> b/clang/include/clang/Basic/Attr.td >>>> index 4557a614d361..d5018f444e1c 100644 >>>> --- a/clang/include/clang/Basic/Attr.td >>>> +++ b/clang/include/clang/Basic/Attr.td >>>> @@ -3427,3 +3427,10 @@ def ObjCExternallyRetained : InheritableAttr { >>>> let Subjects = SubjectList<[NonParmVar, Function, Block, >>>> ObjCMethod]>; >>>> let Documentation = [ObjCExternallyRetainedDocs]; >>>> } >>>> + >>>> +def NoBuiltin : Attr { >>>> + let Spellings = [Clang<"no_builtin">]; >>>> + let Args = [VariadicStringArgument<"BuiltinNames">]; >>>> + let Subjects = SubjectList<[Function]>; >>>> + let Documentation = [NoBuiltinDocs]; >>>> +} >>>> >>>> diff --git a/clang/include/clang/Basic/AttrDocs.td >>>> b/clang/include/clang/Basic/AttrDocs.td >>>> index 6e79d0bb3631..9d0d27407573 100644 >>>> --- a/clang/include/clang/Basic/AttrDocs.td >>>> +++ b/clang/include/clang/Basic/AttrDocs.td >>>> @@ -4413,3 +4413,40 @@ and is not a general mechanism for declaring >>>> arbitrary aliases for >>>> clang builtin functions. >>>> }]; >>>> } >>>> + >>>> +def NoBuiltinDocs : Documentation { >>>> + let Category = DocCatFunction; >>>> + let Content = [{ >>>> +.. Note:: This attribute is not yet fully implemented, it is validated >>>> but has >>>> +no effect on the generated code. >>>> + >>>> +The ``__attribute__((no_builtin))`` is similar to the ``-fno-builtin`` >>>> flag >>>> +except it is specific to the body of a function. The attribute may >>>> also be >>>> +applied to a virtual function but has no effect on the behavior of >>>> overriding >>>> +functions in a derived class. >>>> + >>>> +It accepts one or more strings corresponding to the specific names of >>>> the >>>> +builtins to disable (e.g. "memcpy", "memset"). >>>> +If the attribute is used without parameters it will disable all >>>> buitins at >>>> +once. >>>> + >>>> +.. code-block:: c++ >>>> + >>>> + // The compiler is not allowed to add any builtin to foo's body. >>>> + void foo(char* data, size_t count) __attribute__((no_builtin)) { >>>> + // The compiler is not allowed to convert the loop into >>>> + // `__builtin_memset(data, 0xFE, count);`. >>>> + for (size_t i = 0; i < count; ++i) >>>> + data[i] = 0xFE; >>>> + } >>>> + >>>> + // The compiler is not allowed to add the `memcpy` builtin to bar's >>>> body. >>>> + void bar(char* data, size_t count) >>>> __attribute__((no_builtin("memcpy"))) { >>>> + // The compiler is allowed to convert the loop into >>>> + // `__builtin_memset(data, 0xFE, count);` but cannot generate any >>>> + // `__builtin_memcpy` >>>> + for (size_t i = 0; i < count; ++i) >>>> + data[i] = 0xFE; >>>> + } >>>> + }]; >>>> +} >>>> >>>> diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td >>>> b/clang/include/clang/Basic/DiagnosticSemaKinds.td >>>> index db877a46c300..20670a98fe03 100644 >>>> --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td >>>> +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td >>>> @@ -3624,6 +3624,15 @@ def err_attribute_overloadable_no_prototype : >>>> Error< >>>> def err_attribute_overloadable_multiple_unmarked_overloads : Error< >>>> "at most one overload for a given name may lack the 'overloadable' " >>>> "attribute">; >>>> +def warn_attribute_no_builtin_invalid_builtin_name : Warning< >>>> + "'%0' is not a valid builtin name for %1">, >>>> + InGroup<DiagGroup<"invalid-no-builtin-names">>; >>>> +def err_attribute_no_builtin_wildcard_or_builtin_name : Error< >>>> + "empty %0 cannot be composed with named ones">; >>>> +def err_attribute_no_builtin_on_non_definition : Error< >>>> + "%0 attribute is permitted on definitions only">; >>>> +def err_attribute_no_builtin_on_defaulted_deleted_function : Error< >>>> + "%0 attribute has no effect on defaulted or deleted functions">; >>>> def warn_ns_attribute_wrong_return_type : Warning< >>>> "%0 attribute only applies to %select{functions|methods|properties}1 >>>> that " >>>> "return %select{an Objective-C object|a pointer|a non-retainable >>>> pointer}2">, >>>> >>>> diff --git a/clang/lib/CodeGen/CGCall.cpp >>>> b/clang/lib/CodeGen/CGCall.cpp >>>> index b74f6f942426..62e8fa037013 100644 >>>> --- a/clang/lib/CodeGen/CGCall.cpp >>>> +++ b/clang/lib/CodeGen/CGCall.cpp >>>> @@ -1853,11 +1853,27 @@ void CodeGenModule::ConstructAttributeList( >>>> if (const FunctionDecl *Fn = dyn_cast<FunctionDecl>(TargetDecl)) { >>>> AddAttributesFromFunctionProtoType( >>>> getContext(), FuncAttrs, >>>> Fn->getType()->getAs<FunctionProtoType>()); >>>> - // Don't use [[noreturn]] or _Noreturn for a call to a virtual >>>> function. >>>> - // These attributes are not inherited by overloads. >>>> const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Fn); >>>> - if (Fn->isNoReturn() && !(AttrOnCallSite && MD && >>>> MD->isVirtual())) >>>> - FuncAttrs.addAttribute(llvm::Attribute::NoReturn); >>>> + const bool IsVirtualCall = MD && MD->isVirtual(); >>>> + // Don't use [[noreturn]], _Noreturn or [[no_builtin]] for a >>>> call to a >>>> + // virtual function. These attributes are not inherited by >>>> overloads. >>>> + if (!(AttrOnCallSite && IsVirtualCall)) { >>>> + if (Fn->isNoReturn()) >>>> + FuncAttrs.addAttribute(llvm::Attribute::NoReturn); >>>> + >>>> + if (const auto *NBA = TargetDecl->getAttr<NoBuiltinAttr>()) { >>>> + bool HasWildcard = llvm::is_contained(NBA->builtinNames(), >>>> "*"); >>>> + if (HasWildcard) >>>> + FuncAttrs.addAttribute("no-builtins"); >>>> + else >>>> + for (StringRef BuiltinName : NBA->builtinNames()) { >>>> + SmallString<32> AttributeName; >>>> + AttributeName += "no-builtin-"; >>>> + AttributeName += BuiltinName; >>>> + FuncAttrs.addAttribute(AttributeName); >>>> + } >>>> + } >>>> + } >>>> } >>>> >>>> // 'const', 'pure' and 'noalias' attributed functions are also >>>> nounwind. >>>> >>>> diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp >>>> index 6202391ee0b8..aba7049b0a51 100644 >>>> --- a/clang/lib/Sema/SemaDecl.cpp >>>> +++ b/clang/lib/Sema/SemaDecl.cpp >>>> @@ -9529,6 +9529,29 @@ Sema::ActOnFunctionDeclarator(Scope *S, >>>> Declarator &D, DeclContext *DC, >>>> } >>>> } >>>> >>>> + // Diagnose no_builtin attribute on function declaration that are >>>> not a >>>> + // definition. >>>> + // FIXME: We should really be doing this in >>>> + // SemaDeclAttr.cpp::handleNoBuiltinAttr, unfortunately we only have >>>> access to >>>> + // the FunctionDecl and at this point of the code >>>> + // FunctionDecl::isThisDeclarationADefinition() which always returns >>>> `false` >>>> + // because Sema::ActOnStartOfFunctionDef has not been called yet. >>>> + if (const auto *NBA = NewFD->getAttr<NoBuiltinAttr>()) >>>> + switch (D.getFunctionDefinitionKind()) { >>>> + case FDK_Defaulted: >>>> + case FDK_Deleted: >>>> + Diag(NBA->getLocation(), >>>> + >>>> diag::err_attribute_no_builtin_on_defaulted_deleted_function) >>>> + << NBA->getSpelling(); >>>> + break; >>>> + case FDK_Declaration: >>>> + Diag(NBA->getLocation(), >>>> diag::err_attribute_no_builtin_on_non_definition) >>>> + << NBA->getSpelling(); >>>> + break; >>>> + case FDK_Definition: >>>> + break; >>>> + } >>>> + >>>> return NewFD; >>>> } >>>> >>>> >>>> diff --git a/clang/lib/Sema/SemaDeclAttr.cpp >>>> b/clang/lib/Sema/SemaDeclAttr.cpp >>>> index abbd597a26d0..99eb23c3fe61 100644 >>>> --- a/clang/lib/Sema/SemaDeclAttr.cpp >>>> +++ b/clang/lib/Sema/SemaDeclAttr.cpp >>>> @@ -1069,6 +1069,56 @@ static void handleDiagnoseIfAttr(Sema &S, Decl >>>> *D, const ParsedAttr &AL) { >>>> S.Context, AL, Cond, Msg, DiagType, ArgDependent, >>>> cast<NamedDecl>(D))); >>>> } >>>> >>>> +static void handleNoBuiltinAttr(Sema &S, Decl *D, const ParsedAttr >>>> &AL) { >>>> + static constexpr const StringRef kWildcard = "*"; >>>> + >>>> + llvm::SmallVector<StringRef, 16> Names; >>>> + bool HasWildcard = false; >>>> + >>>> + const auto AddBuiltinName = [&Names, &HasWildcard](StringRef Name) { >>>> + if (Name == kWildcard) >>>> + HasWildcard = true; >>>> + Names.push_back(Name); >>>> + }; >>>> + >>>> + // Add previously defined attributes. >>>> + if (const auto *NBA = D->getAttr<NoBuiltinAttr>()) >>>> + for (StringRef BuiltinName : NBA->builtinNames()) >>>> + AddBuiltinName(BuiltinName); >>>> + >>>> + // Add current attributes. >>>> + if (AL.getNumArgs() == 0) >>>> + AddBuiltinName(kWildcard); >>>> + else >>>> + for (unsigned I = 0, E = AL.getNumArgs(); I != E; ++I) { >>>> + StringRef BuiltinName; >>>> + SourceLocation LiteralLoc; >>>> + if (!S.checkStringLiteralArgumentAttr(AL, I, BuiltinName, >>>> &LiteralLoc)) >>>> + return; >>>> + >>>> + if (Builtin::Context::isBuiltinFunc(BuiltinName.data())) >>>> + AddBuiltinName(BuiltinName); >>>> + else >>>> + S.Diag(LiteralLoc, >>>> diag::warn_attribute_no_builtin_invalid_builtin_name) >>>> + << BuiltinName << AL.getAttrName()->getName(); >>>> + } >>>> + >>>> + // Repeating the same attribute is fine. >>>> + llvm::sort(Names); >>>> + Names.erase(std::unique(Names.begin(), Names.end()), Names.end()); >>>> + >>>> + // Empty no_builtin must be on its own. >>>> + if (HasWildcard && Names.size() > 1) >>>> + S.Diag(D->getLocation(), >>>> + diag::err_attribute_no_builtin_wildcard_or_builtin_name) >>>> + << AL.getAttrName()->getName(); >>>> + >>>> + if (D->hasAttr<NoBuiltinAttr>()) >>>> + D->dropAttr<NoBuiltinAttr>(); >>>> + D->addAttr(::new (S.Context) >>>> + NoBuiltinAttr(S.Context, AL, Names.data(), >>>> Names.size())); >>>> +} >>>> + >>>> static void handlePassObjectSizeAttr(Sema &S, Decl *D, const >>>> ParsedAttr &AL) { >>>> if (D->hasAttr<PassObjectSizeAttr>()) { >>>> S.Diag(D->getBeginLoc(), >>>> diag::err_attribute_only_once_per_parameter) << AL; >>>> @@ -6608,6 +6658,9 @@ static void ProcessDeclAttribute(Sema &S, Scope >>>> *scope, Decl *D, >>>> case ParsedAttr::AT_DiagnoseIf: >>>> handleDiagnoseIfAttr(S, D, AL); >>>> break; >>>> + case ParsedAttr::AT_NoBuiltin: >>>> + handleNoBuiltinAttr(S, D, AL); >>>> + break; >>>> case ParsedAttr::AT_ExtVectorType: >>>> handleExtVectorTypeAttr(S, D, AL); >>>> break; >>>> >>>> diff --git a/clang/test/CodeGen/no-builtin.cpp >>>> b/clang/test/CodeGen/no-builtin.cpp >>>> new file mode 100644 >>>> index 000000000000..3c5d681282da >>>> --- /dev/null >>>> +++ b/clang/test/CodeGen/no-builtin.cpp >>>> @@ -0,0 +1,64 @@ >>>> +// RUN: %clang_cc1 -triple x86_64-linux-gnu -S -emit-llvm -o - %s | >>>> FileCheck %s >>>> + >>>> +// CHECK-LABEL: define void @foo_no_mempcy() #0 >>>> +extern "C" void foo_no_mempcy() __attribute__((no_builtin("memcpy"))) >>>> {} >>>> + >>>> +// CHECK-LABEL: define void @foo_no_mempcy_twice() #0 >>>> +extern "C" void foo_no_mempcy_twice() >>>> __attribute__((no_builtin("memcpy"))) __attribute__((no_builtin("memcpy"))) >>>> {} >>>> + >>>> +// CHECK-LABEL: define void @foo_no_builtins() #1 >>>> +extern "C" void foo_no_builtins() __attribute__((no_builtin)) {} >>>> + >>>> +// CHECK-LABEL: define void @foo_no_mempcy_memset() #2 >>>> +extern "C" void foo_no_mempcy_memset() >>>> __attribute__((no_builtin("memset", "memcpy"))) {} >>>> + >>>> +// CHECK-LABEL: define void @separate_attrs() #2 >>>> +extern "C" void separate_attrs() __attribute__((no_builtin("memset"))) >>>> __attribute__((no_builtin("memcpy"))) {} >>>> + >>>> +// CHECK-LABEL: define void @separate_attrs_ordering() #2 >>>> +extern "C" void separate_attrs_ordering() >>>> __attribute__((no_builtin("memcpy"))) __attribute__((no_builtin("memset"))) >>>> {} >>>> + >>>> +struct A { >>>> + virtual int foo() const __attribute__((no_builtin("memcpy"))) { >>>> return 1; } >>>> + virtual ~A(); >>>> +}; >>>> + >>>> +struct B : public A { >>>> + int foo() const override __attribute__((no_builtin("memmove"))) { >>>> return 2; } >>>> + virtual ~B(); >>>> +}; >>>> + >>>> +// CHECK-LABEL: define void @call_a_foo(%struct.A* %a) #3 >>>> +extern "C" void call_a_foo(A *a) { >>>> + // CHECK: %call = call i32 %2(%struct.A* %0) >>>> + a->foo(); // virtual call is not annotated >>>> +} >>>> + >>>> +// CHECK-LABEL: define void @call_b_foo(%struct.B* %b) #3 >>>> +extern "C" void call_b_foo(B *b) { >>>> + // CHECK: %call = call i32 %2(%struct.B* %0) >>>> + b->foo(); // virtual call is not annotated >>>> +} >>>> + >>>> +// CHECK-LABEL: define void @call_foo_no_mempcy() #3 >>>> +extern "C" void call_foo_no_mempcy() { >>>> + // CHECK: call void @foo_no_mempcy() #6 >>>> + foo_no_mempcy(); // call gets annotated with "no-builtin-memcpy" >>>> +} >>>> + >>>> +A::~A() {} // Anchoring A so A::foo() gets generated >>>> +B::~B() {} // Anchoring B so B::foo() gets generated >>>> + >>>> +// CHECK-LABEL: define linkonce_odr i32 @_ZNK1A3fooEv(%struct.A* >>>> %this) unnamed_addr #0 comdat align 2 >>>> +// CHECK-LABEL: define linkonce_odr i32 @_ZNK1B3fooEv(%struct.B* >>>> %this) unnamed_addr #5 comdat align 2 >>>> + >>>> +// CHECK: attributes #0 = {{{.*}}"no-builtin-memcpy"{{.*}}} >>>> +// CHECK-NOT: attributes #0 = {{{.*}}"no-builtin-memmove"{{.*}}} >>>> +// CHECK-NOT: attributes #0 = {{{.*}}"no-builtin-memset"{{.*}}} >>>> +// CHECK: attributes #1 = {{{.*}}"no-builtins"{{.*}}} >>>> +// CHECK: attributes #2 = >>>> {{{.*}}"no-builtin-memcpy"{{.*}}"no-builtin-memset"{{.*}}} >>>> +// CHECK-NOT: attributes #2 = {{{.*}}"no-builtin-memmove"{{.*}}} >>>> +// CHECK: attributes #5 = {{{.*}}"no-builtin-memmove"{{.*}}} >>>> +// CHECK-NOT: attributes #5 = {{{.*}}"no-builtin-memcpy"{{.*}}} >>>> +// CHECK-NOT: attributes #5 = {{{.*}}"no-builtin-memset"{{.*}}} >>>> +// CHECK: attributes #6 = { "no-builtin-memcpy" } >>>> >>>> diff --git >>>> a/clang/test/Misc/pragma-attribute-supported-attributes-list.test >>>> b/clang/test/Misc/pragma-attribute-supported-attributes-list.test >>>> index 25802bd73c51..729e9b7a6f77 100644 >>>> --- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test >>>> +++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test >>>> @@ -75,6 +75,7 @@ >>>> // CHECK-NEXT: NSConsumed (SubjectMatchRule_variable_is_parameter) >>>> // CHECK-NEXT: NSConsumesSelf (SubjectMatchRule_objc_method) >>>> // CHECK-NEXT: Naked (SubjectMatchRule_function) >>>> +// CHECK-NEXT: NoBuiltin (SubjectMatchRule_function) >>>> // CHECK-NEXT: NoCommon (SubjectMatchRule_variable) >>>> // CHECK-NEXT: NoDebug (SubjectMatchRule_type_alias, >>>> SubjectMatchRule_hasType_functionType, SubjectMatchRule_objc_method, >>>> SubjectMatchRule_variable_not_is_parameter) >>>> // CHECK-NEXT: NoDestroy (SubjectMatchRule_variable) >>>> >>>> diff --git a/clang/test/Sema/no-builtin.cpp >>>> b/clang/test/Sema/no-builtin.cpp >>>> new file mode 100644 >>>> index 000000000000..40781abd3037 >>>> --- /dev/null >>>> +++ b/clang/test/Sema/no-builtin.cpp >>>> @@ -0,0 +1,51 @@ >>>> +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -fsyntax-only >>>> -verify %s >>>> + >>>> +/// Prevent use of all builtins. >>>> +void valid_attribute_all_1() __attribute__((no_builtin)) {} >>>> +void valid_attribute_all_2() __attribute__((no_builtin())) {} >>>> + >>>> +/// Prevent use of specific builtins. >>>> +void valid_attribute_function() __attribute__((no_builtin("memcpy"))) >>>> {} >>>> +void valid_attribute_functions() __attribute__((no_builtin("memcpy"))) >>>> __attribute__((no_builtin("memcmp"))) {} >>>> + >>>> +/// Many times the same builtin is fine. >>>> +void many_attribute_function_1() __attribute__((no_builtin)) >>>> __attribute__((no_builtin)) {} >>>> +void many_attribute_function_2() __attribute__((no_builtin("memcpy"))) >>>> __attribute__((no_builtin("memcpy"))) {} >>>> +void many_attribute_function_3() __attribute__((no_builtin("memcpy", >>>> "memcpy"))) {} >>>> +void many_attribute_function_4() __attribute__((no_builtin("memcpy", >>>> "memcpy"))) __attribute__((no_builtin("memcpy"))) {} >>>> + >>>> +/// Invalid builtin name. >>>> +void invalid_builtin() __attribute__((no_builtin("not_a_builtin"))) {} >>>> +// expected-warning@-1 {{'not_a_builtin' is not a valid builtin name >>>> for no_builtin}} >>>> + >>>> +/// Can't use bare no_builtin with a named one. >>>> +void wildcard_and_functionname() __attribute__((no_builtin)) >>>> __attribute__((no_builtin("memcpy"))) {} >>>> +// expected-error@-1 {{empty no_builtin cannot be composed with named >>>> ones}} >>>> + >>>> +/// Can't attach attribute to a variable. >>>> +int __attribute__((no_builtin)) variable; >>>> +// expected-warning@-1 {{'no_builtin' attribute only applies to >>>> functions}} >>>> + >>>> +/// Can't attach attribute to a declaration. >>>> +void nobuiltin_on_declaration() __attribute__((no_builtin)); >>>> +// expected-error@-1 {{no_builtin attribute is permitted on >>>> definitions only}} >>>> + >>>> +struct S { >>>> + /// Can't attach attribute to a defaulted function, >>>> + S() >>>> + __attribute__((no_builtin)) = default; >>>> + // expected-error@-1 {{no_builtin attribute has no effect on >>>> defaulted or deleted functions}} >>>> + >>>> + /// Can't attach attribute to a deleted function, >>>> + S(const S &) >>>> + __attribute__((no_builtin)) = delete; >>>> + // expected-error@-1 {{no_builtin attribute has no effect on >>>> defaulted or deleted functions}} >>>> + >>>> + void whatever() __attribute__((no_builtin("memcpy"))); >>>> + // expected-error@-1 {{no_builtin attribute is permitted on >>>> definitions only}} >>>> +}; >>>> + >>>> +/// Can't attach attribute to an aliased function. >>>> +void alised_function() {} >>>> +void aliasing_function() __attribute__((no_builtin)) >>>> __attribute__((alias("alised_function"))); >>>> +// expected-error@-1 {{no_builtin attribute is permitted on >>>> definitions only}} >>>> >>>> >>>> >>>> _______________________________________________ >>>> cfe-commits mailing list >>>> cfe-commits@lists.llvm.org >>>> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >>>> >>> _______________________________________________ >> cfe-commits mailing list >> cfe-commits@lists.llvm.org >> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >> >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits