- /* if noun different then src overrides */
- if ( SPEC_NOUN(dest) != SPEC_NOUN(src) && !SPEC_NOUN(dest))
- SPEC_NOUN(dest) = SPEC_NOUN(src) ;
-
- if (! SPEC_SCLS(dest)) /* if destination has no storage class */
- SPEC_SCLS(dest) = SPEC_SCLS(src) ;
-
- /* copy all the specifications */
- SPEC_LONG(dest) |= SPEC_LONG(src);
- SPEC_SHORT(dest) |= SPEC_SHORT(src);
- SPEC_USIGN(dest) |= SPEC_USIGN(src);
- SPEC_STAT(dest) |= SPEC_STAT(src);
- SPEC_EXTR(dest) |= SPEC_EXTR(src);
- SPEC_ABSA(dest) |= SPEC_ABSA(src);
- SPEC_RENT(dest) |= SPEC_RENT(src);
- SPEC_INTN(dest) |= SPEC_INTN(src);
- SPEC_BANK(dest) |= SPEC_BANK(src);
- SPEC_VOLATILE(dest) |= SPEC_VOLATILE(src);
- SPEC_CRTCL(dest) |= SPEC_CRTCL(src);
- SPEC_ADDR(dest) |= SPEC_ADDR(src);
- SPEC_OCLS(dest) = SPEC_OCLS(src);
- SPEC_BLEN(dest) |= SPEC_BLEN(src);
- SPEC_BSTR(dest) |= SPEC_BSTR(src);
- SPEC_TYPEDEF(dest) |= SPEC_TYPEDEF(src);
- SPEC_NONBANKED(dest) |= SPEC_NONBANKED(src);
-
- if ( IS_STRUCT(dest) && SPEC_STRUCT(dest) == NULL )
- SPEC_STRUCT(dest) = SPEC_STRUCT(src);
-
- return dest ;
+ sym_link *symlink=dest;
+
+ if (!IS_SPEC(dest) || !IS_SPEC(src)) {
+#if 0
+ werror (E_INTERNAL_ERROR, __FILE__, __LINE__, "cannot merge declarator");
+ exit (1);
+#else
+ werror (E_SYNTAX_ERROR, yytext);
+ // the show must go on
+ return newIntLink();
+#endif
+ }
+
+ if (SPEC_NOUN(src)) {
+ if (!SPEC_NOUN(dest)) {
+ SPEC_NOUN(dest)=SPEC_NOUN(src);
+ } else {
+ /* we shouldn't redeclare the type */
+ if (getenv("DEBUG_SANITY")) {
+ fprintf (stderr, "mergeSpec: ");
+ }
+ werror(E_TWO_OR_MORE_DATA_TYPES, name);
+ }
+ }
+
+ if (SPEC_SCLS(src)) {
+ /* if destination has no storage class */
+ if (!SPEC_SCLS (dest) || SPEC_SCLS(dest)==S_REGISTER) {
+ SPEC_SCLS (dest) = SPEC_SCLS (src);
+ } else {
+ if (getenv("DEBUG_SANITY")) {
+ fprintf (stderr, "mergeSpec: ");
+ }
+ werror(E_TWO_OR_MORE_STORAGE_CLASSES, name);
+ }
+ }
+
+ /* copy all the specifications */
+
+ // we really should do:
+#if 0
+ if (SPEC_what(src)) {
+ if (SPEC_what(dest)) {
+ werror(W_DUPLICATE_SPEC, "what");
+ }
+ SPEC_what(dst)|=SPEC_what(src);
+ }
+#endif
+ // but there are more important thing right now
+
+ SPEC_LONG (dest) |= SPEC_LONG (src);
+ dest->select.s._short|=src->select.s._short;
+ SPEC_USIGN (dest) |= SPEC_USIGN (src);
+ dest->select.s._signed|=src->select.s._signed;
+ SPEC_STAT (dest) |= SPEC_STAT (src);
+ SPEC_EXTR (dest) |= SPEC_EXTR (src);
+ SPEC_CONST(dest) |= SPEC_CONST (src);
+ SPEC_ABSA (dest) |= SPEC_ABSA (src);
+ SPEC_VOLATILE (dest) |= SPEC_VOLATILE (src);
+ SPEC_ADDR (dest) |= SPEC_ADDR (src);
+ SPEC_OCLS (dest) = SPEC_OCLS (src);
+ SPEC_BLEN (dest) |= SPEC_BLEN (src);
+ SPEC_BSTR (dest) |= SPEC_BSTR (src);
+ SPEC_TYPEDEF (dest) |= SPEC_TYPEDEF (src);
+
+ if (IS_STRUCT (dest) && SPEC_STRUCT (dest) == NULL)
+ SPEC_STRUCT (dest) = SPEC_STRUCT (src);
+
+ /* these are the only function attributes that will be set
+ in a specifier while parsing */
+ FUNC_NONBANKED(dest) |= FUNC_NONBANKED(src);
+ FUNC_BANKED(dest) |= FUNC_BANKED(src);
+ FUNC_ISCRITICAL(dest) |= FUNC_ISCRITICAL(src);
+ FUNC_ISREENT(dest) |= FUNC_ISREENT(src);
+ FUNC_ISNAKED(dest) |= FUNC_ISNAKED(src);
+ FUNC_ISISR(dest) |= FUNC_ISISR(src);
+ FUNC_INTNO(dest) |= FUNC_INTNO(src);
+ FUNC_REGBANK(dest) |= FUNC_REGBANK(src);
+
+ return symlink;