+2003-09-12 Erik Petrich <epetrich@ivorytower.norman.ok.us>
+
+ Fixed bug #621531 (const & volatile confusion in the type chain).
+ DCL_PTR_CONST, DCL_PTR_VOLATILE, & IS_PTR_CONST now exclusively
+ refer to the const or volatile state of the pointer itself.
+
+ * src/SDCCast.c
+ * src/SDCCglue.c
+ * src/SDCCicode.c
+ * src/SDCCsymt.c
+ * src/SDCCval.c
+ * src/SDCC.y
+ * src/SDCCsymt.h
+ * src/pic/gen.c
+ * src/pic/ralloc.c
+ * src/pic16/gen.c
+ * src/pic16/ralloc.c
+ * support/regression/tests/const.c
+
2003-09-10 Jesus Calvino-Fraga <jesusc@ece.ubc.ca>
When checking for duplicated modules, use absolute paths
{
$$ = $1 ;
DCL_TSPEC($1) = $2;
+ DCL_PTR_CONST($1) = SPEC_CONST($2);
+ DCL_PTR_VOLATILE($1) = SPEC_VOLATILE($2);
}
| unqualified_pointer pointer
{
DCL_TYPE($3) = POINTER ;
break;
case S_CODE:
- DCL_PTR_CONST($3) = 1;
DCL_TYPE($3) = CPOINTER ;
break;
case S_EEPROM:
}
RRVAL (tree) = 1;
COPYTYPE (TTYPE (tree), TETYPE (tree), LTYPE (tree)->next);
- if (IS_PTR(LTYPE(tree))) {
- SPEC_CONST (TETYPE (tree)) = DCL_PTR_CONST (LTYPE(tree));
- }
return tree;
/*------------------------------------------------------------------*/
/*----------------------------*/
/* ++/-- operation */
/*----------------------------*/
- case INC_OP: /* incerement operator unary so left only */
+ case INC_OP: /* increment operator unary so left only */
case DEC_OP:
{
sym_link *ltc = (tree->right ? RTYPE (tree) : LTYPE (tree));
COPYTYPE (TTYPE (tree), TETYPE (tree), ltc);
- if (!tree->initMode && IS_CONSTANT(TETYPE(tree)))
+ if (!tree->initMode && IS_CONSTANT(TTYPE(tree)))
werror (E_CODE_WRITE, tree->opval.op==INC_OP ? "++" : "--");
if (tree->right)
goto errorTreeReturn;
}
if (SPEC_SCLS (tree->left->etype) == S_CODE)
- {
- DCL_TYPE (p) = CPOINTER;
- DCL_PTR_CONST (p) = port->mem.code_ro;
- }
+ DCL_TYPE (p) = CPOINTER;
else if (SPEC_SCLS (tree->left->etype) == S_XDATA)
DCL_TYPE (p) = FPOINTER;
else if (SPEC_SCLS (tree->left->etype) == S_XSTACK)
p->next = LTYPE (tree);
TTYPE (tree) = p;
TETYPE (tree) = getSpec (TTYPE (tree));
- DCL_PTR_CONST (p) = SPEC_CONST (TETYPE (tree));
- DCL_PTR_VOLATILE (p) = SPEC_VOLATILE (TETYPE (tree));
LLVAL (tree) = 1;
TLVAL (tree) = 1;
return tree;
goto errorTreeReturn;
}
TTYPE (tree) = copyLinkChain (LTYPE (tree)->next);
- TETYPE (tree) = getSpec (TTYPE (tree));
- SPEC_CONST (TETYPE (tree)) = DCL_PTR_CONST (LTYPE(tree));
+ TETYPE (tree) = getSpec (TTYPE (tree));
return tree;
}
RRVAL (tree) = 1;
LLVAL (tree) = 1;
if (!tree->initMode ) {
- if ((IS_SPEC(LETYPE(tree)) && IS_CONSTANT (LETYPE (tree))))
+ if (IS_CONSTANT(LTYPE(tree)))
werror (E_CODE_WRITE, "=");
}
if (LRVAL (tree))
SPEC_OCLS(newSym->etype)=xinit;
SNPRINTF (newSym->name, sizeof(newSym->name), "__xinit_%s", sym->name);
SNPRINTF (newSym->rname, sizeof(newSym->rname), "__xinit_%s", sym->rname);
- SPEC_CONST(newSym->etype)=1;
+ if (IS_SPEC (newSym->type))
+ SPEC_CONST (newSym->type) = 1;
+ else
+ DCL_PTR_CONST (newSym->type) = 1;
SPEC_STAT(newSym->etype)=1;
resolveIvalSym(newSym->ival);
ptype->next = type;
- /* if the output class is code */
- if ((DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype))) == CPOINTER)
- DCL_PTR_CONST (ptype) = port->mem.code_ro;
-
- /* if the variable was declared a constant */
- /* then the pointer points to a constant */
- if (IS_CONSTANT (etype))
- DCL_PTR_CONST (ptype) = 1;
-
- /* the variable was volatile then pointer to volatile */
- if (IS_VOLATILE (etype))
- DCL_PTR_VOLATILE (ptype) = 1;
-
+ /* set the pointer depending on the storage class */
+ DCL_TYPE (ptype) = PTR_TYPE (SPEC_OCLS (etype));
return ptype;
}
sym_link *opetype = getSpec (optype);
/* set the pointer depending on the storage class */
- if ((DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
- DCL_PTR_CONST (optype) = port->mem.code_ro;
-
- /* if the variable was declared a constant */
- /* then the pointer points to a constant */
- if (IS_CONSTANT (opetype))
- DCL_PTR_CONST (optype) = 1;
-
- /* the variable was volatile then pointer to volatile */
- if (IS_VOLATILE (opetype))
- DCL_PTR_VOLATILE (optype) = 1;
+ DCL_TYPE (optype) = PTR_TYPE (SPEC_OCLS (opetype));
op->isaddr = 0;
return op;
retype = getSpec (operandType (IC_RESULT (ic)));
SPEC_SCLS (retype) = SPEC_SCLS (etype);
SPEC_OCLS (retype) = SPEC_OCLS (etype);
- SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype);
+ SPEC_VOLATILE (retype) |= SPEC_VOLATILE (etype); /* EEP - I'm doubtful about this */
if (IS_PTR (element->type))
setOperandType (IC_RESULT (ic), aggrToPtr (operandType (IC_RESULT (ic)), TRUE));
p = newLink (DECLARATOR);
/* set the pointer depending on the storage class */
- if ((DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype))) == CPOINTER)
- DCL_PTR_CONST (p) = port->mem.code_ro;
-
- /* make sure we preserve the const & volatile */
- if (IS_CONSTANT (opetype))
- DCL_PTR_CONST (p) = 1;
-
- if (IS_VOLATILE (opetype))
- DCL_PTR_VOLATILE (p) = 1;
+ DCL_TYPE (p) = PTR_TYPE (SPEC_OCLS (opetype));
p->next = copyLinkChain (optype);
op->isGptr = IS_GENPTR (optype);
- /* if the pointer was declared as a constant */
- /* then we cannot allow assignment to the derefed */
- if (IS_PTR_CONST (optype))
- SPEC_CONST (retype) = 1;
-
op->isaddr = (IS_PTR (rtype) ||
IS_STRUCT (rtype) ||
IS_INT (rtype) ||
#include "newalloc.h"
value *aggregateToPointer (value *val);
+void printTypeChainRaw (sym_link * start, FILE * of);
void printFromToType(sym_link *from, sym_link *to) {
fprintf (stderr, "from type '");
storage class of the type */
if (IS_SPEC (type))
{
- DCL_PTR_CONST (ptr) = SPEC_CONST (type);
- DCL_PTR_VOLATILE (ptr) = SPEC_VOLATILE (type);
switch (SPEC_SCLS (type))
{
case S_XDATA:
DCL_TYPE (ptr) = POINTER;
break;
case S_CODE:
- DCL_PTR_CONST (ptr) = port->mem.code_ro;
DCL_TYPE (ptr) = CPOINTER;
break;
case S_EEPROM:
break;
}
/* the storage class of type ends here */
- SPEC_SCLS (type) =
- SPEC_CONST (type) =
- SPEC_VOLATILE (type) = 0;
+ SPEC_SCLS (type) = 0;
}
/* now change all the remaining unknown pointers
DCL_TYPE (type) = port->unqualified_pointer;
type = type->next;
}
-
}
/*------------------------------------------------------------------*/
sym->etype = sym->etype->next = newLink (SPECIFIER);
}
SPEC_SCLS (sym->etype) = SPEC_SCLS (DCL_TSPEC (p));
- SPEC_CONST (sym->etype) = SPEC_CONST (DCL_TSPEC (p));
- SPEC_VOLATILE (sym->etype) = SPEC_VOLATILE (DCL_TSPEC (p));
DCL_TSPEC (p) = NULL;
}
static void
checkSClass (symbol * sym, int isProto)
{
+ sym_link *t;
+
if (getenv("DEBUG_SANITY")) {
fprintf (stderr, "checkSClass: %s \n", sym->name);
}
- /* type is literal can happen foe enums change
+ /* type is literal can happen for enums change
to auto */
if (SPEC_SCLS (sym->etype) == S_LITERAL && !SPEC_ENUM (sym->etype))
SPEC_SCLS (sym->etype) = S_AUTO;
if (IS_ABSOLUTE (sym->etype))
SPEC_VOLATILE (sym->etype) = 1;
+ /* If code memory is read only, then pointers to code memory */
+ /* implicitly point to constants -- make this explicit */
+ t = sym->type;
+ while (t && t->next) {
+ if (IS_CODEPTR(t) && port->mem.code_ro) {
+ if (IS_SPEC(t->next)) {
+ SPEC_CONST (t->next) = 1;
+ } else {
+ DCL_PTR_CONST (t->next) = 1;
+ }
+ }
+ t = t->next;
+ }
/* global variables declared const put into code */
/* if no other storage class specified */
if (sym->level == 0 &&
- SPEC_CONST (sym->etype) &&
SPEC_SCLS(sym->etype) == S_FIXED &&
!IS_FUNC(sym->type)) {
- SPEC_SCLS (sym->etype) = S_CODE;
+ /* find the first non-array link */
+ t = sym->type;
+ while (IS_ARRAY(t))
+ t = t->next;
+ if (IS_CONSTANT (t)) {
+ SPEC_SCLS (sym->etype) = S_CODE;
+ }
}
/* global variable in code space is a constant */
if (sym->level == 0 &&
SPEC_SCLS (sym->etype) == S_CODE &&
port->mem.code_ro) {
- if (IS_SPEC(sym->type)) {
- SPEC_CONST (sym->type) = 1;
+ /* find the first non-array link */
+ t = sym->type;
+ while (IS_ARRAY(t))
+ t = t->next;
+ if (IS_SPEC(t)) {
+ SPEC_CONST (t) = 1;
} else {
- DCL_PTR_CONST (sym->type) = 1;
+ DCL_PTR_CONST (t) = 1;
}
}
sym->ival = NULL;
}
- /* if this is an atomatic symbol */
+ /* if this is an automatic symbol */
if (sym->level && (options.stackAuto || reentrant)) {
if ((SPEC_SCLS (sym->etype) == S_AUTO ||
SPEC_SCLS (sym->etype) == S_FIXED ||
rType = copyLinkChain (type2);
reType = getSpec (rType);
+#if 0
+ if (SPEC_NOUN (reType) == V_CHAR)
+ SPEC_NOUN (reType) = V_INT;
+#endif
/* if either of them unsigned but not val then make this unsigned */
if (((/*!IS_LITERAL(type1) &&*/ SPEC_USIGN (etype1)) ||
for (type = start; type && type->next; type = type->next)
;
- scls=SPEC_SCLS(type);
+ if (IS_SPEC (type))
+ scls=SPEC_SCLS(type);
+ else
+ scls=0;
while (type)
{
if (type==start) {
fprintf (of, "pdata* ");
break;
case UPOINTER:
- fprintf (of, "unkown* ");
+ fprintf (of, "unknown* ");
break;
case ARRAY:
if (DCL_ELEM(type)) {
fprintf (of, "\n");
}
+/*--------------------------------------------------------------------*/
+/* printTypeChainRaw - prints the type chain in human readable form */
+/* in the raw data structure ordering */
+/*--------------------------------------------------------------------*/
+void
+printTypeChainRaw (sym_link * start, FILE * of)
+{
+ int nlr = 0;
+ value *args;
+ sym_link * type;
+
+ if (!of)
+ {
+ of = stdout;
+ nlr = 1;
+ }
+
+ if (start==NULL) {
+ fprintf (of, "void");
+ return;
+ }
+
+ type = start;
+
+ while (type)
+ {
+ if (IS_DECL (type))
+ {
+ if (!IS_FUNC(type)) {
+ if (DCL_PTR_VOLATILE (type)) {
+ fprintf (of, "volatile-");
+ }
+ if (DCL_PTR_CONST (type)) {
+ fprintf (of, "const-");
+ }
+ }
+ switch (DCL_TYPE (type))
+ {
+ case FUNCTION:
+ fprintf (of, "function %s %s",
+ (IFFUNC_ISBUILTIN(type) ? "__builtin__" : " "),
+ (IFFUNC_ISJAVANATIVE(type) ? "_JavaNative" : " "));
+ fprintf (of, "( ");
+ for (args = FUNC_ARGS(type);
+ args;
+ args=args->next) {
+ printTypeChain(args->type, of);
+ if (args->next)
+ fprintf(of, ", ");
+ }
+ fprintf (of, ") ");
+ break;
+ case GPOINTER:
+ fprintf (of, "generic* ");
+ break;
+ case CPOINTER:
+ fprintf (of, "code* ");
+ break;
+ case FPOINTER:
+ fprintf (of, "xdata* ");
+ break;
+ case EEPPOINTER:
+ fprintf (of, "eeprom* ");
+ break;
+ case POINTER:
+ fprintf (of, "near* ");
+ break;
+ case IPOINTER:
+ fprintf (of, "idata* ");
+ break;
+ case PPOINTER:
+ fprintf (of, "pdata* ");
+ break;
+ case UPOINTER:
+ fprintf (of, "unknown* ");
+ break;
+ case ARRAY:
+ if (DCL_ELEM(type)) {
+ fprintf (of, "[%d] ", DCL_ELEM(type));
+ } else {
+ fprintf (of, "[] ");
+ }
+ break;
+ }
+ if (DCL_TSPEC(type))
+ {
+ fprintf (of, "{");
+ printTypeChainRaw(DCL_TSPEC(type), of);
+ fprintf (of, "}");
+ }
+ }
+ else if (IS_SPEC (type))
+ {
+ switch (SPEC_SCLS (type))
+ {
+ case S_DATA: fprintf (of, "data-"); break;
+ case S_XDATA: fprintf (of, "xdata-"); break;
+ case S_SFR: fprintf (of, "sfr-"); break;
+ case S_SBIT: fprintf (of, "sbit-"); break;
+ case S_CODE: fprintf (of, "code-"); break;
+ case S_IDATA: fprintf (of, "idata-"); break;
+ case S_PDATA: fprintf (of, "pdata-"); break;
+ case S_LITERAL: fprintf (of, "literal-"); break;
+ case S_STACK: fprintf (of, "stack-"); break;
+ case S_XSTACK: fprintf (of, "xstack-"); break;
+ case S_BIT: fprintf (of, "bit-"); break;
+ case S_EEPROM: fprintf (of, "eeprom-"); break;
+ default: break;
+ }
+ if (SPEC_VOLATILE (type))
+ fprintf (of, "volatile-");
+ if (SPEC_CONST (type))
+ fprintf (of, "const-");
+ if (SPEC_USIGN (type))
+ fprintf (of, "unsigned-");
+ switch (SPEC_NOUN (type))
+ {
+ case V_INT:
+ if (IS_LONG (type))
+ fprintf (of, "long-");
+ fprintf (of, "int");
+ break;
+
+ case V_CHAR:
+ fprintf (of, "char");
+ break;
+
+ case V_VOID:
+ fprintf (of, "void");
+ break;
+
+ case V_FLOAT:
+ fprintf (of, "float");
+ break;
+
+ case V_STRUCT:
+ fprintf (of, "struct %s", SPEC_STRUCT (type)->tag);
+ break;
+
+ case V_SBIT:
+ fprintf (of, "sbit");
+ break;
+
+ case V_BIT:
+ fprintf (of, "bit");
+ break;
+
+ case V_BITFIELD:
+ fprintf (of, "bitfield {%d,%d}", SPEC_BSTR (type), SPEC_BLEN (type));
+ break;
+
+ case V_DOUBLE:
+ fprintf (of, "double");
+ break;
+
+ default:
+ fprintf (of, "unknown type");
+ break;
+ }
+ }
+ else
+ fprintf (of, "NOT_SPEC_OR_DECL");
+ type = type->next;
+ if (type)
+ fputc (' ', of);
+ }
+ if (nlr)
+ fprintf (of, "\n");
+}
+
/*-----------------------------------------------------------------*/
/* powof2 - returns power of two for the number if number is pow 2 */
int isSymbolEqual (symbol *, symbol *);
int powof2 (unsigned long);
void printTypeChain (sym_link *, FILE *);
+void printTypeChainRaw (sym_link *, FILE *);
void initCSupport ();
void initBuiltIns ();
void pointerTypes (sym_link *, sym_link *);
val->type = newLink (DECLARATOR);
if (SPEC_SCLS (arrExpr->left->etype) == S_CODE)
- {
- DCL_TYPE (val->type) = CPOINTER;
- DCL_PTR_CONST (val->type) = port->mem.code_ro;
- }
+ DCL_TYPE (val->type) = CPOINTER;
else if (SPEC_SCLS (arrExpr->left->etype) == S_XDATA)
DCL_TYPE (val->type) = FPOINTER;
else if (SPEC_SCLS (arrExpr->left->etype) == S_XSTACK)
val->type = newLink (DECLARATOR);
if (SPEC_SCLS (structT->etype) == S_CODE)
- {
- DCL_TYPE (val->type) = CPOINTER;
- DCL_PTR_CONST (val->type) = port->mem.code_ro;
- }
+ DCL_TYPE (val->type) = CPOINTER;
else if (SPEC_SCLS (structT->etype) == S_XDATA)
DCL_TYPE (val->type) = FPOINTER;
else if (SPEC_SCLS (structT->etype) == S_XSTACK)
offset = OP_SYMBOL(IC_LEFT(ic))->offset;
aop->aopu.pcop = popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val,0);
+#if 0
PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
+#else
+ PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
+#endif
PCOI(aop->aopu.pcop)->index = val;
DEBUGpic14_emitcode(";","%d: rname %s, val %d, const = %d",
{
sym_link *type = operandType(op);
+#if 0
if(IS_PTR_CONST(type))
+#else
+ if(IS_CODEPTR(type))
+#endif
DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
}
{
sym_link *type = operandType(op);
+#if 0
if(IS_PTR_CONST(type))
+#else
+ if(IS_CODEPTR(type))
+#endif
DEBUGpic14_emitcode(";","%d aop type is const pointer",__LINE__);
}
type = operandType(left);
etype = getSpec(type);
+#if 0
if (IS_PTR_CONST(type))
+#else
+ if (IS_CODEPTR(type))
+#endif
DEBUGpic14_emitcode ("; ***","%d - const pointer",__LINE__);
/* if left is of type of pointer then it is simple */
break;
case GPOINTER:
+#if 0
if (IS_PTR_CONST(type))
genConstPointerGet (left,result,ic);
else
+#endif
genGenPointerGet (left,result,ic);
break;
}
goto release;
DEBUGpic14_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
+#if 0
if (IS_PTR_CONST(rtype))
+#else
+ if (IS_CODEPTR(rtype))
+#endif
DEBUGpic14_emitcode ("; ***","%d - right is const pointer",__LINE__);
+#if 0
if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
+#else
+ if (IS_CODEPTR(operandType(IC_RESULT(ic))))
+#endif
DEBUGpic14_emitcode ("; ***","%d - result is const pointer",__LINE__);
if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
getSize (sym->type));
+#if 0
if(IS_PTR_CONST (sym->type)) {
+#else
+ if(IS_CODEPTR (sym->type)) {
+#endif
debugLog (" %d const pointer type requires %d registers, changing to 2\n",__LINE__,sym->nRegs);
sym->nRegs = 2;
}
sym_link *etype = getSpec (operandType (IC_LEFT (ic)));
debugAopGet (" left:", IC_LEFT (ic));
+#if 0
if(IS_PTR_CONST(OP_SYMBOL(IC_LEFT(ic))->type))
+#else
+ if(IS_CODEPTR(OP_SYMBOL(IC_LEFT(ic))->type))
+#endif
debugLog (" is a pointer\n");
if(IS_OP_VOLATILE(IC_LEFT(ic)))
offset = OP_SYMBOL(IC_LEFT(ic))->offset;
aop->aopu.pcop = pic16_popGetImmd(OP_SYMBOL(IC_LEFT(ic))->rname,0,val);
+#if 0
PCOI(aop->aopu.pcop)->_const = IS_PTR_CONST(operandType(op));
+#else
+ PCOI(aop->aopu.pcop)->_const = IS_CODEPTR(operandType(op));
+#endif
PCOI(aop->aopu.pcop)->index = val;
DEBUGpic16_emitcode(";","%d: rname %s, val %d, const = %d",
__LINE__,OP_SYMBOL(IC_LEFT(ic))->rname,
+#if 0
val, IS_PTR_CONST(operandType(op)));
+#else
+ val, IS_CODEPTR(operandType(op)));
+#endif
// DEBUGpic16_emitcode(";","aop type %s",pic16_AopType(AOP_TYPE(IC_LEFT(ic))));
{
sym_link *type = operandType(op);
+#if 0
if(IS_PTR_CONST(type))
+#else
+ if(IS_CODEPTR(type))
+#endif
DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
}
{
sym_link *type = operandType(op);
+#if 0
if(IS_PTR_CONST(type))
+#else
+ if(IS_CODEPTR(type))
+#endif
DEBUGpic16_emitcode(";","%d aop type is const pointer",__LINE__);
}
type = operandType(left);
etype = getSpec(type);
+#if 0
if (IS_PTR_CONST(type))
+#else
+ if (IS_CODEPTR(type))
+#endif
DEBUGpic16_emitcode ("; ***","%d - const pointer",__LINE__);
/* if left is of type of pointer then it is simple */
break;
case GPOINTER:
+#if 0
if (IS_PTR_CONST(type))
genConstPointerGet (left,result,ic);
else
+#endif
genGenPointerGet (left,result,ic);
break;
}
goto release;
DEBUGpic16_emitcode("; ***","%s %d",__FUNCTION__,__LINE__);
+#if 0
if (IS_PTR_CONST(rtype))
+#else
+ if (IS_CODEPTR(rtype))
+#endif
DEBUGpic16_emitcode ("; ***","%d - right is const pointer",__LINE__);
+#if 0
if (IS_PTR_CONST(operandType(IC_RESULT(ic))))
+#else
+ if (IS_CODEPTR(operandType(IC_RESULT(ic))))
+#endif
DEBUGpic16_emitcode ("; ***","%d - result is const pointer",__LINE__);
if ((AOP_TYPE(right) == AOP_PCODE) && AOP(right)->aopu.pcop->type == PO_IMMEDIATE) {
getSize (sym->type));
+#if 0
if(IS_PTR_CONST (sym->type)) {
+#else
+ if(IS_CODEPTR (sym->type)) {
+#endif
debugLog (" %d const pointer type requires %d registers, changing to 2\n",__LINE__,sym->nRegs);
sym->nRegs = 2;
}
sym_link *etype = getSpec (operandType (IC_LEFT (ic)));
debugAopGet (" left:", IC_LEFT (ic));
+#if 0
if(IS_PTR_CONST(OP_SYMBOL(IC_LEFT(ic))->type))
+#else
+ if(IS_CODEPTR(OP_SYMBOL(IC_LEFT(ic))->type))
+#endif
debugLog (" is a pointer\n");
if(IS_OP_VOLATILE(IC_LEFT(ic)))
--- /dev/null
+/* Tests usage of const qualifier.
+ */
+#include <testfwk.h>
+
+char k; /* char */
+const char const_char = 123; /* constant char */
+const char * const_char_ptr; /* pointer to constant char */
+char * const char_ptr_const = &k; /* constant pointer to char */
+const char * const const_char_ptr_const = &const_char;
+ /* constant pointer to constant char */
+char char_array[3]; /* array of char */
+const char const_char_array[] = {1,2,3}; /* array of constant char */
+const char ** const_char_ptr_ptr; /* pointer to pointer to constant char */
+
+char
+ident(char x)
+{
+ return x;
+}
+
+void
+testConst(void)
+{
+ /* Since const_char_ptr is in itself not constant, we can change it */
+ const_char_ptr = const_char_array;
+ const_char_ptr++;
+ ASSERT(*const_char_ptr == 2);
+
+ /* Check for bug #621531 */
+ const_char_ptr = const_char_array;
+ ASSERT(const_char_ptr[0] == 1);
+ const_char_ptr++;
+
+ /* Since char_ptr_const is constant, we cannot change it. However, */
+ /* we can change the object that it points to. */
+ *char_ptr_const = 5;
+ ASSERT(ident(*char_ptr_const)==5);
+ (*char_ptr_const)++;
+ ASSERT(ident(*char_ptr_const)==6);
+
+ /* We can't modify const_char_ptr_const or the object that it points */
+ /* to. Unfortunately, we can't test that compiler enforces these */
+ /* restriction, so just verify its initialization. */
+ ASSERT(*const_char_ptr_const == const_char);
+
+ /* We can change const_char_ptr_ptr or the object that it points to. */
+ const_char_ptr = const_char_array;
+ const_char_ptr_ptr = &const_char_ptr;
+ ASSERT(ident(**const_char_ptr_ptr)==1);
+ (*const_char_ptr_ptr)++;
+ ASSERT(ident(**const_char_ptr_ptr)==2);
+}