Line data Source code
1 : #ifndef ROSE_AstAttributeMechanism_H
2 : #define ROSE_AstAttributeMechanism_H
3 :
4 : #include "rosedll.h"
5 : #include <Sawyer/Attribute.h>
6 : #include <list>
7 : #include <set>
8 :
9 : class SgNode;
10 : class SgNamedType;
11 : class SgTemplateParameter;
12 : class SgTemplateParameterList;
13 :
14 : /** Base class for all IR node attribute values.
15 : *
16 : * This is the base class for all attribute values stored in the Sage IR node using the @ref AstAttributeMechanism. IR node
17 : * attributes are polymorphic based on this abstract class, and are always allocated on the heap. Once the attribute value is
18 : * handed to an attribute container method the container owns the value and is reponsible for deleting it. In the case of
19 : * methods that only optionally insert a value, the value is deleted immediately if it's not inserted. But see @ref
20 : * getOwnershipPolicy for additional information.
21 : *
22 : * The underlying @ref Sawyer::Attribute mechanism can store values of any type, including POD, 3rd party types, and
23 : * pointers. On the other hand, the @ref AstAttributeMechanism interface described here stores only pointers to values
24 : * allocated on the stack, owns those values, and supports operations that are useful specifically in IR nodes.
25 : *
26 : * Subclasses should each implement a virtual @ref copy constructor, which should allocate a new copy of the value. The
27 : * implementation in this base class returns a null pointer, which means that the attribute is not copied into a new AST node
28 : * when its AST node is copied. If a subclass fails to implement the virtual copy constructor and a superclass has an
29 : * implementation that return non-null, then copying the AST node will copy only the superclass part of the attribute and the
30 : * new attribute will have the dynamic type of the superclass--probably not what you want!
31 : *
32 : *
33 : *
34 : * For a more detailed description of using attributes in ROSE (and your own classes) see @ref attributes. */
35 0 : class ROSE_DLL_API AstAttribute {
36 : public:
37 : /** Who owns this attribute.
38 : *
39 : * See @ref getOwnershipPolicy. */
40 : enum OwnershipPolicy {
41 : CONTAINER_OWNERSHIP, /**< Container owns attribute. New subclasses should use this! */
42 : NO_OWNERSHIP, /**< Attributes are always leaked. */
43 : CUSTOM_OWNERSHIP, /**< Subclass defines ownership policy. */
44 : UNKNOWN_OWNERSHIP /**< Default for old subclasses. */
45 : };
46 :
47 : /** Who owns this attribute.
48 : *
49 : * The original implementation of this class from the early 2000's did not have clear rules about who owned a
50 : * heap-allocated attribute. The documentation was silent on the issue, and the implementation seemed to imply that
51 : * container ownership was intended but was then commented out at some point. Any ownership policy should have the
52 : * following properties:
53 : *
54 : * @li Attributes allocated on the heap should not be leaked. For instance, if an AST is deleted, then the attributes that
55 : * were referenced by the AST nodes should also be eventually deleted.
56 : * @li The mechanism should not place undue burden on the user. For instance, if a user copies and later deletes an AST
57 : * to which some analysis has attached attributes, the user should not need to be concerned with deleting attributes
58 : * stored in the copy.
59 : * @li The mechanism should be able to support either deep or shallow attribute copies as appropriate for the
60 : * attribute. The deep vs. shallow copying policy is implemented by the virtual @ref copy method, which must
61 : * coordinate with the ownership policy to ensure no leaks.
62 : *
63 : * We define four ownership policies, although from the standpoint of an attribute container there are really only two:
64 : * the container either deletes attributes or doesn't delete attributes. The four ownership policies are:
65 : *
66 : * @li @c CONTAINER_OWHERSHIP: The simple approach to ownership, and the one that we recommend for all new attribute
67 : * subclasses, is that the attribute container owns the attributes. When the container is copied (e.g., as part of
68 : * copying an AST node) then it invokes the @ref copy methods of its attributes, and when the container is deleted
69 : * (e.g., as part of deleting an AST node) then it explicitly deletes its attributes. This policy is an "allocate and
70 : * forget" approach: once the creator inserts an attribute into the container it transfers/moves ownership to the
71 : * container and the creator never needs to invoke @c delete. This policy also means that users never need to
72 : * explicitly delete attributes if they copy and then delete an AST. Newly designed attribute subclasses should use
73 : * this policy unless they have a very good reason to use another policy.
74 : *
75 : * @li @c NO_OWNERSHIP: Another simple approach is that ownership is transfered to the operating system. In other words,
76 : * the attribute is <em>never</em> deleted by the program and its memory is reclaimed only when the program terminates.
77 : * Attribute containers that are incorporated into objects that are frequently allocated and/or copied and then deleted
78 : * will result in a large number of leaked attributes. This approach is not recommended and is present only for
79 : * laziness.
80 : *
81 : * @li @c CUSTOM_OWNERSHIP: A third approach is that the attribute subclass implements its own ownership policy, which
82 : * ideally should have the properties listed above. An attribute using this policy will never be deleted by an
83 : * attribute container; the class must implement some other mechanism for tracking which attributes are allocated and
84 : * whether they can be safely deleted.
85 : *
86 : * @li @c UNKNOWN_OWNERSHIP: This final policy is for subclasses implemented before clear attribute ownership rules were
87 : * defined. Due to the ambiguity in the original AstAttributeMechanism implementation and the fact that attributes
88 : * are used by code outside the ROSE library, this must be the default implementation.
89 : *
90 : * Regardless of the ownership policy, an attribute must not be deleted while it is a member of an AstAttributeMechanism
91 : * container. This is because in order for the container to decide whether it should delete the attribute, it must first
92 : * ask the attribute for its ownership policy. In other words, the following code will likely result in a segmentation
93 : * fault:
94 : *
95 : * @code
96 : * SgDirectedGraphEdge *edge = ...;
97 : * delete edge->getAttribute("info");
98 : * delete edge; // INVALID ACCESS TO EDGE ATTRIBUTE HERE
99 : * @endcode */
100 : virtual OwnershipPolicy getOwnershipPolicy() const;
101 :
102 : /** Support for attibutes to specify edges in the dot graphs. */
103 : class ROSE_DLL_API AttributeEdgeInfo {
104 : public:
105 : SgNode* fromNode;
106 : SgNode* toNode;
107 : std::string label;
108 : std::string options;
109 :
110 0 : AttributeEdgeInfo(SgNode* fromNode, SgNode* toNode, std::string label, std::string options)
111 0 : : fromNode(fromNode), toNode(toNode), label(label), options(options) {}
112 :
113 0 : ~AttributeEdgeInfo() {
114 0 : fromNode = NULL;
115 0 : toNode = NULL;
116 0 : };
117 : };
118 :
119 : /** Support for adding nodes to DOT graphs. */
120 : class ROSE_DLL_API AttributeNodeInfo {
121 : public:
122 : SgNode* nodePtr;
123 : std::string label;
124 : std::string options;
125 :
126 : AttributeNodeInfo(SgNode* nodePtr, std::string label, std::string options)
127 : : nodePtr(nodePtr), label(label), options(options) {}
128 :
129 0 : ~AttributeNodeInfo() {};
130 : };
131 :
132 : public:
133 15 : AstAttribute() {}
134 7 : virtual ~AstAttribute() {}
135 :
136 : /** Virtual default constructor.
137 : *
138 : * Default-constructs a new object on the heap and returns its pointer. All subclasses <em>must</em> implement this in
139 : * order to instantiate the correct dynamic type, although many don't. Invoking this constructor in a subclass that fails
140 : * to implement it will return an attribute that's an incorrect dynamic type.
141 : *
142 : * It would be nice if we could make this pure virtual, but unfortunately ROSETTA-generated code fails to compile because
143 : * it generates an instantiation of this interface (whether or not that code is ever executed is unknown). [Robb Matzke
144 : * 2015-11-10]. */
145 0 : virtual AstAttribute* constructor() const {
146 0 : return new AstAttribute; // it doesn't make much sense to instantiate this type!
147 : }
148 :
149 : /** Virtual copy constructor.
150 : *
151 : * Copy-constructs a new object on the heap and returns its pointer. All subclasses must implement this in order to
152 : * instantiate the correct dynamic type, although many don't. If this @ref copy method returns a null pointer (like the
153 : * base implementation) then the attribute is not copied as part of copying its container. E.g., an attribute stored in
154 : * an AST will not be copied when the AST is copied if that attribute is directly derived from @ref AstAttribute and fails
155 : * to implement @ref copy. If a subclass fails to implement @ref copy and inherits from a class that does implement a
156 : * @ref copy that returns non-null, then the copied attribute will have an incorrect dynamic type.
157 : *
158 : * It would be nice if we could make this pure virtual, but unfortunately ROSETTA-generated code fails to compile because
159 : * it generates an instantiation of this interface (whether or not that code is ever executed is unkown). [Robb Matzke
160 : * 2015-11-10] */
161 0 : virtual AstAttribute* copy() const {
162 0 : return NULL; // attribute will not be copied when the containing obj is copied
163 : }
164 :
165 : // DO NOT DOCUMENT! The original implementation used a non-const copy constructor and many subclasses that implemented a
166 : // copy constructor didn't use C++11's "override" word as a defensive measure. Since we don't have access to all those
167 : // subclasses, we must continue to support the non-const version. Subclasses should only have to implement one or the
168 : // other, not both.
169 0 : virtual AstAttribute* copy() {
170 0 : return const_cast<const AstAttribute*>(this)->copy();
171 : }
172 :
173 : /** Attribute class name.
174 : *
175 : * Returns the name of the dynamic type. All subclasses must implement this in order to return the correct type name,
176 : * although many don't. If a subclass fails to implement this then it will return an incorrect class name.
177 : *
178 : * It would be nice if this could be pure virtual, but unfortunately ROSETTA-generated code fails to compile because it
179 : * generates an instantiation of this interface (whether or not that code is ever executed is unknown). [Robb Matzke
180 : * 2015-11-10] */
181 7 : virtual std::string attribute_class_name() const {
182 7 : return "AstAttribute"; // almost certainly not the right dynamic type name!
183 : }
184 :
185 : /** Convert an attribute to a string.
186 : *
187 : * This is used by other components to print the value of an attribute. For example the pdf generation calls this function
188 : * to print the value of an attribute in the pdf file. The default implementation is to return the attribute address in
189 : * the heap as a string. */
190 : virtual std::string toString();
191 :
192 : /** Packing support.
193 : *
194 : * @{ */
195 : virtual int packed_size();
196 : virtual char* packed_data();
197 : virtual void unpacked_data( int size, char* data );
198 : /** @} */
199 :
200 : /** DOT support.
201 : *
202 : * @{ */
203 : virtual std::string additionalNodeOptions();
204 : virtual std::vector<AttributeEdgeInfo> additionalEdgeInfo();
205 : virtual std::vector<AttributeNodeInfo> additionalNodeInfo();
206 : /** @} */
207 :
208 : /** Eliminate IR nodes in DOT graphs.
209 : *
210 : * Or to tailor the presentation of information about ASTs. */
211 : virtual bool commentOutNodeInGraph();
212 : };
213 :
214 :
215 : /** Stores named attributes in Sage IR nodes.
216 : *
217 : * This attribute container stores one non-null, heap-allocated attribute per user-specified name. All values are derived
218 : * from @ref AstAttribute. Any object can have an attribute container data member. For example, each AST node (@ref SgNode)
219 : * contains one attribute container named @ref SgNode::get_attributeMechanism.
220 : *
221 : * The value class's @ref AstAttribute::getOwnershipPolicy "getOwnershipPolicy" method indicates whether the container owns
222 : * the heap-allocated attribute and therefore whether the container is responsible for invoking @c delete on the attribute
223 : * when the container is destroyed. New attribute subclasses should use the @ref AstAttribute::CONTAINER_OWNERSHIP policy if
224 : * possible.
225 : *
226 : * IR node attribute values are always on the heap. Whenever an attribute container is copied, the container invokes the @ref
227 : * AstAttribute::copy "copy" method on all its attributes. The attributes' @c copy should either allocate a new copy of the
228 : * attribute or return a null pointer. Since these values must be derived from @ref AstAttribute, it is not possible to
229 : * directly store values whose type the user cannot modify to inherit from @ref AstAttribute. This includes POD types and
230 : * classes defined in 3rd party libraries (e.g., @c std::vector). To store such values, the user must wrap them in another
231 : * class that does inherit from @ref AstAttribute and which implements the necessary virtual functions.
232 : *
233 : * The names of attributes are strings and the container does not check whether the string supplied to various container
234 : * methods is spelled correctly. Using a misspelled attribute name is the same as using a different value name--in effect,
235 : * operating on a completely different, unintended attribute.
236 : *
237 : * The @ref AstAttributeMechanism is used by AST nodes (@ref SgNode) and is available via @ref SgNode::get_attributeMechanism,
238 : * although that is not the preferred API. Instead, @ref SgNode provides an additional methods that contain "attribute" as
239 : * part of their name. These "attribute" methods are mostly just wrappers around @ref SgNode::get_attributeMechanism.
240 : *
241 : * Users can also use @ref AstAttributeMechanism as a data member in their own classes. However, @ref Sawyer::Attribute is
242 : * another choice: not only does it serve as the implementation for @ref AstAttributeMechanism, but it also supports checked
243 : * attribute names and attributes that are values rather than pointers, including POD, 3rd-party types, and shared-ownership
244 : * pointers. The amount of boilerplate that needs to be written in order to store a @ref Sawyer::Attribute is much less than
245 : * that required to store an attribute with @ref AstAttributeMechanism.
246 : *
247 : * For additional information, including examples, see @ref attributes. */
248 : class ROSE_DLL_API AstAttributeMechanism {
249 : // Use containment because we want to keep the original API.
250 : Sawyer::Attribute::Storage<> attributes_;
251 :
252 : public:
253 : /** Default constructor.
254 : *
255 : * Constructs an attribute mechanism that holds no attributes. */
256 8 : AstAttributeMechanism() {}
257 :
258 : /** Copy constructor.
259 : *
260 : * Copying an attribute container will copy the heap-allocated attribute values by invoking each value's @c copy
261 : * method. If the method returns null then the new attribute container will not have that attribute; i.e., the @ref exists
262 : * method returns false.
263 : *
264 : * <b>New semantics:</b> The original behavior was that if the value's @c copy method returned null, the @ref exists
265 : * predicate returned true even though no value existed. */
266 0 : AstAttributeMechanism(const AstAttributeMechanism &other) {
267 0 : assignFrom(other);
268 0 : }
269 :
270 : /** Assignment operator.
271 : *
272 : * Assigning one attribute container to another will cause the destination container's attributes to be erased and
273 : * deleted, and the source container's attributes to be copied. The assignment operator is exception safe: it will either
274 : * successfully copy and assign all attributes or not assign any attributes. However, if an attribute uses anything other
275 : * than the @ref AstAttribute::CONTAINER_OWNERHSIP ownership policy then it is up to the attribute type's designer to
276 : * handle deletion of attributes that were copied before the exception occurred.
277 : *
278 : * <b>New semantics:</b> The original implementation had a copy constructor but no assignment operator. Assignment of one
279 : * attribute container to another caused both containers to share the attribute values allocated on the heap, making it
280 : * nearly impossible to figure out when they could be safely deleted and therefore leading to memory leaks. */
281 : AstAttributeMechanism& operator=(const AstAttributeMechanism &other);
282 :
283 : /** Destructor.
284 : *
285 : * Destroying the attribute container should cause unused attributes to be destroyed. If an attribute implements the @ref
286 : * AstAttribute::CONTAINER_OWNERHSIP policy then the container explicitly deletes the attribute, otherwise it is up to the
287 : * attribute class's designer to implement a deletion policy that prevents leaks.
288 : *
289 : * <b>New semantics:</b> The original implementation did not delete attributes when the container was destroyed, although
290 : * it had commented-out code to do so. */
291 : ~AstAttributeMechanism();
292 :
293 : /** Test for attribute existence.
294 : *
295 : * Test whether this container holds an attribute with the specified name. This predicate returns true only if the name
296 : * exists and points to a non-null attribute value. The name need not be declared in the attribute system.
297 : *
298 : * <b>New semantics:</b> It is now permissible to invoke this method on a const attribute container and this method no
299 : * longer copies the name argument. */
300 : bool exists(const std::string &name) const;
301 :
302 : /** Insert an attribute.
303 : *
304 : * Inserts the specified heap-allocated value for the given attribute name, replacing any previous value stored for
305 : * that same name.
306 : *
307 : * If the new value uses the @ref AstAttribute::CONTAINER_OWNERSHIP policy then ownership is immediately transferred/moved
308 : * to this container, which becomes responsible for deleting the attribute as appropriate to prevent leasks. Otherwise,
309 : * the attribute's designer is responsible for implementing an ownership policy that safely prevents leaks.
310 : *
311 : * If the old value (if present) uses the @ref AstAttribute::CONTAINER_OWNERSHIP policy then it is deleted. Otherwise the
312 : * attribute's designer is responsible for implementing an ownership policy that safely prevents leaks, and the attribute
313 : * must not be deleted until after this method returns.
314 : *
315 : * <b>New semantics:</b> The old implementation didn't delete the previous attribute value. The old implementation
316 : * allowed setting a null value, in which case the old @c exists returned true but the @c operator[] returned no
317 : * attribute. */
318 : void set(const std::string &name, AstAttribute *value);
319 :
320 : /** Insert a new value if the attribute doesn't already exist.
321 : *
322 : * Tests whether an attribute with the specified name @ref exists and if not, invokes @ref set. See @ref set for details
323 : * about ownership of the new attribute. Returns true if an attribute with the specified name did not already existed.
324 : *
325 : * <b>New semantics:</b> The old implementation was ambiguous about who owned the object after this call. It didn't take
326 : * ownership of an attribute that wasn't inserted, but it also didn't indicate whether it was inserted. The old
327 : * implementation printed an error message on standard error if the attribute existed (even if only its name existed but
328 : * it had no value) and then returned to the caller without doing anything. Inserting a null value was allowed by the old
329 : * implementation, in which case the old @c exists returned true but the old @c operator[] returned no attribute. */
330 : bool add(const std::string &name, AstAttribute *value);
331 :
332 : /** Insert a new value if the attribute already exists.
333 : *
334 : * Tests whether the specified attribute exists, and if so, invokes @ref set. See @ref set for details about ownership of
335 : * the old and new attributes. Returns true if an attribute with the specified name already existed.
336 : *
337 : * <b>New semantics:</b> The old implementation was ambiguous about who owned the object after this call. It didn't take
338 : * ownership of an attribute that wasn't inserted, but it also didn't indicate whether it was inserted. The old
339 : * implementation printed an error message on standard error if the attribute didn't exist and then returned to the caller
340 : * without doing anything. Inserting a null value was allowed by the old implementation, in which case the old @c exists
341 : * returned true but the old @c operator[] returned no attribute. */
342 : bool replace(const std::string &name, AstAttribute *value);
343 :
344 : /** Get an attribute value.
345 : *
346 : * Returns the value associated with the given attribute, or null if the attribute does not exist. This method does not
347 : * copy the attribute before returning it, therefore the caller should not delete the attribute. Erasing the attribute
348 : * from the container may cause the pointer to become invalid, depending on the attribute's ownership policy. If the
349 : * attribute uses the @ref AstAttribute::CONTAINER_OWNERSHIP method then the attribute can be modified through its pointer
350 : * without affecting attributes in other containers, otherwise the behavior is up to the attribute's designer.
351 : *
352 : * The caller will need to @c dynamic_cast the returned pointer to the appropriate subclass of @ref AstAttribute.
353 : *
354 : * <b>New semantics:</b> The old implementation partly created an attribute if it didn't exist: @c exists started
355 : * returning true although @c operator[] continued to return no attribute. The old implementation printed an error message
356 : * to standard error if the attribute did not exist. */
357 : AstAttribute* operator[](const std::string &name) const;
358 :
359 : /** Erases the specified attribute.
360 : *
361 : * If an attribute with the specified name exists then it is removed from the container. If the attribute implements the
362 : * @ref AstAttribute::CONTAINER_OWNERSHIP policy then this container deletes the attribute, otherwise it is up to the
363 : * attribute's designer to implement a safe way to prevent attribute leaks, and the attribute must not be deleted until
364 : * after this method returns.
365 : *
366 : * <b>New semantics:</b> The old implementation did not delete the attribute value. It also printed an error message
367 : * to standard error if the attribute did not exist. */
368 : void remove(const std::string &name);
369 :
370 : /** Set of attribute names. */
371 : typedef std::set<std::string> AttributeIdentifiers;
372 :
373 : /** List of stored attribute names.
374 : *
375 : * Returns the set of names for attributes stored in this container. This can be used to iterate over the attributes,
376 : * as in:
377 : *
378 : * @snippet binaryAttribute.C iterate 2
379 : *
380 : * Or using the @ref SgNode API for attributes:
381 : *
382 : * @snippet binaryAttribute.C iterate 3
383 : *
384 : * <b>New semantics:</b> The old implementation also returned some names that had no attribute values. For instance, if
385 : * @c operator[] was invoked for an attribute that didn't exist then that name was also returned. */
386 : AttributeIdentifiers getAttributeIdentifiers() const;
387 :
388 : /** Number of attributes stored.
389 : *
390 : * Returns the number of attributes stored in this container.
391 : *
392 : * <b>New semantics:</b> The old implementation returned a signed integer instead of @c size_t as is customary for size
393 : * measurements. It also could not be invoked on a const container. It also could return a value larger larger than the
394 : * number of stored attributes (such as when a previous query for a non-existing attribute occurred). */
395 : size_t size() const;
396 :
397 : private:
398 : // Called by copy constructor and assignment.
399 : void assignFrom(const AstAttributeMechanism &other);
400 : };
401 :
402 :
403 :
404 : /** Attribute corresponding to a metric.
405 : *
406 : * A metric attribute represents a numeric value obtained by either dynamic analysis (gprof or hpct) or static analysis (for
407 : * example number of flop operations in a function) It MetricAttribute can be a raw (observed), or a propagated (derived)
408 : * count It containes no name-string, because the attribute is stored in an AttributeMechanism-map, where the name is the
409 : * key. */
410 0 : class ROSE_DLL_API MetricAttribute: public AstAttribute {
411 : protected:
412 : bool is_derived_;
413 : double value_;
414 :
415 : public:
416 : MetricAttribute()
417 : : is_derived_(false), value_(0) {}
418 :
419 : MetricAttribute(double value, bool is_derived=false)
420 : : is_derived_(is_derived), value_(value) {}
421 :
422 : virtual AstAttribute* copy() const override;
423 : virtual std::string attribute_class_name() const override;
424 :
425 0 : virtual bool isDerived() const { return is_derived_; }
426 0 : virtual double getValue() const { return value_; }
427 0 : virtual void setValue(double newVal) { value_ = newVal; }
428 :
429 : virtual std::string toString() override;
430 :
431 : virtual int packed_size() override;
432 : virtual char* packed_data() override;
433 : virtual void unpacked_data(int size, char* data) override;
434 :
435 : MetricAttribute& operator+=(const MetricAttribute &other);
436 : MetricAttribute& operator-=(const MetricAttribute &other);
437 : MetricAttribute& operator*=(const MetricAttribute &other);
438 : MetricAttribute& operator/=(const MetricAttribute &other);
439 : };
440 :
441 :
442 : /** IR node attribute that stores a copyable value.
443 : *
444 : * Since IR node attributes must all inherit from @ref AstAttribute we need to write wrappers around POD types and 3rd party
445 : * types when we want to store them as IR attributes. We've ended up with a proliferation of such attributes that all do
446 : * almost the same thing but have different names to access their data members. Hopefully by providing one class template we
447 : * can avoid further proliferation. */
448 : template<class T>
449 : class ROSE_DLL_API AstValueAttribute: public AstAttribute {
450 : public:
451 : /** Type of value this wrapper holds. */
452 : typedef T Value;
453 : private:
454 : Value value_;
455 : public:
456 : /** Default constructor. Constructs an attribute wrapper having a default-constructed value. */
457 : AstValueAttribute() {}
458 :
459 : /** Constructs an attribute containing a specified value. */
460 : explicit AstValueAttribute(const T &value): value_(value) {}
461 :
462 : /** Copy constructor. Invokes the copy-constructor of the contained value. */
463 0 : AstValueAttribute(const AstValueAttribute &other): value_(other.value_) {}
464 :
465 0 : virtual AstAttribute* copy() const override { return new AstValueAttribute(*this); }
466 0 : virtual std::string attribute_class_name() const override { return "AstValueAttribute"; }
467 :
468 : /** Return the stored value by reference.
469 : *
470 : * @{ */
471 : const T& get() const { return value_; }
472 0 : T& get() { return value_; }
473 : /** @} */
474 :
475 : /** Assign a new value. */
476 : void set(const T& value) { value_ = value; }
477 : };
478 :
479 : // DQ (11/21/2009): Added new kind of attribute for handling regex trees.
480 : /** Attribute containing a regex expression as a string.
481 : *
482 : * An AstRegExAttribute is added to each part of an AST tree pattern specification to a RegEx tree. */
483 0 : class ROSE_DLL_API AstRegExAttribute: public AstAttribute {
484 : public:
485 : std::string expression;
486 :
487 : AstRegExAttribute() {}
488 :
489 : explicit AstRegExAttribute(const std::string & s)
490 : : expression(s) {}
491 :
492 0 : virtual AstAttribute* copy() const override {
493 0 : return new AstRegExAttribute(*this);
494 : }
495 :
496 0 : virtual std::string attribute_class_name() const override {
497 0 : return "AstRegExAttribute";
498 : }
499 : };
500 :
501 :
502 : // PC (10/21/2012): Added new kind of attribute for handling regex trees.
503 : /** Attribute storing an SgNode.
504 : *
505 : * A SgNode attribute may be used to "dynamically add" an SgNode field to an AST node. */
506 : class ROSE_DLL_API AstSgNodeAttribute: public AstValueAttribute<SgNode*> {
507 : public:
508 : typedef AstValueAttribute<SgNode*> Super;
509 : AstSgNodeAttribute(): Super(NULL) {}
510 : explicit AstSgNodeAttribute(SgNode *value): Super(value) {}
511 0 : AstSgNodeAttribute(const AstSgNodeAttribute &other): Super(other) {}
512 0 : virtual AstAttribute* copy() const override { return new AstSgNodeAttribute(*this); }
513 0 : virtual std::string attribute_class_name() const override { return "AstSgNodeAttribute"; }
514 0 : SgNode* getNode() { return get(); }
515 : void setNode(SgNode *node) { set(node); }
516 : };
517 :
518 : class ROSE_DLL_API AstSgNodeListAttribute: public AstValueAttribute<std::vector<SgNode*> > {
519 : public:
520 : typedef AstValueAttribute<std::vector<SgNode*> > Super;
521 : AstSgNodeListAttribute() {}
522 : explicit AstSgNodeListAttribute(std::vector<SgNode *> &value): Super(value) {}
523 0 : AstSgNodeListAttribute(const AstSgNodeListAttribute &other): Super(other) {}
524 0 : virtual AstAttribute* copy() const override { return new AstSgNodeListAttribute(*this); }
525 0 : virtual std::string attribute_class_name() const override { return "AstSgNodeListAttribute"; }
526 : std::vector<SgNode*> &getNodeList() { return get(); }
527 : void addNode(SgNode *n) { get().push_back(n); }
528 : void setNode(SgNode*, int);
529 : SgNode *getNode(int);
530 : int size() { return get().size(); }
531 : };
532 :
533 : class ROSE_DLL_API AstIntAttribute : public AstValueAttribute<int> {
534 : public:
535 : typedef AstValueAttribute<int> Super;
536 : AstIntAttribute(): Super(0) {}
537 : explicit AstIntAttribute(int value): Super(value) {}
538 0 : AstIntAttribute(const AstIntAttribute &other): Super(other) {}
539 0 : virtual AstAttribute* copy() const override { return new AstIntAttribute(*this); }
540 0 : virtual std::string attribute_class_name() const override { return "AstIntAttribute"; }
541 : int getValue() { return get(); }
542 : };
543 :
544 : #endif
|