diff --git a/clang/examples/Attribute/Attribute.cpp b/clang/examples/Attribute/Attribute.cpp --- a/clang/examples/Attribute/Attribute.cpp +++ b/clang/examples/Attribute/Attribute.cpp @@ -55,23 +55,29 @@ S.Diag(Attr.getLoc(), ID); return AttributeNotApplied; } - // Check if we have an optional string argument. - 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->getExprLoc(), diag::err_attribute_argument_type) - << Attr.getAttrName() << AANT_ArgumentString; - return AttributeNotApplied; - } + + // First we have to create an `StringLiteralExpr`. + StringRef AnnotationString = "example"; + QualType StrTy = S.Context.getConstantArrayType( + S.Context.adjustStringLiteralBaseType(S.Context.CharTy.withConst()), + llvm::APInt(32, AnnotationString.size()), nullptr, ArrayType::Normal, + 0); + const auto AnnotationStringLoc = Attr.getLoc(); + auto *StringExpr = + StringLiteral::Create(S.Context, AnnotationString, StringLiteral::Ascii, + /*Pascal*/ false, StrTy, &AnnotationStringLoc, 1); + + llvm::SmallVector Args; + Args.reserve(Attr.getNumArgs() + 1); + + // Add the `StringLiteralExpr` as the first argument to an `AnnotationAttr` + Args.push_back(StringExpr); + for (unsigned Idx = 1; Idx < Attr.getNumArgs(); Idx++) { + Args.push_back(Attr.getArgAsExpr(Idx)); } + // Attach an annotate attribute to the Decl. - D->addAttr(AnnotateAttr::Create(S.Context, "example(" + Str.str() + ")", - Attr.getRange())); + S.AddAnnotationAttr(D, {Attr.getRange()}, AnnotationString, Args); return AttributeApplied; } }; diff --git a/clang/test/Frontend/plugin-attribute.cpp b/clang/test/Frontend/plugin-attribute.cpp --- a/clang/test/Frontend/plugin-attribute.cpp +++ b/clang/test/Frontend/plugin-attribute.cpp @@ -6,20 +6,17 @@ [[example]] void fn1b() { } [[plugin::example]] void fn1c() { } void fn2() __attribute__((example("somestring"))) { } -// ATTRIBUTE: warning: 'example' attribute only applies to functions +// ATTRIBUTE: warning: 'example' attribute only applies to functions [-Wignored-attributes] int var1 __attribute__((example("otherstring"))) = 1; -// 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: @llvm.global.annotations = {{.*}}@{{.*}}fn1a{{.*}}[[STR1_VAR]]{{.*}}@{{.*}}fn1b{{.*}}[[STR1_VAR]]{{.*}}@{{.*}}fn1c{{.*}}[[STR1_VAR]]{{.*}}@{{.*}}fn2{{.*}}[[STR2_VAR]] +// ATTRIBUTE: [[STR1_VAR:@.+]] = private unnamed_addr constant [8 x i8] c"example\00", section "llvm.metadata" +// ATTRIBUTE: @llvm.global.annotations = {{.*}}@{{.*}}fn1a{{.*}}[[STR1_VAR]]{{.*}}@{{.*}}fn1b{{.*}}[[STR1_VAR]]{{.*}}@{{.*}}fn1c{{.*}}[[STR1_VAR]]{{.*}}@{{.*}}fn2{{.*}} #ifdef BAD_ATTRIBUTE class Example { // BADATTRIBUTE: error: 'example' attribute only allowed at file scope void __attribute__((example)) fn3(); }; -// 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