diff options
author | Yafei Liu <psionic12@outlook.com> | 2020-12-21 08:22:56 -0500 |
---|---|---|
committer | Aaron Ballman <aaron@aaronballman.com> | 2020-12-21 08:24:09 -0500 |
commit | b2ba6867eac10874bd279c739639bdb9e60c1996 (patch) | |
tree | cbd916bd15fb038c67b09256079e9b374c3d1496 /clang/examples | |
parent | a3a896d1cdc0fd2f87de4787120eaac08e69eb5f (diff) | |
download | llvm-b2ba6867eac10874bd279c739639bdb9e60c1996.zip llvm-b2ba6867eac10874bd279c739639bdb9e60c1996.tar.gz llvm-b2ba6867eac10874bd279c739639bdb9e60c1996.tar.bz2 |
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.cpp | 49 |
1 files changed, 33 insertions, 16 deletions
diff --git a/clang/examples/Attribute/Attribute.cpp b/clang/examples/Attribute/Attribute.cpp index 998f175..159b09e 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; } }; |