1/* 2 * Copyright (c) 2010 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 3. Neither the name of Apple Inc. ("Apple") nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 20 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 22 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 23 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 25 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 26 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 28 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * Portions of this software have been released under the following terms: 31 * 32 * (c) Copyright 1989-1993 OPEN SOFTWARE FOUNDATION, INC. 33 * (c) Copyright 1989-1993 HEWLETT-PACKARD COMPANY 34 * (c) Copyright 1989-1993 DIGITAL EQUIPMENT CORPORATION 35 * 36 * To anyone who acknowledges that this file is provided "AS IS" 37 * without any express or implied warranty: 38 * permission to use, copy, modify, and distribute this file for any 39 * purpose is hereby granted without fee, provided that the above 40 * copyright notices and this notice appears in all source code copies, 41 * and that none of the names of Open Software Foundation, Inc., Hewlett- 42 * Packard Company or Digital Equipment Corporation be used 43 * in advertising or publicity pertaining to distribution of the software 44 * without specific, written prior permission. Neither Open Software 45 * Foundation, Inc., Hewlett-Packard Company nor Digital 46 * Equipment Corporation makes any representations about the suitability 47 * of this software for any purpose. 48 * 49 * Copyright (c) 2007, Novell, Inc. All rights reserved. 50 * Redistribution and use in source and binary forms, with or without 51 * modification, are permitted provided that the following conditions 52 * are met: 53 * 54 * 1. Redistributions of source code must retain the above copyright 55 * notice, this list of conditions and the following disclaimer. 56 * 2. Redistributions in binary form must reproduce the above copyright 57 * notice, this list of conditions and the following disclaimer in the 58 * documentation and/or other materials provided with the distribution. 59 * 3. Neither the name of Novell Inc. nor the names of its contributors 60 * may be used to endorse or promote products derived from this 61 * this software without specific prior written permission. 62 * 63 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 64 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 65 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 66 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY 67 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 68 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 69 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 70 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 71 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 72 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 73 * 74 * @APPLE_LICENSE_HEADER_END@ 75 */ 76 77/* 78** 79** NAME: 80** 81** checker.c 82** 83** FACILITY: 84** 85** Interface Definition Language (IDL) Compiler 86** 87** ABSTRACT: 88** 89** IDL Compiler Semantic Checking. 90** 91** VERSION: DCE 1.0 92*/ 93 94#include <stdarg.h> 95 96#include <nidl.h> /* Standard IDL defs */ 97#include <checker.h> /* Type and constant macros */ 98#include <chkichar.h> /* Protos for I-char checking */ 99 100#include <acf_y.h> /* ACF token values */ 101#include <ast.h> /* Abstract Syntax Tree defs */ 102#include <astp.h> /* AST processing defs */ 103#include <command.h> /* Command option defs */ 104#include <errors.h> /* Error reporting functions */ 105#include <message.h> /* reporting functions */ 106 107extern const char *acf_keyword_lookup( 108 int token_value /* Numeric value of keyword token */ 109); 110 111extern int error_count; /* Count of semantic errors */ 112 113/* Local copy of pointers to command line information. */ 114 115static boolean *cmd_opt; /* Array of command option flags */ 116static void **cmd_val; /* Array of command option values */ 117 118/* Necessary forward function declarations. */ 119 120static void type_check( 121 AST_type_n_t *type_p, /* [in] Ptr to AST type node */ 122 ASTP_node_t *node_p, /* [in] Parent node of type node */ 123 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 124); 125 126/* 127** s t r u c t u r e u t i l i t y r o u t i n e s 128** 129** Structure "properties" used by other checks. 130*/ 131 132/* 133** C H K _ s t r u c t _ i s _ a l l _ b y t e _ f i e l d s 134** 135** Returns TRUE if a struct consists only of scalar byte fields. 136*/ 137 138boolean CHK_struct_is_all_byte_fields 139( 140 AST_structure_n_t *struct_p /* [in] Ptr to AST structure node */ 141) 142 143{ 144 AST_field_n_t *field_p; /* A field in the structure */ 145 146 for (field_p = struct_p->fields ; field_p != NULL ; field_p = field_p->next) 147 if (field_p->type->kind != AST_byte_k) 148 return FALSE; 149 150 return TRUE; 151} 152 153/* 154** t y p e u t i l i t y r o u t i n e s 155** 156** Type "properties" used by other checks. 157*/ 158 159/* 160** t y p e _ i s _ s t r i n g 161** 162** Returns TRUE if a type can be used as a valid [string] data type: 163** A 1-dim array of char or byte, or a pointer to a char or byte, OR 164** a (1-dim array of) or (pointer to) (struct containing only byte fields). 165** OR, a {1-dim array of | pointer to} unsigned short or unsigned long. 166*/ 167 168static boolean type_is_string 169( 170 AST_type_n_t *type_p /* [in] Ptr to AST type node */ 171) 172{ 173 unsigned short index_count; /* Number of array dimensions */ 174 AST_type_n_t *base_type_p; /* Base type of array */ 175 176 if (type_p->kind == AST_array_k) 177 { 178 index_count = type_p->type_structure.array->index_count; 179 base_type_p = type_p->type_structure.array->element_type; 180 } 181 else if (type_p->kind == AST_pointer_k) 182 { 183 index_count = 1; 184 base_type_p = type_p->type_structure.pointer->pointee_type; 185 } 186 else 187 return FALSE; 188 189 if (index_count == 1 190 && (base_type_p->kind == AST_character_k 191 || base_type_p->kind == AST_byte_k 192 || base_type_p->kind == AST_short_unsigned_k 193 || base_type_p->kind == AST_long_unsigned_k 194 || (base_type_p->kind == AST_structure_k 195 && CHK_struct_is_all_byte_fields 196 (base_type_p->type_structure.structure)))) 197 return TRUE; 198 199 return FALSE; 200} 201 202/* 203** t y p e _ i s _ v 1 _ s t r i n g 204** 205** Returns TRUE if a type can be used as a valid [v1_string] data type: 206** An array of char, in array syntax, with lower bound 0 and fixed upper 207** bound. If the array is multidimensional, the minor dimension must meet 208** these criteria. 209*/ 210 211static boolean type_is_v1_string 212( 213 AST_type_n_t *type_p /* [in] Ptr to AST type node */ 214) 215{ 216 AST_array_n_t *array_p; /* Ptr to array node */ 217 AST_array_index_n_t *index_p; /* Array index node for minor dim */ 218 219 if (type_p->kind != AST_array_k) 220 return FALSE; 221 222 array_p = type_p->type_structure.array; 223 224 if (array_p->element_type->kind != AST_character_k) 225 return FALSE; 226 227 index_p = &array_p->index_vec[array_p->index_count - 1]; 228 229 if (!AST_CONFORMANT_SET(type_p) 230 && index_p->lower_bound != NULL 231 && index_p->lower_bound->kind == AST_int_const_k 232 && index_p->lower_bound->value.int_val == 0 233 && index_p->upper_bound != NULL 234 && index_p->upper_bound->kind == AST_int_const_k) 235 return TRUE; 236 237 return FALSE; 238} 239 240/* 241** t y p e _ x m i t _ t y p e 242** 243** Given a (presented) type, returns the transmissible type. These two types 244** are only different when the type has a [transmit_as] attribute. 245*/ 246 247static AST_type_n_t * type_xmit_type 248( 249 AST_type_n_t *type_p /* [in] Ptr to AST type node */ 250) 251{ 252 while (type_p->xmit_as_type != NULL) 253 type_p = type_p->xmit_as_type; 254 255 return type_p; 256} 257 258/* 259** a r r a y u t i l i t y r o u t i n e s 260** 261** Array "properties" used by other checks. 262*/ 263 264/* 265** a r r a y _ i s _ c o n f o r m a n t _ u p p e r 266** 267** Returns TRUE if an array is conformant in an upper dimension 268** (i.e., a dimension other than the first dimension). 269*/ 270 271static boolean array_is_conformant_upper 272( 273 AST_array_n_t *array_p /* [in] Ptr to AST array node */ 274) 275{ 276 AST_array_index_n_t *index_p; /* Ptr to array index node */ 277 int i; /* Integer array dimension 0..N-1 */ 278 279 index_p = array_p->index_vec; /* Point at index vector */ 280 281 /* Check dimensions 1..N-1 for conformance (1st dim is index 0). */ 282 283 for (i = 1, index_p++ ; i < array_p->index_count ; i++, index_p++) 284 { 285 if (!AST_FIXED_LOWER_SET(index_p) 286 || !AST_FIXED_UPPER_SET(index_p)) 287 return TRUE; /* Conformant in this dimension */ 288 } 289 290 return FALSE; 291} 292 293/* 294** a r r a y _ i s _ l a r g e 295** 296** Returns TRUE if an array has a total (all dimensions) of >65535 elements. 297*/ 298 299static boolean array_is_large 300( 301 AST_array_n_t *array_p /* [in] Ptr to AST array node */ 302) 303{ 304 AST_array_index_n_t *index_p; /* Ptr to array index node */ 305 int i; /* Integer array dimension 0..N-1 */ 306 long dim_size; /* Size of one array dimension */ 307 long elem_cnt; /* Running total of array elements */ 308 309 index_p = array_p->index_vec; /* Point at index vector */ 310 elem_cnt = 1; 311 312 /* 313 * Go through each dimension of the array computing the size of the 314 * array in that dimension, and multiplying it into the running total 315 * of elements. If the total becomes >65535, the array is "large". 316 * For conformant dimensions, we don't know the eventual 317 * size of the dimension. All we can really do is assume the smallest 318 * size for that dimension (1) and continue with our check, as the 319 * array still might be large from the fixed dimensions alone. 320 */ 321 for (i = 0 ; i < array_p->index_count ; i++, index_p++) 322 { 323 if (AST_FIXED_LOWER_SET(index_p) 324 && AST_FIXED_UPPER_SET(index_p)) 325 { 326 dim_size = index_p->upper_bound->value.int_val - 327 index_p->lower_bound->value.int_val + 1; 328 /* 329 * If the dimension itself has >65535 elements, the array is large. 330 * This special case check is needed to avoid the possibility of 331 * integer overflow on the running product. 332 */ 333 if (dim_size > 65535) 334 return TRUE; /* Large in this dimension */ 335 336 /* If the total number of elements is >65535, the array is large. */ 337 elem_cnt = elem_cnt * dim_size; 338 if (elem_cnt > 65535) 339 return TRUE; /* Large in overall size */ 340 } 341 } 342 343 return FALSE; 344} 345 346/* 347** a r r a y _ h a s _ o p e n _ l b 348** 349** Returns TRUE if an array has an open lower bound in any dimension. 350*/ 351 352static boolean array_has_open_lb 353( 354 AST_array_n_t *array_p /* [in] Ptr to AST array node */ 355) 356{ 357 AST_array_index_n_t *index_p; /* Ptr to array index node */ 358 int i; /* Integer array dimension 0..N-1 */ 359 360 index_p = array_p->index_vec; /* Point at index vector */ 361 362 /* Go through each dimension of the array checking for open lower bound. */ 363 364 for (i = 0 ; i < array_p->index_count ; i++, index_p++) 365 if (!AST_FIXED_LOWER_SET(index_p)) 366 return TRUE; 367 368 return FALSE; 369} 370 371/* 372** p a r a m e t e r u t i l i t y r o u t i n e s 373** 374** Utility routines for parameter nodes, used by other checks. 375*/ 376 377/* 378** p a r a m _ f o l l o w _ r e f _ p t r 379** 380** Dereferences a parameter's type if it is a pointer and it meets certain 381** conditions. Some of the conditions apply always; others are dependent 382** on the 'mode' argument (see below, and checker.h). 383** 384** The general intent of this function is to follow reference pointers. 385** However, there are ambiguities as to what that really means, and 386** different dereferencing behavior is required depending on the need. 387** Thus, the 'mode' argument allows one to tweak what this routine does. 388** 389** Returns address of pointee type node if the type was dereferenced. 390** Returns address of parameter's type node if the type was NOT dereferenced. 391*/ 392 393AST_type_n_t * param_follow_ref_ptr /* Returns ptr to type node */ 394( 395 AST_parameter_n_t *param_p, /* [in] Ptr to AST parameter node */ 396 CHK_follow_t mode /* [in] Follow mode */ 397) 398{ 399 AST_type_n_t *type_p; /* Ptr to AST type node */ 400 AST_type_n_t *ptee_type_p; /* Pointee type */ 401 402 type_p = param_p->type; 403 404 if (type_p->kind != AST_pointer_k) 405 return type_p; 406 407 ptee_type_p = type_p->type_structure.pointer->pointee_type; 408 409 /* 410 * The pointer is followed, with these EXCEPTIONS: 411 * - on a function result parameter, which by def can't be a ref ptr 412 * - void *, since "void passed-by-reference" makes no sense 413 * - function pointer 414 * - arrayified [string] pointers (but not pointer to string array) 415 * 416 * These additional EXCEPTIONS apply when the indicated mode(s) are selected 417 * (see checker.h): 418 * - a named pointer (mode == CHK_follow_any) 419 * - a [unique] or [ptr] pointer (mode != CHK_follow_any) 420 * - arrayified via size attributes (mode != CHK_follow_ref_arr_siz) 421 */ 422 /* EXCEPTIONS to following: */ 423 if (param_p == param_p->uplink->result /* The result param */ 424 || ptee_type_p->kind == AST_void_k /* (void *) */ 425 || ptee_type_p->kind == AST_function_k /* Function pointer */ 426 || (type_p->name != NAMETABLE_NIL_ID /* Not anonymous */ 427 && mode == CHK_follow_any) /* AND follow any mode */ 428 || (!AST_REF_SET(param_p) /* [unique] attribute */ 429 && mode != CHK_follow_any) /* AND not follow any mode */ 430 || (param_p->field_attrs != NULL /* Arrayified via size attrs */ 431 && instance_has_array_attr(param_p)/* array not switch attr */ 432 && mode != CHK_follow_ref_arr_siz) /* BUT mode = don't follow */ 433 || ((AST_STRING_SET(type_p) /* Arrayified via [string] */ 434 || AST_STRING_SET(param_p)) /* on type or param, AND */ 435 && type_is_string(type_p))) /* not superfluous pointer */ 436 return type_p; 437 438 return ptee_type_p; 439} 440 441/* 442** d e f a u l t _ t o _ a u t o _ h a n d l e 443** 444** Issues message that auto_handle is assumed for a particular operation. 445** 446** Implicit Outputs: def_auto_handle 447*/ 448 449static int def_auto_handle = 0; 450 451static void default_to_auto_handle 452( 453 AST_operation_n_t *op_p, /* [in] Ptr to AST operation node */ 454 int message_id /* [in] message it display */ 455) 456{ 457 char const *id_name; /* Operation name */ 458 459 NAMETABLE_id_to_string(op_p->name, &id_name); 460 message_print(message_id, id_name); 461 def_auto_handle++; 462} 463 464 465/* 466** i n s t a n c e u t i l i t y r o u t i n e s 467** 468** Instance "properties" used by other checks. 469** An "instance" is an instance (arm, field, parameter) of some data type. 470*/ 471 472/* 473** i n s t a n c e _ i s _ v a r y i n g _ u p p e r 474** 475** Returns TRUE if an instance of an array is varying in an upper dimension 476** (i.e., a dimension other than the first dimension). 477*/ 478 479static boolean instance_is_varying_upper 480( 481 AST_array_n_t *array_p, /* [in] Ptr to AST array node */ 482 AST_field_attr_n_t *fattr_p /* [in] Ptr to AST field attr. node */ 483) 484{ 485 AST_field_ref_n_t *first_p; /* first_is ref for a dimension */ 486 AST_field_ref_n_t *last_p; /* last_is ref for a dimension */ 487 AST_field_ref_n_t *length_p; /* length_is ref for a dimension */ 488 int i; /* Integer array dimension 0..N-1 */ 489 490 if (fattr_p == NULL) 491 return FALSE; 492 493 first_p = fattr_p->first_is_vec; 494 last_p = fattr_p->last_is_vec; 495 length_p = fattr_p->length_is_vec; 496 497 /* Check dimensions 1..N-1 for varying attribute (1st dim is index 0). */ 498 499 for (i = 1 ; i < array_p->index_count ; i++) 500 { 501 if (first_p != NULL) 502 { 503 first_p++; 504 if (first_p->valid) 505 return TRUE; /* Varying in this dimension */ 506 } 507 508 if (last_p != NULL) 509 { 510 last_p++; 511 if (last_p->valid) 512 return TRUE; /* Varying in this dimension */ 513 } 514 515 if (length_p != NULL) 516 { 517 length_p++; 518 if (length_p->valid) 519 return TRUE; /* Varying in this dimension */ 520 } 521 } 522 523 return FALSE; 524} 525 526/* 527** f a t t r _ s w i t c h _ i s 528** 529** Checks a field attribute node's [switch_is] attribute. 530*/ 531 532static void fattr_switch_is 533( 534 AST_field_attr_n_t *fattr_p, /* [in] Ptr to AST field attr. node */ 535 ASTP_node_t *node_p, /* [in] Ptr to field or param node */ 536 AST_type_n_t *type_p /* [in] Ptr to field/param data type */ 537) 538{ 539 AST_type_n_t *ref_type_p; /* Ptr to size info field/param type */ 540 AST_type_n_t *deref_type_p; /* Dereferenced field/param type */ 541 AST_type_n_t *sw_type_p; /* [switch_type] type */ 542 NAMETABLE_id_t ref_name; /* Field/param name */ 543 boolean is_ref_ptr; /* TRUE => ref_type_p is [ref] ptr */ 544 545 /* Checks assume presence of switch_is attr and union data type. */ 546 547 if (fattr_p->switch_is == NULL) 548 return; 549 550 type_p = ASTP_chase_ptr_to_kind(type_p, AST_disc_union_k); 551 if (type_p == NULL) 552 /* Parser supposed to catch this. */ 553 error(NIDL_INTERNAL_ERROR, __FILE__, __LINE__); 554 555 sw_type_p = type_p->type_structure.disc_union->discrim_type; 556 if (sw_type_p == NULL) return; 557 558 /* Pick up [switch_is] field or parameter reference, if any. */ 559 560 if (node_p->fe_info->node_kind == fe_field_n_k) 561 { 562 ref_type_p = fattr_p->switch_is->ref.f_ref->type; 563 ref_name = fattr_p->switch_is->ref.f_ref->name; 564 is_ref_ptr = (AST_REF_SET(fattr_p->switch_is->ref.f_ref)); 565 } 566 else 567 { 568 ref_type_p = fattr_p->switch_is->ref.p_ref->type; 569 ref_name = fattr_p->switch_is->ref.p_ref->name; 570 is_ref_ptr = (AST_REF_SET(fattr_p->switch_is->ref.p_ref)); 571 } 572 573 /* 574 * Param/field referenced in [switch_is] might be a ptr. Chase ptr 575 * to its base type. This sets deref_type_p->fe_info->pointer_count 576 * to the number of dereferences needed to get to the base type. 577 */ 578 deref_type_p = ASTP_chase_ptr_to_type(ref_type_p); 579 580 /* The union switch variable 'name' cannot have [ptr] or [unique] attr */ 581 582 if (deref_type_p->fe_info->pointer_count > 0 583 && !is_ref_ptr) 584 { 585 char const *id_name; /* [switch_is] variable name */ 586 NAMETABLE_id_to_string(ref_name, &id_name); 587 CHECKER_error(fattr_p, NIDL_NEUSWPTR, id_name); 588 } 589 590 /* Data type of [switch_is] variable does not agree with [switch_type] */ 591 592 if (deref_type_p->kind != sw_type_p->kind) 593 { 594 char const *id_name; /* [switch_is] variable name */ 595 char const *sw_type_name; /* [switch_type] name, if any */ 596 597 NAMETABLE_id_to_string(ref_name, &id_name); 598 NAMETABLE_id_to_string(sw_type_p->name, &sw_type_name); 599 if (sw_type_name == NULL) sw_type_name = ""; 600 601 CHECKER_error(fattr_p, NIDL_SWDATATYPE, id_name, sw_type_name); 602 } 603 604 /* A [switch_is] variable must not have a represent_as type */ 605 606 if (deref_type_p->rep_as_type != NULL) 607 CHECKER_error(fattr_p, NIDL_DISCRIMREPAS); 608 609 /* A [switch_is] variable must not have a transmit_as type */ 610 611 if (deref_type_p->xmit_as_type != NULL) 612 CHECKER_error(fattr_p, NIDL_DISCRIMXMITAS); 613} 614/* 615** f a t t r _ c h e c k _ s i z e 616** 617** Checks a field attribute node for missing or inconsistent size attributes. 618*/ 619 620static void fattr_check_size 621( 622 AST_field_attr_n_t *fattr_p, /* [in] Ptr to AST field attr. node */ 623 ASTP_node_t *node_p, /* [in] Ptr to field or param node */ 624 AST_type_n_t *type_p, /* [in] Ptr to field data type node */ 625 AST_interface_n_t *int_p, /* [in] Ptr to interface node */ 626 unsigned short dim /* [in] Array dimension to check */ 627) 628{ 629 AST_array_n_t *array_p; /* Ptr to array node */ 630 AST_array_index_n_t *index_p = NULL; /* Ptr to array index node */ 631 boolean str_attr_set; /* T => [string] on type or instance */ 632 633 /* Determine if [string] attribute set on type or instance. */ 634 635 if (AST_STRING_SET(type_p) 636 || (node_p->fe_info->node_kind == fe_field_n_k 637 && AST_STRING_SET((AST_field_n_t *)node_p)) 638 || (node_p->fe_info->node_kind == fe_parameter_n_k 639 && AST_STRING_SET((AST_parameter_n_t *)node_p))) 640 str_attr_set = TRUE; 641 else 642 str_attr_set = FALSE; 643 644 /* 645 * Assume parser won't put field attribute node on non-arrays. 646 * An array can be represented either in normal array syntax, 647 * or as a pointer that has any of the array attributes. 648 */ 649 if (type_p->kind == AST_array_k) 650 { 651 array_p = type_p->type_structure.array; 652 index_p = &array_p->index_vec[dim]; 653 } 654 else 655 array_p = NULL; 656 657 /* Can't have both [max_is] and [size_is] attributes */ 658 659 if (fattr_p->max_is_vec != NULL 660 && fattr_p->max_is_vec[dim].valid 661 && fattr_p->size_is_vec != NULL 662 && fattr_p->size_is_vec[dim].valid) 663 CHECKER_error(fattr_p, NIDL_MAXSIZECONF); 664 665 /* Can't have constant [size_is] and varying [min_is] */ 666 667 if (fattr_p->min_is_vec != NULL 668 && fattr_p->min_is_vec[dim].valid 669 && fattr_p->min_is_vec[dim].constant == false 670 && fattr_p->size_is_vec != NULL 671 && fattr_p->size_is_vec[dim].valid 672 && fattr_p->size_is_vec[dim].constant == true) 673 CHECKER_error(fattr_p, NIDL_CONSTREQ); 674 675 /* Can't have both [last_is] and [length_is] attributes */ 676 677 if (fattr_p->last_is_vec != NULL 678 && fattr_p->last_is_vec[dim].valid 679 && fattr_p->length_is_vec != NULL 680 && fattr_p->length_is_vec[dim].valid) 681 CHECKER_error(fattr_p, NIDL_LASTLENCONF); 682 683 /* Can't have constant [length_is] and varying [first_is] */ 684 685 if (fattr_p->first_is_vec != NULL 686 && fattr_p->first_is_vec[dim].valid 687 && fattr_p->first_is_vec[dim].constant == false 688 && fattr_p->length_is_vec != NULL 689 && fattr_p->length_is_vec[dim].valid 690 && fattr_p->length_is_vec[dim].constant == true) 691 CHECKER_error(fattr_p, NIDL_CONSTREQ); 692 693 /* 694 * Forgo the remaining checks if the field or parameter type is a pointer 695 * to an array, since mixed pointer and array declarations with array size 696 * attributes are disallowed by other checks. 697 */ 698 if (type_p->kind == AST_pointer_k) 699 { 700 AST_type_n_t *ref_type_p; /* Pointee data type */ 701 702 ref_type_p = ASTP_chase_ptr_to_type(type_p); 703 if (ref_type_p->kind == AST_array_k) 704 return; 705 } 706 else if (fattr_p->range != NULL && !type_is_rangeable(type_p)) 707 { 708 CHECKER_error(fattr_p, NIDL_RANGEATTR); 709 } 710 711 /* [max_is] or [size_is] attribute required */ 712 713 if (array_p != NULL /* Array in array syntax */ 714 && !AST_LOCAL_SET(int_p) 715 && type_p->xmit_as_type == NULL 716 && !AST_FIXED_UPPER_SET(index_p) 717 && (fattr_p->max_is_vec == NULL 718 || !fattr_p->max_is_vec[dim].valid) 719 && (fattr_p->size_is_vec == NULL 720 || !fattr_p->size_is_vec[dim].valid)) 721 CHECKER_error(fattr_p, NIDL_MAXSIZEATTR); 722 723 if (array_p == NULL /* Non-[string] array in pointer syntax */ 724 && !str_attr_set 725 && (fattr_p->first_is_vec != NULL 726 || fattr_p->last_is_vec != NULL 727 || fattr_p->length_is_vec != NULL 728 || fattr_p->min_is_vec != NULL) 729 && fattr_p->max_is_vec == NULL 730 && fattr_p->size_is_vec == NULL) 731 CHECKER_error(fattr_p, NIDL_MAXSIZEATTR); 732 733 /* [min_is] attribute required */ 734 735 if (array_p != NULL 736 && !AST_LOCAL_SET(int_p) 737 && type_p->xmit_as_type == NULL 738 && !AST_FIXED_LOWER_SET(index_p) 739 && (fattr_p->min_is_vec == NULL 740 || !fattr_p->min_is_vec[dim].valid)) 741 CHECKER_error(fattr_p, NIDL_MINATTREQ); 742 743 if (array_p != NULL && fattr_p->range != NULL) 744 CHECKER_error(fattr_p, NIDL_RANGEATTR); 745} 746 747/* 748** f a t t r _ f i r s t _ i s 749** 750** Checks a field attribute node's [first_is] attribute. 751*/ 752 753static void fattr_first_is 754( 755 AST_field_attr_n_t *fattr_p, /* [in] Ptr to AST field attr. node */ 756 ASTP_node_t *node_p, /* [in] Ptr to field or param node */ 757 unsigned short dim /* [in] Array dimension to check */ 758) 759{ 760 AST_type_n_t *ref_type_p; /* Ptr to size info field/param type */ 761 AST_type_n_t *deref_type_p = NULL; /* Dereferenced field/param type */ 762 NAMETABLE_id_t ref_name = 0; /* Field/param name */ 763 boolean is_ref_ptr = false; /* TRUE => ref_type_p is [ref] ptr */ 764 765 /* Pick up [first_is] field or parameter reference, if any. */ 766 767 if (fattr_p->first_is_vec != NULL 768 && fattr_p->first_is_vec[dim].valid) 769 { 770 if (fattr_p->first_is_vec[dim].constant) 771 return; 772 773 if (node_p->fe_info->node_kind == fe_field_n_k) 774 { 775 ref_type_p = fattr_p->first_is_vec[dim].ref.f_ref->type; 776 ref_name = fattr_p->first_is_vec[dim].ref.f_ref->name; 777 is_ref_ptr = (AST_REF_SET(fattr_p->first_is_vec[dim].ref.f_ref)); 778 } 779 else 780 { 781 ref_type_p = fattr_p->first_is_vec[dim].ref.p_ref->type; 782 ref_name = fattr_p->first_is_vec[dim].ref.p_ref->name; 783 is_ref_ptr = (AST_REF_SET(fattr_p->first_is_vec[dim].ref.p_ref)); 784 } 785 786 /* 787 * Param/field referenced in [first_is] might be a ptr. Chase ptr 788 * to its base type. This sets deref_type_p->fe_info->pointer_count 789 * to the number of dereferences needed to get to the base type. 790 */ 791 deref_type_p = ASTP_chase_ptr_to_type(ref_type_p); 792 assert(deref_type_p != NULL); 793 794 /* [first_is] variable must be of type integer */ 795 796 if (!type_is_index(deref_type_p) 797 || deref_type_p->fe_info->pointer_count 798 != fattr_p->first_is_vec[dim].fe_info->pointer_count) 799 CHECKER_error(fattr_p, NIDL_FIRSTYPEINT); 800 801 /* A size attribute variable must not have a represent_as type */ 802 803 if (deref_type_p->rep_as_type != NULL) 804 CHECKER_error(fattr_p, NIDL_SIZEVARREPAS); 805 806 /* A size attribute variable must not have a transmit_as type */ 807 808 if (deref_type_p->xmit_as_type != NULL) 809 CHECKER_error(fattr_p, NIDL_SIZEVARXMITAS); 810 811 /* The array size attr var 'name' can not have [ptr] or [unique] attr */ 812 813 if (deref_type_p->fe_info->pointer_count > 0 814 && !is_ref_ptr) 815 { 816 char const *id_name; /* [first_is] variable name */ 817 818 NAMETABLE_id_to_string(ref_name, &id_name); 819 820 CHECKER_error(fattr_p, NIDL_SIZEPRMPTR, id_name); 821 } 822 } 823} 824 825/* 826** f a t t r _ l a s t _ i s 827** 828** Checks a field attribute node's [last_is] attribute. 829*/ 830 831static void fattr_last_is 832( 833 AST_field_attr_n_t *fattr_p, /* [in] Ptr to AST field attr. node */ 834 ASTP_node_t *node_p, /* [in] Ptr to field or param node */ 835 unsigned short dim /* [in] Array dimension to check */ 836) 837{ 838 AST_type_n_t *ref_type_p; /* Ptr to size info field/param type */ 839 AST_type_n_t *deref_type_p = NULL; /* Dereferenced field/param type */ 840 NAMETABLE_id_t ref_name = 0; /* Field/param name */ 841 boolean is_ref_ptr = false; /* TRUE => ref_type_p is [ref] ptr */ 842 843 /* Pick up [last_is] field or parameter reference, if any. */ 844 845 if (fattr_p->last_is_vec != NULL 846 && fattr_p->last_is_vec[dim].valid) 847 { 848 if (fattr_p->last_is_vec[dim].constant) 849 return; 850 851 if (node_p->fe_info->node_kind == fe_field_n_k) 852 { 853 ref_type_p = fattr_p->last_is_vec[dim].ref.f_ref->type; 854 ref_name = fattr_p->last_is_vec[dim].ref.f_ref->name; 855 is_ref_ptr = (AST_REF_SET(fattr_p->last_is_vec[dim].ref.f_ref)); 856 } 857 else 858 { 859 ref_type_p = fattr_p->last_is_vec[dim].ref.p_ref->type; 860 ref_name = fattr_p->last_is_vec[dim].ref.p_ref->name; 861 is_ref_ptr = (AST_REF_SET(fattr_p->last_is_vec[dim].ref.p_ref)); 862 } 863 864 /* 865 * Param/field referenced in [last_is] might be a ptr. Chase ptr 866 * to its base type. This sets deref_type_p->fe_info->pointer_count 867 * to the number of dereferences needed to get to the base type. 868 */ 869 deref_type_p = ASTP_chase_ptr_to_type(ref_type_p); 870 assert(deref_type_p != NULL); 871 872 /* [last_is] variable must be of type integer */ 873 874 if (!type_is_index(deref_type_p) 875 || deref_type_p->fe_info->pointer_count 876 != fattr_p->last_is_vec[dim].fe_info->pointer_count) 877 CHECKER_error(fattr_p, NIDL_LASTYPEINT); 878 879 /* A size attribute variable must not have a represent_as type */ 880 881 if (deref_type_p->rep_as_type != NULL) 882 CHECKER_error(fattr_p, NIDL_SIZEVARREPAS); 883 884 /* A size attribute variable must not have a transmit_as type */ 885 886 if (deref_type_p->xmit_as_type != NULL) 887 CHECKER_error(fattr_p, NIDL_SIZEVARXMITAS); 888 889 /* The array size attr var 'name' can not have [ptr] or [unique] attr */ 890 891 if (deref_type_p->fe_info->pointer_count > 0 892 && !is_ref_ptr) 893 { 894 char const *id_name; /* [last_is] variable name */ 895 896 NAMETABLE_id_to_string(ref_name, &id_name); 897 898 CHECKER_error(fattr_p, NIDL_SIZEPRMPTR, id_name); 899 } 900 } 901} 902 903/* 904** f a t t r _ l e n g t h _ i s 905** 906** Checks a field attribute node's [length_is] attribute. 907*/ 908 909static void fattr_length_is 910( 911 AST_field_attr_n_t *fattr_p, /* [in] Ptr to AST field attr. node */ 912 ASTP_node_t *node_p, /* [in] Ptr to field or param node */ 913 unsigned short dim /* [in] Array dimension to check */ 914) 915{ 916 AST_type_n_t *ref_type_p; /* Ptr to size info field/param type */ 917 AST_type_n_t *deref_type_p = NULL; /* Dereferenced field/param type */ 918 NAMETABLE_id_t ref_name = 0; /* Field/param name */ 919 boolean is_ref_ptr = false; /* TRUE => ref_type_p is [ref] ptr */ 920 921 /* Pick up [length_is] field or parameter reference, if any. */ 922 923 if (fattr_p->length_is_vec != NULL 924 && fattr_p->length_is_vec[dim].valid) 925 { 926 if (fattr_p->length_is_vec[dim].constant) 927 return; 928 929 if (node_p->fe_info->node_kind == fe_field_n_k) 930 { 931 ref_type_p = fattr_p->length_is_vec[dim].ref.f_ref->type; 932 ref_name = fattr_p->length_is_vec[dim].ref.f_ref->name; 933 is_ref_ptr = (AST_REF_SET(fattr_p->length_is_vec[dim].ref.f_ref)); 934 } 935 else 936 { 937 ref_type_p = fattr_p->length_is_vec[dim].ref.p_ref->type; 938 ref_name = fattr_p->length_is_vec[dim].ref.p_ref->name; 939 is_ref_ptr = (AST_REF_SET(fattr_p->length_is_vec[dim].ref.p_ref)); 940 } 941 942 /* 943 * Param/field referenced in [length_is] might be a ptr. Chase ptr 944 * to its base type. This sets deref_type_p->fe_info->pointer_count 945 * to the number of dereferences needed to get to the base type. 946 */ 947 deref_type_p = ASTP_chase_ptr_to_type(ref_type_p); 948 assert(deref_type_p != NULL); 949 950 /* [length_is] variable must be of type integer */ 951 952 if (!type_is_index(deref_type_p) 953 || deref_type_p->fe_info->pointer_count 954 != fattr_p->length_is_vec[dim].fe_info->pointer_count) 955 CHECKER_error(fattr_p, NIDL_LENTYPEINT); 956 957 /* A size attribute variable must not have a represent_as type */ 958 959 if (deref_type_p->rep_as_type != NULL) 960 CHECKER_error(fattr_p, NIDL_SIZEVARREPAS); 961 962 /* A size attribute variable must not have a transmit_as type */ 963 964 if (deref_type_p->xmit_as_type != NULL) 965 CHECKER_error(fattr_p, NIDL_SIZEVARXMITAS); 966 967 /* The array size attr var 'name' can not have [ptr] or [unique] attr */ 968 969 if (deref_type_p->fe_info->pointer_count > 0 970 && !is_ref_ptr) 971 { 972 char const *id_name; /* [length_is] variable name */ 973 974 NAMETABLE_id_to_string(ref_name, &id_name); 975 976 CHECKER_error(fattr_p, NIDL_SIZEPRMPTR, id_name); 977 } 978 } 979} 980 981/* 982** f a t t r _ m i n _ i s 983** 984** Checks a field attribute node's [min_is] attribute. 985*/ 986 987static void fattr_min_is 988( 989 AST_field_attr_n_t *fattr_p, /* [in] Ptr to AST field attr. node */ 990 ASTP_node_t *node_p, /* [in] Ptr to field or param node */ 991 AST_type_n_t *type_p, /* [in] Ptr to field/param data type */ 992 unsigned short dim /* [in] Array dimension to check */ 993) 994{ 995 AST_array_n_t *array_p; /* Ptr to array node */ 996 AST_array_index_n_t *index_p = NULL; /* Ptr to array index node */ 997 AST_type_n_t *ref_type_p; /* Ptr to size info field/param type */ 998 AST_type_n_t *deref_type_p = NULL; /* Dereferenced field/param type */ 999 NAMETABLE_id_t ref_name = 0; /* Field/param name */ 1000 boolean is_ref_ptr = false; /* TRUE => ref_type_p is [ref] ptr */ 1001 1002 /* 1003 * Assume parser won't put field attribute node on non-arrays. 1004 * An array can be represented either in normal array syntax, 1005 * or as a pointer that has any of the array attributes. 1006 */ 1007 if (type_p->kind == AST_array_k) 1008 { 1009 array_p = type_p->type_structure.array; 1010 index_p = &array_p->index_vec[dim]; 1011 } 1012 else 1013 array_p = NULL; 1014 1015 /* Pick up [min_is] field or parameter reference, if any. */ 1016 1017 if (fattr_p->min_is_vec != NULL 1018 && fattr_p->min_is_vec[dim].valid 1019 && fattr_p->min_is_vec[dim].constant == false) 1020 { 1021 if (node_p->fe_info->node_kind == fe_field_n_k) 1022 { 1023 ref_type_p = fattr_p->min_is_vec[dim].ref.f_ref->type; 1024 ref_name = fattr_p->min_is_vec[dim].ref.f_ref->name; 1025 is_ref_ptr = (AST_REF_SET(fattr_p->min_is_vec[dim].ref.f_ref)); 1026 } 1027 else 1028 { 1029 ref_type_p = fattr_p->min_is_vec[dim].ref.p_ref->type; 1030 ref_name = fattr_p->min_is_vec[dim].ref.p_ref->name; 1031 is_ref_ptr = (AST_REF_SET(fattr_p->min_is_vec[dim].ref.p_ref)); 1032 } 1033 1034 /* 1035 * Param/field referenced in [min_is] might be a ptr. Chase ptr 1036 * to its base type. This sets deref_type_p->fe_info->pointer_count 1037 * to the number of dereferences needed to get to the base type. 1038 */ 1039 deref_type_p = ASTP_chase_ptr_to_type(ref_type_p); 1040 } 1041 1042 /* Arrays with a nonzero lower bound require -standard extended */ 1043 1044 /* 1045 * Anonymous type checking will pick this up for anonymous array types in 1046 * array syntax. Normal type checking will pick it up for named types at 1047 * the typedef site. Therefore, we only need to handle the pointer case. 1048 */ 1049 if (type_p->kind == AST_pointer_k 1050 && fattr_p->min_is_vec != NULL 1051 && (*(int *)cmd_val[opt_standard] <= opt_standard_dce_1_0)) 1052 CHECKER_warning(fattr_p, NIDL_NOPORTNZLB, OPT_STD_EXTENDED); 1053 1054 /* [min_is] variable <var> invalid: lower bound fixed in dimension <n> */ 1055 1056 if (array_p != NULL 1057 && fattr_p->min_is_vec != NULL 1058 && (!type_is_array(type_p) 1059 || (type_is_array(type_p) 1060 && fattr_p->min_is_vec[dim].valid 1061 && AST_FIXED_LOWER_SET(index_p)))) 1062 CHECKER_error(fattr_p, NIDL_MINCFMTYPE, dim+1); 1063 1064 /* Constants are excused from further checks */ 1065 1066 if (fattr_p->min_is_vec != NULL 1067 && fattr_p->min_is_vec[dim].valid 1068 && fattr_p->min_is_vec[dim].constant) 1069 return; 1070 1071 /* [min_is] variable must be of type integer */ 1072 1073 if (fattr_p->min_is_vec != NULL 1074 && fattr_p->min_is_vec[dim].valid) { 1075 1076 assert(deref_type_p != NULL); 1077 1078 if (!type_is_index(deref_type_p) 1079 || deref_type_p->fe_info->pointer_count 1080 != fattr_p->min_is_vec[dim].fe_info->pointer_count) 1081 CHECKER_error(fattr_p, NIDL_MINTYPEINT); 1082 1083 /* A size attribute variable must not have a represent_as type */ 1084 1085 if (deref_type_p->rep_as_type != NULL) 1086 CHECKER_error(fattr_p, NIDL_SIZEVARREPAS); 1087 1088 /* A size attribute variable must not have a transmit_as type */ 1089 1090 if (deref_type_p->xmit_as_type != NULL) 1091 CHECKER_error(fattr_p, NIDL_SIZEVARXMITAS); 1092 1093 /* The array size attr var 'name' can not have [ptr] or [unique] attr */ 1094 1095 if (deref_type_p->fe_info->pointer_count > 0 1096 && !is_ref_ptr) 1097 { 1098 char const *id_name; /* [min_is] variable name */ 1099 1100 NAMETABLE_id_to_string(ref_name, &id_name); 1101 1102 CHECKER_error(fattr_p, NIDL_SIZEPRMPTR, id_name); 1103 } 1104 } 1105} 1106 1107/* 1108** f a t t r _ m a x _ i s 1109** 1110** Checks a field attribute node's [max_is] attribute. 1111*/ 1112 1113static void fattr_max_is 1114( 1115 AST_field_attr_n_t *fattr_p, /* [in] Ptr to AST field attr. node */ 1116 ASTP_node_t *node_p, /* [in] Ptr to field or param node */ 1117 AST_type_n_t *type_p, /* [in] Ptr to field/param data type */ 1118 unsigned short dim /* [in] Array dimension to check */ 1119) 1120{ 1121 AST_array_n_t *array_p; /* Ptr to array node */ 1122 AST_array_index_n_t *index_p = NULL; /* Ptr to array index node */ 1123 AST_type_n_t *ref_type_p; /* Ptr to size info field/param type */ 1124 AST_type_n_t *deref_type_p = NULL; /* Dereferenced field/param type */ 1125 NAMETABLE_id_t ref_name = 0; /* Field/param name */ 1126 boolean is_ref_ptr = false; /* TRUE => ref_type_p is [ref] ptr */ 1127 1128 /* 1129 * Assume parser won't put field attribute node on non-arrays. 1130 * An array can be represented either in normal array syntax, 1131 * or as a pointer that has any of the array attributes. 1132 */ 1133 if (type_p->kind == AST_array_k) 1134 { 1135 array_p = type_p->type_structure.array; 1136 index_p = &array_p->index_vec[dim]; 1137 } 1138 else 1139 array_p = NULL; 1140 1141 /* Pick up [max_is] field or parameter reference, if any. */ 1142 1143 if (fattr_p->max_is_vec != NULL 1144 && fattr_p->max_is_vec[dim].valid 1145 && fattr_p->max_is_vec[dim].constant == false) 1146 { 1147 if (node_p->fe_info->node_kind == fe_field_n_k) 1148 { 1149 ref_type_p = fattr_p->max_is_vec[dim].ref.f_ref->type; 1150 ref_name = fattr_p->max_is_vec[dim].ref.f_ref->name; 1151 is_ref_ptr = (AST_REF_SET(fattr_p->max_is_vec[dim].ref.f_ref)); 1152 } 1153 else 1154 { 1155 ref_type_p = fattr_p->max_is_vec[dim].ref.p_ref->type; 1156 ref_name = fattr_p->max_is_vec[dim].ref.p_ref->name; 1157 is_ref_ptr = (AST_REF_SET(fattr_p->max_is_vec[dim].ref.p_ref)); 1158 } 1159 1160 /* 1161 * Param/field referenced in [max_is] might be a ptr. Chase ptr 1162 * to its base type. This sets deref_type_p->fe_info->pointer_count 1163 * to the number of dereferences needed to get to the base type. 1164 */ 1165 deref_type_p = ASTP_chase_ptr_to_type(ref_type_p); 1166 } 1167 1168 /* [max_is] variable <var> invalid: upper bound fixed in dimension <n> */ 1169 1170 if (array_p != NULL 1171 && fattr_p->max_is_vec != NULL 1172 && (!type_is_array(type_p) 1173 || (type_is_array(type_p) 1174 && fattr_p->max_is_vec[dim].valid 1175 && AST_FIXED_UPPER_SET(index_p)))) 1176 CHECKER_error(fattr_p, NIDL_MAXCFMTYPE, dim+1); 1177 1178 /* Constants are excused from further checks */ 1179 1180 if (fattr_p->max_is_vec != NULL 1181 && fattr_p->max_is_vec[dim].valid 1182 && fattr_p->max_is_vec[dim].constant == true) 1183 return; 1184 1185 /* [max_is] variable must be of type integer */ 1186 1187 if (fattr_p->max_is_vec != NULL 1188 && fattr_p->max_is_vec[dim].valid) { 1189 1190 assert(deref_type_p != NULL); 1191 1192 if (!type_is_index(deref_type_p) 1193 || deref_type_p->fe_info->pointer_count 1194 != fattr_p->max_is_vec[dim].fe_info->pointer_count) 1195 CHECKER_error(fattr_p, NIDL_MAXTYPEINT); 1196 1197 /* A size attribute variable must not have a represent_as type */ 1198 1199 if (deref_type_p->rep_as_type != NULL) 1200 CHECKER_error(fattr_p, NIDL_SIZEVARREPAS); 1201 1202 /* A size attribute variable must not have a transmit_as type */ 1203 1204 if (deref_type_p->xmit_as_type != NULL) 1205 CHECKER_error(fattr_p, NIDL_SIZEVARXMITAS); 1206 1207 /* The array size attr var 'name' can not have [ptr] or [unique] attr */ 1208 1209 if (deref_type_p->fe_info->pointer_count > 0 1210 && !is_ref_ptr) 1211 { 1212 char const *id_name; /* [max_is] variable name */ 1213 1214 NAMETABLE_id_to_string(ref_name, &id_name); 1215 1216 CHECKER_error(fattr_p, NIDL_SIZEPRMPTR, id_name); 1217 } 1218 } 1219} 1220 1221/* 1222** f a t t r _ s i z e _ i s 1223** 1224** Checks a field attribute node's [size_is] attribute. 1225*/ 1226 1227static void fattr_size_is 1228( 1229 AST_field_attr_n_t *fattr_p, /* [in] Ptr to AST field attr. node */ 1230 ASTP_node_t *node_p, /* [in] Ptr to field or param node */ 1231 AST_type_n_t *type_p, /* [in] Ptr to field/param data type */ 1232 unsigned short dim /* [in] Array dimension to check */ 1233) 1234{ 1235 AST_array_n_t *array_p; /* Ptr to array node */ 1236 AST_array_index_n_t *index_p = NULL; /* Ptr to array index node */ 1237 AST_type_n_t *ref_type_p; /* Ptr to size info field/param type */ 1238 AST_type_n_t *deref_type_p = NULL; /* Dereferenced field/param type */ 1239 NAMETABLE_id_t ref_name = 0; /* Field/param name */ 1240 boolean is_ref_ptr = false; /* TRUE => ref_type_p is [ref] ptr */ 1241 1242 /* 1243 * Assume parser won't put field attribute node on non-arrays. 1244 * An array can be represented either in normal array syntax, 1245 * or as a pointer that has any of the array attributes. 1246 */ 1247 if (type_p->kind == AST_array_k) 1248 { 1249 array_p = type_p->type_structure.array; 1250 index_p = &array_p->index_vec[dim]; 1251 } 1252 else 1253 array_p = NULL; 1254 1255 /* Pick up [size_is] field or parameter reference, if any. */ 1256 1257 if (fattr_p->size_is_vec != NULL 1258 && fattr_p->size_is_vec[dim].valid 1259 && fattr_p->size_is_vec[dim].constant == false) 1260 { 1261 if (node_p->fe_info->node_kind == fe_field_n_k) 1262 { 1263 ref_type_p = fattr_p->size_is_vec[dim].ref.f_ref->type; 1264 ref_name = fattr_p->size_is_vec[dim].ref.f_ref->name; 1265 is_ref_ptr = (AST_REF_SET(fattr_p->size_is_vec[dim].ref.f_ref)); 1266 } 1267 else 1268 { 1269 ref_type_p = fattr_p->size_is_vec[dim].ref.p_ref->type; 1270 ref_name = fattr_p->size_is_vec[dim].ref.p_ref->name; 1271 is_ref_ptr = (AST_REF_SET(fattr_p->size_is_vec[dim].ref.p_ref)); 1272 } 1273 1274 /* 1275 * Param/field referenced in [size_is] might be a ptr. Chase ptr 1276 * to its base type. This sets deref_type_p->fe_info->pointer_count 1277 * to the number of dereferences needed to get to the base type. 1278 */ 1279 deref_type_p = ASTP_chase_ptr_to_type(ref_type_p); 1280 } 1281 1282 /* [size_is] variable <var> invalid: upper bound fixed in dimension <n> */ 1283 1284 if (array_p != NULL 1285 && fattr_p->size_is_vec != NULL 1286 && (!type_is_array(type_p) 1287 || (type_is_array(type_p) 1288 && fattr_p->size_is_vec[dim].valid 1289 && AST_FIXED_UPPER_SET(index_p)))) 1290 CHECKER_error(fattr_p, NIDL_SIZECFMTYPE, dim+1); 1291 1292 /* Constants are excused from further checks */ 1293 1294 if (fattr_p->size_is_vec != NULL 1295 && fattr_p->size_is_vec[dim].valid 1296 && fattr_p->size_is_vec[dim].constant == true) 1297 return; 1298 1299 /* [size_is] variable must be of type integer */ 1300 1301 if (fattr_p->size_is_vec != NULL 1302 && fattr_p->size_is_vec[dim].valid) { 1303 1304 assert(deref_type_p != NULL); 1305 1306 if (!type_is_index(deref_type_p) 1307 || deref_type_p->fe_info->pointer_count 1308 != fattr_p->size_is_vec[dim].fe_info->pointer_count) 1309 CHECKER_error(fattr_p, NIDL_SIZETYPEINT); 1310 1311 /* A size attribute variable must not have a represent_as type */ 1312 1313 if (deref_type_p->rep_as_type != NULL) 1314 CHECKER_error(fattr_p, NIDL_SIZEVARREPAS); 1315 1316 /* A size attribute variable must not have a transmit_as type */ 1317 1318 if (deref_type_p->xmit_as_type != NULL) 1319 CHECKER_error(fattr_p, NIDL_SIZEVARXMITAS); 1320 1321 /* The array size attr var 'name' can not have [ptr] or [unique] attr */ 1322 1323 if (deref_type_p->fe_info->pointer_count > 0 1324 && !is_ref_ptr) 1325 { 1326 char const *id_name; /* [size_is] variable name */ 1327 1328 NAMETABLE_id_to_string(ref_name, &id_name); 1329 1330 CHECKER_error(fattr_p, NIDL_SIZEPRMPTR, id_name); 1331 } 1332 } 1333} 1334 1335/* 1336** f a t t r _ p a r a m _ c o n f o r m a n t 1337** 1338** Checks an field attribute node associated with a parameter node to make 1339** sure that a conformant array's size information parameters have the [in] 1340** parameter attribute. 1341*/ 1342 1343static void fattr_param_conformant 1344( 1345 AST_field_attr_n_t *fattr_p, /* [in] Ptr to AST field attr. node */ 1346 AST_parameter_n_t *param_p, /* [in] Ptr to associated param node */ 1347 AST_interface_n_t *int_p, /* [in] Ptr to interface node */ 1348 unsigned short dim /* [in] Array dimension */ 1349) 1350{ 1351 /* [min_is] parameter must have [in] attribute */ 1352 1353 if (!AST_LOCAL_SET(int_p) 1354 && param_p->type->xmit_as_type == NULL 1355 && fattr_p->min_is_vec != NULL 1356 && fattr_p->min_is_vec[dim].valid 1357 && fattr_p->min_is_vec[dim].constant == false 1358 && AST_IN_SET(param_p) 1359 && !AST_IN_SET(fattr_p->min_is_vec[dim].ref.p_ref)) 1360 CHECKER_error(fattr_p, NIDL_MININATTR); 1361 1362 /* [max_is] parameter must have [in] attribute */ 1363 1364 if (!AST_LOCAL_SET(int_p) 1365 && param_p->type->xmit_as_type == NULL 1366 && fattr_p->max_is_vec != NULL 1367 && fattr_p->max_is_vec[dim].valid 1368 && fattr_p->max_is_vec[dim].constant == false 1369 && AST_IN_SET(param_p) 1370 && !AST_IN_SET(fattr_p->max_is_vec[dim].ref.p_ref)) 1371 CHECKER_error(fattr_p, NIDL_MAXINATTR); 1372 1373 /* [size_is] parameter must have [in] attribute */ 1374 1375 if (!AST_LOCAL_SET(int_p) 1376 && param_p->type->xmit_as_type == NULL 1377 && fattr_p->size_is_vec != NULL 1378 && fattr_p->size_is_vec[dim].valid 1379 && fattr_p->size_is_vec[dim].constant == false 1380 && AST_IN_SET(param_p) 1381 && !AST_IN_SET(fattr_p->size_is_vec[dim].ref.p_ref)) 1382 CHECKER_error(fattr_p, NIDL_SIZEINATTR); 1383} 1384 1385/* 1386** f a t t r _ p a r a m _ v a r y i n g 1387** 1388** Checks an field attribute node associated with a parameter node to make 1389** sure that a varying array's directional attributes are consistent with 1390** the corresponding size information parameter's directional attributes. 1391*/ 1392 1393static void fattr_param_varying 1394( 1395 AST_field_attr_n_t *fattr_p, /* [in] Ptr to AST field attr. node */ 1396 AST_parameter_n_t *param_p, /* [in] Ptr to associated param node */ 1397 AST_interface_n_t *int_p, /* [in] Ptr to interface node */ 1398 unsigned short dim /* [in] Array dimension */ 1399) 1400{ 1401 /* [first_is] parameter must have [in] attribute */ 1402 1403 if (!AST_LOCAL_SET(int_p) 1404 && param_p->type->xmit_as_type == NULL 1405 && fattr_p->first_is_vec != NULL 1406 && fattr_p->first_is_vec[dim].valid 1407 && fattr_p->first_is_vec[dim].constant == false 1408 && AST_IN_SET(param_p) 1409 && !AST_IN_SET(fattr_p->first_is_vec[dim].ref.p_ref)) 1410 CHECKER_error(fattr_p, NIDL_FIRSTINATTR); 1411 1412 /* [last_is] parameter must have [in] attribute */ 1413 1414 if (!AST_LOCAL_SET(int_p) 1415 && param_p->type->xmit_as_type == NULL 1416 && fattr_p->last_is_vec != NULL 1417 && fattr_p->last_is_vec[dim].valid 1418 && fattr_p->last_is_vec[dim].constant == false 1419 && AST_IN_SET(param_p) 1420 && !AST_IN_SET(fattr_p->last_is_vec[dim].ref.p_ref)) 1421 CHECKER_error(fattr_p, NIDL_LASTINATTR); 1422 1423 /* [length_is] parameter must have [in] attribute */ 1424 1425 if (!AST_LOCAL_SET(int_p) 1426 && param_p->type->xmit_as_type == NULL 1427 && fattr_p->length_is_vec != NULL 1428 && fattr_p->length_is_vec[dim].valid 1429 && fattr_p->length_is_vec[dim].constant == false 1430 && AST_IN_SET(param_p) 1431 && !AST_IN_SET(fattr_p->length_is_vec[dim].ref.p_ref)) 1432 CHECKER_error(fattr_p, NIDL_LENINATTR); 1433} 1434 1435/* 1436** f a t t r _ p a r a m _ c h e c k 1437** 1438** Checks an AST field attribute node. This set of checks is specific to 1439** field attribute nodes associated with parameters. (Field attribute nodes 1440** can also occur in field nodes). 1441*/ 1442 1443static void fattr_param_check 1444( 1445 AST_field_attr_n_t *fattr_p, /* [in] Ptr to AST field attr. node */ 1446 AST_parameter_n_t *param_p, /* [in] Ptr to associated param node */ 1447 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 1448) 1449{ 1450 unsigned short dim; /* Array dimension */ 1451 unsigned short max_dim; /* Maximum dimension */ 1452 AST_type_n_t *type_p; /* Parameter data type */ 1453 1454 type_p = param_p->type; 1455 1456 /* 1457 * Assume parser won't put field attribute node on non-arrays. 1458 * An array can be represented either in normal array syntax, 1459 * or as a pointer that has any of the array attributes. 1460 */ 1461 if (type_p->kind == AST_array_k) 1462 max_dim = type_p->type_structure.array->index_count; 1463 else 1464 max_dim = 1; /* Arrays in pointer form can only be 1-dimensional */ 1465 1466 /* Check field attributes in each dimension of the array. */ 1467 1468 for (dim = 0 ; dim < max_dim ; dim++) 1469 { 1470 fattr_param_conformant(fattr_p, param_p, int_p, dim); 1471 fattr_param_varying(fattr_p, param_p, int_p, dim); 1472 } 1473} 1474 1475/* 1476** f a t t r _ c h e c k 1477** 1478** Checks an AST field attribute node. 1479*/ 1480 1481static void fattr_check 1482( 1483 AST_field_attr_n_t *fattr_p, /* [in] Ptr to AST field attr. node */ 1484 ASTP_node_t *node_p, /* [in] Ptr to field or param node */ 1485 AST_type_n_t *type_p, /* [in] Ptr to field/param data type */ 1486 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 1487) 1488{ 1489 unsigned short dim; /* Array dimension */ 1490 unsigned short max_dim; /* Maximum dimension */ 1491 1492 /* 1493 * Assume parser won't put field attribute node on non-arrays. 1494 * An array can be represented either in normal array syntax, 1495 * or as a pointer that has any of the array attributes. 1496 */ 1497 if (type_p->kind == AST_array_k) 1498 max_dim = type_p->type_structure.array->index_count; 1499 else 1500 max_dim = 1; /* Arrays in pointer form can only be 1-dimensional */ 1501 1502 /* [max_is,length_is] or [size_is,last_is] used together */ 1503 1504 if ( ((fattr_p->max_is_vec != NULL) && (fattr_p->length_is_vec != NULL)) 1505 || ((fattr_p->size_is_vec != NULL) && (fattr_p->last_is_vec != NULL))) 1506 CHECKER_warning(fattr_p, NIDL_MIXEDARRATTR); 1507 1508 fattr_switch_is(fattr_p, node_p, type_p); 1509 /* Check field attributes in each dimension of the array. */ 1510 1511 for (dim = 0 ; dim < max_dim ; dim++) 1512 { 1513 fattr_check_size(fattr_p, node_p, type_p, int_p, dim); 1514 fattr_first_is(fattr_p, node_p, dim); 1515 fattr_last_is(fattr_p, node_p, dim); 1516 fattr_length_is(fattr_p, node_p, dim); 1517 fattr_min_is(fattr_p, node_p, type_p, dim); 1518 fattr_max_is(fattr_p, node_p, type_p, dim); 1519 fattr_size_is(fattr_p, node_p, type_p, dim); 1520 } 1521} 1522 1523/* 1524** i n d e x _ c o n s t _ t y p e 1525** 1526** Checks an array index node's constant type. 1527*/ 1528 1529static void index_const_type 1530( 1531 AST_array_index_n_t *index_p /* [in] Ptr to AST array index node */ 1532) 1533{ 1534 /* Invalid array index type */ 1535 1536 if ((AST_FIXED_LOWER_SET(index_p) 1537 && !const_is_integer(index_p->lower_bound)) 1538 || 1539 (AST_FIXED_UPPER_SET(index_p) 1540 && !const_is_integer(index_p->upper_bound))) 1541 CHECKER_error(index_p, NIDL_INVARRIND); 1542} 1543 1544/* 1545** i n d e x _ b o u n d s 1546** 1547** Checks an array index node's bounds. 1548*/ 1549 1550static void index_bounds 1551( 1552 AST_array_index_n_t *index_p /* [in] Ptr to AST array index node */ 1553) 1554{ 1555 /* Lower bound must not be greater than upper bound */ 1556 1557 if (AST_FIXED_LOWER_SET(index_p) 1558 && AST_FIXED_UPPER_SET(index_p) 1559 && index_p->lower_bound->value.int_val 1560 > index_p->upper_bound->value.int_val) 1561 CHECKER_error(index_p, NIDL_LBLESSUB); 1562 1563 /* Arrays with a nonzero lower bound require -standard extended */ 1564 1565 if ( (!AST_FIXED_LOWER_SET(index_p) 1566 || index_p->lower_bound->value.int_val != 0) 1567 && (*(int *)cmd_val[opt_standard] <= opt_standard_dce_1_0) ) 1568 CHECKER_warning(index_p, NIDL_NOPORTNZLB, OPT_STD_EXTENDED); 1569} 1570 1571/* 1572** i n d e x _ c h e c k 1573** 1574** Checks an AST array index node. 1575*/ 1576 1577static void index_check 1578( 1579 AST_array_index_n_t *index_p /* [in] Ptr to AST array index node */ 1580) 1581{ 1582 index_const_type(index_p); 1583 index_bounds(index_p); 1584} 1585 1586/* 1587** a r r a y _ e l e m e n t _ t y p e 1588** 1589** Checks the data type of the elements of an array. 1590*/ 1591 1592static void array_element_type 1593( 1594 ASTP_node_t *node_p, /* [in] Ptr to array or pointer node */ 1595 AST_type_n_t *type_p, /* [in] Ptr to array elem type node */ 1596 AST_type_n_t *arr_type_p, /* [in] Ptr to array | ptr type node */ 1597 AST_interface_n_t *int_p, /* [in] Ptr to interface node */ 1598 boolean arrayified /* [in] true if arrayified pointer */ 1599) 1600{ 1601 AST_type_n_t *etype_p; /* Array element presented type */ 1602 1603 /* If the array element type is anonymous, it must undergo type checks. */ 1604 1605 if (type_is_anonymous(type_p)) 1606 type_check(type_p, (ASTP_node_t *)node_p, int_p); 1607 1608 etype_p = type_p; 1609 type_p = type_xmit_type(type_p); /* Pick up transmissible type */ 1610 1611 /* 1612 * Array elements cannot be conformant arrays or structures 1613 * Exceptions: Array elements types that are the target of a [transmit_as] 1614 * and have determinable size (i.e. either [string] or a struct). 1615 */ 1616 if (AST_CONFORMANT_SET(type_p) 1617 && !(etype_p != type_p && AST_STRING_SET(type_p)) 1618 && !(etype_p != type_p && type_p->kind == AST_structure_k) ) 1619 CHECKER_error(node_p, NIDL_ARRELEMCFMT); 1620 1621 /* Array elements cannot be pipes */ 1622 1623 if (type_p->kind == AST_pipe_k) 1624 CHECKER_error(node_p, NIDL_ARRELEMPIPE); 1625 1626 /* Array elements cannot be context handles */ 1627 1628 if (AST_CONTEXT_RD_SET(type_p)) 1629 CHECKER_error(node_p, NIDL_ARRELEMCTX); 1630 1631 /* Function pointers are not valid as elements of conformant arrays */ 1632 1633 if (!AST_LOCAL_SET(int_p) 1634 && type_is_function(type_p) 1635 && (AST_CONFORMANT_SET(arr_type_p) || arrayified)) 1636 CHECKER_error(node_p, NIDL_FPCFMTARR); 1637 1638 /* Array elements cannot be of type handle_t */ 1639 1640 if (!AST_LOCAL_SET(int_p) 1641 && type_p->kind == AST_handle_k) 1642#if 0 /** Obsolete **/ 1643 && type_p->xmit_as_type == NULL) 1644#endif 1645 CHECKER_error(node_p, NIDL_HANARRELEM); 1646 1647 /* void is valid only in an operation or pointer declaration */ 1648 1649 if (type_p->kind == AST_void_k) 1650 CHECKER_error(node_p, NIDL_VOIDOPPTR); 1651 1652 /* void * must be used in conjunction with the [context_handle] attribute */ 1653 1654 if (!AST_LOCAL_SET(int_p) 1655#if 0 /** Obsolete **/ 1656 && type_p->xmit_as_type == NULL 1657#endif 1658 && type_p->kind == AST_pointer_k 1659 && type_p->type_structure.pointer->pointee_type->kind == AST_void_k 1660 && !AST_CONTEXT_RD_SET(type_p) 1661 ) 1662 { 1663 CHECKER_error(node_p, NIDL_PTRVOIDCTX); 1664 } 1665 1666 /* The [ignore] attribute is not allowed on array elements */ 1667 1668 if (AST_IGNORE_SET(type_p)) 1669 CHECKER_error(node_p, NIDL_IGNARRELEM); 1670} 1671 1672/* 1673** a r r a y _ c h e c k 1674** 1675** Checks an array. Note that both array and pointer nodes can 1676** represent arrays. 1677*/ 1678 1679static void array_check 1680( 1681 ASTP_node_t *node_p, /* [in] Ptr to array or pointer node */ 1682 AST_type_n_t *arr_type_p, /* [in] Array or ptr type node */ 1683 ASTP_node_t *parent_p, /* [in] Parent of array or ptr type */ 1684 AST_type_n_t *type_p, /* [in] Ptr to array elem type node */ 1685 AST_interface_n_t *int_p, /* [in] Ptr to interface node */ 1686 boolean arrayified /* [in] true if arrayified pointer */ 1687) 1688{ 1689 unsigned short dim; /* Array dimension */ 1690 1691 /* Arrays with [transmit_as] can't be conformant or varying */ 1692 1693 if (arr_type_p->xmit_as_type != NULL 1694 && (AST_CONFORMANT_SET(arr_type_p) 1695 || (parent_p->fe_info->node_kind == fe_parameter_n_k 1696 && ((AST_parameter_n_t *)parent_p)->field_attrs != NULL) 1697 || (parent_p->fe_info->node_kind == fe_field_n_k 1698 && ((AST_field_n_t *)parent_p)->field_attrs != NULL))) 1699 CHECKER_error(parent_p, NIDL_ARRXMITOPEN); 1700 1701 array_element_type(node_p, type_p, arr_type_p, int_p, arrayified); 1702 1703 /* Arrays of non-encapsulated unions are not allowed */ 1704 1705 if (type_p->kind == AST_disc_union_k 1706 && type_p->type_structure.disc_union->discrim_name == NAMETABLE_NIL_ID) 1707 CHECKER_error(arr_type_p, NIDL_NEUARRAY); 1708 1709 /* Don't allow arrays of interfaces */ 1710 if (type_p->kind == AST_interface_k) { 1711 char const * id_name; 1712 NAMETABLE_id_to_string(type_p->name, &id_name); 1713 CHECKER_error(arr_type_p, NIDL_INTREFNOTALO, id_name); 1714 } 1715 1716 /* 1717 * If the array is represented in array (as opposed to pointer) syntax, 1718 * then check the indices of each dimension of the array. 1719 */ 1720 if (node_p->fe_info->node_kind == fe_array_n_k) 1721 { 1722 AST_array_n_t *array_p; /* Ptr to array node */ 1723 1724 array_p = (AST_array_n_t *)node_p; 1725 1726 for (dim = 0 1727 ; dim < array_p->index_count 1728 ; dim++) 1729 index_check(&array_p->index_vec[dim]); 1730 } 1731} 1732 1733/* 1734** p a r a m _ t y p e 1735** 1736** Checks an parameter node's data type. 1737*/ 1738 1739static void param_type 1740( 1741 AST_parameter_n_t *param_p, /* [in] Ptr to AST parameter node */ 1742 AST_type_n_t *top_type_p, /* [in] Top-level parameter type */ 1743 AST_type_n_t *type_p, /* [in] Parameter type */ 1744 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 1745) 1746{ 1747#if 0 1748 AST_type_n_t *btype_p; /* Base type */ 1749 1750 /* 1751 * First, special case checks that do want to look at a toplevel [ref] 1752 * pointer (most look through this pointer). 1753 */ 1754 1755 /* Cannot have more than one level of indirection to a ne union */ 1756 1757 btype_p = ASTP_chase_ptr_to_kind(top_type_p, AST_disc_union_k); 1758 1759 if (btype_p != NULL 1760 && btype_p->kind == AST_disc_union_k 1761 && btype_p->type_structure.disc_union->discrim_name == NAMETABLE_NIL_ID 1762 && btype_p->fe_info->pointer_count > 1) 1763 CHECKER_error(top_type_p, NIDL_PTRNEUNION); 1764#endif 1765 1766 /* 1767 * If the parameter type is anonymous, it must undergo type checks. 1768 * Note that the passed type_p is the dereferenced parameter type if 1769 * pass-by-reference mechanism was implied; i.e. top-level *'s that 1770 * indicate pass-by-reference and are not arrays are not type-checked. 1771 */ 1772 if (type_is_anonymous(type_p)) 1773 type_check(type_p, (ASTP_node_t *)param_p, int_p); 1774 1775 type_p = type_xmit_type(type_p); /* Pick up transmissible type */ 1776 1777 /* void is valid only in an operation or pointer declaration */ 1778 1779 if (type_p->kind == AST_void_k 1780 && param_p != param_p->uplink->result) /* Not the result param */ 1781 CHECKER_error(param_p, NIDL_VOIDOPPTR); 1782 1783 /* void * must be used in conjunction with the [context_handle] attr */ 1784 1785 if (!AST_LOCAL_SET(int_p) 1786 && type_p->xmit_as_type == NULL /* Allow if void* is NOT transmitted */ 1787 && type_p->kind == AST_pointer_k 1788 && type_p->type_structure.pointer->pointee_type->kind == AST_void_k 1789 && !AST_CONTEXT_RD_SET(type_p) 1790 && !AST_CONTEXT_SET(param_p) 1791 && !AST_LOCAL_SET(param_p->uplink) 1792 ) 1793 CHECKER_error(param_p, NIDL_PTRVOIDCTX); 1794 1795 /* A type with [transmit_as] may not have other type attributes */ 1796 1797 if (top_type_p->xmit_as_type != NULL 1798 && 1799 (AST_STRING_SET(param_p) 1800 || AST_STRING0_SET(param_p) 1801 || AST_UNIQUE_SET(param_p) 1802 || AST_SMALL_SET(param_p) 1803 || AST_CONTEXT_SET(param_p) 1804 )) 1805 CHECKER_error(param_p, NIDL_XMITTYPEATTRS); 1806 1807 /* 1808 * V1 attributes are incompatible with this type 1809 * Note: Issue error only if the same error doesn't fire for the type. 1810 */ 1811 if (FE_TEST(param_p->fe_info->flags, FE_HAS_V1_ATTR) 1812 && FE_TEST(param_p->fe_info->flags, FE_HAS_V2_ATTR) 1813 && ! ( FE_TEST(type_p->fe_info->flags, FE_HAS_V1_ATTR) 1814 && FE_TEST(type_p->fe_info->flags, FE_HAS_V2_ATTR) )) 1815 CHECKER_warning(param_p, NIDL_INCOMPATV1); 1816 1817 /* Array function results are not allowed */ 1818 1819 if (type_p->kind == AST_array_k 1820 && param_p == param_p->uplink->result) 1821 CHECKER_error(param_p, NIDL_ARRFUNRES); 1822} 1823 1824/* 1825** p a r a m _ s i z e 1826** 1827** Checks an parameter node to see if array size information is required. 1828*/ 1829 1830static void param_size 1831( 1832 AST_parameter_n_t *param_p, /* [in] Ptr to AST parameter node */ 1833 AST_type_n_t *top_type_p, /* [in] Top-level parameter type */ 1834 AST_type_n_t *type_p, /* [in] Parameter type */ 1835 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 1836) 1837{ 1838 AST_field_attr_n_t *fattr_p; /* Field attributes */ 1839 1840 fattr_p = param_p->field_attrs; 1841 1842 /* Array size information required */ 1843 1844 if (!AST_LOCAL_SET(int_p) 1845 && type_p->xmit_as_type == NULL 1846 && fattr_p == NULL 1847 && type_is_array(type_p) 1848 && (AST_CONFORMANT_SET(type_p) 1849 || AST_VARYING_SET(param_p)) 1850 && !AST_STRING_SET(type_p) /* [string] cases handled below */ 1851 && !AST_STRING_SET(param_p)) 1852 { 1853 char const *id_name; 1854 1855 NAMETABLE_id_to_string(param_p->name, &id_name); 1856 CHECKER_error(param_p, NIDL_ARRSIZEINFO, id_name); 1857 } 1858 1859 /* 1860 * Array size information required on conformant [string] arrays only 1861 * if an [out]-only parameter; otherwise, size is implicitly determined 1862 * by the length of the string. Size info is not required for a [ptr] 1863 * char * string (which includes an operation result char * string) 1864 * or a [unique] char * string. 1865 */ 1866 if (!AST_LOCAL_SET(int_p) 1867 && type_p->xmit_as_type == NULL 1868 && fattr_p == NULL 1869 && ( (type_p->kind == AST_array_k 1870 && AST_CONFORMANT_SET(type_p)) 1871 || (type_p->kind == AST_pointer_k 1872 && param_p->uplink->result != param_p /* not op result */ 1873 && !AST_PTR_SET(type_p) && !AST_UNIQUE_SET(type_p)) ) 1874 && (AST_STRING_SET(type_p) || AST_STRING_SET(param_p)) 1875 && !AST_IN_SET(param_p)) 1876 { 1877 char const *id_name; 1878 1879 NAMETABLE_id_to_string(param_p->name, &id_name); 1880 CHECKER_error(param_p, NIDL_ARRSIZEINFO, id_name); 1881 } 1882 1883 /* A [string] array can not have varying array attributes */ 1884 1885 if (!AST_LOCAL_SET(int_p) 1886 && type_p->xmit_as_type == NULL 1887 && AST_STRING_SET(param_p) 1888 && fattr_p != NULL 1889 && (fattr_p->first_is_vec != NULL 1890 || fattr_p->last_is_vec != NULL 1891 || fattr_p->length_is_vec != NULL)) 1892 CHECKER_error(param_p, NIDL_STRVARY); 1893 1894 /* Arrays with [transmit_as] can't be conformant or varying */ 1895 1896 if (type_p->xmit_as_type != NULL 1897 && fattr_p != NULL) 1898 CHECKER_error(param_p, NIDL_ARRXMITOPEN); 1899 1900 /* 1901 * Current rules allow mixed open array [] and pointer * syntax ONLY 1902 * of the form *..*param[][N]..[N], i.e. when param is a [multidimensional] 1903 * array of pointers (that, currently, can be conformant or varying in the 1904 * first dimension only). Pointers to open arrays are not allowed due to 1905 * the ambiguity as to which * or [] the array size attributes apply to. 1906 * 1907 * Builder only allows one open array dimension when pointer and array 1908 * syntax is mixed. It will detect errors on such examples as: 1909 * [in, size_is(s1,s2)] long (*param)[] 1910 * 1911 * A corollary is that in declarations with more than one * and no [] or 1912 * [N], array size information applies to the rightmost * only. 1913 * Builder will detect errors on such examples as: 1914 * [in, size_is(s1,s2)] long **param 1915 * 1916 * Checker detects these 3 cases separately: 1917 * [in, size_is(s)] long (*..*param)[N]..[N] ARRSYNTAX 1918 * [in, size_is(s)] long (*..*param)[][N]..[N] PTRCFMTARR 1919 * [in, length_is(l)] long (*..*param)[N]..[N] PTRVARYARR 1920 */ 1921 if (top_type_p->kind == AST_pointer_k) 1922 { 1923 AST_type_n_t *ref_type_p; /* Pointee data type */ 1924 1925 ref_type_p = ASTP_chase_ptr_to_type(top_type_p); 1926 1927 /* Use array syntax to declare multidimensional arrays */ 1928 1929 if (ref_type_p->kind == AST_array_k 1930 && !AST_CONFORMANT_SET(ref_type_p) 1931 && fattr_p != NULL 1932 && (fattr_p->min_is_vec != NULL 1933 || fattr_p->max_is_vec != NULL 1934 || fattr_p->size_is_vec != NULL)) 1935 CHECKER_error(param_p, NIDL_ARRSYNTAX); 1936 1937 /* Pointers to conformant arrays are not allowed */ 1938 1939 /* 1940 * Can't just check for conformant set since a string can be conformant 1941 * and not require size attributes; a ptr to such a string is legal. 1942 */ 1943 if (ref_type_p->kind == AST_array_k 1944 && AST_CONFORMANT_SET(ref_type_p) 1945 && (!AST_STRING_SET(ref_type_p) 1946 || (fattr_p != NULL 1947 && (fattr_p->min_is_vec != NULL 1948 || fattr_p->max_is_vec != NULL 1949 || fattr_p->size_is_vec != NULL)))) 1950 { 1951 CHECKER_error(param_p, NIDL_PTRCFMTARR); 1952 return; /* Return with no further checking */ 1953 } 1954 1955 /* Pointers to varying arrays are not allowed */ 1956 1957 /* 1958 * Can't just check for varying set since a string is implicitly vary- 1959 * ing and cannot have length attrs; a ptr to such a string is legal. 1960 */ 1961 if (ref_type_p->kind == AST_array_k 1962 && fattr_p != NULL 1963 && (fattr_p->first_is_vec != NULL 1964 || fattr_p->last_is_vec != NULL 1965 || fattr_p->length_is_vec != NULL)) 1966 { 1967 CHECKER_error(param_p, NIDL_PTRVARYARR); 1968 return; /* Return with no further checking */ 1969 } 1970 } 1971 1972 /* An [out] conformant array must be a top-level param or under a full pointer */ 1973 1974 /* 1975 * Note that this check covers any [out] conformant array below top-level 1976 * that is not under a full pointer. Top-level [out] conformant arrays 1977 * are handled by the ARRSIZEINFO and *INATTR checks. 1978 */ 1979 if (!AST_LOCAL_SET(int_p) 1980 && param_p->type->xmit_as_type == NULL 1981 && !AST_IN_SET(param_p) 1982 && FE_TEST(param_p->fe_info->flags, FE_HAS_CFMT_ARR)) 1983 CHECKER_error(param_p, NIDL_OUTCFMTARR); 1984} 1985 1986/* 1987** p a r a m _ s t r u c t 1988** 1989** Checks a parameter node - structure specific checks. 1990*/ 1991 1992static void param_struct 1993( 1994 AST_parameter_n_t *param_p, /* [in] Ptr to AST parameter node */ 1995 AST_type_n_t *top_type_p, /* [in] Top-level parameter type */ 1996 AST_type_n_t *type_p /* [in] Parameter type */ 1997) 1998{ 1999 type_p = type_xmit_type(type_p); /* Pick up transmissible type */ 2000 2001 /* All checks below assume that parameter data type is structure. */ 2002 2003 if (type_p->kind != AST_structure_k) 2004 return; 2005 2006 /* Structures containing conformant arrays must be passed by reference */ 2007 2008 if (!AST_OUT_SET(param_p) 2009 && top_type_p->kind != AST_pointer_k 2010 && AST_CONFORMANT_SET(type_p)) 2011 CHECKER_error(param_p, NIDL_CFMTARRREF); 2012} 2013 2014/* 2015** p a r a m _ p i p e 2016** 2017** Checks a parameter node - pipe specific checks. 2018*/ 2019 2020static void param_pipe 2021( 2022 AST_parameter_n_t *param_p, /* [in] Ptr to AST parameter node */ 2023 AST_type_n_t *top_type_p ATTRIBUTE_UNUSED, /* [in] Top-level parameter type */ 2024 AST_type_n_t *type_p /* [in] Parameter type */ 2025) 2026{ 2027 type_p = type_xmit_type(type_p); /* Pick up transmissible type */ 2028 2029 /* [ptr] attribute not valid on pipe parameters */ 2030 2031 if (type_p->kind == AST_pipe_k 2032 && AST_PTR_SET(param_p)) 2033 CHECKER_error(param_p, NIDL_PTRPIPE); 2034 2035 /* Operation result may not be a pipe */ 2036 2037 if (param_p == param_p->uplink->result 2038 && type_p->kind == AST_pipe_k) 2039 CHECKER_error(param_p, NIDL_OPRESPIPE); 2040} 2041 2042/* 2043** p a r a m _ i n _ l i n e 2044** 2045** Checks an parameter node's [in_line] and [out_of_line] attributes. 2046*/ 2047 2048static void param_in_line 2049( 2050 AST_parameter_n_t *param_p, /* [in] Ptr to AST parameter node */ 2051 AST_type_n_t *type_p /* [in] Parameter type */ 2052) 2053{ 2054 /* Can't have both [in_line] and [out_of_line] parameter attributes */ 2055 2056 if (AST_IN_LINE_SET(param_p) 2057 && AST_OUT_OF_LINE_SET(param_p)) 2058 CHECKER_acf_error(param_p, NIDL_PRMLINEATTR); 2059 2060 /* [in_line] and [out_of_line] attributes apply only to non-scalar types */ 2061 2062 if ((AST_IN_LINE_SET(param_p) || AST_OUT_OF_LINE_SET(param_p)) 2063 && type_is_scalar(type_p)) 2064 { 2065 char const *file_name; /* Related file name */ 2066 char const *type_name; /* Data type name */ 2067 2068 STRTAB_str_to_string(type_p->fe_info->file, &file_name); 2069 NAMETABLE_id_to_string(type_p->name, &type_name); 2070 2071 CHECKER_acf_warning(param_p, NIDL_LINENONSCAL); 2072 CHECKER_acf_warning(param_p, NIDL_NAMEDECLAT, type_name, file_name, 2073 type_p->fe_info->source_line); 2074 } 2075} 2076 2077/* 2078** p a r a m _ s t r i n g 2079** 2080** Checks an parameter node's [string] and [v1_string] attributes. 2081*/ 2082 2083static void param_string 2084( 2085 AST_parameter_n_t *param_p, /* [in] Ptr to AST parameter node */ 2086 AST_type_n_t *type_p /* [in] Parameter type */ 2087) 2088{ 2089 /* A [v1_string] must be an array of char with fixed bounds */ 2090 2091 if (AST_STRING0_SET(param_p) 2092 && !type_is_v1_string(type_p)) 2093 CHECKER_error(param_p, NIDL_STRV1FIXED); 2094 2095 /* The [v1_string] attribute can only be applied to a [v1_array] */ 2096 2097 if ((AST_STRING0_SET(param_p) || AST_STRING0_SET(type_p)) 2098 && !(AST_SMALL_SET(param_p) || AST_SMALL_SET(type_p))) 2099 CHECKER_error(param_p, NIDL_STRV1ARRAY); 2100 2101 /* The [string] attribute cannot be applied to a [v1_array] */ 2102 2103 if ((AST_STRING_SET(param_p) && AST_SMALL_SET(param_p)) 2104 || (AST_STRING_SET(param_p) && AST_SMALL_SET(type_p)) 2105 || (AST_STRING_SET(type_p) && AST_SMALL_SET(param_p))) 2106 CHECKER_error(param_p, NIDL_STRARRAYV1); 2107 2108 /* Cannot have both [string] and [v1_string] attributes */ 2109 2110 if ( (AST_STRING_SET(param_p) || AST_STRING_SET(type_p)) 2111 && (AST_STRING0_SET(param_p) || AST_STRING0_SET(type_p)) ) 2112 { 2113 ASTP_attr_flag_t attr1 = ASTP_STRING; 2114 ASTP_attr_flag_t attr2 = ASTP_STRING0; 2115 2116 CHECKER_error(param_p, NIDL_CONFLICTATTR, 2117 KEYWORDS_lookup_text(AST_attribute_to_token(&attr1)), 2118 KEYWORDS_lookup_text(AST_attribute_to_token(&attr2))); 2119 } 2120 2121 /* 2122 * Forgo last check if the declaration is a pointer to an array and either 2123 * (the declaration has size attributes) or (the array is conformant and 2124 * not a string), since mixed pointer and array declarations that either 2125 * have or require array size attributes are disallowed by other checks. 2126 */ 2127 if (type_p->kind == AST_pointer_k) 2128 { 2129 AST_type_n_t *ref_type_p; /* Pointee data type */ 2130 2131 ref_type_p = ASTP_chase_ptr_to_type(type_p); 2132 if (ref_type_p->kind == AST_array_k 2133 && (param_p->field_attrs != NULL 2134 || (AST_CONFORMANT_SET(ref_type_p) 2135 && !AST_STRING_SET(ref_type_p)))) 2136 return; 2137 } 2138 2139 /* [string] attribute valid only for one-dim arrays of char or byte */ 2140 2141 if (AST_STRING_SET(param_p) 2142 && !type_is_string(param_p->type)) 2143 CHECKER_error(param_p, NIDL_STRCHARBYTE); 2144} 2145 2146/* 2147** p a r a m _ p o i n t e r 2148** 2149** Checks an parameter node's attributes related to pointers. 2150*/ 2151 2152static void param_pointer 2153( 2154 AST_parameter_n_t *param_p, /* [in] Ptr to AST parameter node */ 2155 AST_type_n_t *top_type_p, /* [in] Top-level parameter type */ 2156 AST_type_n_t *type_p, /* [in] Parameter type */ 2157 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 2158) 2159{ 2160 boolean pointer_attr_valid = FALSE; 2161 2162 /* 2163 * The AST Builder catches these errors on param ptr attributes: 2164 * [ref] parameter requires explicit top-level '*' 2165 * [ptr] parameter requires explicit top-level '*' 2166 * [unique] parameter requires explicit top-level '*' 2167 */ 2168 2169 /* [out,ptr] parameters are not allowed */ 2170 2171 if (AST_OUT_SET(param_p) 2172 && !AST_IN_SET(param_p) 2173 && AST_PTR_SET(param_p) 2174 && param_p->uplink->result != param_p) /* Not the result param */ 2175 CHECKER_error(param_p, NIDL_OUTPTRPRM); 2176 2177 /* [out,unique] parameters are not allowed */ 2178 2179 if (AST_OUT_SET(param_p) 2180 && !AST_IN_SET(param_p) 2181 && AST_UNIQUE_SET(param_p) 2182 && param_p->uplink->result != param_p) /* Not the result param */ 2183 CHECKER_error(param_p, NIDL_OUTUNIQPRM); 2184 2185 /* [ref] function results are not valid */ 2186 2187 if (param_p->uplink->result == param_p /* IS the result param */ 2188 && AST_REF_SET(param_p)) 2189 CHECKER_error(param_p, NIDL_REFFUNRES); 2190 2191 /* [unique] function results are not valid */ 2192 2193 if (param_p->uplink->result == param_p /* IS the result param */ 2194 && AST_UNIQUE_SET(param_p)) 2195 CHECKER_error(param_p, NIDL_UNIQFUNRES); 2196 2197 if (top_type_p->kind == AST_array_k 2198 || (top_type_p->kind == AST_pointer_k 2199 && top_type_p->type_structure.pointer->pointee_type->kind 2200 != AST_void_k)) 2201 pointer_attr_valid = TRUE; 2202 2203 /* [ref] attribute valid only for pointer or array types */ 2204 2205 if (AST_REF_SET(param_p) && !pointer_attr_valid) 2206 CHECKER_error(param_p, NIDL_REFATTRPTR); 2207 2208 /* [unique] attribute valid only for pointer or array types */ 2209 2210 if (AST_UNIQUE_SET(param_p) && !pointer_attr_valid) 2211 CHECKER_error(param_p, NIDL_UNIQATTRPTR); 2212 2213 /* [ptr] attribute valid only for pointer or array types */ 2214 2215 if (AST_PTR_SET(param_p) && !pointer_attr_valid) 2216 CHECKER_error(param_p, NIDL_PTRATTRPTR); 2217 2218 /* [unique] attribute requires -standard extended */ 2219 2220 if (AST_UNIQUE_SET(param_p) 2221 && (*(int *)cmd_val[opt_standard] <= opt_standard_dce_1_0)) 2222 CHECKER_warning(param_p, NIDL_NOPORTUNIQUE, OPT_STD_EXTENDED); 2223 2224#if 0 2225 /* if the parameter is a pointer to an interface, then it should ignore 2226 * the pointer attributes REF, UNIQUE or PTR */ 2227 if (top_type_p->kind == AST_pointer_k && type_p->kind == AST_interface_k 2228 && AST_REF_SET(param_p)) 2229 CHECKER_warning(param_p, NIDL_PTRATTBIGN); 2230 if (type_p->kind == AST_pointer_k && type_p->type_structure.pointer->pointee_type->kind == AST_interface_k 2231 && (AST_UNIQUE_SET(param_p) || AST_PTR_SET(param_p))) 2232 CHECKER_warning(param_p, NIDL_PTRATTBIGN); 2233#endif 2234 2235 /* 2236 * If the parameter is a pointer, and it is not a pointer to an array, 2237 * and it has any of the array attributes, then it is an arrayified 2238 * pointer and it must undergo the checks for arrays. 2239 */ 2240 if (type_p->kind == AST_pointer_k 2241 && type_p->type_structure.pointer->pointee_type->kind != AST_array_k 2242#if 0 2243 && (param_p->field_attrs != NULL 2244#endif 2245 && (instance_has_array_attr(param_p) 2246 || AST_STRING_SET(type_p) 2247 || AST_STRING_SET(param_p))) 2248 { 2249 array_check((ASTP_node_t *)type_p->type_structure.pointer, 2250 type_p, 2251 (ASTP_node_t *)param_p, 2252 type_p->type_structure.pointer->pointee_type, 2253 int_p, 2254 true); 2255 2256 /* <7810113> [in, out,unique] parameters are not allowed for arrays */ 2257 if (AST_OUT_SET(param_p) 2258 && AST_IN_SET(param_p) 2259 && AST_UNIQUE_SET(param_p) 2260 && param_p->uplink->result != param_p) /* Not the result param */ 2261 CHECKER_error(param_p, NIDL_OUTUNIQPRM); 2262 } 2263} 2264 2265/* 2266** p a r a m _ s m a l l 2267** 2268** Checks an parameter node's [v1_array] attribute. 2269*/ 2270 2271static void param_small 2272( 2273 AST_parameter_n_t *param_p, /* [in] Ptr to AST parameter node */ 2274 AST_type_n_t *top_type_p, /* [in] Top-level parameter type */ 2275 AST_type_n_t *type_p /* [in] Parameter type */ 2276) 2277{ 2278 AST_array_n_t *array_p; /* Ptr to array node */ 2279 AST_field_attr_n_t *fattr_p; /* Ptr to field attribute node */ 2280 2281 /* A [v1_array] must be in array, not pointer, syntax */ 2282 2283 if (AST_SMALL_SET(param_p) 2284 && (type_p->kind == AST_pointer_k 2285 || top_type_p->kind == AST_pointer_k)) 2286 CHECKER_error(param_p, NIDL_SMALLARRSYN); 2287 2288 /* 2289 * Remaining checks only apply to array types in array syntax. 2290 * V1 did not allow arrays in pointer syntax. 2291 */ 2292 if (!type_is_array_np(type_p)) 2293 return; 2294 2295 fattr_p = param_p->field_attrs; 2296 array_p = type_p->type_structure.array; 2297 2298 /* A [v1_array] can be conformant or varying in the first dimension only */ 2299 2300 if (AST_SMALL_SET(param_p) 2301 && ((AST_CONFORMANT_SET(type_p) 2302 && array_is_conformant_upper(array_p)) 2303 || 2304 (AST_VARYING_SET(param_p) 2305 && instance_is_varying_upper(array_p, param_p->field_attrs)))) 2306 CHECKER_error(param_p, NIDL_SMALLMULTID); 2307 2308 /* [v1_array] attribute invalid for array with more than 65535 elements */ 2309 2310 if (AST_SMALL_SET(param_p) 2311 && array_is_large(array_p)) 2312 CHECKER_error(param_p, NIDL_SMALLINV); 2313 2314 /* A conformant [v1_array] must also be varying */ 2315 2316 if ((AST_SMALL_SET(type_p) || AST_SMALL_SET(param_p)) 2317 && AST_CONFORMANT_SET(type_p) 2318 && !AST_VARYING_SET(param_p)) 2319 CHECKER_error(param_p, NIDL_SMALLCFMT); 2320 2321 /* A [v1_array] can not have the [min_is] or [first_is] attributes */ 2322 2323 if ((AST_SMALL_SET(type_p) || AST_SMALL_SET(param_p)) 2324 && fattr_p != NULL 2325 && (fattr_p->min_is_vec != NULL 2326 || fattr_p->first_is_vec != NULL)) 2327 CHECKER_error(param_p, NIDL_SMALLMINFIRST); 2328} 2329 2330/* 2331** p a r a m _ c o n t e x t 2332** 2333** Checks an parameter node's [context_handle] attribute. 2334*/ 2335 2336static void param_context 2337( 2338 AST_parameter_n_t *param_p, /* [in] Ptr to AST parameter node */ 2339 AST_type_n_t *top_type_p, /* [in] Top-level parameter type */ 2340 AST_type_n_t *type_p /* [in] Parameter type */ 2341) 2342{ 2343 AST_type_n_t *deref_type_p; /* Explicit pointer's pointee type */ 2344 boolean type_is_pointer;/* Type is real pointer, not void* */ 2345 2346 deref_type_p = param_follow_ref_ptr(param_p, CHK_follow_any); 2347 /* 2348 * Special case code to follow an operation result pointer. This allows 2349 * us to catch and disallow pointer to context handle operation results. 2350 */ 2351 if (param_p->uplink->result == param_p 2352 && type_p->kind == AST_pointer_k 2353 && type_p->type_structure.pointer->pointee_type->kind != AST_void_k) 2354 deref_type_p = type_p->type_structure.pointer->pointee_type; 2355 2356 /* [context_handle] attribute only applies to void * types */ 2357 2358 if (AST_CONTEXT_SET(param_p) 2359 && !AST_CONTEXT_RD_SET(type_p) /* no error if already done for type */ 2360 && (deref_type_p->kind != AST_pointer_k 2361 || (deref_type_p->kind == AST_pointer_k 2362 && deref_type_p->type_structure.pointer->pointee_type->kind 2363 != AST_void_k))) 2364 CHECKER_error(param_p, NIDL_CTXPTRVOID); 2365 2366 type_is_pointer = (deref_type_p != top_type_p); 2367 2368 /* [unique] pointers to context handles are not allowed */ 2369 2370 if (type_is_pointer 2371 && (AST_CONTEXT_SET(param_p) || AST_CONTEXT_RD_SET(deref_type_p)) 2372 && AST_UNIQUE_SET(param_p)) 2373 CHECKER_error(param_p, NIDL_UNIQCTXHAN); 2374 2375 /* Full pointers to context handles are not allowed */ 2376 2377 if (type_is_pointer 2378 && (AST_CONTEXT_SET(param_p) || AST_CONTEXT_RD_SET(deref_type_p)) 2379 && AST_PTR_SET(param_p) 2380 && deref_type_p->kind != AST_structure_k) /* opaque ctx handle */ 2381 CHECKER_error(param_p, NIDL_PTRCTXHAN); 2382} 2383 2384/* 2385** p a r a m _ v a r y i n g 2386** 2387** Checks an parameter node's "varying" (synthesized) attribute. 2388*/ 2389 2390static void param_varying 2391( 2392 AST_parameter_n_t *param_p, /* [in] Ptr to AST parameter node */ 2393 AST_type_n_t *type_p, /* [in] Parameter type */ 2394 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 2395) 2396{ 2397 /* 2398 * Assume that if the varying attribute is set, the parameter is an 2399 * array type and the field_attrs field is valid. An array can be 2400 * represented either in normal array syntax, or as a pointer that 2401 * has any of the array attributes. 2402 */ 2403 if (type_p->kind != AST_array_k) 2404 return; /* All checks below assume normal array syntax */ 2405 2406 /* Arrays varying in other than the first dim require -standard extended */ 2407 2408 if (!AST_LOCAL_SET(int_p) 2409 && type_p->xmit_as_type == NULL 2410 && AST_VARYING_SET(param_p) 2411 && instance_is_varying_upper(type_p->type_structure.array, 2412 param_p->field_attrs) 2413 && (*(int *)cmd_val[opt_standard] <= opt_standard_dce_1_0)) 2414 CHECKER_warning(param_p, NIDL_NOPORTVARY, OPT_STD_EXTENDED); 2415} 2416 2417/* 2418** p a r a m _ d i r e c t i o n 2419** 2420** Checks an parameter node's [in] and [out] attributes. 2421*/ 2422 2423static void param_direction 2424( 2425 AST_parameter_n_t *param_p, /* [in] Ptr to AST parameter node */ 2426 AST_type_n_t *top_type_p, /* [in] Top-level parameter type */ 2427 AST_type_n_t *type_p, /* [in] Parameter type */ 2428 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 2429) 2430{ 2431 type_p = type_xmit_type(type_p); /* Pick up transmissible type */ 2432 2433 /* Parameter must have a least one of [in] and [out] attributes */ 2434 2435 if (type_p->kind != AST_void_k 2436 && !AST_LOCAL_SET(int_p) 2437 && !AST_IN_SET(param_p) 2438 && !AST_OUT_SET(param_p)) 2439 CHECKER_error(param_p, NIDL_PRMINOROUT); 2440 2441 /* [out] parameters must be passed by reference */ 2442 2443 if (AST_OUT_SET(param_p) 2444 && top_type_p->kind != AST_array_k /* Arrays are implicitly by ref */ 2445 && param_p->uplink->result != param_p /* Not the result param */ 2446 && ((top_type_p->kind != AST_pointer_k 2447 && top_type_p->kind != AST_pipe_k) /* Pipes an exception */ 2448 || (top_type_p->kind == AST_pointer_k /* void * is special */ 2449 && top_type_p->type_structure.pointer->pointee_type->kind 2450 == AST_void_k) 2451 || (top_type_p->kind == AST_pointer_k 2452 && top_type_p->type_structure.pointer->pointee_type->kind == AST_interface_k) 2453 )) 2454 CHECKER_error(param_p, NIDL_OUTPRMREF); 2455 2456 /* [out] parameter requires explicit top-level '*' */ 2457 2458 if (!AST_LOCAL_SET(int_p) 2459 && AST_OUT_SET(param_p) 2460 && param_p->uplink->result != param_p /* Not the result param */ 2461 && top_type_p->kind == AST_pointer_k 2462 && top_type_p->type_structure.pointer->pointee_type->kind 2463 != AST_function_k /* Func ptrs an exception */ 2464 && top_type_p->name != NAMETABLE_NIL_ID) 2465 CHECKER_error(param_p, NIDL_OUTSTAR); 2466 2467 /* Function pointer parameters can only be [in] parameters */ 2468 2469 if (AST_OUT_SET(param_p) 2470 && type_p->kind == AST_pointer_k 2471 && type_p->type_structure.pointer->pointee_type->kind 2472 == AST_function_k) 2473 CHECKER_error(param_p, NIDL_FPINPRM); 2474 2475 /* [in(shape)] is not yet supported */ 2476 2477 if (AST_IN_SHAPE_SET(param_p)) 2478 CHECKER_error(param_p, NIDL_NYSINSHAPE); 2479 2480 /* [out(shape)] is not yet supported */ 2481 2482 if (AST_OUT_SHAPE_SET(param_p)) 2483 CHECKER_error(param_p, NIDL_NYSOUTSHAPE); 2484 2485 if (type_p->kind == AST_pointer_k) 2486 type_p = ASTP_chase_ptr_to_kind(type_p, AST_disc_union_k); 2487 2488 /* An [in] or [in,out] union must have an [in] discriminator */ 2489 2490 if (AST_IN_SET(param_p) 2491 && type_p != NULL 2492 && type_p->kind == AST_disc_union_k 2493 && type_p->type_structure.disc_union->discrim_name == NAMETABLE_NIL_ID 2494 && param_p->field_attrs != NULL 2495 && param_p->field_attrs->switch_is != NULL 2496 && !AST_IN_SET(param_p->field_attrs->switch_is->ref.p_ref)) 2497 CHECKER_error(param_p, NIDL_DISCRIMIN); 2498 2499 /* An [in,out] or [out] union must have an [out] discriminator */ 2500 2501#if 0 2502 if (AST_OUT_SET(param_p) 2503 && type_p != NULL 2504 && type_p->kind == AST_disc_union_k 2505 && type_p->type_structure.disc_union->discrim_name == NAMETABLE_NIL_ID 2506 && param_p->field_attrs != NULL 2507 && param_p->field_attrs->switch_is != NULL 2508 && !AST_OUT_SET(param_p->field_attrs->switch_is->ref.p_ref)) 2509 CHECKER_error(param_p, NIDL_DISCRIMOUT); 2510#endif 2511 2512} 2513 2514/* 2515** p a r a m _ c o m m _ s t a t u s 2516** 2517** Checks an parameter node's [comm_status] attribute. 2518*/ 2519 2520static void param_comm_status 2521( 2522 AST_parameter_n_t *param_p, /* [in] Ptr to AST parameter node */ 2523 AST_type_n_t *type_p /* [in] Parameter type */ 2524) 2525{ 2526 char const *type_name; /* Data type name */ 2527 2528 /* [comm_status] parameter must be an [out] parameter */ 2529 2530 if (AST_COMM_STATUS_SET(param_p) 2531 && param_p != param_p->uplink->result /* Op result special cased */ 2532 && !AST_OUT_SET(param_p)) 2533 CHECKER_error(param_p, NIDL_STSPRMOUT, 2534 acf_keyword_lookup(COMM_STATUS_KW)); 2535 2536 /* [fault_status] parameter must be an [out] parameter */ 2537 2538 if (AST_FAULT_STATUS_SET(param_p) 2539 && param_p != param_p->uplink->result /* Op result special cased */ 2540 && !AST_OUT_SET(param_p)) 2541 CHECKER_error(param_p, NIDL_STSPRMOUT, 2542 acf_keyword_lookup(FAULT_STATUS_KW)); 2543 2544 /* Chase type down to base named type. */ 2545 2546 while (type_p->defined_as != NULL) 2547 type_p = type_p->defined_as; 2548 NAMETABLE_id_to_string(type_p->name, &type_name); 2549 2550 /* [comm_status] parameter must be of type error_status_t */ 2551 2552 if (AST_COMM_STATUS_SET(param_p) 2553 && param_p != param_p->uplink->result /* Op result special cased */ 2554 && strcmp(type_name, "error_status_t") != 0) 2555 CHECKER_error(param_p, NIDL_STSVARTYPE, 2556 acf_keyword_lookup(COMM_STATUS_KW)); 2557 2558 /* [fault_status] parameter must be of type error_status_t */ 2559 2560 if (AST_FAULT_STATUS_SET(param_p) 2561 && param_p != param_p->uplink->result /* Op result special cased */ 2562 && strcmp(type_name, "error_status_t") != 0) 2563 CHECKER_error(param_p, NIDL_STSVARTYPE, 2564 acf_keyword_lookup(FAULT_STATUS_KW)); 2565 2566 /* A [comm_status] operation must return a value of type error_status_t */ 2567 2568 if (AST_COMM_STATUS_SET(param_p) 2569 && param_p == param_p->uplink->result /* The operation result */ 2570 && strcmp(type_name, "error_status_t") != 0) 2571 CHECKER_error(param_p->uplink, NIDL_STSRETVAL, 2572 acf_keyword_lookup(COMM_STATUS_KW)); 2573 2574 /* A [fault_status] operation must return a value of type error_status_t */ 2575 2576 if (AST_FAULT_STATUS_SET(param_p) 2577 && param_p == param_p->uplink->result /* The operation result */ 2578 && strcmp(type_name, "error_status_t") != 0) 2579 CHECKER_error(param_p->uplink, NIDL_STSRETVAL, 2580 acf_keyword_lookup(FAULT_STATUS_KW)); 2581} 2582static void param_switch_is 2583( 2584 AST_parameter_n_t *param_p, /* [in] Ptr to AST parameter node */ 2585 AST_type_n_t *type_p /* [in] Parameter type */ 2586) 2587{ 2588 if (type_p->kind == AST_pointer_k) 2589 type_p = ASTP_chase_ptr_to_kind(type_p, AST_disc_union_k); 2590 2591 /* A non-encapsulated union declaration must have a [switch_is] attribute */ 2592 2593 if (type_p != NULL 2594 && type_p->kind == AST_disc_union_k 2595 && type_p->type_structure.disc_union->discrim_name == NAMETABLE_NIL_ID 2596 && (param_p->field_attrs == NULL 2597 || param_p->field_attrs->switch_is == NULL)) 2598 CHECKER_error(param_p, NIDL_NEUSWATTR); 2599} 2600 2601/* 2602** p a r a m _ f i r s t _ h a n d l e 2603** 2604** Checks a parameter node's first parameter to make sure it is a 2605** handle if explicit handles are in use. 2606*/ 2607 2608static void param_first_handle 2609( 2610 AST_parameter_n_t *param_p, /* [in] Ptr to AST parameter node */ 2611 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 2612) 2613{ 2614 AST_operation_n_t *op_p; /* Operation containing the parameter */ 2615 AST_type_n_t *type_p; /* Param type (deref'd if necess.) */ 2616 2617 op_p = param_p->uplink; 2618 2619 /* 2620 * If the parameter type has a top-level '*' which indicates passing 2621 * mechanism only, follow the pointer to the data of interest. 2622 * top_type_p = top-level parameter type 2623 * type_p = possibly dereferenced parameter type 2624 */ 2625 type_p = param_follow_ref_ptr(param_p, CHK_follow_any); 2626 2627 /* No binding handle parameter for 'operation' - auto_handle assumed. */ 2628 2629 if (int_p->implicit_handle_name == NAMETABLE_NIL_ID 2630 && !AST_OBJECT_SET(int_p) 2631 && !AST_AUTO_HANDLE_SET(int_p) 2632 && !AST_LOCAL_SET(int_p) 2633 && !type_is_handle(type_p) 2634 && !AST_HAS_IN_CTX_SET(op_p)) 2635 default_to_auto_handle(op_p, NIDL_DEFAUTOHAN); 2636#if 0 /** Don't default to auto_handle for op ct. [in,out] context handles **/ 2637 else if (int_p->implicit_handle_name == NAMETABLE_NIL_ID 2638 && !AST_AUTO_HANDLE_SET(int_p) 2639 && !AST_LOCAL_SET(int_p) 2640 && !type_is_handle(type_p) 2641 && AST_HAS_IN_OUT_CTX_SET(op_p)) 2642 default_to_auto_handle(op_p, NIDL_POSSAUTOHAN); 2643#endif 2644 2645 /* handle_t binding parameter must be an [in] parameter */ 2646 2647 if (!AST_LOCAL_SET(int_p) 2648 && type_p->kind == AST_handle_k 2649 && (!AST_IN_SET(param_p) || AST_OUT_SET(param_p))) 2650 CHECKER_error(param_p, NIDL_HANPRMIN); 2651 2652 /* [handle] binding parameter must be an in parameter */ 2653 2654 if (!AST_LOCAL_SET(int_p) 2655 && AST_HANDLE_SET(type_p) 2656 && !AST_IN_SET(param_p)) 2657 CHECKER_error(param_p, NIDL_HANDLEIN); 2658 2659 /* [ptr] attribute invalid on binding handle parameter */ 2660 2661 if (!AST_LOCAL_SET(int_p) 2662 && type_is_handle(type_p) 2663 && AST_PTR_SET(param_p)) 2664 CHECKER_error(param_p, NIDL_PTRATTRHAN); 2665 2666 /* [unique] attribute invalid on binding handle parameter */ 2667 2668 if (!AST_LOCAL_SET(int_p) 2669 && type_is_handle(type_p) 2670 && AST_UNIQUE_SET(param_p)) 2671 CHECKER_error(param_p, NIDL_UNIQATTRHAN); 2672 2673 /* handle_t first parameter must not have [transmit_as] type */ 2674 2675 if (!AST_LOCAL_SET(int_p) 2676 && type_p->kind == AST_handle_k 2677 && !AST_HANDLE_SET(type_p) 2678 && type_p->xmit_as_type != NULL) 2679 CHECKER_error(param_p, NIDL_HANXMITAS); 2680 2681 /* Type with [transmit_as] cannot be used in defn of type with [handle] */ 2682 2683 if (AST_HANDLE_SET(type_p) 2684 && type_p->defined_as != NULL 2685 && FE_TEST(type_p->defined_as->fe_info->flags, FE_HAS_XMIT_AS)) 2686 { 2687 ASTP_attr_flag_t attr1 = ASTP_TRANSMIT_AS; 2688 ASTP_attr_flag_t attr2 = ASTP_HANDLE; 2689 CHECKER_error(param_p, NIDL_TYPEATTRUSE, 2690 KEYWORDS_lookup_text(AST_attribute_to_token(&attr1)), 2691 KEYWORDS_lookup_text(AST_attribute_to_token(&attr2))); 2692 } 2693 2694 /* Type with [handle] cannot be used in defn of type with [transmit_as] */ 2695 2696 if (type_p->xmit_as_type != NULL 2697 && type_p->defined_as != NULL 2698 && AST_HANDLE_SET(type_p->defined_as)) 2699 { 2700 ASTP_attr_flag_t attr1 = ASTP_HANDLE; 2701 ASTP_attr_flag_t attr2 = ASTP_TRANSMIT_AS; 2702 CHECKER_error(param_p, NIDL_TYPEATTRUSE, 2703 KEYWORDS_lookup_text(AST_attribute_to_token(&attr1)), 2704 KEYWORDS_lookup_text(AST_attribute_to_token(&attr2))); 2705 } 2706} 2707 2708/* 2709** p a r a m _ c h e c k _ f i r s t 2710** 2711** Checks an AST parameter node. This set of checks applies only to 2712** the first parameter in an operation. 2713*/ 2714 2715static void param_check_first 2716( 2717 AST_parameter_n_t *param_p, /* [in] Ptr to AST parameter node */ 2718 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 2719) 2720{ 2721 param_first_handle(param_p, int_p); 2722} 2723 2724/* 2725** p a r a m _ c h e c k _ n o n _ h a n d l e 2726** 2727** Checks an AST parameter node. This check applies only to parameters 2728** in an operation that can not be handles. 2729*/ 2730 2731static void param_check_non_handle 2732( 2733 AST_parameter_n_t *param_p, /* [in] Ptr to AST parameter node */ 2734 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 2735) 2736{ 2737 AST_type_n_t *type_p; /* Param type (deref'd if necess.) */ 2738 2739 /* 2740 * If the parameter type has a top-level '*' which indicates passing 2741 * mechanism only, follow the pointer to the data of interest. 2742 * top_type_p = top-level parameter type 2743 * type_p = possibly dereferenced parameter type 2744 */ 2745 type_p = param_follow_ref_ptr(param_p, CHK_follow_ref); 2746 2747 /* handle_t as other than first parameter requires [transmit_as] */ 2748 2749 if (!AST_LOCAL_SET(int_p) 2750 && type_p->kind == AST_handle_k 2751 && type_p->xmit_as_type == NULL) 2752 CHECKER_error(param_p, NIDL_HANFIRSTPRM); 2753} 2754 2755/* 2756** p a r a m _ c h e c k 2757** 2758** Checks an AST parameter node. 2759*/ 2760 2761static void param_check 2762( 2763 AST_parameter_n_t *param_p, /* [in] Ptr to AST parameter node */ 2764 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 2765) 2766{ 2767 AST_field_attr_n_t *fattr_p; /* Field attributes assoc. with param */ 2768 AST_type_n_t *top_type_p; /* Top-level parameter type */ 2769 AST_type_n_t *type_p; /* Param type (deref'd if necess.) */ 2770 AST_type_n_t *deref_type_p; /* Param type (deref'd if necess.) */ 2771 2772 /* 2773 * If the parameter type has a top-level '*' which indicates passing 2774 * mechanism only, follow the pointer to the data of interest. 2775 * top_type_p = top-level parameter type 2776 * type_p = possibly dereferenced parameter type 2777 * deref_type_p = possibly dereferenced parameter type 2778 */ 2779 top_type_p = param_p->type; 2780 type_p = param_follow_ref_ptr(param_p, CHK_follow_ref); 2781 deref_type_p = param_follow_ref_ptr(param_p, CHK_follow_any); 2782 2783 param_type(param_p, top_type_p, type_p, int_p); 2784 2785 /* Check parameter's field attributes, if any. */ 2786 2787 fattr_p = param_p->field_attrs; 2788 if (fattr_p != NULL) 2789 { 2790 fattr_check(fattr_p, (ASTP_node_t *)param_p, type_p, int_p); 2791 fattr_param_check(fattr_p, param_p, int_p); 2792 } 2793 2794 /* Interface must have a * */ 2795 if (type_p->kind == AST_interface_k) { 2796 char const * id_name; 2797 NAMETABLE_id_to_string(type_p->name, &id_name); 2798 CHECKER_error(param_p, NIDL_INTREFNOTALO, id_name); 2799 } 2800 2801 param_size(param_p, top_type_p, type_p, int_p); 2802 param_struct(param_p, top_type_p, type_p); 2803 param_pipe(param_p, top_type_p, deref_type_p); 2804 2805 param_in_line(param_p, type_p); 2806 param_string(param_p, type_p); 2807 param_pointer(param_p, top_type_p, type_p, int_p); 2808 param_small(param_p, top_type_p, type_p); 2809 param_context(param_p, top_type_p, deref_type_p); 2810 param_varying(param_p, type_p, int_p); 2811 2812 param_direction(param_p, top_type_p, type_p, int_p); 2813 param_comm_status(param_p, type_p); 2814 param_switch_is(param_p, type_p); 2815 2816 CHK_param_cs(param_p, type_p); 2817} 2818 2819/* 2820** o p _ h a n d l e 2821** 2822** Checks an operation node to see if a handle parameter is required. 2823*/ 2824 2825static void op_handle 2826( 2827 AST_operation_n_t *op_p, /* [in] Ptr to AST operation node */ 2828 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 2829) 2830{ 2831 /* No binding handle parameter for 'operation' - auto_handle assumed. */ 2832 2833 if (int_p->implicit_handle_name == NAMETABLE_NIL_ID 2834 && !AST_AUTO_HANDLE_SET(int_p) 2835 && !AST_LOCAL_SET(int_p) 2836 && !AST_OBJECT_SET(int_p) 2837 && op_p->parameters == NULL) 2838 default_to_auto_handle(op_p, NIDL_DEFAUTOHAN); 2839} 2840 2841/* 2842** o p _ c o m m _ s t a t u s 2843** 2844** Checks an operation node to make sure there is at most 1 comm_status param. 2845*/ 2846 2847static void op_comm_status 2848( 2849 AST_operation_n_t *op_p /* [in] Ptr to AST operation node */ 2850) 2851{ 2852 AST_parameter_n_t *param_p; /* A parameter in the operation */ 2853 int comm_status_count; /* Number [comm_status] parameters */ 2854 int fault_status_count; /* Number [fault_status] parameters */ 2855 2856 comm_status_count = 0; 2857 fault_status_count = 0; 2858 2859 if (AST_COMM_STATUS_SET(op_p->result)) 2860 comm_status_count++; 2861 if (AST_FAULT_STATUS_SET(op_p->result)) 2862 fault_status_count++; 2863 2864 for (param_p = op_p->parameters; param_p != NULL; param_p = param_p->next) 2865 { 2866 if (AST_COMM_STATUS_SET(param_p) || AST_ADD_COMM_STATUS_SET(param_p)) 2867 comm_status_count++; 2868 if (AST_FAULT_STATUS_SET(param_p) || AST_ADD_FAULT_STATUS_SET(param_p)) 2869 fault_status_count++; 2870 } 2871 2872 /* Operation can have at most one [comm_status] parameter */ 2873 2874 if (comm_status_count > 1) 2875 CHECKER_acf_error(op_p, NIDL_STSATTRONCE, 2876 acf_keyword_lookup(COMM_STATUS_KW)); 2877 2878 /* Operation can have at most one [fault_status] parameter */ 2879 2880 if (fault_status_count > 1) 2881 CHECKER_acf_error(op_p, NIDL_STSATTRONCE, 2882 acf_keyword_lookup(FAULT_STATUS_KW)); 2883} 2884 2885/* 2886** o p _ b r o a d c a s t 2887** 2888** Checks an operation node's [broadcast] attribute. 2889*/ 2890 2891static void op_broadcast 2892( 2893 AST_operation_n_t *op_p /* [in] Ptr to AST operation node */ 2894) 2895{ 2896 /* Can't have [broadcast] attribute on operation with pipes */ 2897 2898 if (AST_BROADCAST_SET(op_p) 2899 && (AST_HAS_IN_PIPES_SET(op_p) || AST_HAS_OUT_PIPES_SET(op_p))) 2900 CHECKER_error(op_p, NIDL_BROADPIPE); 2901} 2902 2903/* 2904** o p _ m a y b e 2905** 2906** Checks an operation node's [maybe] attribute. 2907*/ 2908 2909static void op_maybe 2910( 2911 AST_operation_n_t *op_p /* [in] Ptr to AST operation node */ 2912) 2913{ 2914 /* [maybe] operations cannot have [out] parameters */ 2915 2916 if (AST_MAYBE_SET(op_p) 2917 && (AST_HAS_OUTS_SET(op_p) || AST_HAS_OUT_PIPES_SET(op_p))) 2918 CHECKER_error(op_p, NIDL_MAYBEOUTPRM); 2919} 2920 2921/* 2922** o p _ c o d e 2923** 2924** Checks an operation node's [code] and [nocode] attributes. 2925*/ 2926 2927static void op_code 2928( 2929 AST_operation_n_t *op_p /* [in] Ptr to AST operation node */ 2930) 2931{ 2932 /* Can't have both [code] and [nocode] operation attributes */ 2933 2934 if (AST_CODE_SET(op_p) 2935 && AST_NO_CODE_SET(op_p)) 2936 CHECKER_acf_error(op_p, NIDL_OPCODEATTR); 2937 2938 /* [nocode] attribute does not apply to server stub */ 2939 2940 if (AST_NO_CODE_SET(op_p) 2941 && cmd_opt[opt_emit_sstub] 2942 && !cmd_opt[opt_emit_cstub]) 2943 CHECKER_acf_warning(op_p, NIDL_SRVNOCODE); 2944} 2945 2946/* 2947** o p _ i d e m p o t e n t 2948** 2949** Checks an operation node's [idempotent] attribute. 2950*/ 2951 2952static void op_idempotent 2953( 2954 AST_operation_n_t *op_p /* [in] Ptr to AST operation node */ 2955) 2956{ 2957 /* Can't have [idempotent] attribute on operation with pipes */ 2958 2959 if (AST_IDEMPOTENT_SET(op_p) 2960 && !AST_BROADCAST_SET(op_p) /* broadcast gens its own error */ 2961 && (AST_HAS_IN_PIPES_SET(op_p) || AST_HAS_OUT_PIPES_SET(op_p))) 2962 CHECKER_error(op_p, NIDL_IDEMPIPE); 2963} 2964 2965/* 2966** o p _ e n c o d e 2967** 2968** Checks an operation node's [encode] and [decode] attributes. 2969*/ 2970 2971static void op_encode 2972( 2973 AST_operation_n_t *op_p /* [in] Ptr to AST operation node */ 2974) 2975{ 2976 AST_parameter_n_t *param_p; /* A parameter in the operation */ 2977 AST_parameter_n_t *p1; /* First parameter in the operation */ 2978 boolean all_in_out; /* T => all parameters [in,out] */ 2979 boolean all_in; /* T => all parameters [in]-only */ 2980 boolean all_out; /* T => all parameters [out]-only */ 2981 boolean p1_is_handle_t; /* T => p1 non-NULL, type handle_t */ 2982 2983 if (AST_NO_CODE_SET(op_p)) 2984 return; 2985 if (!AST_ENCODE_SET(op_p) && !AST_DECODE_SET(op_p)) 2986 return; 2987 2988 all_in_out = TRUE; 2989 all_in = TRUE; 2990 all_out = TRUE; 2991 p1 = op_p->parameters; 2992 if (p1 != NULL 2993 && (p1->type->kind == AST_handle_k 2994 || (p1->type->kind == AST_pointer_k 2995 && p1->type->type_structure.pointer->pointee_type->kind 2996 == AST_handle_k))) 2997 p1_is_handle_t = TRUE; 2998 else 2999 p1_is_handle_t = FALSE; 3000 param_p = ((p1 != NULL) ? p1 : op_p->result); 3001 3002 while (TRUE) 3003 { 3004 if (AST_IN_SET(param_p) && !AST_OUT_SET(param_p)) 3005 { 3006 /* [in]-only (binding handle parameter excluded) */ 3007 if ( !(param_p == p1 && p1_is_handle_t) ) 3008 { 3009 all_out = FALSE; 3010 all_in_out = FALSE; 3011 } 3012 } 3013 else if (!AST_IN_SET(param_p) && AST_OUT_SET(param_p)) 3014 { 3015 /* [out]-only (ACF-added [*_status] parameter excluded) */ 3016 if (!AST_ADD_COMM_STATUS_SET(param_p) 3017 && !AST_ADD_FAULT_STATUS_SET(param_p)) 3018 { 3019 all_in = FALSE; 3020 all_in_out = FALSE; 3021 } 3022 } 3023 else if (AST_IN_SET(param_p) && AST_OUT_SET(param_p)) 3024 { 3025 /* [in,out] */ 3026 all_in = FALSE; 3027 all_out = FALSE; 3028 } 3029 3030 /* Operation with [encode] has [out]-only parameter P */ 3031 /* Note an ACF-added [*_status] parameter is exception to this rule */ 3032 if (AST_ENCODE_SET(op_p) && !AST_DECODE_SET(op_p) 3033 && AST_OUT_SET(param_p) && !AST_IN_SET(param_p) 3034 && !AST_ADD_COMM_STATUS_SET(param_p) 3035 && !AST_ADD_FAULT_STATUS_SET(param_p)) 3036 { 3037 char const *id_name; 3038 NAMETABLE_id_to_string(param_p->name, &id_name); 3039 CHECKER_warning(param_p, NIDL_ENCOUTONLY, id_name); 3040 } 3041 3042 /* Operation with [decode] has [in]-only parameter P */ 3043 /* Note a handle_t first parameter is an exception to this rule */ 3044 if (AST_DECODE_SET(op_p) && !AST_ENCODE_SET(op_p) 3045 && AST_IN_SET(param_p) && !AST_OUT_SET(param_p) 3046 && !(param_p == p1 && p1_is_handle_t) ) 3047 { 3048 char const *id_name; 3049 NAMETABLE_id_to_string(param_p->name, &id_name); 3050 CHECKER_warning(param_p, NIDL_DECINONLY, id_name); 3051 } 3052 3053 /* A [fault_status] parameter has no utility in this operation */ 3054 if (AST_FAULT_STATUS_SET(param_p) || AST_ADD_FAULT_STATUS_SET(param_p)) 3055 CHECKER_acf_warning(op_p, NIDL_NOFLTPARAM); 3056 3057 /* Update to next parameter or operation result */ 3058 if (param_p == op_p->result) 3059 break; 3060 param_p = param_p->next; 3061 if (param_p == NULL) 3062 param_p = op_p->result; 3063 } 3064 3065 /* Operation with [encode] must have at least one [in] or [in,out] param */ 3066 3067 if (AST_ENCODE_SET(op_p) && !AST_DECODE_SET(op_p) && all_out) 3068 CHECKER_error(op_p, NIDL_ENCNOPARAMS); 3069 3070 /* Operation with [decode] must have at least one [out] or [in,out] param */ 3071 3072 if (AST_DECODE_SET(op_p) && !AST_ENCODE_SET(op_p) && all_in) 3073 CHECKER_error(op_p, NIDL_DECNOPARAMS); 3074 3075 /* Operation with [encode,decode] must have all [in,out] parameters */ 3076 3077 if (AST_ENCODE_SET(op_p) && AST_DECODE_SET(op_p) && !all_in_out) 3078 CHECKER_error(op_p, NIDL_ENCDECDIR); 3079 3080 /* Operation with [encode] or [decode] may not contain pipe parameters */ 3081 3082 if ( (AST_ENCODE_SET(op_p) || AST_DECODE_SET(op_p)) 3083 && (AST_HAS_IN_PIPES_SET(op_p) || AST_HAS_OUT_PIPES_SET(op_p)) ) 3084 CHECKER_error(op_p, NIDL_ENCDECPIPE); 3085 3086 /* Operation with [encode] or [decode] must use explicit binding */ 3087 3088 /* 3089 * Note: if explicit handle added via ACF attribute, propagator has 3090 * already added a handle_t parameter to the operation. 3091 */ 3092 if ( (AST_ENCODE_SET(op_p) || AST_DECODE_SET(op_p)) 3093 && !p1_is_handle_t ) 3094 CHECKER_error(op_p, NIDL_ENCDECBIND); 3095 3096 /* Use of [encode] attribute requires -standard extended */ 3097 if (AST_ENCODE_SET(op_p) 3098 && (*(int *)cmd_val[opt_standard] < opt_standard_dce_1_1)) 3099 CHECKER_acf_warning(op_p, NIDL_NOPORTATTR, "encode", OPT_STD_EXTENDED); 3100 3101 /* Use of [decode] attribute requires -standard extended */ 3102 if (AST_DECODE_SET(op_p) 3103 && (*(int *)cmd_val[opt_standard] < opt_standard_dce_1_1)) 3104 CHECKER_acf_warning(op_p, NIDL_NOPORTATTR, "decode", OPT_STD_EXTENDED); 3105} 3106 3107/* 3108** o p e r a t i o n _ c h e c k 3109** 3110** Checks an AST operation node. 3111*/ 3112 3113static void operation_check 3114( 3115 AST_operation_n_t *op_p, /* [in] Ptr to AST operation node */ 3116 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 3117) 3118{ 3119 AST_parameter_n_t *param_p; /* A parameter in the operation */ 3120 3121 op_handle(op_p, int_p); 3122 op_comm_status(op_p); 3123 3124 op_broadcast(op_p); 3125 op_maybe(op_p); 3126 op_code(op_p); 3127 op_idempotent(op_p); 3128 op_encode(op_p); 3129 CHK_op_cs(op_p); 3130 3131 /* Must compile stubs with ANSI C to avoid promotion of float to double */ 3132 3133 if (FE_TEST(op_p->fe_info->flags, FE_HAS_VAL_FLOAT) 3134 ) 3135 { 3136 char const *id_name; /* Operation name */ 3137 3138 NAMETABLE_id_to_string(op_p->name, &id_name); 3139 CHECKER_warning(op_p, NIDL_FLOATPROM, id_name); 3140 } 3141 3142 /* Operation with [reflect_deletions] has no [in] or [in,out] full ptrs */ 3143 3144 if (AST_REFLECT_DELETIONS_SET(op_p) 3145 && !FE_TEST(op_p->fe_info->flags, FE_HAS_IN_FULL_PTR)) 3146 CHECKER_warning(op_p, NIDL_OPREFDELIN); 3147 3148 /* Use of [reflect_deletions] attribute requires -standard extended */ 3149 if (AST_REFLECT_DELETIONS_SET(op_p) 3150 && (*(int *)cmd_val[opt_standard] < opt_standard_dce_1_1)) 3151 { 3152 ASTP_attr_flag_t attr1 = ASTP_REFLECT_DELETIONS; 3153 CHECKER_warning(op_p, NIDL_NOPORTATTR, 3154 KEYWORDS_lookup_text(AST_attribute_to_token(&attr1)), 3155 OPT_STD_EXTENDED); 3156 } 3157 3158 /* Check each parameter in the operation. */ 3159 3160 param_p = op_p->parameters; 3161 if (param_p != NULL) 3162 { 3163 /* The first parameter in an operation is handled separately. */ 3164 3165 param_check_first(param_p, int_p); 3166 param_check(param_p, int_p); 3167 3168 /* Check the remaining parameters, if any. */ 3169 3170 while ((param_p = param_p->next) != NULL) 3171 { 3172 param_check_non_handle(param_p, int_p); 3173 param_check(param_p, int_p); 3174 } 3175 } 3176 3177 /* Check the operation result, if any. */ 3178 3179 if (op_p->result != NULL) 3180 { 3181 param_check_non_handle(op_p->result, int_p); 3182 param_check(op_p->result, int_p); 3183 } 3184} 3185 3186/* 3187** f i e l d _ t y p e 3188** 3189** Checks a field node's data type. 3190*/ 3191 3192static void field_type 3193( 3194 AST_field_n_t *field_p, /* [in] Ptr to AST field node */ 3195 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 3196) 3197{ 3198 AST_type_n_t *type_p; /* Data type of the field */ 3199 3200 type_p = field_p->type; 3201 3202 /* If the field type is anonymous, it must undergo type checks. */ 3203 3204 if (type_is_anonymous(type_p)) 3205 type_check(type_p, (ASTP_node_t *)field_p, int_p); 3206 3207 /* A type with [transmit_as] may not have other type attributes */ 3208 3209 if (type_p->xmit_as_type != NULL 3210 && 3211 (AST_STRING_SET(field_p) 3212 || AST_STRING0_SET(field_p) 3213 || AST_UNIQUE_SET(field_p) 3214 || AST_REF_SET(field_p) 3215 || AST_IGNORE_SET(field_p) 3216 || AST_SMALL_SET(field_p) 3217 || AST_CONTEXT_SET(field_p) 3218 || AST_PTR_SET(field_p))) 3219 CHECKER_error(field_p, NIDL_XMITTYPEATTRS); 3220 3221 /* A field cannot be of presented type for which xmit type is conformant */ 3222 3223 if (type_p->xmit_as_type != NULL 3224 && AST_CONFORMANT_SET(type_p->xmit_as_type)) 3225 CHECKER_error(field_p, NIDL_FLDXMITCFMT); 3226 3227 type_p = type_xmit_type(type_p); /* Pick up transmissible type */ 3228 3229 /* A conformant field must be the last field in structure */ 3230 3231 if (!AST_LOCAL_SET(int_p) 3232 && field_p->next != NULL 3233 && AST_CONFORMANT_SET(type_p) 3234 && type_p->kind != AST_pointer_k) /* ptr does not make struct cfmt */ 3235 CHECKER_error(field_p, NIDL_CFMTFLDLAST); 3236 3237 /* Pipes not valid as structure fields */ 3238 3239 if (type_p->kind == AST_pipe_k) 3240 CHECKER_error(field_p, NIDL_PIPESTRFLD); 3241 3242 /* interface must have a * */ 3243 if (type_p->kind == AST_interface_k) { 3244 char const * id_name; 3245 NAMETABLE_id_to_string(type_p->name, &id_name); 3246 CHECKER_error(field_p, NIDL_INTREFNOTALO, id_name); 3247 } 3248 3249 /* Context handles not valid as structure fields */ 3250 3251 if (AST_CONTEXT_RD_SET(type_p) 3252 || AST_CONTEXT_SET(field_p)) 3253 CHECKER_error(field_p, NIDL_CTXSTRFLD); 3254 3255 /* Function pointers not valid as structure fields */ 3256 3257 if (!AST_LOCAL_SET(int_p) 3258 && type_is_function(type_p) 3259 && type_p->xmit_as_type == NULL /* allowed if void* is not xmited */ 3260 ) 3261 CHECKER_error(field_p, NIDL_FPSTRFLD); 3262 3263 /* Structure fields cannot be of type handle_t */ 3264 3265 if (type_p->kind == AST_handle_k) 3266#if 0 /** Obsolete **/ 3267 && type_p->xmit_as_type == NULL) 3268#endif 3269 CHECKER_error(field_p, NIDL_HANSTRFLD); 3270 3271 /* void is valid only in an operation or pointer declaration */ 3272 3273 if (type_p->kind == AST_void_k) 3274 CHECKER_error(field_p, NIDL_VOIDOPPTR); 3275 3276 /* void * must be used in conjunction with the [context_handle] attr */ 3277 3278 if (!AST_LOCAL_SET(int_p) 3279 && type_p->kind == AST_pointer_k 3280 && type_p->type_structure.pointer->pointee_type->kind == AST_void_k 3281 && !AST_CONTEXT_RD_SET(type_p) 3282 && !AST_CONTEXT_SET(field_p) 3283 ) 3284 CHECKER_error(field_p, NIDL_PTRVOIDCTX); 3285 3286 /* 3287 * V1 attributes are incompatible with this type 3288 * Note: Issue error only if the same error doesn't fire for the type. 3289 */ 3290 if (FE_TEST(field_p->fe_info->flags, FE_HAS_V1_ATTR) 3291 && FE_TEST(field_p->fe_info->flags, FE_HAS_V2_ATTR) 3292 && ! ( FE_TEST(type_p->fe_info->flags, FE_HAS_V1_ATTR) 3293 && FE_TEST(type_p->fe_info->flags, FE_HAS_V2_ATTR) )) 3294 CHECKER_warning(field_p, NIDL_INCOMPATV1); 3295} 3296 3297/* 3298** f i e l d _ s i z e 3299** 3300** Checks a field node to see if array size information is required. 3301*/ 3302 3303static void field_size 3304( 3305 AST_field_n_t *field_p, /* [in] Ptr to AST field node */ 3306 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 3307) 3308{ 3309 AST_type_n_t *type_p; /* Data type of the field */ 3310 AST_field_attr_n_t *fattr_p; /* Field attributes */ 3311 3312 type_p = field_p->type; 3313 fattr_p = field_p->field_attrs; 3314 3315 /* Array size information required */ 3316 3317 if (!AST_LOCAL_SET(int_p) 3318 && type_p->kind != AST_structure_k /* Struct has its own size info */ 3319 && type_p->xmit_as_type == NULL 3320 && fattr_p == NULL 3321 && (AST_CONFORMANT_SET(type_p) 3322 || AST_VARYING_SET(field_p)) 3323 && !AST_STRING_SET(type_p) /* [string] a possible exception */ 3324 && !AST_STRING_SET(field_p)) /* if used in an [in] param */ 3325 { 3326 char const *id_name; 3327 3328 NAMETABLE_id_to_string(field_p->name, &id_name); 3329 CHECKER_error(field_p, NIDL_ARRSIZEINFO, id_name); 3330 } 3331 3332 /* A [string] array can not have varying array attributes */ 3333 3334 if (!AST_LOCAL_SET(int_p) 3335 && type_p->xmit_as_type == NULL 3336 && AST_STRING_SET(field_p) 3337 && fattr_p != NULL 3338 && (fattr_p->first_is_vec != NULL 3339 || fattr_p->last_is_vec != NULL 3340 || fattr_p->length_is_vec != NULL)) 3341 CHECKER_error(field_p, NIDL_STRVARY); 3342 3343 /* Arrays with [transmit_as] can't be conformant or varying */ 3344 3345 /* 3346 * Note that pointers that represent arrays are excluded from the test. 3347 * Since the instance of the pointer turns it into an array, 3348 * field_pointer calls array_check, which will detect the error. 3349 */ 3350 if (type_p->xmit_as_type != NULL 3351 && fattr_p != NULL 3352 && type_p->kind != AST_pointer_k) 3353 CHECKER_error(field_p, NIDL_ARRXMITOPEN); 3354 3355 /* 3356 * Current rules allow mixed open array [] and pointer * syntax ONLY 3357 * of the form *..*param[][N]..[N], i.e. when param is a [multidimensional] 3358 * array of pointers (that, currently, can be conformant or varying in the 3359 * first dimension only). Pointers to open arrays are not allowed due to 3360 * the ambiguity as to which * or [] the array size attributes apply to. 3361 * 3362 * Builder only allows one open array dimension when pointer and array 3363 * syntax is mixed. It will detect errors on such examples as: 3364 * [in, size_is(s1,s2)] long (*param)[] 3365 * 3366 * A corollary is that in declarations with more than one * and no [] or 3367 * [N], array size information applies to the rightmost * only. 3368 * Builder will detect errors on such examples as: 3369 * [in, size_is(s1,s2)] long **param 3370 * 3371 * Checker detects these 3 cases separately: 3372 * [in, size_is(s)] long (*..*param)[N]..[N] ARRSYNTAX 3373 * [in, size_is(s)] long (*..*param)[][N]..[N] PTRCFMTARR 3374 * [in, length_is(l)] long (*..*param)[N]..[N] PTRVARYARR 3375 */ 3376 if (type_p->kind == AST_pointer_k) 3377 { 3378 AST_type_n_t *ref_type_p; /* Pointee data type */ 3379 3380 ref_type_p = ASTP_chase_ptr_to_type(type_p); 3381 3382 /* Use array syntax to declare multidimensional arrays */ 3383 3384 if (ref_type_p->kind == AST_array_k 3385 && !AST_CONFORMANT_SET(ref_type_p) 3386 && fattr_p != NULL 3387 && (fattr_p->min_is_vec != NULL 3388 || fattr_p->max_is_vec != NULL 3389 || fattr_p->size_is_vec != NULL)) 3390 CHECKER_error(field_p, NIDL_ARRSYNTAX); 3391 3392 /* Pointers to conformant arrays are not allowed */ 3393 3394 /* 3395 * Can't just check for conformant set since a string can be conformant 3396 * and not require size attributes; a ptr to such a string is legal. 3397 */ 3398 if (ref_type_p->kind == AST_array_k 3399 && AST_CONFORMANT_SET(ref_type_p) 3400 && (!AST_STRING_SET(ref_type_p) 3401 || (fattr_p != NULL 3402 && (fattr_p->min_is_vec != NULL 3403 || fattr_p->max_is_vec != NULL 3404 || fattr_p->size_is_vec != NULL)))) 3405 { 3406 CHECKER_error(field_p, NIDL_PTRCFMTARR); 3407 return; /* Return with no further checking */ 3408 } 3409 3410 /* Pointers to varying arrays are not allowed */ 3411 3412 /* 3413 * Can't just check for varying set since a string is implicitly vary- 3414 * ing and cannot have length attrs; a ptr to such a string is legal. 3415 */ 3416 if (ref_type_p->kind == AST_array_k 3417 && fattr_p != NULL 3418 && (fattr_p->first_is_vec != NULL 3419 || fattr_p->last_is_vec != NULL 3420 || fattr_p->length_is_vec != NULL)) 3421 { 3422 CHECKER_error(field_p, NIDL_PTRVARYARR); 3423 return; /* Return with no further checking */ 3424 } 3425 } 3426} 3427 3428/* 3429** f i e l d _ i n _ l i n e 3430** 3431** Checks a field node's [in_line] and [out_of_line] attributes. 3432*/ 3433 3434static void field_in_line 3435( 3436 AST_field_n_t *field_p /* [in] Ptr to AST field node */ 3437) 3438{ 3439 AST_type_n_t *type_p; /* Data type of the field */ 3440 3441 type_p = field_p->type; 3442 3443 /* Can't have both [in_line] and [out_of_line] attributes */ 3444 3445 if (AST_IN_LINE_SET(field_p) 3446 && AST_OUT_OF_LINE_SET(field_p)) 3447 CHECKER_acf_error(field_p, NIDL_CONFLINEATTR); 3448 3449 /* [in_line] and [out_of_line] attributes apply only to non-scalar types */ 3450 3451 if ((AST_IN_LINE_SET(field_p) || AST_OUT_OF_LINE_SET(field_p)) 3452 && type_is_scalar(type_p)) 3453 { 3454 char const *file_name; /* Related file name */ 3455 char const *type_name; /* Data type name */ 3456 3457 STRTAB_str_to_string(type_p->fe_info->file, &file_name); 3458 NAMETABLE_id_to_string(type_p->name, &type_name); 3459 3460 CHECKER_acf_warning(field_p, NIDL_LINENONSCAL); 3461 CHECKER_acf_warning(field_p, NIDL_NAMEDECLAT, type_name, file_name, 3462 type_p->fe_info->source_line); 3463 } 3464} 3465 3466/* 3467** f i e l d _ s t r i n g 3468** 3469** Checks a field node's [string] and [v1_string] attributes. 3470*/ 3471 3472static void field_string 3473( 3474 AST_field_n_t *field_p /* [in] Ptr to AST field node */ 3475) 3476{ 3477 AST_type_n_t *type_p; /* Data type of the field */ 3478 3479 type_p = field_p->type; 3480 3481 /* A [v1_string] must be an array of char with fixed bounds */ 3482 3483 if (AST_STRING0_SET(field_p) 3484 && !type_is_v1_string(type_p)) 3485 CHECKER_error(field_p, NIDL_STRV1FIXED); 3486 3487 /* The [v1_string] attribute can only be applied to a [v1_array] */ 3488 3489 if ((AST_STRING0_SET(field_p) || AST_STRING0_SET(type_p)) 3490 && !(AST_SMALL_SET(field_p) || AST_SMALL_SET(type_p))) 3491 CHECKER_error(field_p, NIDL_STRV1ARRAY); 3492 3493 /* The [string] attribute cannot be applied to a [v1_array] */ 3494 3495 if ((AST_STRING_SET(field_p) && AST_SMALL_SET(field_p)) 3496 || (AST_STRING_SET(field_p) && AST_SMALL_SET(type_p)) 3497 || (AST_STRING_SET(type_p) && AST_SMALL_SET(field_p))) 3498 CHECKER_error(field_p, NIDL_STRARRAYV1); 3499 3500 /* Cannot have both [string] and [v1_string] attributes */ 3501 3502 if ( (AST_STRING_SET(field_p) || AST_STRING_SET(type_p)) 3503 && (AST_STRING0_SET(field_p) || AST_STRING0_SET(type_p)) ) 3504 { 3505 ASTP_attr_flag_t attr1 = ASTP_STRING; 3506 ASTP_attr_flag_t attr2 = ASTP_STRING0; 3507 3508 CHECKER_error(field_p, NIDL_CONFLICTATTR, 3509 KEYWORDS_lookup_text(AST_attribute_to_token(&attr1)), 3510 KEYWORDS_lookup_text(AST_attribute_to_token(&attr2))); 3511 } 3512 3513 /* 3514 * Forgo last check if the declaration is a pointer to an array and either 3515 * (the declaration has size attributes) or (the array is conformant and 3516 * not a string), since mixed pointer and array declarations that either 3517 * have or require array size attributes are disallowed by other checks. 3518 */ 3519 if (type_p->kind == AST_pointer_k) 3520 { 3521 AST_type_n_t *ref_type_p; /* Pointee data type */ 3522 3523 ref_type_p = ASTP_chase_ptr_to_type(type_p); 3524 if (ref_type_p->kind == AST_array_k 3525 && (field_p->field_attrs != NULL 3526 || (AST_CONFORMANT_SET(ref_type_p) 3527 && !AST_STRING_SET(ref_type_p)))) 3528 return; 3529 } 3530 3531 /* [string] attribute valid only for one-dim arrays of char or byte */ 3532 3533 if (AST_STRING_SET(field_p) 3534 && !type_is_string(type_p)) 3535 CHECKER_error(field_p, NIDL_STRCHARBYTE); 3536} 3537 3538/* 3539** f i e l d _ p o i n t e r 3540** 3541** Checks a field node's attributes related to pointers. 3542*/ 3543 3544static void field_pointer 3545( 3546 AST_field_n_t *field_p, /* [in] Ptr to AST field node */ 3547 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 3548) 3549{ 3550 AST_type_n_t *type_p; /* Data type of the field */ 3551 boolean pointer_attr_valid = FALSE; 3552 3553 type_p = field_p->type; 3554 3555 if (type_p->kind == AST_pointer_k 3556 && type_p->type_structure.pointer->pointee_type->kind != AST_void_k) 3557 pointer_attr_valid = TRUE; 3558 3559 /* [ref] attribute valid only for pointer or array types */ 3560 3561 if (AST_REF_SET(field_p) && !pointer_attr_valid) 3562 CHECKER_error(field_p, NIDL_REFATTRPTR); 3563 3564 /* [unique] attribute valid only for pointer or array types */ 3565 3566 if (AST_UNIQUE_SET(field_p) && !pointer_attr_valid) 3567 CHECKER_error(field_p, NIDL_UNIQATTRPTR); 3568 3569 /* [ptr] attribute valid only for pointer or array types */ 3570 3571 if (AST_PTR_SET(field_p) && !pointer_attr_valid) 3572 CHECKER_error(field_p, NIDL_PTRATTRPTR); 3573 3574 /* [unique] attribute requires -standard extended */ 3575 3576 if (AST_UNIQUE_SET(field_p) 3577 && (*(int *)cmd_val[opt_standard] <= opt_standard_dce_1_0)) 3578 CHECKER_warning(field_p, NIDL_NOPORTUNIQUE, OPT_STD_EXTENDED); 3579 3580 /* An array with a pointer attribute is valid only as a parameter. */ 3581 3582 if (type_p->kind == AST_array_k && 3583 (AST_REF_SET(field_p) || AST_PTR_SET(field_p) || AST_UNIQUE_SET(field_p))) 3584 CHECKER_error(field_p, NIDL_ARRPTRPRM); 3585 3586 /* ignore REF, UNIQUE, PTR attributes on pointers to interfaces */ 3587#if 0 3588 if (type_p->kind == AST_pointer_k && type_p->type_structure.pointer->pointee_type->kind == AST_interface_k 3589 && (AST_UNIQUE_SET(field_p) || AST_REF_SET(field_p) || AST_PTR_SET(field_p))) 3590 CHECKER_warning(field_p, NIDL_PTRATTBIGN); 3591#endif 3592 /* 3593 * If the field is a pointer, and it is not a pointer to an array, 3594 * and it has any of the array attributes, then it is an arrayified 3595 * pointer and it must undergo the checks for arrays. 3596 */ 3597 if (type_p->kind == AST_pointer_k 3598 && type_p->type_structure.pointer->pointee_type->kind != AST_array_k 3599#if 0 3600 && (field_p->field_attrs != NULL 3601#endif 3602 && (instance_has_array_attr(field_p) 3603 || AST_STRING_SET(type_p) 3604 || AST_STRING_SET(field_p))) 3605 { 3606 array_check((ASTP_node_t *)type_p->type_structure.pointer, 3607 type_p, 3608 (ASTP_node_t *)field_p, 3609 type_p->type_structure.pointer->pointee_type, 3610 int_p, 3611 true); 3612 } 3613} 3614 3615/* 3616** f i e l d _ s m a l l 3617** 3618** Checks a field node's [v1_array] attribute. 3619*/ 3620 3621static void field_small 3622( 3623 AST_field_n_t *field_p /* [in] Ptr to AST field node */ 3624) 3625{ 3626 AST_type_n_t *type_p; /* Data type of the field */ 3627 AST_array_n_t *array_p; /* Ptr to array node */ 3628 AST_field_attr_n_t *fattr_p; /* Ptr to field attribute node */ 3629 3630 type_p = field_p->type; 3631 3632 /* A [v1_array] must be in array, not pointer, syntax */ 3633 3634 if (AST_SMALL_SET(field_p) 3635 && type_p->kind == AST_pointer_k) 3636 CHECKER_error(field_p, NIDL_SMALLARRSYN); 3637 3638 /* 3639 * Remaining checks only apply to array types in array syntax. 3640 * V1 did not allow arrays in pointer syntax. 3641 */ 3642 if (!type_is_array_np(type_p)) 3643 return; 3644 3645 fattr_p = field_p->field_attrs; 3646 array_p = type_p->type_structure.array; 3647 3648 /* A [v1_array] can be conformant or varying in the first dimension only */ 3649 3650 if (AST_SMALL_SET(field_p) 3651 && ((AST_CONFORMANT_SET(type_p) 3652 && array_is_conformant_upper(array_p)) 3653 || 3654 (AST_VARYING_SET(field_p) 3655 && instance_is_varying_upper(array_p, field_p->field_attrs)))) 3656 CHECKER_error(field_p, NIDL_SMALLMULTID); 3657 3658 /* [v1_array] attribute invalid for array with more than 65535 elements */ 3659 3660 if (AST_SMALL_SET(field_p) 3661 && array_is_large(array_p)) 3662 CHECKER_error(field_p, NIDL_SMALLINV); 3663 3664 /* A conformant [v1_array] must also be varying */ 3665 3666 if ((AST_SMALL_SET(type_p) || AST_SMALL_SET(field_p)) 3667 && AST_CONFORMANT_SET(type_p) 3668 && !AST_VARYING_SET(field_p)) 3669 CHECKER_error(field_p, NIDL_SMALLCFMT); 3670 3671 /* A [v1_array] can not have the [min_is] or [first_is] attributes */ 3672 3673 if ((AST_SMALL_SET(type_p) || AST_SMALL_SET(field_p)) 3674 && fattr_p != NULL 3675 && (fattr_p->min_is_vec != NULL 3676 || fattr_p->first_is_vec != NULL)) 3677 CHECKER_error(field_p, NIDL_SMALLMINFIRST); 3678} 3679 3680/* 3681** f i e l d _ c o n t e x t 3682** 3683** Checks a field node's [context_handle] attribute. 3684*/ 3685 3686static void field_context 3687( 3688 AST_field_n_t *field_p /* [in] Ptr to AST field node */ 3689) 3690{ 3691 AST_type_n_t *type_p; /* Data type of the field */ 3692 3693 type_p = field_p->type; 3694 3695 /* [context_handle] attribute only applies to void * types */ 3696 3697 if (AST_CONTEXT_SET(field_p) 3698 && (type_p->kind != AST_pointer_k 3699 || (type_p->kind == AST_pointer_k 3700 && type_p->type_structure.pointer->pointee_type->kind 3701 != AST_void_k))) 3702 CHECKER_error(field_p, NIDL_CTXPTRVOID); 3703 3704 /* [unique] pointers to context handles are not allowed */ 3705 3706 if (AST_UNIQUE_SET(field_p) 3707 && type_p->kind == AST_pointer_k 3708 && AST_CONTEXT_RD_SET(type_p->type_structure.pointer->pointee_type)) 3709 CHECKER_error(field_p, NIDL_UNIQCTXHAN); 3710 3711 /* Full pointers to context handles are not allowed */ 3712 3713 if (AST_PTR_SET(field_p) 3714 && type_p->kind == AST_pointer_k 3715 && AST_CONTEXT_RD_SET(type_p->type_structure.pointer->pointee_type)) 3716 CHECKER_error(field_p, NIDL_PTRCTXHAN); 3717} 3718 3719/* 3720** f i e l d _ v a r y i n g 3721** 3722** Checks an field node's "varying" (synthesized) attribute. 3723*/ 3724 3725static void field_varying 3726( 3727 AST_field_n_t *field_p, /* [in] Ptr to AST field node */ 3728 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 3729) 3730{ 3731 AST_type_n_t *type_p; /* Field data type */ 3732 3733 type_p = field_p->type; 3734 3735 /* 3736 * Assume that if the varying attribute is set, the field is an 3737 * array type and the field_attrs field is valid. An array can be 3738 * represented either in normal array syntax, or as a pointer that 3739 * has any of the array attributes. 3740 */ 3741 if (type_p->kind != AST_array_k) 3742 return; /* All checks below assume normal array syntax */ 3743 3744 /* Arrays varying in other than the first dim require -standard extended */ 3745 3746 if (!AST_LOCAL_SET(int_p) 3747 && type_p->xmit_as_type == NULL 3748 && AST_VARYING_SET(field_p) 3749 && instance_is_varying_upper(type_p->type_structure.array, 3750 field_p->field_attrs) 3751 && (*(int *)cmd_val[opt_standard] <= opt_standard_dce_1_0)) 3752 CHECKER_warning(field_p, NIDL_NOPORTVARY, OPT_STD_EXTENDED); 3753} 3754 3755/* 3756** f i e l d _ i g n o r e 3757** 3758** Checks an field node's [ignore] attribute. 3759*/ 3760 3761static void field_ignore 3762( 3763 AST_field_n_t *field_p /* [in] Ptr to AST field node */ 3764) 3765{ 3766 AST_type_n_t *type_p; /* Field data type */ 3767 3768 type_p = field_p->type; 3769 3770 /* The [ignore] attribute is valid only for pointers */ 3771 3772 if (AST_IGNORE_SET(field_p) 3773 && type_p->kind != AST_pointer_k) 3774 CHECKER_error(field_p, NIDL_IGNATTRPTR); 3775} 3776static void field_switch_is 3777( 3778 AST_field_n_t *field_p /* [in] Ptr to AST field node */ 3779) 3780{ 3781 AST_type_n_t *type_p; /* Field data type */ 3782 3783 type_p = field_p->type; 3784 3785 if (type_p->kind == AST_pointer_k) 3786 type_p = ASTP_chase_ptr_to_kind(type_p, AST_disc_union_k); 3787 3788 /* A non-encapsulated union declaration must have a [switch_is] attribute */ 3789 3790 if (type_p != NULL 3791 && type_p->kind == AST_disc_union_k 3792 && type_p->type_structure.disc_union->discrim_name == NAMETABLE_NIL_ID 3793 && (field_p->field_attrs == NULL 3794 || field_p->field_attrs->switch_is == NULL)) 3795 CHECKER_error(field_p, NIDL_NEUSWATTR); 3796} 3797 3798/* 3799** f i e l d _ c h e c k 3800** 3801** Checks an AST field node. 3802*/ 3803 3804static void field_check 3805( 3806 AST_field_n_t *field_p, /* [in] Ptr to AST field node */ 3807 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 3808) 3809{ 3810 AST_field_attr_n_t *fattr_p; /* Ptr to field attribute node */ 3811 3812 field_type(field_p, int_p); 3813 field_size(field_p, int_p); 3814 3815 field_in_line(field_p); 3816 field_string(field_p); 3817 field_pointer(field_p, int_p); 3818 field_small(field_p); 3819 field_context(field_p); 3820 field_varying(field_p, int_p); 3821 field_ignore(field_p); 3822 field_switch_is(field_p); 3823 3824 CHK_field_cs(field_p); 3825 3826 /* If there is a field attribute node, check it. */ 3827 3828 fattr_p = field_p->field_attrs; 3829 if (fattr_p != NULL) 3830 fattr_check(fattr_p, (ASTP_node_t *)field_p, field_p->type, int_p); 3831} 3832 3833/* 3834** s t r u c t _ c h e c k 3835** 3836** Checks an AST structure node. 3837*/ 3838 3839static void struct_check 3840( 3841 AST_structure_n_t *struct_p, /* [in] Ptr to AST structure node */ 3842 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 3843) 3844{ 3845 AST_field_n_t *field_p; /* A field of the structure */ 3846 3847 /* Check each field node in the structure. */ 3848 3849 field_p = struct_p->fields; 3850 while (field_p != NULL) 3851 { 3852 field_check(field_p, int_p); 3853 field_p = field_p->next; 3854 } 3855} 3856 3857/* 3858** f p _ p a r a m _ h a n d l e 3859** 3860** Checks a parameter node that is part of a function pointer operation 3861** for any issues around handles. 3862*/ 3863 3864static void fp_param_handle 3865( 3866 AST_parameter_n_t *param_p, /* [in] Ptr to AST parameter node */ 3867 AST_type_n_t *type_p, /* [in] Parameter type */ 3868 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 3869) 3870{ 3871 type_p = type_xmit_type(type_p); /* Pick up transmissible type */ 3872 3873 /* Function pointer parameters cannot be of type handle_t */ 3874 3875 if (!AST_LOCAL_SET(int_p) 3876 && type_p->kind == AST_handle_k) 3877 CHECKER_error(param_p, NIDL_FPHANPRM); 3878 3879#if 0 /** This warning is disabled. **/ 3880 /* [handle] attribute of function pointer parameter ignored */ 3881 3882 if (AST_HANDLE_SET(type_p)) 3883 CHECKER_warning(param_p, NIDL_FPHANATTR); 3884#endif 3885} 3886 3887/* 3888** f p _ p a r a m _ c h e c k 3889** 3890** Checks a parameter node that is part of a function pointer operation. 3891** Many of these checks are identical to those for interface operations. 3892** Compare this routine to param_check to see the differences. 3893*/ 3894 3895static void fp_param_check 3896( 3897 AST_parameter_n_t *param_p, /* [in] Ptr to AST parameter node */ 3898 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 3899) 3900{ 3901 AST_field_attr_n_t *fattr_p; /* Field attributes assoc. with param */ 3902 AST_type_n_t *top_type_p; /* Top-level parameter type */ 3903 AST_type_n_t *type_p; /* Param type (deref'd if necess.) */ 3904 AST_type_n_t *deref_type_p; /* Param type (deref'd if necess.) */ 3905 3906 /* 3907 * If the parameter type has a top-level '*' which indicates passing 3908 * mechanism only, follow the pointer to the data of interest. 3909 * top_type_p = top-level parameter type 3910 * type_p = possibly dereferenced parameter type 3911 * deref_type_p = possibly dereferenced parameter type 3912 */ 3913 top_type_p = param_p->type; 3914 type_p = param_follow_ref_ptr(param_p, CHK_follow_ref); 3915 deref_type_p = param_follow_ref_ptr(param_p, CHK_follow_any); 3916 3917 param_type(param_p, top_type_p, type_p, int_p); 3918 3919 /* Check parameter's field attributes, if any. */ 3920 3921 fattr_p = param_p->field_attrs; 3922 if (fattr_p != NULL) 3923 fattr_check(fattr_p, (ASTP_node_t *)param_p, param_p->type, int_p); 3924 3925 param_size(param_p, top_type_p, type_p, int_p); 3926 param_struct(param_p, top_type_p, type_p); 3927 param_pipe(param_p, top_type_p, deref_type_p); 3928 3929 param_string(param_p, type_p); 3930 param_pointer(param_p, top_type_p, type_p, int_p); 3931 param_small(param_p, top_type_p, type_p); 3932 param_context(param_p, top_type_p, deref_type_p); 3933 param_varying(param_p, type_p, int_p); 3934 3935 fp_param_handle(param_p, type_p, int_p); 3936} 3937 3938/* 3939** f u n c t i o n _ p t r _ c h e c k 3940** 3941** Checks an AST function pointer node. 3942*/ 3943 3944static void function_ptr_check 3945( 3946 AST_operation_n_t *op_p, /* [in] Ptr to operation node */ 3947 AST_type_n_t *type_p, /* [in] Ptr to type node of pointer */ 3948 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 3949) 3950{ 3951 AST_parameter_n_t *param_p; /* A parameter in the operation */ 3952 3953/* 3954 * For now, assume that none of the operation attributes are allowed 3955 * on function pointer operations. 3956 */ 3957 3958 /* Function pointers are currently allowed only in local interfaces */ 3959 3960 if (!AST_LOCAL_SET(int_p) 3961 && type_p->xmit_as_type == NULL) 3962 CHECKER_error(op_p, NIDL_FPLOCINT); 3963 3964 /* Check each parameter in the function. */ 3965 3966 for (param_p = op_p->parameters; param_p != NULL; param_p = param_p->next) 3967 fp_param_check(param_p, int_p); 3968 3969 /* Check the function result, if any. */ 3970 3971 if (op_p->result != NULL) 3972 fp_param_check(op_p->result, int_p); 3973} 3974 3975/* 3976** p t r _ p o i n t e e _ t y p e 3977** 3978** Checks a pointer node's pointee type. 3979*/ 3980 3981static void ptr_pointee_type 3982( 3983 AST_pointer_n_t *ptr_p, /* [in] Ptr to AST pointer node */ 3984 AST_type_n_t *ptr_type_p, /* [in] Pointer type node */ 3985 ASTP_node_t *node_p, /* [in] Parent node of ptr type node */ 3986 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 3987) 3988{ 3989 AST_type_n_t *type_p; /* Pointee data type node */ 3990 3991 /* 3992 * Note: No need to pick up transmissible type - if a pointed-at type is 3993 * used in [transmit_as] it must be a named type, so type checking will do. 3994 */ 3995 type_p = ptr_p->pointee_type; 3996 3997 /* 3998 * If the pointer's parent has any array size attributes, then this 3999 * pointer represents an array - ignore the normal pointer checking. 4000 */ 4001 if ( (node_p->fe_info->node_kind == fe_parameter_n_k 4002 && ((AST_parameter_n_t *)node_p)->field_attrs != NULL) 4003 || (node_p->fe_info->node_kind == fe_field_n_k 4004 && ((AST_field_n_t *)node_p)->field_attrs != NULL)) 4005 return; 4006 4007 /* Pointers to pipes valid only in parameter declarations */ 4008 4009 if (type_p->kind == AST_pipe_k 4010 && node_p->fe_info->node_kind != fe_parameter_n_k) 4011 CHECKER_error(ptr_p, NIDL_INVPTRPIPE); 4012 4013 /* Pointers to context handles valid only in parameter declarations */ 4014 4015 if (AST_CONTEXT_RD_SET(type_p) 4016 && node_p->fe_info->node_kind != fe_parameter_n_k 4017 /* OK in opaque context handle typedef */ 4018 && !(node_p->fe_info->node_kind == fe_export_n_k 4019 && type_p->kind == AST_structure_k 4020 && AST_DEF_AS_TAG_SET(type_p))) 4021 CHECKER_error(ptr_p, NIDL_INVPTRCTX); 4022 4023 /* Pointers to type handle_t valid only in parameter declarations */ 4024 4025 if (type_p->kind == AST_handle_k 4026 && node_p->fe_info->node_kind != fe_parameter_n_k) 4027 CHECKER_error(ptr_p, NIDL_HANDLEPTR); 4028 4029 /* void * must be used in conjunction with the [context_handle] attribute */ 4030 /* 4031 * (1) Don't report error if parent node is parameter and [context_handle] 4032 * is set on the parameter. This is one case where an attribute can apply 4033 * to other than the top-level * (e.g. in [out,context_handle] void **p, 4034 * the [context_handle] parameter attribute applies to the second-level * 4035 * which is an anonymous type without the [context_handle] attribute). 4036 */ 4037 if (!AST_LOCAL_SET(int_p) 4038 && type_p->kind == AST_pointer_k 4039 && type_p->type_structure.pointer->pointee_type->kind == AST_void_k 4040 && !AST_CONTEXT_RD_SET(type_p) 4041 && !(node_p->fe_info->node_kind == fe_parameter_n_k /* (1) */ 4042 && AST_CONTEXT_SET((AST_parameter_n_t *)node_p)) 4043 ) 4044 CHECKER_error(node_p, NIDL_PTRVOIDCTX); 4045 4046 /* If this is a function pointer, call routine to check it. */ 4047 4048 if (type_p->kind == AST_function_k) 4049 function_ptr_check(type_p->type_structure.function, ptr_type_p, int_p); 4050} 4051 4052/* 4053** p t r _ c h e c k 4054** 4055** Checks an AST pointer node. 4056*/ 4057 4058static void ptr_check 4059( 4060 AST_pointer_n_t *ptr_p, /* [in] Ptr to AST pointer node */ 4061 AST_type_n_t *ptr_type_p, /* [in] Pointer type node */ 4062 ASTP_node_t *node_p, /* [in] Parent node of ptr type node */ 4063 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 4064) 4065{ 4066 ptr_pointee_type(ptr_p, ptr_type_p, node_p, int_p); 4067} 4068 4069/* 4070** p i p e _ b a s e _ t y p e 4071** 4072** Checks a pipe node's base data type. 4073*/ 4074 4075static void pipe_base_type 4076( 4077 AST_pipe_n_t *pipe_p, /* [in] Ptr to AST pipe node */ 4078 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 4079) 4080{ 4081 AST_type_n_t *type_p; /* Pipe base data type node */ 4082 4083 type_p = pipe_p->base_type; 4084 4085 /* If the pipe base type is anonymous, it must undergo type checks. */ 4086 4087 if (type_is_anonymous(type_p)) 4088 type_check(type_p, (ASTP_node_t *)pipe_p, int_p); 4089 4090 /* Base type of a pipe can't be a pipe type */ 4091 4092 if (type_p->kind == AST_pipe_k) 4093 CHECKER_error(pipe_p, NIDL_PIPEBASETYP); 4094 4095 /* Base type of a pipe can't be a [context_handle] type */ 4096 4097 if (AST_CONTEXT_RD_SET(type_p)) 4098 CHECKER_error(pipe_p, NIDL_CTXBASETYP); 4099 4100 /* Base type of a pipe can't be a conformant type */ 4101 4102 if (AST_CONFORMANT_SET(type_p)) 4103 CHECKER_error(pipe_p, NIDL_CFMTBASETYP); 4104 4105 /* Base type of a pipe cannot be handle_t */ 4106 4107 if (type_p->kind == AST_handle_k) 4108 CHECKER_error(pipe_p, NIDL_HANPIPEBASE); 4109 4110 /* Base type of a pipe cannot be a function pointer */ 4111 4112 if (type_is_function(type_p)) 4113 CHECKER_error(pipe_p, NIDL_FPPIPEBASE); 4114 4115 /* Cant be an interface or interface reference */ 4116 if (type_p->kind == AST_interface_k) 4117 CHECKER_error(pipe_p, NIDL_PIPECTYPE, "interface"); 4118 if (type_p->kind == AST_pointer_k && type_p->type_structure.pointer->pointee_type->kind == AST_interface_k) 4119 CHECKER_error(pipe_p, NIDL_PIPECTYPE, "interface reference"); 4120 4121 /* Base type of a pipe can't be or contain a pointer */ 4122 4123 if (!type_is_function(type_p) 4124 && FE_TEST(type_p->fe_info->flags, FE_HAS_PTR)) 4125 CHECKER_error(pipe_p, NIDL_PTRBASETYP); 4126 4127 /* Base type of a pipe may not have a [transmit_as] type */ 4128 4129 if (type_p->xmit_as_type != NULL) 4130 CHECKER_error(pipe_p, NIDL_XMITPIPEBASE); 4131 4132 /* void is valid only in an operation or pointer declaration */ 4133 4134 if (type_p->kind == AST_void_k) 4135 CHECKER_error(pipe_p, NIDL_VOIDOPPTR); 4136 4137 /* void * must be used in conjunction with the [context_handle] attribute */ 4138 4139 if (!AST_LOCAL_SET(int_p) 4140 && type_p->xmit_as_type == NULL 4141 && type_p->kind == AST_pointer_k 4142 && type_p->type_structure.pointer->pointee_type->kind == AST_void_k 4143 && !AST_CONTEXT_RD_SET(type_p) 4144 ) 4145 CHECKER_error(pipe_p, NIDL_PTRVOIDCTX); 4146 4147 CHK_pipe_base_type_cs(pipe_p, int_p); 4148} 4149 4150/* 4151** p i p e _ c h e c k 4152** 4153** Checks an AST pipe node. 4154*/ 4155 4156static void pipe_check 4157( 4158 AST_pipe_n_t *pipe_p, /* [in] Ptr to AST pipe node */ 4159 AST_type_n_t *type_p, /* [in] Ptr to pipe data type node */ 4160 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 4161) 4162{ 4163 /* A pipe may not have a [transmit_as] type */ 4164 4165 if (type_p->xmit_as_type != NULL) 4166 CHECKER_error(pipe_p, NIDL_PIPEXMITAS); 4167 4168 /* Pipes must be defined with typedef */ 4169 4170 if (type_p->name == NAMETABLE_NIL_ID) 4171 CHECKER_error(pipe_p, NIDL_ANONPIPE); 4172 4173 pipe_base_type(pipe_p, int_p); 4174} 4175 4176/* 4177** e n u m _ c h e c k 4178** 4179** Checks an AST enumeration node. 4180*/ 4181 4182static void enum_check 4183( 4184 AST_enumeration_n_t *enum_p, /* [in] Ptr to AST enumeration node */ 4185 AST_type_n_t *type_p /* [in] Ptr to enum data type node */ 4186) 4187{ 4188 /* Use of anonymous enum may not be portable across C compilers */ 4189 if (type_is_anonymous(type_p)) 4190 CHECKER_warning(enum_p, NIDL_NOPORTANON, "enum"); 4191} 4192 4193/* 4194** c l a b e l _ v a l u e 4195** 4196** Checks a case label node's constant value. 4197*/ 4198 4199static void clabel_value 4200( 4201 AST_case_label_n_t *clabel_p, /* [in] Ptr to AST case label node */ 4202 AST_type_n_t *type_p /* [in] Union discriminator data type */ 4203) 4204{ 4205 AST_constant_n_t *const_p; /* Constant value in case label */ 4206 4207 /* Ignore if default case in union, which does not have a value. */ 4208 4209 if (clabel_p->default_label) 4210 return; 4211 4212 const_p = clabel_p->value; 4213 4214 /* Invalid case label type */ 4215 4216 if (!const_is_integer(const_p) 4217 && !const_is_enum(const_p) 4218 && const_p->kind != AST_boolean_const_k 4219 && const_p->kind != AST_char_const_k) 4220 { 4221 CHECKER_error(clabel_p, NIDL_INVCASETYP); 4222 return; 4223 } 4224 4225 /* Case label type does not agree with discriminator type */ 4226 4227 if ((type_is_integer(type_p) 4228 && !const_is_integer(const_p)) 4229 || (type_is_enum(type_p) 4230 && !const_is_enum(const_p)) 4231 || (type_p->kind == AST_boolean_k 4232 && const_p->kind != AST_boolean_const_k) 4233 || (type_p->kind == AST_character_k 4234 && const_p->kind != AST_char_const_k)) 4235 { 4236 CHECKER_error(clabel_p, NIDL_CASEDISCTYPE); 4237 return; 4238 } 4239 4240 /* Case label must be a constant from discriminator's enumeration type */ 4241 4242 if (type_is_enum(type_p)) 4243 { 4244 char const *clabel_name; /* Name of case label constant */ 4245 char const *econst_name; /* Name of a constant in enumeration */ 4246 AST_enumeration_n_t *enum_p; /* Ptr to enumeration node */ 4247 AST_constant_n_t *econst_p; /* Ptr to a constant node in the enum */ 4248 4249 NAMETABLE_id_to_string(const_p->name, &clabel_name); 4250 if (clabel_name == NULL) 4251 return; /* Shouldn't happen */ 4252 4253 enum_p = type_p->type_structure.enumeration; 4254 4255 econst_p = enum_p->enum_constants; 4256 while (econst_p != NULL) 4257 { 4258 NAMETABLE_id_to_string(econst_p->name, &econst_name); 4259 if (econst_name == NULL) 4260 continue; /* Shouldn't happen */ 4261 4262 if (strcmp(clabel_name, econst_name) == 0) 4263 return; /* Matching constant in right enum; return */ 4264 4265 econst_p = econst_p->next; 4266 } 4267 4268 /* Matching constant name not found in the relevant enumeration. */ 4269 4270 CHECKER_error(clabel_p, NIDL_CASECONENUM); 4271 } 4272} 4273 4274/* 4275** c l a b e l _ c h e c k 4276** 4277** Checks an AST case label node. 4278*/ 4279 4280static void clabel_check 4281( 4282 AST_case_label_n_t *clabel_p, /* [in] Ptr to AST case label node */ 4283 AST_type_n_t *type_p /* [in] Union discriminator data type */ 4284) 4285{ 4286 clabel_value(clabel_p, type_p); 4287} 4288 4289/* 4290** a r m _ t y p e 4291** 4292** Check an arm node's data type. 4293*/ 4294 4295static void arm_type 4296( 4297 AST_arm_n_t *arm_p, /* [in] Ptr to AST arm node */ 4298 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 4299) 4300{ 4301 AST_type_n_t *type_p; /* Data type of the arm */ 4302 4303 type_p = arm_p->type; 4304 if (type_p == NULL) 4305 return; 4306 4307 /* If the arm type is anonymous, it must undergo type checks. */ 4308 4309 if (type_is_anonymous(type_p)) 4310 type_check(type_p, (ASTP_node_t *)arm_p, int_p); 4311 4312 /* A type with [transmit_as] may not have other type attributes */ 4313 4314 if (type_p->xmit_as_type != NULL 4315 && 4316 (AST_STRING_SET(arm_p) 4317 || AST_STRING0_SET(arm_p) 4318 || AST_UNIQUE_SET(arm_p) 4319 || AST_REF_SET(arm_p) 4320 || AST_SMALL_SET(arm_p) 4321 || AST_CONTEXT_SET(arm_p) 4322 || AST_PTR_SET(arm_p))) 4323 CHECKER_error(arm_p, NIDL_XMITTYPEATTRS); 4324 4325 type_p = type_xmit_type(type_p); /* Pick up transmissible type */ 4326 4327 /* Conformant arrays or structures are invalid within unions */ 4328 /* WEZ:FIXME we need them for ORPC! */ 4329#ifdef notdef 4330 if (AST_CONFORMANT_SET(type_p)) 4331 CHECKER_error(arm_p, NIDL_CFMTUNION); 4332#endif 4333 4334 /* interface must have a * */ 4335 if (type_p->kind == AST_interface_k) { 4336 char const * id_name; 4337 NAMETABLE_id_to_string(type_p->name, &id_name); 4338 CHECKER_error(arm_p, NIDL_INTREFNOTALO, id_name); 4339 } 4340 4341 /* Pipes not valid as members of unions */ 4342 4343 if (type_p->kind == AST_pipe_k) 4344 CHECKER_error(arm_p, NIDL_PIPEUNIMEM); 4345 4346 /* Context handles not valid as members of unions */ 4347 4348 if (AST_CONTEXT_RD_SET(type_p) 4349 || AST_CONTEXT_SET(arm_p)) 4350 CHECKER_error(arm_p, NIDL_CTXUNIMEM); 4351 4352 /* Function pointers not valid as members of unions */ 4353 4354 if (!AST_LOCAL_SET(int_p) 4355 && type_is_function(type_p)) 4356#if 0 /** Obsolete **/ 4357 && type_p->xmit_as_type == NULL) 4358#endif 4359 CHECKER_error(arm_p, NIDL_FPUNIMEM); 4360 4361 /* Members of unions cannot be of type handle_t */ 4362 4363 if (type_p->kind == AST_handle_k) 4364#if 0 /** Obsolete **/ 4365 && type_p->xmit_as_type == NULL) 4366#endif 4367 CHECKER_error(arm_p, NIDL_HANUNIMEM); 4368 4369 /* void is valid only in an operation or pointer declaration */ 4370 4371 if (type_p->kind == AST_void_k) 4372 CHECKER_error(arm_p, NIDL_VOIDOPPTR); 4373 4374 /* void * must be used in conjunction with the [context_handle] attribute */ 4375 4376 if (!AST_LOCAL_SET(int_p) 4377#if 0 /** Obsolete **/ 4378 && type_p->xmit_as_type == NULL 4379#endif 4380 && type_p->kind == AST_pointer_k 4381 && type_p->type_structure.pointer->pointee_type->kind == AST_void_k 4382 && !AST_CONTEXT_RD_SET(type_p) 4383 && !AST_CONTEXT_SET(arm_p) 4384 ) 4385 CHECKER_error(arm_p, NIDL_PTRVOIDCTX); 4386 4387 /* 4388 * V1 attributes are incompatible with this type 4389 * Note: Issue error only if the same error doesn't fire for the type. 4390 */ 4391 if (FE_TEST(arm_p->fe_info->flags, FE_HAS_V1_ATTR) 4392 && FE_TEST(arm_p->fe_info->flags, FE_HAS_V2_ATTR) 4393 && ! ( FE_TEST(type_p->fe_info->flags, FE_HAS_V1_ATTR) 4394 && FE_TEST(type_p->fe_info->flags, FE_HAS_V2_ATTR) )) 4395 CHECKER_warning(arm_p, NIDL_INCOMPATV1); 4396} 4397 4398/* 4399** a r m _ s t r i n g 4400** 4401** Checks an arm node's [string] and [v1_string] attributes. 4402*/ 4403 4404static void arm_string 4405( 4406 AST_arm_n_t *arm_p /* [in] Ptr to AST arm node */ 4407) 4408{ 4409 AST_type_n_t *type_p; /* Data type of the arm */ 4410 4411 type_p = arm_p->type; /* Possibly NULL */ 4412 4413 /* Remaining checks do not apply to an empty arm. */ 4414 4415 if (type_p == NULL) 4416 return; 4417 4418 /* A [v1_string] must be an array of char with fixed bounds */ 4419 4420 if (AST_STRING0_SET(arm_p) 4421 && !type_is_v1_string(type_p)) 4422 CHECKER_error(arm_p, NIDL_STRV1FIXED); 4423 4424 /* The [v1_string] attribute can only be applied to a [v1_array] */ 4425 4426 if ((AST_STRING0_SET(arm_p) || AST_STRING0_SET(type_p)) 4427 && !(AST_SMALL_SET(arm_p) || AST_SMALL_SET(type_p))) 4428 CHECKER_error(arm_p, NIDL_STRV1ARRAY); 4429 4430 /* The [string] attribute cannot be applied to a [v1_array] */ 4431 4432 if ((AST_STRING_SET(arm_p) && AST_SMALL_SET(arm_p)) 4433 || (AST_STRING_SET(arm_p) && AST_SMALL_SET(type_p)) 4434 || (AST_STRING_SET(type_p) && AST_SMALL_SET(arm_p))) 4435 CHECKER_error(arm_p, NIDL_STRARRAYV1); 4436 4437 /* [string] attribute valid only for one-dim arrays of char or byte */ 4438 4439 if (AST_STRING_SET(arm_p) 4440 && !type_is_string(type_p)) 4441 CHECKER_error(arm_p, NIDL_STRCHARBYTE); 4442 4443 /* Cannot have both [string] and [v1_string] attributes */ 4444 4445 if ( (AST_STRING_SET(arm_p) || AST_STRING_SET(type_p)) 4446 && (AST_STRING0_SET(arm_p) || AST_STRING0_SET(type_p)) ) 4447 { 4448 ASTP_attr_flag_t attr1 = ASTP_STRING; 4449 ASTP_attr_flag_t attr2 = ASTP_STRING0; 4450 4451 CHECKER_error(arm_p, NIDL_CONFLICTATTR, 4452 KEYWORDS_lookup_text(AST_attribute_to_token(&attr1)), 4453 KEYWORDS_lookup_text(AST_attribute_to_token(&attr2))); 4454 } 4455} 4456 4457/* 4458** a r m _ p o i n t e r 4459** 4460** Checks an arm node's attributes related to pointers. 4461*/ 4462 4463static void arm_pointer 4464( 4465 AST_arm_n_t *arm_p, /* [in] Ptr to AST arm node */ 4466 AST_interface_n_t *int_p ATTRIBUTE_UNUSED /* [in] Ptr to interface node */ 4467) 4468{ 4469 AST_type_n_t *type_p; /* Data type of the arm */ 4470 boolean pointer_attr_valid = FALSE; 4471 4472 type_p = arm_p->type; 4473 if (type_p == NULL) 4474 return; 4475 4476 type_p = type_xmit_type(type_p); /* Pick up transmissible type */ 4477 4478 /* An arm of a union can't be or contain a [ref] pointer */ 4479 /* WEZ:FIXME we need this for ORPC */ 4480#ifdef nodef 4481 if (FE_TEST(type_p->fe_info->flags, FE_HAS_REF_PTR) || 4482 AST_REF_SET(arm_p)) 4483 CHECKER_error(arm_p, NIDL_ARMREFPTR); 4484#endif 4485 if (type_p->kind == AST_pointer_k 4486 && type_p->type_structure.pointer->pointee_type->kind != AST_void_k) 4487 pointer_attr_valid = TRUE; 4488 4489 /* [ref] attribute valid only for pointer or array types */ 4490 4491 if (AST_REF_SET(arm_p) && !pointer_attr_valid) 4492 CHECKER_error(arm_p, NIDL_REFATTRPTR); 4493 4494#if 0 4495 /* ignore REF, UNIQUE or PTR for pointers to interfaces */ 4496 if (type_p->kind == AST_pointer_k && type_p->type_structure.pointer->pointee_type->kind == AST_interface_k 4497 && (AST_UNIQUE_SET(arm_p) || AST_REF_SET(arm_p) || AST_PTR_SET(arm_p))) 4498 CHECKER_warning(arm_p, NIDL_PTRATTBIGN); 4499#endif 4500 /* An arm of a union can't be or contain a [unique] pointer */ 4501 4502#ifdef notdef 4503 if (FE_TEST(type_p->fe_info->flags, FE_HAS_UNIQUE_PTR) || 4504 AST_UNIQUE_SET(arm_p)) 4505 CHECKER_error(arm_p, NIDL_ARMUNIQUEPTR); 4506#endif 4507 4508 /* [unique] attribute valid only for pointer or array types */ 4509 4510 if (AST_UNIQUE_SET(arm_p) && !pointer_attr_valid) 4511 CHECKER_error(arm_p, NIDL_UNIQATTRPTR); 4512 4513 /* [ptr] attribute valid only for pointer or array types */ 4514 4515 if (AST_PTR_SET(arm_p) && !pointer_attr_valid) 4516 CHECKER_error(arm_p, NIDL_PTRATTRPTR); 4517 4518 /* [unique] attribute requires -standard extended */ 4519 4520 if (AST_UNIQUE_SET(arm_p) 4521 && (*(int *)cmd_val[opt_standard] <= opt_standard_dce_1_0)) 4522 CHECKER_warning(arm_p, NIDL_NOPORTUNIQUE, OPT_STD_EXTENDED); 4523 4524 /* An array with a pointer attribute is valid only as a parameter. */ 4525 4526 /* 4527 * Have to check type attrs as well as arm attributes for the obscure case 4528 * of transmit_as type whose transmissible type is an array with a pointer 4529 * attr, since propagation from type to arm doesn't happen in this case. 4530 */ 4531 if (type_p->kind == AST_array_k && 4532 (AST_REF_SET(arm_p) || AST_PTR_SET(arm_p) || AST_UNIQUE_SET(arm_p) || 4533 AST_REF_SET(type_p) || AST_PTR_SET(type_p) || AST_UNIQUE_SET(type_p))) 4534 CHECKER_error(arm_p, NIDL_ARRPTRPRM); 4535 4536 /* 4537 * **NOTE**: It could be valid for an arm to be a varying array, however 4538 * the AST can not represent this since there is no arm_p->field_attrs 4539 * field. If there were, an arm that is a pointer and has any of the 4540 * array attributes would undergo the checks for arrays here. 4541 */ 4542} 4543 4544/* 4545** a r m _ s m a l l 4546** 4547** Checks an arm node's [v1_array] attribute. 4548*/ 4549 4550static void arm_small 4551( 4552 AST_arm_n_t *arm_p /* [in] Ptr to AST arm node */ 4553) 4554{ 4555 AST_type_n_t *type_p; /* Data type of the arm */ 4556 AST_array_n_t *array_p; /* Ptr to array node */ 4557 4558 type_p = arm_p->type; /* Possibly NULL */ 4559 4560 /* Check only applies to array types. */ 4561 4562 if (type_p == NULL 4563 || !type_is_array_np(type_p)) 4564 return; 4565 4566 array_p = type_p->type_structure.array; 4567 4568 /* [v1_array] attribute invalid for array with more than 65535 elements */ 4569 4570 if (AST_SMALL_SET(arm_p) 4571 && array_is_large(array_p)) 4572 CHECKER_error(arm_p, NIDL_SMALLINV); 4573} 4574 4575/* 4576** a r m _ c o n t e x t 4577** 4578** Checks an arm node's [context_handle] attribute. 4579*/ 4580 4581static void arm_context 4582( 4583 AST_arm_n_t *arm_p /* [in] Ptr to AST arm node */ 4584) 4585{ 4586 AST_type_n_t *type_p; /* Data type of the arm */ 4587 4588 type_p = arm_p->type; 4589 if (type_p == NULL) 4590 return; 4591 4592 /* [context_handle] attribute only applies to void * types */ 4593 4594 if (AST_CONTEXT_SET(arm_p) 4595 && (type_p->kind != AST_pointer_k 4596 || (type_p->kind == AST_pointer_k 4597 && type_p->type_structure.pointer->pointee_type->kind 4598 != AST_void_k))) 4599 CHECKER_error(arm_p, NIDL_CTXPTRVOID); 4600 4601 /* [unique] pointers to context handles are not allowed */ 4602 4603 if (AST_UNIQUE_SET(arm_p) 4604 && type_p->kind == AST_pointer_k 4605 && AST_CONTEXT_RD_SET(type_p->type_structure.pointer->pointee_type)) 4606 CHECKER_error(arm_p, NIDL_UNIQCTXHAN); 4607 4608 /* Full pointers to context handles are not allowed */ 4609 4610 if (AST_PTR_SET(arm_p) 4611 && type_p->kind == AST_pointer_k 4612 && AST_CONTEXT_RD_SET(type_p->type_structure.pointer->pointee_type)) 4613 CHECKER_error(arm_p, NIDL_PTRCTXHAN); 4614} 4615 4616/* 4617** a r m _ c h e c k 4618** 4619** Checks an AST arm node. 4620*/ 4621 4622static void arm_check 4623( 4624 AST_arm_n_t *arm_p, /* [in] Ptr to AST arm node */ 4625 AST_type_n_t *type_p, /* [in] Discriminator data type */ 4626 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 4627) 4628{ 4629 AST_case_label_n_t *clabel_p; /* List of case labels for this arm */ 4630 4631 arm_type(arm_p, int_p); 4632 4633 arm_string(arm_p); 4634 arm_pointer(arm_p, int_p); 4635 arm_small(arm_p); 4636 arm_context(arm_p); 4637 4638 /* Check each case label for this arm. */ 4639 4640 if (type_p == NULL) return; 4641 clabel_p = arm_p->labels; 4642 while (clabel_p != NULL) 4643 { 4644 clabel_check(clabel_p, type_p); 4645 clabel_p = clabel_p->next; 4646 } 4647} 4648 4649/* 4650** u n i o n _ d i s c r i m _ t y p e 4651** 4652** Checks a discriminated union node's discriminator data type. 4653*/ 4654 4655static void union_discrim_type 4656( 4657 AST_disc_union_n_t *union_p /* [in] Ptr to AST discr. union node */ 4658) 4659{ 4660 AST_type_n_t *type_p; /* Discriminator data type */ 4661 4662 type_p = union_p->discrim_type; 4663 if (type_p == NULL) return; 4664 4665 /* Union discriminator type must be int, char, boolean, or enum */ 4666 4667 if (!type_is_index(type_p) 4668 && !type_is_enum(type_p) 4669 && type_p->kind != AST_boolean_k 4670 && type_p->kind != AST_character_k) 4671 CHECKER_error(union_p, NIDL_UNIDISCTYP); 4672} 4673 4674/* 4675** u n i o n _ c a s e _ l a b e l s 4676** 4677** Checks a discriminated union's case label values for uniqueness. 4678*/ 4679 4680static void union_case_labels 4681( 4682 AST_disc_union_n_t *union_p /* [in] Ptr to AST discr. union node */ 4683) 4684{ 4685 AST_arm_n_t *arm_p; /* Ptr to one arm node of the union */ 4686 AST_case_label_n_t *clabel_p; /* Ptr to one case label of the arm */ 4687 AST_arm_n_t *s_arm_p; /* Ptr to a subsequent arm */ 4688 AST_case_label_n_t *s_clabel_p; /* Ptr to a subsequent case label */ 4689 boolean dup; /* True if duplicate case label */ 4690 4691 arm_p = union_p->arms; 4692 while (arm_p != NULL) 4693 { 4694 clabel_p = arm_p->labels; 4695 while (clabel_p != NULL) 4696 { 4697 /* 4698 * Check all subsequent arms for a repeated case label value. 4699 * A repeated case label value within an arm is OK. 4700 */ 4701 s_arm_p = arm_p->next; 4702 while (s_arm_p != NULL) 4703 { 4704 s_clabel_p = s_arm_p->labels; 4705 4706 /* Go through all labels of this subsequent arm. */ 4707 4708 dup = FALSE; 4709 4710 while (s_clabel_p != NULL) 4711 { 4712 /* Check for duplicate "case default:" */ 4713 4714 if (clabel_p->default_label && s_clabel_p->default_label) 4715 dup = TRUE; 4716 else if (clabel_p->value != NULL 4717 && s_clabel_p->value != NULL 4718 && clabel_p->value->kind == s_clabel_p->value->kind) 4719 { 4720 /* Check for duplicate case label values. */ 4721 4722 switch (clabel_p->value->kind) 4723 { 4724 case AST_nil_const_k: 4725 break; 4726 case AST_int_const_k: 4727 dup = (clabel_p->value->value.int_val 4728 == s_clabel_p->value->value.int_val); 4729 break; 4730 case AST_hyper_int_const_k: 4731 dup = (clabel_p->value->value.hyper_int_val.high 4732 == s_clabel_p->value->value.hyper_int_val.high 4733 && 4734 clabel_p->value->value.hyper_int_val.low 4735 == s_clabel_p->value->value.hyper_int_val.low); 4736 break; 4737 case AST_char_const_k: 4738 dup = (clabel_p->value->value.char_val 4739 == s_clabel_p->value->value.char_val); 4740 break; 4741 case AST_string_const_k: 4742 break; 4743 case AST_boolean_const_k: 4744 dup = (clabel_p->value->value.boolean_val 4745 == s_clabel_p->value->value.boolean_val); 4746 break; 4747 default: 4748 error(NIDL_INTERNAL_ERROR, __FILE__, __LINE__); 4749 } /* switch (clabel_p->value->kind) */ 4750 } /* else if (same constant kinds) */ 4751 4752 /* Duplicate case label value invalid */ 4753 4754 if (dup) 4755 { 4756 CHECKER_error(s_clabel_p, NIDL_DUPCASEVAL); 4757 break; 4758 } 4759 4760 s_clabel_p = s_clabel_p->next; 4761 } /* while (s_clabel_p != NULL) */ 4762 4763 if (dup) 4764 break; 4765 else 4766 s_arm_p = s_arm_p->next; 4767 } /* while (s_arm_p != NULL) */ 4768 4769 clabel_p = clabel_p->next; 4770 } /* while (clabel_p != NULL) */ 4771 4772 arm_p = arm_p->next; 4773 } /* while (arm_p != NULL) */ 4774} 4775 4776/* 4777** u n i o n _ c h e c k 4778** 4779** Checks an AST discriminated union node. 4780*/ 4781 4782static void union_check 4783( 4784 AST_disc_union_n_t *union_p, /* [in] Ptr to AST discr. union node */ 4785 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 4786) 4787{ 4788 AST_arm_n_t *arm_p; /* Ptr to one arm node of the union */ 4789 4790 union_discrim_type(union_p); 4791 union_case_labels(union_p); 4792 4793 /* Use of a nonencapsulated union requires -standard extended */ 4794 4795 if (union_p->discrim_name == NAMETABLE_NIL_ID 4796 && (*(int *)cmd_val[opt_standard] <= opt_standard_dce_1_0)) 4797 CHECKER_warning(union_p, NIDL_NOPORTNEU, OPT_STD_EXTENDED); 4798 4799 /* Check each arm of the union. */ 4800 4801 arm_p = union_p->arms; 4802 while (arm_p != NULL) 4803 { 4804 arm_check(arm_p, union_p->discrim_type, int_p); 4805 arm_p = arm_p->next; 4806 } 4807} 4808 4809/* 4810** t y p e _ n a m e _ l e n 4811** 4812** Checks a type node's name length. 4813*/ 4814 4815static void type_name_len 4816( 4817 AST_type_n_t *top_type_p, /* [in] Top-level presented type */ 4818 AST_type_n_t *type_p, /* [in] Ptr to AST type node */ 4819 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 4820) 4821{ 4822 char const *type_name; /* Type name */ 4823 int type_len; /* Length of type name */ 4824 int max_len; /* Maximum identifier length */ 4825 4826 if (!AST_LOCAL_SET(int_p) 4827 && top_type_p->name != NAMETABLE_NIL_ID 4828 && top_type_p->xmit_as_type != NULL) /* Pres type != transmit type */ 4829 { 4830 NAMETABLE_id_to_string(top_type_p->name, &type_name); 4831 if (type_name == NULL) 4832 return; /* Shouldn't happen */ 4833 4834 type_len = strlen(type_name); 4835 4836 /* Maximum id length for type with [transmit_as] is <n> characters */ 4837 4838 max_len = MAX_ID - strlen("_from_xmit"); 4839 if (type_len > max_len) 4840 CHECKER_error(top_type_p, NIDL_MAXIDTYPTA, max_len); 4841 } 4842 4843 if (type_p->name == NAMETABLE_NIL_ID) 4844 return; 4845 4846 NAMETABLE_id_to_string(type_p->name, &type_name); 4847 if (type_name == NULL) 4848 return; /* Shouldn't happen */ 4849 4850 type_len = strlen(type_name); 4851 4852 /* Maximum identifier length for [handle] type is <n> characters */ 4853 4854 max_len = MAX_ID - strlen("_unbind"); 4855 if (!AST_LOCAL_SET(int_p) 4856 && type_len > max_len 4857 && AST_HANDLE_SET(type_p)) 4858 CHECKER_error(type_p, NIDL_MAXIDTYPHAN, max_len); 4859 4860 /* Maximum identifier length for [context_handle] type is <n> characters */ 4861 4862 max_len = MAX_ID - strlen("_rundown"); 4863 if (!AST_LOCAL_SET(int_p) 4864 && type_len > max_len 4865 && AST_CONTEXT_RD_SET(type_p)) 4866 CHECKER_error(type_p, NIDL_MAXIDTYPCH, max_len); 4867 4868 /* Maximum identifier length for pointed-to type is <n> characters */ 4869 4870 max_len = MAX_ID - strlen("_mr"); 4871 if (!AST_LOCAL_SET(int_p) 4872 && !AST_IN_VARYING_SET(type_p) && !AST_OUT_VARYING_SET(type_p) 4873 && type_len > max_len 4874 && FE_TEST(type_p->fe_info->flags,FE_POINTED_AT)) 4875 { 4876 char const *file_name; 4877 AST_type_n_t *ptr_type_p = type_p->fe_info->type_specific.pointer_type; 4878 4879 CHECKER_error(type_p, NIDL_MAXIDTYPPT, max_len); 4880 /* Give location of pointer declaration that points at this type. */ 4881 STRTAB_str_to_string(ptr_type_p->fe_info->file, &file_name); 4882 CHECKER_warning(type_p, NIDL_NAMEREFAT, file_name, 4883 ptr_type_p->fe_info->source_line); 4884 } 4885 4886 max_len = MAX_ID - strlen("_mrV"); 4887 if (!AST_LOCAL_SET(int_p) 4888 && (AST_IN_VARYING_SET(type_p) || AST_OUT_VARYING_SET(type_p)) 4889 && type_len > max_len 4890 && FE_TEST(type_p->fe_info->flags,FE_POINTED_AT)) 4891 { 4892 char const *file_name; 4893 AST_type_n_t *ptr_type_p = type_p->fe_info->type_specific.pointer_type; 4894 4895 CHECKER_error(type_p, NIDL_MAXIDTYPPT, max_len); 4896 /* Give location of pointer declaration that points at this type. */ 4897 STRTAB_str_to_string(ptr_type_p->fe_info->file, &file_name); 4898 CHECKER_warning(type_p, NIDL_NAMEREFAT, file_name, 4899 ptr_type_p->fe_info->source_line); 4900 } 4901 4902 /* Maximum identifier length for pipe type is <n> characters */ 4903 4904 max_len = MAX_ID - strlen("_h"); 4905 if (!AST_LOCAL_SET(int_p) 4906 && type_len > max_len 4907 && type_p->kind == AST_pipe_k) 4908 CHECKER_error(type_p, NIDL_MAXIDTYPPIPE, max_len); 4909 4910 /* Maximum identifier length for [represent_as] type is <n> characters */ 4911 4912 max_len = MAX_ID - strlen("_from_local"); 4913 if (!AST_LOCAL_SET(int_p) 4914 && type_len > max_len 4915 && type_p->rep_as_type != NULL) 4916 CHECKER_error(type_p, NIDL_MAXIDTYPRA, max_len); 4917 4918 /* Maximum identifier length for [out_of_line] type is <n> characters */ 4919 4920 max_len = MAX_ID - strlen("Omr"); 4921 if (!AST_LOCAL_SET(int_p) 4922 && !AST_IN_VARYING_SET(type_p) && !AST_OUT_VARYING_SET(type_p) 4923 && type_len > max_len 4924 && AST_OUT_OF_LINE_SET(type_p)) 4925 CHECKER_error(type_p, NIDL_MAXIDTYPOOL, max_len); 4926 4927 max_len = MAX_ID - strlen("OmrV"); 4928 if (!AST_LOCAL_SET(int_p) 4929 && (AST_IN_VARYING_SET(type_p) || AST_OUT_VARYING_SET(type_p)) 4930 && type_len > max_len 4931 && AST_OUT_OF_LINE_SET(type_p)) 4932 CHECKER_error(type_p, NIDL_MAXIDTYPOOL, max_len); 4933} 4934 4935/* 4936** t y p e _ i n _ l i n e 4937** 4938** Checks a type node's [in_line] and [out_of_line] attributes. 4939*/ 4940 4941static void type_in_line 4942( 4943 AST_type_n_t *type_p /* [in] Ptr to AST type node */ 4944) 4945{ 4946 /* Can't have both [in_line] and [out_of_line] type attributes */ 4947 4948 if (AST_IN_LINE_SET(type_p) 4949 && AST_OUT_OF_LINE_SET(type_p)) 4950 CHECKER_acf_error(type_p, NIDL_TYPLINEATTR); 4951 4952 /* [in_line] and [out_of_line] attributes apply only to non-scalar types */ 4953 4954 if ((AST_IN_LINE_SET(type_p) || AST_OUT_OF_LINE_SET(type_p)) 4955 && type_is_scalar(type_p)) 4956 { 4957 char const *file_name; /* Related file name */ 4958 char const *type_name; /* Data type name */ 4959 4960 STRTAB_str_to_string(type_p->fe_info->file, &file_name); 4961 NAMETABLE_id_to_string(type_p->name, &type_name); 4962 4963 CHECKER_acf_warning(type_p, NIDL_LINENONSCAL); 4964 CHECKER_acf_warning(type_p, NIDL_NAMEDECLAT, type_name, file_name, 4965 type_p->fe_info->source_line); 4966 } 4967} 4968 4969/* 4970** t y p e _ s t r i n g 4971** 4972** Checks a type node's [string] and [v1_string] attributes. 4973*/ 4974 4975static void type_string 4976( 4977 AST_type_n_t *type_p /* [in] Ptr to AST type node */ 4978) 4979{ 4980 /* A [v1_string] must be an array of char with fixed bounds */ 4981 4982 if (AST_STRING0_SET(type_p) 4983 && !type_is_v1_string(type_p)) 4984 CHECKER_error(type_p, NIDL_STRV1FIXED); 4985 4986 /* The [string] attribute cannot be applied to a [v1_array] */ 4987 4988 if (AST_STRING_SET(type_p) && AST_SMALL_SET(type_p)) 4989 CHECKER_error(type_p, NIDL_STRARRAYV1); 4990 4991 /* [string] attribute valid only for one-dim arrays of char or byte */ 4992 4993 if (AST_STRING_SET(type_p) 4994 && !type_is_string(type_p)) 4995 CHECKER_error(type_p, NIDL_STRCHARBYTE); 4996 4997 /* Cannot have both [string] and [v1_string] attributes */ 4998 4999 if (AST_STRING_SET(type_p) 5000 && AST_STRING0_SET(type_p)) 5001 { 5002 ASTP_attr_flag_t attr1 = ASTP_STRING; 5003 ASTP_attr_flag_t attr2 = ASTP_STRING0; 5004 5005 CHECKER_error(type_p, NIDL_CONFLICTATTR, 5006 KEYWORDS_lookup_text(AST_attribute_to_token(&attr1)), 5007 KEYWORDS_lookup_text(AST_attribute_to_token(&attr2))); 5008 } 5009} 5010 5011/* 5012** t y p e _ p o i n t e r 5013** 5014** Checks a type node's attributes related to pointers. 5015*/ 5016 5017static void type_pointer 5018( 5019 AST_type_n_t *type_p /* [in] Ptr to AST type node */ 5020) 5021{ 5022 boolean pointer_attr_valid = FALSE; 5023 5024 if (type_p->kind == AST_array_k 5025 || (type_p->kind == AST_pointer_k 5026 && type_p->type_structure.pointer->pointee_type->kind 5027 != AST_void_k)) 5028 pointer_attr_valid = TRUE; 5029 5030 /* [ref] attribute valid only for pointer or array types */ 5031 5032 if (AST_REF_SET(type_p) && !pointer_attr_valid) 5033 CHECKER_error(type_p, NIDL_REFATTRPTR); 5034 5035 /* [unique] attribute valid only for pointer or array types */ 5036 5037 if (AST_UNIQUE_SET(type_p) && !pointer_attr_valid) 5038 CHECKER_error(type_p, NIDL_UNIQATTRPTR); 5039#if 0 5040 /* ignore REF, UNIQUE or PTR for pointers to interfaces */ 5041 if (type_p->kind == AST_pointer_k && type_p->type_structure.pointer->pointee_type->kind == AST_interface_k 5042 && (AST_UNIQUE_SET(type_p) || AST_REF_SET(type_p) || AST_PTR_SET(type_p))) 5043 CHECKER_warning(type_p, NIDL_PTRATTBIGN); 5044#endif 5045 /* [ptr] attribute valid only for pointer or array types */ 5046 5047 if (AST_PTR_SET(type_p) && !pointer_attr_valid) 5048 CHECKER_error(type_p, NIDL_PTRATTRPTR); 5049 5050 /* [unique] attribute requires -standard extended */ 5051 5052 if (AST_UNIQUE_SET(type_p) 5053 && (*(int *)cmd_val[opt_standard] <= opt_standard_dce_1_0)) 5054 CHECKER_warning(type_p, NIDL_NOPORTUNIQUE, OPT_STD_EXTENDED); 5055 5056 /* An array with a pointer attribute is valid only as a parameter. */ 5057 5058 if (FE_TEST(type_p->fe_info->flags, FE_HAS_PTR_ARRAY)) 5059 CHECKER_error(type_p, NIDL_ARRPTRPRM); 5060 5061 /* Cannot have more than one level of indirection to a ne union */ 5062 5063#if 0 5064 { 5065 AST_type_n_t *top_type_p = type_p; 5066 type_p = ASTP_chase_ptr_to_kind(type_p, AST_disc_union_k); 5067 if (type_p != NULL 5068 && type_p->kind == AST_disc_union_k 5069 && type_p->type_structure.disc_union->discrim_name == NAMETABLE_NIL_ID 5070 && type_p->fe_info->pointer_count > 1) 5071 CHECKER_error(top_type_p, NIDL_PTRNEUNION); 5072 } 5073#endif 5074} 5075 5076/* 5077** t y p e _ s m a l l 5078** 5079** Checks a type node's [v1_array] attribute. 5080*/ 5081 5082static void type_small 5083( 5084 AST_type_n_t *type_p /* [in] Ptr to AST type node */ 5085) 5086{ 5087 AST_array_n_t *array_p; /* Ptr to array node */ 5088 5089 /* A [v1_array] must be in array, not pointer, syntax */ 5090 5091 if (AST_SMALL_SET(type_p) 5092 && type_p->kind == AST_pointer_k) 5093 CHECKER_error(type_p, NIDL_SMALLARRSYN); 5094 5095 /* 5096 * Remaining checks only apply to array types in array syntax. 5097 * V1 did not allow arrays in pointer syntax. 5098 */ 5099 if (!type_is_array_np(type_p)) 5100 return; 5101 5102 array_p = type_p->type_structure.array; 5103 5104 /* A [v1_array] can be conformant or varying in the first dimension only */ 5105 5106 if (AST_SMALL_SET(type_p) 5107 && AST_CONFORMANT_SET(type_p) 5108 && array_is_conformant_upper(array_p)) 5109 CHECKER_error(type_p, NIDL_SMALLMULTID); 5110 5111 /* [v1_array] attribute invalid for array with more than 65535 elements */ 5112 5113 if (AST_SMALL_SET(type_p) 5114 && array_is_large(array_p)) 5115 CHECKER_error(type_p, NIDL_SMALLINV); 5116 5117 /* A [v1_array] cannot have a conformant lower bound */ 5118 5119 if (AST_SMALL_SET(type_p) 5120 && AST_CONFORMANT_SET(type_p) 5121 && array_has_open_lb(array_p)) 5122 CHECKER_error(type_p, NIDL_SMALLOPENLB); 5123} 5124 5125/* 5126** t y p e _ c o n t e x t 5127** 5128** Checks a type node's [context_handle] and [handle] attributes. 5129*/ 5130 5131static void type_context 5132( 5133 AST_type_n_t *type_p /* [in] Ptr to AST type node */ 5134) 5135{ 5136 /* [context_handle] attribute only applies to void * types */ 5137 5138 if (AST_CONTEXT_RD_SET(type_p) 5139 && (type_p->kind != AST_pointer_k 5140 || (type_p->kind == AST_pointer_k 5141 && type_p->type_structure.pointer->pointee_type->kind 5142 != AST_void_k 5143 /* OK in opaque context handle typedef */ 5144 && !(type_p->type_structure.pointer->pointee_type->kind 5145 == AST_structure_k 5146 && AST_DEF_AS_TAG_SET(type_p->type_structure.pointer-> 5147 pointee_type))))) 5148 CHECKER_error(type_p, NIDL_CTXPTRVOID); 5149 5150 /* [unique] pointers to context handles are not allowed */ 5151 5152 if (AST_UNIQUE_SET(type_p) 5153 && type_p->kind == AST_pointer_k 5154 && AST_CONTEXT_RD_SET(type_p->type_structure.pointer->pointee_type)) 5155 CHECKER_error(type_p, NIDL_UNIQCTXHAN); 5156 5157 /* Full pointers to context handles are not allowed */ 5158 5159 if (AST_PTR_SET(type_p) 5160 && type_p->kind == AST_pointer_k 5161 && AST_CONTEXT_RD_SET(type_p->type_structure.pointer->pointee_type)) 5162 CHECKER_error(type_p, NIDL_PTRCTXHAN); 5163 5164 /* Attribute [handle] cannot be applied to a void * type */ 5165 5166 if (AST_HANDLE_SET(type_p) 5167 && type_p->kind == AST_pointer_k 5168 && type_p->type_structure.pointer->pointee_type->kind == AST_void_k) 5169 { 5170 ASTP_attr_flag_t attr1 = ASTP_HANDLE; 5171 CHECKER_error(type_p, NIDL_ATTRPTRVOID, 5172 KEYWORDS_lookup_text(AST_attribute_to_token(&attr1))); 5173 } 5174 5175 /* The [handle] attribute is valid only on transmittable types */ 5176 5177 if (AST_HANDLE_SET(type_p) 5178 && type_p->kind == AST_handle_k) 5179 CHECKER_error(type_p, NIDL_HANATTRTRAN); 5180 5181 /* The attributes [handle] and [represent_as] cannot occur together */ 5182 5183 if (AST_HANDLE_SET(type_p) 5184 && type_p->rep_as_type != NULL) 5185 { 5186 ASTP_attr_flag_t attr1 = ASTP_HANDLE; 5187 CHECKER_error(type_p, NIDL_CONFLICTATTR, 5188 KEYWORDS_lookup_text(AST_attribute_to_token(&attr1)), 5189 "represent_as"); 5190 } 5191} 5192 5193/* 5194** t y p e _ c o n f o r m a n t 5195** 5196** Checks a type node's "conformant" (synthesized) attribute. 5197*/ 5198 5199static void type_conformant 5200( 5201 AST_type_n_t *type_p, /* [in] Ptr to AST type node */ 5202 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 5203) 5204{ 5205 AST_array_n_t *array_p; /* Ptr to array node */ 5206 5207 /* Remaining check only applies to array types in array syntax. */ 5208 5209 if (!type_is_array_np(type_p)) 5210 return; 5211 5212 array_p = type_p->type_structure.array; 5213 5214 /* Arrays conformant in other than first dim require -standard extended */ 5215 5216 if (!AST_LOCAL_SET(int_p) 5217 && AST_CONFORMANT_SET(type_p) 5218 && array_is_conformant_upper(array_p) 5219 && (*(int *)cmd_val[opt_standard] <= opt_standard_dce_1_0)) 5220 CHECKER_warning(type_p, NIDL_NOPORTCFMT, OPT_STD_EXTENDED); 5221} 5222 5223/* 5224** t y p e _ i g n o r e 5225** 5226** Checks a type node's [ignore] attribute. 5227*/ 5228 5229static void type_ignore 5230( 5231 AST_type_n_t *type_p /* [in] Ptr to AST type node */ 5232) 5233{ 5234 /* The [ignore] attribute is valid only for pointers */ 5235 5236 if (AST_IGNORE_SET(type_p) 5237 && type_p->kind != AST_pointer_k) 5238 CHECKER_error(type_p, NIDL_IGNATTRPTR); 5239} 5240 5241/* 5242** t y p e _ s w i t c h _ t y p e 5243** 5244** Checks a type node's [switch_type] attribute. 5245*/ 5246 5247static void type_switch_type 5248( 5249 AST_type_n_t *type_p /* [in] Ptr to AST type node */ 5250) 5251{ 5252 /* A non-encapsulated union type must have a [switch_type] attribute */ 5253 5254 if (type_p->kind == AST_disc_union_k 5255 && type_p->type_structure.disc_union->discrim_name == NAMETABLE_NIL_ID 5256 && type_p->type_structure.disc_union->discrim_type == NULL) 5257 CHECKER_error(type_p, NIDL_NEUSWTYPE); 5258} 5259 5260/* 5261** t y p e _ t r a n s m i t _ a s 5262** 5263** Checks a type node's [transmit_as] attribute. 5264*/ 5265 5266static void type_transmit_as 5267( 5268 AST_type_n_t *top_type_p, /* [in] Top-level presented type */ 5269 AST_type_n_t *type_p /* [in] Ptr to AST type node */ 5270) 5271{ 5272 if (top_type_p->xmit_as_type == NULL) /* Presented type = transmit type */ 5273 return; 5274 5275 /* 5276 * types with [transmit_as] can't be conformant not locally because 5277 * of conversion routines and not on the net because of the net type is 5278 * freed immediately after marshalling so there is no place to unmarshall 5279 * the net type in to on the client side after the call. This restriction 5280 * could be lifted with enough programming. 5281 */ 5282 5283 /* Local [transmit_as] type can not be a conformant array */ 5284 5285 if (AST_CONFORMANT_SET(type_p) 5286 && !AST_STRING_SET(type_p) 5287 && type_is_array(type_p)) 5288 CHECKER_error(top_type_p, NIDL_XMITCFMTARR); 5289 5290 /* Net [transmit_as] type can not be a conformant array */ 5291 5292 if (AST_CONFORMANT_SET(top_type_p->xmit_as_type) 5293 && !AST_STRING_SET(top_type_p->xmit_as_type) 5294 && type_is_array(top_type_p->xmit_as_type)) 5295 CHECKER_error(top_type_p, NIDL_XMITCFMTARR); 5296 5297 /* Presented type can't be conformant */ 5298 5299 if (AST_CONFORMANT_SET(top_type_p) 5300 && top_type_p->kind == AST_structure_k) 5301 CHECKER_error(top_type_p, NIDL_STRUCTXMITCFMT); 5302 5303 /* A translated transmissible type cannot contain pointers. */ 5304 5305 if (FE_TEST(type_p->fe_info->flags, FE_HAS_REF_PTR)) 5306 { 5307 ASTP_attr_flag_t attr = ASTP_REF; 5308 5309 CHECKER_error(type_p, NIDL_XMITPTR, 5310 KEYWORDS_lookup_text(AST_attribute_to_token(&attr))); 5311 } 5312 if (FE_TEST(type_p->fe_info->flags, FE_HAS_FULL_PTR)) 5313 { 5314 ASTP_attr_flag_t attr = ASTP_PTR; 5315 5316 CHECKER_error(type_p, NIDL_XMITPTR, 5317 KEYWORDS_lookup_text(AST_attribute_to_token(&attr))); 5318 } 5319 if (FE_TEST(type_p->fe_info->flags, FE_HAS_UNIQUE_PTR)) 5320 { 5321 ASTP_attr_flag_t attr = ASTP_UNIQUE; 5322 5323 CHECKER_error(type_p, NIDL_XMITPTR, 5324 KEYWORDS_lookup_text(AST_attribute_to_token(&attr))); 5325 } 5326 5327 /* A type used in a transmit_as clause cannot have a represent_as type */ 5328 5329 if (type_p->rep_as_type != NULL) 5330 CHECKER_error(type_p, NIDL_XMITASREP); 5331 5332 /* A type with [transmit_as] may not have other type attributes */ 5333 5334 if (AST_STRING_SET(top_type_p) 5335 || AST_STRING0_SET(top_type_p) 5336 || AST_UNIQUE_SET(top_type_p) 5337 || AST_REF_SET(top_type_p) 5338 || AST_IGNORE_SET(top_type_p) 5339 || AST_SMALL_SET(top_type_p) 5340 || AST_CONTEXT_RD_SET(top_type_p) 5341 || AST_PTR_SET(top_type_p)) 5342 CHECKER_error(top_type_p, NIDL_XMITTYPEATTRS); 5343 5344 /* A [transmit_as] type cannot be a non-encapsulated union */ 5345 5346 if (type_p->kind == AST_disc_union_k 5347 && type_p->type_structure.disc_union->discrim_name == NAMETABLE_NIL_ID) 5348 CHECKER_error(top_type_p, NIDL_NEUXMITAS); 5349 5350 /* A non-encapsulated union cannot have a [transmit_as] type */ 5351 5352 if (top_type_p->kind == AST_disc_union_k 5353 && top_type_p->type_structure.disc_union->discrim_name == NAMETABLE_NIL_ID) 5354 CHECKER_error(top_type_p, NIDL_NEUXMITYPE); 5355} 5356 5357/* 5358** t y p e _ r e p r e s e n t _ a s 5359** 5360** Checks a type node's [represent_as] attribute. 5361*/ 5362 5363static void type_represent_as 5364( 5365 AST_type_n_t *type_p, /* [in] Top-level presented type */ 5366 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 5367) 5368{ 5369 if (type_p->rep_as_type == NULL) /* Presented type = Net type */ 5370 return; 5371 5372 /* 5373 * types with [represent_as] can't be conformant on the net because the 5374 * net type is freed immediately after marshalling so there is no place to 5375 * unmarshall the net type in to on the client side after the call. This 5376 * restriction could be lifted with enough programming. 5377 */ 5378 5379 /* Net type can not be conformant */ 5380 5381 if (AST_CONFORMANT_SET(type_p)) 5382 CHECKER_error(type_p, NIDL_TYPEREPCFMT); 5383 5384 /* A translated transmissible type cannot contain pointers. */ 5385 5386 if (FE_TEST(type_p->fe_info->flags, FE_HAS_REF_PTR)) 5387 { 5388 ASTP_attr_flag_t attr = ASTP_REF; 5389 5390 CHECKER_error(type_p, NIDL_XMITPTR, 5391 KEYWORDS_lookup_text(AST_attribute_to_token(&attr))); 5392 } 5393 if (FE_TEST(type_p->fe_info->flags, FE_HAS_FULL_PTR)) 5394 { 5395 ASTP_attr_flag_t attr = ASTP_PTR; 5396 5397 CHECKER_error(type_p, NIDL_XMITPTR, 5398 KEYWORDS_lookup_text(AST_attribute_to_token(&attr))); 5399 } 5400 if (FE_TEST(type_p->fe_info->flags, FE_HAS_UNIQUE_PTR)) 5401 { 5402 ASTP_attr_flag_t attr = ASTP_UNIQUE; 5403 5404 CHECKER_error(type_p, NIDL_XMITPTR, 5405 KEYWORDS_lookup_text(AST_attribute_to_token(&attr))); 5406 } 5407 5408 /* ACF 'include' statement advised for definition of type 'name' */ 5409 5410 if (int_p->includes == NULL 5411 && ASTP_lookup_binding(null_parser_location, 5412 type_p->rep_as_type->type_name, 5413 fe_type_n_k, FALSE) == NULL) 5414 { 5415 char const*id_name; 5416 5417 NAMETABLE_id_to_string(type_p->rep_as_type->type_name, &id_name); 5418 CHECKER_acf_warning(type_p, NIDL_INCLTYPE, id_name); 5419 } 5420 5421 { 5422 AST_type_n_t *rep_type_p = (AST_type_n_t *) /* IDL rep_as type, if any */ 5423 ASTP_lookup_binding(null_parser_location, 5424 type_p->rep_as_type->type_name, fe_type_n_k, FALSE); 5425 5426 /* A [represent_as] type cannot be a non-encapsulated union */ 5427 5428 if (rep_type_p != NULL 5429 && rep_type_p->kind == AST_disc_union_k 5430 && rep_type_p->type_structure.disc_union->discrim_name 5431 == NAMETABLE_NIL_ID) 5432 CHECKER_acf_error(type_p, NIDL_NEUREPAS); 5433 } 5434 5435 /* A non-encapsulated union cannot have a [represent_as] type */ 5436 5437 if (type_p->kind == AST_disc_union_k 5438 && type_p->type_structure.disc_union->discrim_name == NAMETABLE_NIL_ID) 5439 CHECKER_acf_error(type_p, NIDL_NEUREPTYPE); 5440} 5441 5442/* 5443** t y p e _ c h e c k 5444** 5445** Checks an AST type node. 5446*/ 5447 5448static void type_check 5449( 5450 AST_type_n_t *type_p, /* [in] Ptr to AST type node */ 5451 ASTP_node_t *node_p, /* [in] Parent node of type node */ 5452 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 5453) 5454{ 5455 AST_type_n_t *xmit_type_p; /* Transmissible type */ 5456 char const * id_name; 5457 /* 5458 * Pick up the transmissible type (the top-level, presented, type is 5459 * different from the the transmissible type if it has a [transmit_as]). 5460 * Most checks are done on the transmissible, not presented, type. 5461 */ 5462 xmit_type_p = type_xmit_type(type_p); 5463 5464 if (!AST_LOCAL_SET(int_p)) 5465 type_name_len(type_p, xmit_type_p, int_p); 5466 5467 type_in_line(xmit_type_p); 5468 type_string(xmit_type_p); 5469 type_pointer(xmit_type_p); 5470 type_small(xmit_type_p); 5471 type_context(xmit_type_p); 5472 type_conformant(xmit_type_p, int_p); 5473 type_ignore(xmit_type_p); 5474 type_switch_type(xmit_type_p); 5475 type_transmit_as(type_p, xmit_type_p); 5476 type_represent_as(xmit_type_p, int_p); 5477 CHK_type_cs(type_p, xmit_type_p, int_p); 5478 5479 /* V1 attributes are incompatible with this type */ 5480 5481 if (FE_TEST(type_p->fe_info->flags, FE_HAS_V1_ATTR) 5482 && FE_TEST(type_p->fe_info->flags, FE_HAS_V2_ATTR)) 5483 CHECKER_warning(type_p, NIDL_INCOMPATV1); 5484 5485 switch (type_p->kind) 5486 { 5487 case AST_handle_k: 5488 case AST_boolean_k: 5489 case AST_byte_k: 5490 case AST_character_k: 5491 case AST_small_integer_k: 5492 case AST_short_integer_k: 5493 case AST_long_integer_k: 5494 case AST_hyper_integer_k: 5495 case AST_small_unsigned_k: 5496 case AST_short_unsigned_k: 5497 case AST_long_unsigned_k: 5498 case AST_hyper_unsigned_k: 5499 case AST_short_float_k: 5500 case AST_long_float_k: 5501 case AST_void_k: 5502 break; /* No checks for these types */ 5503 5504 case AST_enum_k: 5505 enum_check(type_p->type_structure.enumeration, type_p); 5506 break; 5507 5508 case AST_array_k: 5509 array_check((ASTP_node_t *)type_p->type_structure.array, 5510 type_p, 5511 node_p, 5512 type_p->type_structure.array->element_type, 5513 int_p, 5514 false); 5515 break; 5516 5517 case AST_structure_k: 5518 struct_check(type_p->type_structure.structure, int_p); 5519 break; 5520 5521 case AST_pipe_k: 5522 pipe_check(type_p->type_structure.pipe, type_p, int_p); 5523 break; 5524 5525 case AST_pointer_k: 5526 ptr_check(type_p->type_structure.pointer, type_p, node_p, int_p); 5527 break; 5528 5529 case AST_function_k: 5530 /* Function type declaration is not allowed */ 5531 if (!AST_LOCAL_SET(int_p)) 5532 CHECKER_error(type_p, NIDL_FUNTYPDCL); 5533 break; 5534 5535 case AST_disc_union_k: 5536 union_check(type_p->type_structure.disc_union, int_p); 5537 break; 5538 5539 case AST_interface_k: 5540 /* Interface type declaration is not allowed */ 5541 NAMETABLE_id_to_string(type_p->name, &id_name); 5542 CHECKER_error(type_p, NIDL_INTREFNOTALO, id_name); 5543 break; 5544 5545 default: 5546 error(NIDL_INTERNAL_ERROR, __FILE__, __LINE__); 5547 } 5548} 5549 5550/* 5551** c o n s t a n t _ c h e c k 5552** 5553** Checks an AST constant node. 5554*/ 5555 5556static void constant_check 5557( 5558 AST_constant_n_t *const_p ATTRIBUTE_UNUSED /* [in] Ptr to AST constant node */ 5559) 5560{ 5561} 5562 5563/* 5564** e x p o r t _ c h e c k 5565** 5566** Checks an AST export node. 5567*/ 5568 5569static void export_check 5570( 5571 AST_export_n_t *export_p, /* [in] Ptr to AST export node */ 5572 AST_interface_n_t *int_p, /* [in] Ptr to interface node */ 5573 AST_interface_n_t *parent_int_p /* [in] Parent interface node */ 5574) 5575{ 5576 5577 switch (export_p->kind) 5578 { 5579 case AST_cpp_quote_k: 5580 break; 5581 5582 case AST_constant_k: 5583 constant_check(export_p->thing_p.exported_constant); 5584 break; 5585 5586 case AST_operation_k: 5587 if (parent_int_p == NULL) /* main interface */ 5588 operation_check(export_p->thing_p.exported_operation, int_p); 5589 break; 5590 5591 case AST_type_k: 5592 type_check(export_p->thing_p.exported_type, (ASTP_node_t *)export_p, 5593 int_p); 5594 break; 5595 5596 default: 5597 error(NIDL_INTERNAL_ERROR, __FILE__, __LINE__); 5598 } 5599} 5600 5601/* 5602** i n t _ n a m e _ l e n 5603** 5604** Checks an interface node's name length. 5605*/ 5606 5607static void int_name_len 5608( 5609 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 5610) 5611{ 5612 char const *int_name; /* Interface name */ 5613 unsigned int max_len; /* Maximum identifier length */ 5614 5615 NAMETABLE_id_to_string(int_p->name, &int_name); 5616 if (int_name == NULL) 5617 return; /* Shouldn't happen */ 5618 5619 /* Maximum identifier length for interface name is <n> characters */ 5620 5621 max_len = MAX_ID - strlen("_v#_#_c_ifspec"); /* Could do better here */ 5622 if (strlen(int_name) > max_len) 5623 CHECKER_error(int_p, NIDL_MAXIDINTF, max_len); 5624} 5625 5626/* 5627** i n t _ i n _ l i n e 5628** 5629** Checks an interface node's [in_line] and [out_of_line] attributes. 5630*/ 5631 5632static void int_in_line 5633( 5634 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 5635) 5636{ 5637 /* Can't have both [in_line] and [out_of_line] interface attributes */ 5638 5639 if (AST_IN_LINE_SET(int_p) 5640 && AST_OUT_OF_LINE_SET(int_p)) 5641 CHECKER_acf_error(int_p, NIDL_INTLINEATTR); 5642} 5643 5644/* 5645** i n t _ c o d e 5646** 5647** Checks an interface node's [code] and [nocode] attributes. 5648*/ 5649 5650static void int_code 5651( 5652 AST_interface_n_t *int_p, /* [in] Ptr to interface node */ 5653 AST_interface_n_t *parent_int_p /* [in] Parent interface node */ 5654) 5655{ 5656 /* Can't have both [code] and [nocode] interface attributes */ 5657 5658 if (AST_CODE_SET(int_p) 5659 && AST_NO_CODE_SET(int_p)) 5660 CHECKER_acf_error(int_p, NIDL_INTCODEATTR); 5661 5662 /* [nocode] attribute does not apply to server stub */ 5663 5664 if (parent_int_p == NULL /* main interface */ 5665 && AST_NO_CODE_SET(int_p) 5666 && cmd_opt[opt_emit_sstub] 5667 && !cmd_opt[opt_emit_cstub]) 5668 CHECKER_acf_warning(int_p, NIDL_SRVNOCODE); 5669 5670 /* At least one operation should have the [code] attribute */ 5671 5672 if (parent_int_p == NULL /* main interface */ 5673 && int_p->op_count > 0) 5674 { 5675 AST_export_n_t *export_p; 5676 boolean code_op = FALSE; 5677 5678 for (export_p = int_p->exports; export_p; export_p = export_p->next) 5679 { 5680 if (export_p->kind != AST_operation_k) continue; 5681 if (AST_CODE_SET(export_p->thing_p.exported_operation)) 5682 { 5683 code_op = TRUE; 5684 break; 5685 } 5686 } 5687 if (!code_op) 5688 CHECKER_acf_warning(int_p, NIDL_NOCODEOPS); 5689 } 5690} 5691 5692/* 5693** i n t _ h a n d l e 5694** 5695** Checks an interface node's attributes relating to handles/binding. 5696*/ 5697 5698static void int_handle 5699( 5700 AST_interface_n_t *int_p /* [in] Ptr to interface node */ 5701) 5702{ 5703 /* Can't have both [auto_handle] and [implicit_handle] interface attrs */ 5704 5705 if (int_p->implicit_handle_name != NAMETABLE_NIL_ID 5706 && AST_AUTO_HANDLE_SET(int_p)) 5707 CHECKER_acf_error(int_p, NIDL_CONFHANATTR); 5708 5709 /* 5710 * [implicit_handle] variable must either be of type handle_t 5711 * or have the [handle] type attribute 5712 */ 5713 if (int_p->implicit_handle_name != NAMETABLE_NIL_ID 5714 && int_p->implicit_handle_type != NULL /* is an IDL-defined type */ 5715 && !type_is_handle(int_p->implicit_handle_type)) 5716 CHECKER_acf_error(int_p, NIDL_IMPHANVAR); 5717} 5718 5719/* 5720** i n t _ l o c a l 5721** 5722** Checks an interface node's [local] and [uuid] attributes. 5723*/ 5724 5725static void int_local 5726( 5727 AST_interface_n_t *int_p, /* [in] Ptr to interface node */ 5728 AST_interface_n_t *parent_int_p /* [in] Parent interface node */ 5729) 5730{ 5731 boolean uuid_null; 5732 5733 uuid_null = uuid_is_null(&int_p->uuid); 5734 5735 /* [uuid] attribute invalid when [local] attribute is specified */ 5736 5737 if (AST_LOCAL_SET(int_p) 5738 && !uuid_null && !AST_OBJECT_SET(int_p)) 5739 CHECKER_error(int_p, NIDL_UUIDINV); 5740 5741 /* 5742 * If this is a non-local interface being imported by a local interface, 5743 * then pretend that it is a local interface as well. 5744 */ 5745 if (!AST_LOCAL_SET(int_p) 5746 && parent_int_p != NULL 5747 && AST_LOCAL_SET(parent_int_p)) 5748 AST_SET_LOCAL(int_p); 5749 5750 /* Interface UUID must be specified */ 5751 5752 if (!AST_LOCAL_SET(int_p) 5753 && uuid_null 5754 && parent_int_p == NULL /* main interface */ 5755 && int_p->op_count != 0) 5756 CHECKER_error(int_p, NIDL_INTUUIDREQ); 5757 5758 /* A non-local interface cannot import a local interface */ 5759 5760 if (parent_int_p != NULL 5761 && !AST_LOCAL_SET(parent_int_p) 5762 && AST_LOCAL_SET(int_p)) 5763 CHECKER_error(int_p, NIDL_IMPORTLOCAL); 5764} 5765 5766/* Checks an interface node's inheritance attributes */ 5767static void int_inherit(AST_interface_n_t * int_p) 5768{ 5769 char const * id_name; /* name for [switch_is] */ 5770 /* check to see if there is a binding for the inherited interface; 5771 * if not, complain about it */ 5772 if (int_p->inherited_interface_name != NAMETABLE_NIL_ID) { 5773 /* WEZ:TODO only valid for ORPC */ 5774 if (!NAMETABLE_lookup_local(int_p->inherited_interface_name)) { 5775 NAMETABLE_id_to_string(int_p->inherited_interface_name, &id_name); 5776 //CHECKER_error(int_p, NIDL_INHERITNOTDEF, id_name); 5777 } 5778 } 5779} 5780 5781/* 5782** i n t e r f a c e _ c h e c k 5783** 5784** Checks the AST interface node. 5785*/ 5786 5787static void interface_check 5788( 5789 AST_interface_n_t *int_p, /* [in] Ptr to interface node */ 5790 AST_interface_n_t *parent_int_p /* [in] Parent interface node */ 5791) 5792{ 5793 AST_export_n_t *export_p; /* Ptr to export node */ 5794 AST_import_n_t *import_p; /* Ptr to import node */ 5795 5796 int_name_len(int_p); 5797 5798 int_in_line(int_p); 5799 int_code(int_p, parent_int_p); 5800 int_handle(int_p); 5801 int_local(int_p, parent_int_p); 5802 int_inherit(int_p); 5803 5804 /* Check any interfaces that this interface imports. */ 5805 5806 import_p = int_p->imports; 5807 while (import_p != NULL) 5808 { 5809 if (import_p->interface != NULL) 5810 interface_check(import_p->interface, int_p); 5811 import_p = import_p->next; 5812 } 5813 5814 /* Check everything that is exported by the interface. */ 5815 5816 export_p = int_p->exports; 5817 while (export_p != NULL) 5818 { 5819 export_check(export_p, int_p, parent_int_p); 5820 export_p = export_p->next; 5821 } 5822 5823 /* For the main interface only, process the pointed-at types list. */ 5824 5825 if (parent_int_p == NULL) 5826 { 5827 AST_type_p_n_t *typep_p; 5828 AST_type_n_t *type_p; 5829 5830 for (typep_p = int_p->pa_types 5831 ; typep_p != NULL 5832 ; typep_p = typep_p->next) 5833 { 5834 type_p = typep_p->type; 5835 5836 /* Pointers to [v1_enum] types are not allowed */ 5837 5838 if (type_p->kind == AST_enum_k 5839 && AST_V1_ENUM_SET(type_p)) 5840 CHECKER_error(type_p, NIDL_PTRV1ENUM); 5841 } 5842 5843 /* Use of [exceptions] attribute requires -standard extended */ 5844 if (int_p->exceptions != NULL 5845 && (*(int *)cmd_val[opt_standard] < opt_standard_dce_1_1)) 5846 CHECKER_warning(int_p, NIDL_NOPORTATTR, 5847 "exceptions", OPT_STD_EXTENDED); 5848 } 5849 if (AST_OBJECT_SET(int_p) && ASTP_IF_AF_SET(int_p, ASTP_IF_VERSION)) { 5850 CHECKER_warning(int_p, NIDL_CONFLICTATTR, "version", "object"); 5851 } 5852 if (!AST_OBJECT_SET(int_p) && int_p->inherited_interface_name != NAMETABLE_NIL_ID) { 5853 CHECKER_warning(int_p, NIDL_ANCREQSOBJ); 5854 } 5855 5856} 5857 5858/* 5859** C H E C K E R _ m a i n 5860** 5861** Main routine of semantic checking component of IDL compiler. 5862** Does semantic checking of the interface definition (and any imported 5863** items that are referred to in the interface). 5864*/ 5865 5866boolean CHECKER_main /* Returns TRUE on success */ 5867( 5868 boolean *cmd_opt_arr, /* [in] Array of command option flags */ 5869 void **cmd_val_arr, /* [in] Array of command option values */ 5870 AST_interface_n_t *int_p /* [in] Ptr to AST interface node */ 5871) 5872{ 5873 /* Save passed command array addresses in static storage. */ 5874 cmd_opt = cmd_opt_arr; 5875 cmd_val = cmd_val_arr; 5876 5877 /* 5878 * Check the interface. The interface node is the root of the AST. 5879 * Each function above checks an AST node that hangs off the main 5880 * interface node. 5881 */ 5882 interface_check(int_p, NULL); 5883 5884 /* 5885 * If we defaulted to auto_handle for any operations, 5886 * set [auto_handle] on the interface. 5887 */ 5888 if (def_auto_handle > 0) 5889 AST_SET_AUTO_HANDLE(int_p); 5890 5891 /* Return success if no errors, failure otherwise. */ 5892 return (error_count == 0); 5893} 5894 5895/* 5896** C H E C K E R _ e r r o r 5897** 5898** Handles any semantic errors detected. Determines the source file and 5899** line number of the error from the AST node; passes this information and 5900** its remaining parameters onto the error logging routine. 5901** 5902*/ 5903void CHECKER_error 5904( 5905 void *in_node_p, 5906 long msgid, 5907 ... 5908) 5909{ 5910 ASTP_node_t *node_p = in_node_p; 5911 va_list arglist; 5912 5913 va_start (arglist, msgid); 5914 5915 vlog_source_error(node_p->fe_info->file, 5916 node_p->fe_info->source_line, 5917 msgid, arglist); 5918 5919 va_end (arglist); 5920} 5921 5922/* 5923** C H E C K E R _ w a r n i n g 5924** 5925** Handles any semantic warnings detected. Determines the source file and 5926** line number of the warning from the AST node; passes this information and 5927** its remaining parameters onto the warning logging routine. 5928** 5929*/ 5930void CHECKER_warning 5931( 5932 void *in_node_p, 5933 long msgid, 5934 ... 5935) 5936{ 5937 ASTP_node_t *node_p = in_node_p; 5938 va_list arglist; 5939 5940 va_start (arglist, msgid); 5941 5942 vlog_source_warning(node_p->fe_info->file, 5943 node_p->fe_info->source_line, 5944 msgid, arglist); 5945 5946 va_end (arglist); 5947} 5948 5949/* 5950** C H E C K E R _ a c f _ e r r o r 5951** 5952** Handles any semantic errors detected on ACF-related attributes. Determines 5953** the source file and line number of the error from the AST node; passes this 5954** information and its remaining parameters onto the error logging routine. 5955** 5956*/ 5957void CHECKER_acf_error 5958( 5959 void *in_node_p, 5960 long msgid, 5961 ... 5962) 5963{ 5964 ASTP_node_t *node_p = in_node_p; 5965 va_list arglist; 5966 5967 va_start (arglist, msgid); 5968 5969 if (node_p->fe_info->acf_file != (STRTAB_str_t)0) 5970 { 5971 vlog_source_error(node_p->fe_info->acf_file, 5972 node_p->fe_info->acf_source_line, 5973 msgid, arglist); 5974 } 5975 else 5976 { 5977 vlog_source_error(node_p->fe_info->file, 5978 node_p->fe_info->source_line, 5979 msgid, arglist); 5980 } 5981 5982 va_end (arglist); 5983} 5984 5985/* 5986** C H E C K E R _ a c f _ w a r n i n g 5987** 5988** Handles any semantic warnings detected on ACF-related attrs. Determines 5989** the source file and line number of warning from the AST node; passes this 5990** information and its remaining parameters onto the warning logging routine. 5991** 5992*/ 5993void CHECKER_acf_warning 5994( 5995 void *in_node_p, 5996 long msgid, 5997 ... 5998) 5999{ 6000 ASTP_node_t *node_p = in_node_p; 6001 va_list arglist; 6002 6003 va_start (arglist, msgid); 6004 6005 if (node_p->fe_info->acf_file != (STRTAB_str_t)0) 6006 vlog_source_warning(node_p->fe_info->acf_file, 6007 node_p->fe_info->acf_source_line, 6008 msgid, arglist); 6009 else 6010 vlog_source_warning(node_p->fe_info->file, 6011 node_p->fe_info->source_line, 6012 msgid, arglist); 6013 6014 va_end (arglist); 6015} 6016 6017/* 6018** t y p e _ i s _ b a s e 6019** 6020** Returns true if the specified type node is for a base type, false otherwise. 6021*/ 6022 6023boolean type_is_base 6024( 6025 AST_type_n_t *type_p /* [in] Ptr to AST type node */ 6026) 6027{ 6028 return ((type_p) == ASTP_char_ptr 6029 || (type_p) == ASTP_boolean_ptr 6030 || (type_p) == ASTP_byte_ptr 6031 || (type_p) == ASTP_void_ptr 6032 || (type_p) == ASTP_handle_ptr 6033 || (type_p) == ASTP_short_float_ptr 6034 || (type_p) == ASTP_long_float_ptr 6035 || (type_p) == ASTP_small_int_ptr 6036 || (type_p) == ASTP_short_int_ptr 6037 || (type_p) == ASTP_long_int_ptr 6038 || (type_p) == ASTP_hyper_int_ptr 6039 || (type_p) == ASTP_small_unsigned_ptr 6040 || (type_p) == ASTP_short_unsigned_ptr 6041 || (type_p) == ASTP_long_unsigned_ptr 6042 || (type_p) == ASTP_hyper_unsigned_ptr); 6043} 6044