diff options
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 18 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclAttr.cpp | 39 |
2 files changed, 57 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index db741bc6e30..0c3c4399f6e 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -2398,6 +2398,24 @@ void Sema::mergeDeclAttributes(NamedDecl *New, Decl *Old, } } + // Re-declaration cannot add abi_tag's. + if (const auto *NewAbiTagAttr = New->getAttr<AbiTagAttr>()) { + if (const auto *OldAbiTagAttr = Old->getAttr<AbiTagAttr>()) { + for (const auto &NewTag : NewAbiTagAttr->tags()) { + if (std::find(OldAbiTagAttr->tags_begin(), OldAbiTagAttr->tags_end(), + NewTag) == OldAbiTagAttr->tags_end()) { + Diag(NewAbiTagAttr->getLocation(), + diag::err_new_abi_tag_on_redeclaration) + << NewTag; + Diag(OldAbiTagAttr->getLocation(), diag::note_previous_declaration); + } + } + } else { + Diag(NewAbiTagAttr->getLocation(), diag::err_abi_tag_on_redeclaration); + Diag(Old->getLocation(), diag::note_previous_declaration); + } + } + if (!Old->hasAttrs()) return; diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index 1fca27f8b95..f8cec752041 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -4615,6 +4615,42 @@ static void handleDeclspecThreadAttr(Sema &S, Decl *D, Attr.getRange(), S.Context, Attr.getAttributeSpellingListIndex())); } +static void handleAbiTagAttr(Sema &S, Decl *D, const AttributeList &Attr) { + SmallVector<StringRef, 4> Tags; + for (unsigned I = 0, E = Attr.getNumArgs(); I != E; ++I) { + StringRef Tag; + if (!S.checkStringLiteralArgumentAttr(Attr, I, Tag)) + return; + Tags.push_back(Tag); + } + + if (const auto *NS = dyn_cast<NamespaceDecl>(D)) { + if (!NS->isInline()) { + S.Diag(Attr.getLoc(), diag::warn_attr_abi_tag_namespace) << 0; + return; + } + if (NS->isAnonymousNamespace()) { + S.Diag(Attr.getLoc(), diag::warn_attr_abi_tag_namespace) << 1; + return; + } + if (Attr.getNumArgs() == 0) + Tags.push_back(NS->getName()); + } else if (!checkAttributeAtLeastNumArgs(S, Attr, 1)) + return; + + // Store tags sorted and without duplicates. + std::sort(Tags.begin(), Tags.end()); + Tags.erase(std::unique(Tags.begin(), Tags.end()), Tags.end()); + + D->addAttr(::new (S.Context) + AbiTagAttr(Attr.getRange(), S.Context, Tags.data(), Tags.size(), + Attr.getAttributeSpellingListIndex())); + + // FIXME: remove this warning as soon as mangled part is ready. + S.Diag(Attr.getRange().getBegin(), diag::warn_attribute_ignored) + << Attr.getName(); +} + static void handleARMInterruptAttr(Sema &S, Decl *D, const AttributeList &Attr) { // Check the attribute arguments. @@ -5637,6 +5673,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, case AttributeList::AT_Thread: handleDeclspecThreadAttr(S, D, Attr); break; + case AttributeList::AT_AbiTag: + handleAbiTagAttr(S, D, Attr); + break; // Thread safety attributes: case AttributeList::AT_AssertExclusiveLock: |