Index: examples/Attribute/Attribute.cpp =================================================================== --- /dev/null +++ examples/Attribute/Attribute.cpp @@ -0,0 +1,61 @@ +//===- Attribute.cpp ------------------------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Example clang plugin which adds an an annotation to file-scope declarations +// with the 'example' attribute. +// +//===----------------------------------------------------------------------===// + +#include "clang/AST/ASTContext.h" +#include "clang/AST/Attr.h" +#include "clang/Sema/AttributeList.h" +#include "clang/Sema/Sema.h" +#include "clang/Sema/SemaDiagnostic.h" +#include "llvm/IR/Attributes.h" +using namespace clang; + +namespace { + +struct ExampleAttrInfo : public ParsedAttrInfo { + ExampleAttrInfo() { + Syntax = AttributeList::AS_GNU; + AttrKind = AttributeList::AT_Annotate; + OptArgs = 1; + } + virtual bool handleDeclAttribute(Sema &S, Decl *D, const AttributeList &Attr) { + /* Check if the decl is at file scope */ + if (!D->getDeclContext()->isFileContext()) { + unsigned ID = S.getDiagnostics().getCustomDiagID( + DiagnosticsEngine::Error, + "'example' attribute only allowed at file scope"); + S.Diag(Attr.getLoc(), ID); + } + /* The attribute can take an optional string argument: check for this */ + StringRef Str = ""; + if (Attr.getNumArgs() > 0) { + Expr *ArgExpr = Attr.getArgAsExpr(0); + StringLiteral *Literal = + dyn_cast(ArgExpr->IgnoreParenCasts()); + if (Literal) { + Str = Literal->getString(); + } else { + S.Diag(ArgExpr->getLocStart(), diag::err_attribute_argument_type) + << Attr.getName() << AANT_ArgumentString; + } + } + /* Attach an annotate attribute to the Decl */ + D->addAttr(new (S.Context)AnnotateAttr(Attr.getRange(), S.Context, + "example("+Str.str()+")", 0)); + return true; + } +}; + +} + +static AttrInfoRegistry::Add X("example", ""); Index: examples/Attribute/CMakeLists.txt =================================================================== --- /dev/null +++ examples/Attribute/CMakeLists.txt @@ -0,0 +1,11 @@ +add_llvm_loadable_module(Attribute Attribute.cpp PLUGIN_TOOL clang) + +if(LLVM_ENABLE_PLUGINS AND (WIN32 OR CYGWIN)) + target_link_libraries(AnnotateFunctions ${cmake_2_8_12_PRIVATE} + clangAST + clangBasic + clangFrontend + clangLex + LLVMSupport + ) +endif() Index: examples/CMakeLists.txt =================================================================== --- examples/CMakeLists.txt +++ examples/CMakeLists.txt @@ -9,3 +9,4 @@ add_subdirectory(clang-interpreter) add_subdirectory(PrintFunctionNames) add_subdirectory(AnnotateFunctions) +add_subdirectory(Attribute) Index: test/CMakeLists.txt =================================================================== --- test/CMakeLists.txt +++ test/CMakeLists.txt @@ -64,6 +64,7 @@ if (CLANG_BUILD_EXAMPLES) list(APPEND CLANG_TEST_DEPS + Attribute AnnotateFunctions clang-interpreter PrintFunctionNames Index: test/Frontend/plugin-attribute.c =================================================================== --- /dev/null +++ test/Frontend/plugin-attribute.c @@ -0,0 +1,22 @@ +// RUN: %clang -fplugin=%llvmshlibdir/Attribute%pluginext -emit-llvm -S %s -o - | FileCheck %s --check-prefix=ATTRIBUTE +// RUN: not %clang -fplugin=%llvmshlibdir/Attribute%pluginext -emit-llvm -DBAD_ATTRIBUTE -S %s -o - 2>&1 | FileCheck %s --check-prefix=BADATTRIBUTE +// REQUIRES: plugins, examples + +// ATTRIBUTE: [[STR1_VAR:@.+]] = private unnamed_addr constant [10 x i8] c"example()\00" +// ATTRIBUTE: [[STR2_VAR:@.+]] = private unnamed_addr constant [20 x i8] c"example(somestring)\00" +// ATTRIBUTE: [[STR3_VAR:@.+]] = private unnamed_addr constant [21 x i8] c"example(otherstring)\00" +// ATTRIBUTE: @llvm.global.annotations = {{.*}}@fn1{{.*}}[[STR1_VAR]]{{.*}}@fn2{{.*}}[[STR2_VAR]]{{.*}}@var1{{.*}}[[STR3_VAR]] +void fn1() __attribute__((example)) { } +void fn2() __attribute__((example("somestring"))) { } +int var1 __attribute__((example("otherstring"))) = 1; + +#ifdef BAD_ATTRIBUTE +void fn3() { + // BADATTRIBUTE: error: 'example' attribute only allowed at file scop + int var2 __attribute__((example)); +} +// BADATTRIBUTE: error: 'example' attribute requires a string +void fn4() __attribute__((example(123))) { } +// BADATTRIBUTE: error: 'example' attribute takes no more than 1 argument +void fn5() __attribute__((example("a","b"))) { } +#endif