From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- build/clang-plugin/CustomAttributes.cpp | 126 ++++++++++++++++++++++++++++++++ 1 file changed, 126 insertions(+) create mode 100644 build/clang-plugin/CustomAttributes.cpp (limited to 'build/clang-plugin/CustomAttributes.cpp') diff --git a/build/clang-plugin/CustomAttributes.cpp b/build/clang-plugin/CustomAttributes.cpp new file mode 100644 index 0000000000..d143f5856d --- /dev/null +++ b/build/clang-plugin/CustomAttributes.cpp @@ -0,0 +1,126 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "CustomAttributes.h" +#include "plugin.h" +#include "clang/Frontend/FrontendPluginRegistry.h" +#include + +/* Having annotations in the AST unexpectedly impacts codegen. + * Ideally, we'd avoid having annotations at all, by using an API such as + * the one from https://reviews.llvm.org/D31338, and storing the attributes + * data separately from the AST on our own. Unfortunately, there is no such + * API currently in clang, so we must do without. + * We can do something similar, though, where we go through the AST before + * running the checks, create a mapping of AST nodes to attributes, and + * remove the attributes/annotations from the AST nodes. + * Not all declarations can be reached from the decl() AST matcher, though, + * so we do our best effort (getting the other declarations we look at in + * checks). We emit a warning when checks look at a note that still has + * annotations attached (aka, hasn't been seen during our first pass), + * so that those don't go unnoticed. (-Werror should then take care of + * making that an error) + */ + +using namespace clang; +using namespace llvm; + +static DenseMap AttributesCache; + +static CustomAttributesSet CacheAttributes(const Decl *D) { + CustomAttributesSet attrs = {}; + for (auto Attr : D->specific_attrs()) { + auto annotation = Attr->getAnnotation(); +#define ATTR(a) \ + if (annotation == #a) { \ + attrs.has_##a = true; \ + } else +#include "CustomAttributes.inc" +#include "external/CustomAttributes.inc" +#undef ATTR + {} + } + const_cast(D)->dropAttr(); + AttributesCache.insert(std::make_pair(D, attrs)); + return attrs; +} + +#ifndef CLANG_TIDY +static void Report(const Decl *D, const char *message) { + ASTContext &Context = D->getASTContext(); + DiagnosticsEngine &Diag = Context.getDiagnostics(); + unsigned ID = + Diag.getDiagnosticIDs()->getCustomDiagID(DiagnosticIDs::Warning, message); + Diag.Report(D->getBeginLoc(), ID); +} + +class CustomAttributesMatcher + : public ast_matchers::MatchFinder::MatchCallback { +public: + void run(const ast_matchers::MatchFinder::MatchResult &Result) final { + if (auto D = Result.Nodes.getNodeAs("decl")) { + CacheAttributes(D); + } else if (auto L = Result.Nodes.getNodeAs("lambda")) { + CacheAttributes(L->getCallOperator()); + CacheAttributes(L->getLambdaClass()); + } + } +}; + +class CustomAttributesAction : public PluginASTAction { +public: + ASTConsumerPtr CreateASTConsumer(CompilerInstance &CI, + StringRef FileName) override { + auto &Context = CI.getASTContext(); + auto AstMatcher = new (Context.Allocate()) MatchFinder(); + auto Matcher = new (Context.Allocate()) + CustomAttributesMatcher(); + AstMatcher->addMatcher(decl().bind("decl"), Matcher); + AstMatcher->addMatcher(lambdaExpr().bind("lambda"), Matcher); + return AstMatcher->newASTConsumer(); + } + + bool ParseArgs(const CompilerInstance &CI, + const std::vector &Args) override { + return true; + } + + ActionType getActionType() override { return AddBeforeMainAction; } +}; + +static FrontendPluginRegistry::Add + X("moz-custom-attributes", "prepare custom attributes for moz-check"); +#endif + +CustomAttributesSet GetAttributes(const Decl *D) { + CustomAttributesSet attrs = {}; + if (D->hasAttr()) { +// If we are not in clang-tidy env push warnings, most likely we are in the +// build environment and this should have been done in AstMatcher - +// CustomAttributesMatcher +#ifndef CLANG_TIDY + Report(D, "Declaration has unhandled annotations."); +#endif + attrs = CacheAttributes(D); + } else { + auto attributes = AttributesCache.find(D); + if (attributes != AttributesCache.end()) { + attrs = attributes->second; + } + } + return attrs; +} + +bool hasCustomAttribute(const clang::Decl *D, CustomAttributes A) { + CustomAttributesSet attrs = GetAttributes(D); + switch (A) { +#define ATTR(a) \ + case a: \ + return attrs.has_##a; +#include "CustomAttributes.inc" +#include "external/CustomAttributes.inc" +#undef ATTR + } + return false; +} -- cgit v1.2.3