brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.9 KiB · 625f164 Raw
151 lines · cpp
1//===- Attribute.cpp ------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// Example clang plugin which adds an an annotation to file-scope declarations10// with the 'example' attribute.11//12// This plugin is used by clang/test/Frontend/plugin-attribute tests.13//14//===----------------------------------------------------------------------===//15 16#include "clang/AST/ASTContext.h"17#include "clang/AST/Attr.h"18#include "clang/Sema/ParsedAttr.h"19#include "clang/Sema/Sema.h"20#include "clang/Sema/SemaDiagnostic.h"21#include "llvm/IR/Attributes.h"22using namespace clang;23 24namespace {25 26struct ExampleAttrInfo : public ParsedAttrInfo {27  ExampleAttrInfo() {28    // Can take up to 15 optional arguments, to emulate accepting a variadic29    // number of arguments. This just illustrates how many arguments a30    // `ParsedAttrInfo` can hold, we will not use that much in this example.31    OptArgs = 15;32    // GNU-style __attribute__(("example")) and C++/C23-style [[example]] and33    // [[plugin::example]] supported.34    static constexpr Spelling S[] = {{ParsedAttr::AS_GNU, "example"},35                                     {ParsedAttr::AS_C23, "example"},36                                     {ParsedAttr::AS_CXX11, "example"},37                                     {ParsedAttr::AS_CXX11, "plugin::example"}};38    Spellings = S;39  }40 41  bool diagAppertainsToDecl(Sema &S, const ParsedAttr &Attr,42                            const Decl *D) const override {43    // This attribute appertains to functions only.44    if (!isa<FunctionDecl>(D)) {45      S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)46          << Attr << Attr.isRegularKeywordAttribute() << ExpectedFunction;47      return false;48    }49    return true;50  }51 52  AttrHandling handleDeclAttribute(Sema &S, Decl *D,53                                   const ParsedAttr &Attr) const override {54    // Check if the decl is at file scope.55    if (!D->getDeclContext()->isFileContext()) {56      unsigned ID = S.getDiagnostics().getCustomDiagID(57          DiagnosticsEngine::Error,58          "'example' attribute only allowed at file scope");59      S.Diag(Attr.getLoc(), ID);60      return AttributeNotApplied;61    }62    // We make some rules here:63    // 1. Only accept at most 3 arguments here.64    // 2. The first argument must be a string literal if it exists.65    if (Attr.getNumArgs() > 3) {66      unsigned ID = S.getDiagnostics().getCustomDiagID(67          DiagnosticsEngine::Error,68          "'example' attribute only accepts at most three arguments");69      S.Diag(Attr.getLoc(), ID);70      return AttributeNotApplied;71    }72    // If there are arguments, the first argument should be a string literal.73    if (Attr.getNumArgs() > 0) {74      auto *Arg0 = Attr.getArgAsExpr(0);75      StringLiteral *Literal =76          dyn_cast<StringLiteral>(Arg0->IgnoreParenCasts());77      if (!Literal) {78        unsigned ID = S.getDiagnostics().getCustomDiagID(79            DiagnosticsEngine::Error, "first argument to the 'example' "80                                      "attribute must be a string literal");81        S.Diag(Attr.getLoc(), ID);82        return AttributeNotApplied;83      }84      SmallVector<Expr *, 16> ArgsBuf;85      for (unsigned i = 0; i < Attr.getNumArgs(); i++) {86        ArgsBuf.push_back(Attr.getArgAsExpr(i));87      }88      D->addAttr(AnnotateAttr::Create(S.Context, "example", ArgsBuf.data(),89                                      ArgsBuf.size(), Attr.getRange()));90    } else {91      // Attach an annotate attribute to the Decl.92      D->addAttr(AnnotateAttr::Create(S.Context, "example", nullptr, 0,93                                      Attr.getRange()));94    }95    return AttributeApplied;96  }97 98  bool diagAppertainsToStmt(Sema &S, const ParsedAttr &Attr,99                            const Stmt *St) const override {100    // This attribute appertains to for loop statements only.101    if (!isa<ForStmt>(St)) {102      S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)103          << Attr << Attr.isRegularKeywordAttribute()104          << ExpectedForLoopStatement;105      return false;106    }107    return true;108  }109 110  AttrHandling handleStmtAttribute(Sema &S, Stmt *St, const ParsedAttr &Attr,111                                   class Attr *&Result) const override {112    // We make some rules here:113    // 1. Only accept at most 3 arguments here.114    // 2. The first argument must be a string literal if it exists.115    if (Attr.getNumArgs() > 3) {116      unsigned ID = S.getDiagnostics().getCustomDiagID(117          DiagnosticsEngine::Error,118          "'example' attribute only accepts at most three arguments");119      S.Diag(Attr.getLoc(), ID);120      return AttributeNotApplied;121    }122    // If there are arguments, the first argument should be a string literal.123    if (Attr.getNumArgs() > 0) {124      auto *Arg0 = Attr.getArgAsExpr(0);125      StringLiteral *Literal =126          dyn_cast<StringLiteral>(Arg0->IgnoreParenCasts());127      if (!Literal) {128        unsigned ID = S.getDiagnostics().getCustomDiagID(129            DiagnosticsEngine::Error, "first argument to the 'example' "130                                      "attribute must be a string literal");131        S.Diag(Attr.getLoc(), ID);132        return AttributeNotApplied;133      }134      SmallVector<Expr *, 16> ArgsBuf;135      for (unsigned i = 0; i < Attr.getNumArgs(); i++) {136        ArgsBuf.push_back(Attr.getArgAsExpr(i));137      }138      Result = AnnotateAttr::Create(S.Context, "example", ArgsBuf.data(),139                                    ArgsBuf.size(), Attr.getRange());140    } else {141      Result = AnnotateAttr::Create(S.Context, "example", nullptr, 0,142                                    Attr.getRange());143    }144    return AttributeApplied;145  }146};147 148} // namespace149 150static ParsedAttrInfoRegistry::Add<ExampleAttrInfo> X("example", "");151