[clang] bd87916 - [clang] Add no_builtin attribute

Vlad Tsyrklevich via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 29 14:21:57 PDT 2019


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 <vitalybuka at 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 at 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 <vlad at 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 at 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 at -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 at -1 {{empty no_builtin cannot be composed with named
>>>> ones}}
>>>> +
>>>> +/// Can't attach attribute to a variable.
>>>> +int __attribute__((no_builtin)) variable;
>>>> +// expected-warning at -1 {{'no_builtin' attribute only applies to
>>>> functions}}
>>>> +
>>>> +/// Can't attach attribute to a declaration.
>>>> +void nobuiltin_on_declaration() __attribute__((no_builtin));
>>>> +// expected-error at -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 at -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 at -1 {{no_builtin attribute has no effect on
>>>> defaulted or deleted functions}}
>>>> +
>>>> +  void whatever() __attribute__((no_builtin("memcpy")));
>>>> +  // expected-error at -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 at -1 {{no_builtin attribute is permitted on
>>>> definitions only}}
>>>>
>>>>
>>>>
>>>> _______________________________________________
>>>> cfe-commits mailing list
>>>> cfe-commits at lists.llvm.org
>>>> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>>>>
>>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits at lists.llvm.org
>> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20191029/62732698/attachment-0001.html>


More information about the cfe-commits mailing list