This article examines "1=3" and "&5" for an incorrect expression that cannot be evaluated.
The following questions will be checked.
Assigning values to an expression that cannot be assigned (example: 1 = 2 + 2)
Calling a function using an illegal function name (example: "String" ("%d\n", I))
Invalid operand array Reference (example: 1[0])
Invalid operand member reference (example: 1.MEMB)
Pointer indirect reference with invalid operand (example: 1->MEMB)
To value a non-pointer object (example: *)
Address to a non-lvalue expression
Specific examples and the detection of the problem are shown in table 10.1, which includes the questions just listed.
Check for non-pointer type value operations
/* Check for a non-pointer type value Operation * represents the handling of the dereferencenode of the value operator (*). * This method checks whether the type of the operand of the value operator is a pointer. * ///#@ @range/dereferencenode{public Void visit (dereferencenode node) {/ * * First, through Super.visit (node) calls the base class visitor method traversal operand (node.expr ()) (that is, check the operand). * /super.visit (node); /* Next, call the Ispointer method of the operand node.expr () to check whether the type of the operand is a pointer, that is, to check whether the value can be taken. If the value cannot be evaluated, the Undereferableerror method output compilation error is called. * /if (! node.expr (). Ispointer ()) { undereferableerror (node.location ()); } /* * Finally, call the Handleimplicitaddress method to deal specifically with array types and function types. This treatment is also related to the next addressnode processing, * /handleimplicitaddress (node); return null; }
Get check for non-lvalue expression address
/* Get a check for non-lvalue expression addresses * Check if the operand is an lvalue. The processing of the addressnode that represents the address operator *//#@ @range/addressnode{public Void visit (addressnode node) {super.visit (nod e); /* * First Call the Islvalue method on node.expr () to check if expr in &expr is an expression that can be taken. Exprnode#islvalue is a method that checks whether an expression on that node can get an address. */if (! node.expr (). Islvalue ()) {Semanticerror (Node.location (), "Invalid expression for &"); The remaining statements are used to determine the type of addressnode. usually node.expr (). Isloadable () returns True, which is the process of performing the else part. The type of &expr is a pointer to the type of expr, so pointer types that point to node.expr (). Type () can be used as the type of the node as a whole. */Type base = node.expr (). Type (); /* * When you set the type of puts to a pointer to a function, you must also set the type of &puts to a pointer to the function. The type of node.expr () is specifically handled in the case of arrays or functions, making the type of &puts consistent with the type of puts. */if (! node.expr (). Isloadable ()) {//Node.expr.type is already pointer. Node.settype (base); } else {Node.settype (Typetable.pointerto (base)); } return Null }
Implicit pointer-generation
A variable of a single array type or function type represents the address of an array or function. For example, assuming that the type of the variable puts is a function type (commonly referred to as a function pointer), then puts and &puts get the same values.
/* * The Handleimplicitaddress method converts an array type or function type to a pointer to an array or function type, which implicitly generates a pointer type. */ private void Handleimplicitaddress (Lhsnode node) { if (! node.isloadable ()) { Type t = Node.type (); C8/>if (T.isarray ()) { //int[4] ary; ary; should generate int* Node.settype (Typetable.pointerto (T.basetype () )); } else { Node.settype (Typetable.pointerto (t));}}}
puts is a pointer to a function, so the result of its value operation *puts is the function type, but this is implicitly converted to a pointer to a function. *puts is still a pointer to a function, so it can still be evaluated for operation and will still be converted to a pointer to a function. Like this can be indefinitely repeated. So the values of "&puts" "puts" "*puts" "**puts" "***puts" in C are the same.
Compiler Development Series--ocelot language 5. Validity check of expressions