+/*-------------------------------------------------------------------.
+| Set the DESTRUCTOR associated with TYPE. Do nothing if passed 0. |
+`-------------------------------------------------------------------*/
+
+void
+semantic_type_destructor_set (semantic_type *type, const char *destructor,
+ location loc)
+{
+ if (destructor)
+ {
+ if (type->destructor)
+ semantic_type_redeclaration (type, "%destructor",
+ type->destructor_location, loc);
+ type->destructor = destructor;
+ type->destructor_location = loc;
+ }
+}
+
+/*---------------------------------------.
+| Get the computed %destructor for SYM. |
+`---------------------------------------*/
+
+const char *
+symbol_destructor_get (symbol *sym)
+{
+ /* Per-symbol %destructor. */
+ if (sym->destructor != NULL)
+ return sym->destructor;
+
+ /* Per-type %destructor. */
+ if (sym->type_name)
+ {
+ semantic_type *type = semantic_type_get (sym->type_name);
+ if (type->destructor)
+ return type->destructor;
+ }
+
+ /* Apply the default %destructor only to user-defined symbols. */
+ if (sym->tag[0] == '$' || sym == errtoken)
+ return NULL;
+ return default_destructor;
+}
+
+/*---------------------------------------------------------------.
+| Get the grammar location of the %destructor computed for SYM. |
+`---------------------------------------------------------------*/
+
+location
+symbol_destructor_location_get (symbol *sym)
+{
+ if (sym->destructor != NULL)
+ return sym->destructor_location;
+ if (sym->type_name)
+ {
+ semantic_type *type = semantic_type_get (sym->type_name);
+ if (type->destructor)
+ return type->destructor_location;
+ }
+ return default_destructor_location;
+}