The content is mainly from the document "Clang" CFE internals manual address: Workshop. I am not talking about it here. I just want to combine some of the code and documents in this example to present them to you. How to add an Attribute before ¶
To add an attribute, you'll have to add it to the list of attributes, add it tothe parsing phase, and look for it in the ast scan. r124217 has a good example
Of adding a warning attribute.
(Beware that this hasn't been reviewed/fixed by the people who designed theattributes system yet .)
Include/clang/basic/ATTR. TD
First, add your attribute to
Include/clang/basic/ATTR. TD file.
Each attribute getsDefInheriting fromATTROr one of itssubclasses.Inheritableattr
Means that the attribute also applies tosubsequent declarations of the same name.
SpellingsLists the strings that can appear in_ Attribute _ (here ))Or[[Here].
All such strings will be synonymous. If you want to allow[[]C ++ 11 syntax, You have to define a listNamespaces, Which willlet users
Write[[Namespace: spelling]. Using the empty string for anamespace will allow users to write just the spelling with no"::". Attributes which
G ++-4.8 accepts shoshould also haveCxx11 <"GNU", "spelling">Spelling.
SubjectsRestricts what kinds of AST node to which this attribute canappertain (roughly, attach ).
ARGsNames the arguments the attribute takes, in order. IfARGsIs
[Stringargument <"arg1">,
Intargument <"arg2">]Then_ Attribute _ (myattribute ("hello", 3 )))Will be a valid use.
--- cfe/trunk/include/clang/Basic/Attr.td2011/01/25 19:39:31124216+++ cfe/trunk/include/clang/Basic/Attr.td2011/01/25 20:08:12124217@@ -232,6 +232,11 @@ let Spellings = []; } +def ForbidTemporaries : Attr {+ let Spellings = ["forbid_temporaries"];+ let Subjects = [CXXRecord];+}+ def Format : InheritableAttr { let Spellings = ["format"]; let Args = [StringArgument<"Type">, IntArgument<"FormatIdx">,
Boilerplate
Write a newHandleyourattr ()Function inlib/SEMA/semadeclattr. cpp, and
Add a case to the switch inProcessnoninheritabledeclattr ()Or
Processinheritabledeclattr ()Forwarding to it.
If your attribute causes extra warnings to fire, define
DiaggroupIn
Include/clang/basic/diagnosticgroups. TD named after the attribute's
SpellingWith "_" S replaced by "-" S. If you're 'reonly defining one diagnostic, you can skip Diagnosticgroups. TDAnd use Ingroup <diaggroup <"Your-attribute">
Directly indiagnosticsemakinds. TD
--- cfe/trunk/lib/Sema/SemaDeclAttr.cpp2011/01/25 19:39:31124216+++ cfe/trunk/lib/Sema/SemaDeclAttr.cpp2011/01/25 20:08:12124217@@ -885,6 +885,24 @@ d->addAttr(::new (S.Context) VecReturnAttr(Attr.getLoc(), S.Context)); } +static void HandleForbidTemporariesAttr(Decl *d, const AttributeList &Attr,+ Sema &S) {+ assert(Attr.isInvalid() == false);++ if (Attr.getNumArgs() != 0) {+ S.Diag(Attr.getLoc(), diag::err_attribute_wrong_number_arguments) << 0;+ return;+ }++ if (!isa<TypeDecl>(d)) {+ S.Diag(Attr.getLoc(), diag::warn_attribute_wrong_decl_type)+ << Attr.getName() << 9 /*class*/;+ return;+ }++ d->addAttr(::new (S.Context) ForbidTemporariesAttr(Attr.getLoc(), S.Context));+}+ static void HandleDependencyAttr(Decl *d, const AttributeList &Attr, Sema &S) { if (!isFunctionOrMethod(d) && !isa<ParmVarDecl>(d)) { S.Diag(Attr.getLoc(), diag::err_attribute_wrong_decl_type)@@ -2674,6 +2692,8 @@ case AttributeList::AT_ext_vector_type: HandleExtVectorTypeAttr(scope, D, Attr, S); break;+ case AttributeList::AT_forbid_temporaries:+ HandleForbidTemporariesAttr(D, Attr, S); break; case AttributeList::AT_format: HandleFormatAttr (D, Attr, S); break; case AttributeList::AT_format_arg: HandleFormatArgAttr (D, Attr, S); break; case AttributeList::AT_global: HandleGlobalAttr (D, Attr, S); break;
The meat of your attribute
Find an appropriate place in clang to do whatever your attribute needs to do. Check for the attribute's presence usingDecl: getattr <yourattr> ().
Update
Clang language extensionsDocument to describe your new attribute.