For instance here are the kind of errors I have by running a sanitized clang on master (with or without my patch it doesn't make a difference)
cd /redacted/git/llvm-project/llvm/build-msan && > /redacted/git/llvm-project/llvm/build-msan/bin/llvm-tblgen > -gen-opt-parser-defs -I /redacted/git/llvm-project/llvm/tools/llvm-lipo -I > /redacted/git/llvm-project/llvm/include > /redacted/git/llvm-project/llvm/tools/llvm-lipo/LipoOpts.td > --write-if-changed -o tools/llvm-lipo/LipoOpts.inc -d > tools/llvm-lipo/LipoOpts.inc.d > ==127351==WARNING: MemorySanitizer: use-of-uninitialized-value > #0 0x1015ae9 in > llvm::StringRef::split(llvm::SmallVectorImpl<llvm::StringRef>&, char, int, > bool) const > /redacted/git/llvm-project/llvm/build-msan/../lib/Support/StringRef.cpp:348:3 > #1 0x102e1d5 in llvm::Triple::Triple(llvm::Twine const&) > /redacted/git/llvm-project/llvm/build-msan/../lib/Support/Triple.cpp:731:19 > #2 0x107dd7d in llvm::sys::getProcessTriple() > /redacted/git/llvm-project/llvm/build-msan/../lib/Support/Host.cpp:1532:10 > #3 0xf873d7 in ParseCommandLineOptions > /redacted/git/llvm-project/llvm/build-msan/../lib/Support/CommandLine.cpp:1267:17 > #4 0xf873d7 in llvm::cl::ParseCommandLineOptions(int, char const* > const*, llvm::StringRef, llvm::raw_ostream*, char const*, bool) > /redacted/git/llvm-project/llvm/build-msan/../lib/Support/CommandLine.cpp:1242:24 > #5 0xef2ea7 in main > /redacted/git/llvm-project/llvm/build-msan/../utils/TableGen/TableGen.cpp:267:3 > #6 0x7f6202abf52a in __libc_start_main > (/lib/x86_64-linux-gnu/libc.so.6+0x2352a) > #7 0x42d4a9 in _start > (/redacted/git/llvm-project/llvm/build-msan/bin/llvm-tblgen+0x42d4a9) > Uninitialized value was stored to memory at > #0 0x102ecc6 in StringRef > /redacted/git/llvm-project/llvm/build-msan/../include/llvm/ADT/StringRef.h:111:27 > #1 0x102ecc6 in llvm::Triple::Triple(llvm::Twine const&) > /redacted/git/llvm-project/llvm/build-msan/../lib/Support/Triple.cpp:731:3 > #2 0x107dd7d in llvm::sys::getProcessTriple() > /redacted/git/llvm-project/llvm/build-msan/../lib/Support/Host.cpp:1532:10 > #3 0xf873d7 in ParseCommandLineOptions > /redacted/git/llvm-project/llvm/build-msan/../lib/Support/CommandLine.cpp:1267:17 > #4 0xf873d7 in llvm::cl::ParseCommandLineOptions(int, char const* > const*, llvm::StringRef, llvm::raw_ostream*, char const*, bool) > /redacted/git/llvm-project/llvm/build-msan/../lib/Support/CommandLine.cpp:1242:24 > #5 0xef2ea7 in main > /redacted/git/llvm-project/llvm/build-msan/../utils/TableGen/TableGen.cpp:267:3 > #6 0x7f6202abf52a in __libc_start_main > (/lib/x86_64-linux-gnu/libc.so.6+0x2352a) > Uninitialized value was created by an allocation of 'PT' in the stack > frame of function '_ZN4llvm3sys16getProcessTripleEv' > #0 0x107d9a0 in llvm::sys::getProcessTriple() > /redacted/git/llvm-project/llvm/build-msan/../lib/Support/Host.cpp:1530 > On Tue, Oct 29, 2019 at 1:32 PM Guillaume Chatelet <gchate...@google.com> 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