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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // Example clang plugin which adds an an annotation to file-scope declarations 10 // with the 'example' attribute. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "clang/AST/ASTContext.h" 15 #include "clang/AST/Attr.h" 16 #include "clang/Sema/ParsedAttr.h" 17 #include "clang/Sema/Sema.h" 18 #include "clang/Sema/SemaDiagnostic.h" 19 #include "llvm/IR/Attributes.h" 20 using namespace clang; 21 22 namespace { 23 24 struct ExampleAttrInfo : public ParsedAttrInfo { 25 ExampleAttrInfo() { 26 // Can take an optional string argument (the check that the argument 27 // actually is a string happens in handleDeclAttribute). 28 OptArgs = 1; 29 // GNU-style __attribute__(("example")) and C++-style [[example]] and 30 // [[plugin::example]] supported. 31 Spellings.push_back({ParsedAttr::AS_GNU, "example"}); 32 Spellings.push_back({ParsedAttr::AS_CXX11, "example"}); 33 Spellings.push_back({ParsedAttr::AS_CXX11, "plugin::example"}); 34 } 35 36 bool diagAppertainsToDecl(Sema &S, const ParsedAttr &Attr, 37 const Decl *D) const override { 38 // This attribute appertains to functions only. 39 if (!isa<FunctionDecl>(D)) { 40 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str) 41 << Attr << "functions"; 42 return false; 43 } 44 return true; 45 } 46 47 AttrHandling handleDeclAttribute(Sema &S, Decl *D, 48 const ParsedAttr &Attr) const override { 49 // Check if the decl is at file scope. 50 if (!D->getDeclContext()->isFileContext()) { 51 unsigned ID = S.getDiagnostics().getCustomDiagID( 52 DiagnosticsEngine::Error, 53 "'example' attribute only allowed at file scope"); 54 S.Diag(Attr.getLoc(), ID); 55 return AttributeNotApplied; 56 } 57 // Check if we have an optional string argument. 58 StringRef Str = ""; 59 if (Attr.getNumArgs() > 0) { 60 Expr *ArgExpr = Attr.getArgAsExpr(0); 61 StringLiteral *Literal = 62 dyn_cast<StringLiteral>(ArgExpr->IgnoreParenCasts()); 63 if (Literal) { 64 Str = Literal->getString(); 65 } else { 66 S.Diag(ArgExpr->getExprLoc(), diag::err_attribute_argument_type) 67 << Attr.getAttrName() << AANT_ArgumentString; 68 return AttributeNotApplied; 69 } 70 } 71 // Attach an annotate attribute to the Decl. 72 D->addAttr(AnnotateAttr::Create(S.Context, "example(" + Str.str() + ")", 73 Attr.getRange())); 74 return AttributeApplied; 75 } 76 }; 77 78 } // namespace 79 80 static ParsedAttrInfoRegistry::Add<ExampleAttrInfo> X("example", ""); 81