diff options
| author | Guillaume Chatelet <gchatelet@google.com> | 2019-09-25 11:31:28 +0200 |
|---|---|---|
| committer | Guillaume Chatelet <gchatelet@google.com> | 2019-10-28 17:30:11 +0100 |
| commit | bd87916109483d33455cbf20da2309197b983cdd (patch) | |
| tree | eb406f69d0ceb93e07ba90781ca52b69a61e83a6 /clang/lib | |
| parent | a062856bcf4fca26dab06afdf14bf1c815831f9c (diff) | |
| download | bcm5719-llvm-bd87916109483d33455cbf20da2309197b983cdd.tar.gz bcm5719-llvm-bd87916109483d33455cbf20da2309197b983cdd.zip | |
[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
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 24 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 23 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 53 |
3 files changed, 96 insertions, 4 deletions
diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index b74f6f94242..62e8fa03701 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 6202391ee0b..aba7049b0a5 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 abbd597a26d..99eb23c3fe6 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; |

