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 { ExampleAttrInfo__anon3f1e5a500111::ExampleAttrInfo25 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 static constexpr Spelling S[] = {{ParsedAttr::AS_GNU, "example"}, 32 {ParsedAttr::AS_CXX11, "example"}, 33 {ParsedAttr::AS_CXX11, "plugin::example"}}; 34 Spellings = S; 35 } 36 diagAppertainsToDecl__anon3f1e5a500111::ExampleAttrInfo37 bool diagAppertainsToDecl(Sema &S, const ParsedAttr &Attr, 38 const Decl *D) const override { 39 // This attribute appertains to functions only. 40 if (!isa<FunctionDecl>(D)) { 41 S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str) 42 << Attr << "functions"; 43 return false; 44 } 45 return true; 46 } 47 handleDeclAttribute__anon3f1e5a500111::ExampleAttrInfo48 AttrHandling handleDeclAttribute(Sema &S, Decl *D, 49 const ParsedAttr &Attr) const override { 50 // Check if the decl is at file scope. 51 if (!D->getDeclContext()->isFileContext()) { 52 unsigned ID = S.getDiagnostics().getCustomDiagID( 53 DiagnosticsEngine::Error, 54 "'example' attribute only allowed at file scope"); 55 S.Diag(Attr.getLoc(), ID); 56 return AttributeNotApplied; 57 } 58 // Check if we have an optional string argument. 59 StringRef Str = ""; 60 if (Attr.getNumArgs() > 0) { 61 Expr *ArgExpr = Attr.getArgAsExpr(0); 62 StringLiteral *Literal = 63 dyn_cast<StringLiteral>(ArgExpr->IgnoreParenCasts()); 64 if (Literal) { 65 Str = Literal->getString(); 66 } else { 67 S.Diag(ArgExpr->getExprLoc(), diag::err_attribute_argument_type) 68 << Attr.getAttrName() << AANT_ArgumentString; 69 return AttributeNotApplied; 70 } 71 } 72 // Attach an annotate attribute to the Decl. 73 D->addAttr(AnnotateAttr::Create(S.Context, "example(" + Str.str() + ")", 74 Attr.getRange())); 75 return AttributeApplied; 76 } 77 }; 78 79 } // namespace 80 81 static ParsedAttrInfoRegistry::Add<ExampleAttrInfo> X("example", ""); 82