summaryrefslogtreecommitdiff
path: root/clang/examples
diff options
context:
space:
mode:
authorYafei Liu <psionic12@outlook.com>2020-12-21 08:22:56 -0500
committerAaron Ballman <aaron@aaronballman.com>2020-12-21 08:24:09 -0500
commitb2ba6867eac10874bd279c739639bdb9e60c1996 (patch)
treecbd916bd15fb038c67b09256079e9b374c3d1496 /clang/examples
parenta3a896d1cdc0fd2f87de4787120eaac08e69eb5f (diff)
downloadllvm-b2ba6867eac10874bd279c739639bdb9e60c1996.tar.gz
Refactoring the attribute plugin example to fit the new API
Make the example compile and the test case pass.
Diffstat (limited to 'clang/examples')
-rw-r--r--clang/examples/Attribute/Attribute.cpp49
1 files changed, 33 insertions, 16 deletions
diff --git a/clang/examples/Attribute/Attribute.cpp b/clang/examples/Attribute/Attribute.cpp
index 998f175dae54..159b09e4b154 100644
--- a/clang/examples/Attribute/Attribute.cpp
+++ b/clang/examples/Attribute/Attribute.cpp
@@ -23,9 +23,10 @@ namespace {
struct ExampleAttrInfo : public ParsedAttrInfo {
ExampleAttrInfo() {
- // Can take an optional string argument (the check that the argument
- // actually is a string happens in handleDeclAttribute).
- OptArgs = 1;
+ // Can take up to 15 optional arguments, to emulate accepting a variadic
+ // number of arguments. This just illustrates how many arguments a
+ // `ParsedAttrInfo` can hold, we will not use that much in this example.
+ OptArgs = 15;
// GNU-style __attribute__(("example")) and C++-style [[example]] and
// [[plugin::example]] supported.
static constexpr Spelling S[] = {{ParsedAttr::AS_GNU, "example"},
@@ -39,7 +40,7 @@ struct ExampleAttrInfo : public ParsedAttrInfo {
// This attribute appertains to functions only.
if (!isa<FunctionDecl>(D)) {
S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type_str)
- << Attr << "functions";
+ << Attr << "functions";
return false;
}
return true;
@@ -55,23 +56,39 @@ struct ExampleAttrInfo : public ParsedAttrInfo {
S.Diag(Attr.getLoc(), ID);
return AttributeNotApplied;
}
- // Check if we have an optional string argument.
- StringRef Str = "";
+ // We make some rules here:
+ // 1. Only accept at most 3 arguments here.
+ // 2. The first argument must be a string literal if it exists.
+ if (Attr.getNumArgs() > 3) {
+ unsigned ID = S.getDiagnostics().getCustomDiagID(
+ DiagnosticsEngine::Error,
+ "'example' attribute only accepts at most three arguments");
+ S.Diag(Attr.getLoc(), ID);
+ return AttributeNotApplied;
+ }
+ // If there are arguments, the first argument should be a string literal.
if (Attr.getNumArgs() > 0) {
- Expr *ArgExpr = Attr.getArgAsExpr(0);
+ auto *Arg0 = Attr.getArgAsExpr(0);
StringLiteral *Literal =
- dyn_cast<StringLiteral>(ArgExpr->IgnoreParenCasts());
- if (Literal) {
- Str = Literal->getString();
- } else {
- S.Diag(ArgExpr->getExprLoc(), diag::err_attribute_argument_type)
- << Attr.getAttrName() << AANT_ArgumentString;
+ dyn_cast<StringLiteral>(Arg0->IgnoreParenCasts());
+ if (!Literal) {
+ unsigned ID = S.getDiagnostics().getCustomDiagID(
+ DiagnosticsEngine::Error, "first argument to the 'example' "
+ "attribute must be a string literal");
+ S.Diag(Attr.getLoc(), ID);
return AttributeNotApplied;
}
+ SmallVector<Expr *, 16> ArgsBuf;
+ for (unsigned i = 0; i < Attr.getNumArgs(); i++) {
+ ArgsBuf.push_back(Attr.getArgAsExpr(i));
+ }
+ D->addAttr(AnnotateAttr::Create(S.Context, "example", ArgsBuf.data(),
+ ArgsBuf.size(), Attr.getRange()));
+ } else {
+ // Attach an annotate attribute to the Decl.
+ D->addAttr(AnnotateAttr::Create(S.Context, "example", nullptr, 0,
+ Attr.getRange()));
}
- // Attach an annotate attribute to the Decl.
- D->addAttr(AnnotateAttr::Create(S.Context, "example(" + Str.str() + ")",
- Attr.getRange()));
return AttributeApplied;
}
};