/*
* xtc - The eXTensible Compiler
* Copyright (C) 2009-2012 New York University
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package xtc.lang.cpp;
import xtc.lang.cpp.ForkMergeParser.Subparser;
/* from c.prologue */
import xtc.Constants;
import xtc.Limits;
import xtc.lang.cpp.CContext.SymbolTable.STField;
import xtc.tree.Attribute;
import xtc.tree.GNode;
import xtc.tree.Location;
import xtc.tree.Node;
import xtc.tree.Visitor;
import xtc.util.Pair;
import xtc.lang.cpp.Syntax.Kind;
import xtc.lang.cpp.Syntax.LanguageTag;
import xtc.lang.cpp.Syntax.ConditionalTag;
import xtc.lang.cpp.Syntax.DirectiveTag;
import xtc.lang.cpp.Syntax.Layout;
import xtc.lang.cpp.Syntax.Language;
import xtc.lang.cpp.Syntax.Text;
import xtc.lang.cpp.Syntax.Directive;
import xtc.lang.cpp.Syntax.Conditional;
import xtc.lang.cpp.Syntax.Error;
import xtc.type.AliasT;
import xtc.type.ArrayT;
import xtc.type.BooleanT;
import xtc.type.C;
import xtc.type.CastReference;
import xtc.type.Constant;
import xtc.type.DynamicReference;
import xtc.type.EnumT;
import xtc.type.EnumeratorT;
import xtc.type.ErrorT;
import xtc.type.FieldReference;
import xtc.type.FunctionT;
import xtc.type.InternalT;
import xtc.type.LabelT;
import xtc.type.NullReference;
import xtc.type.NumberT;
import xtc.type.PointerT;
import xtc.type.Reference;
import xtc.type.StaticReference;
import xtc.type.StringReference;
import xtc.type.StructOrUnionT;
import xtc.type.StructT;
import xtc.type.Tagged;
import xtc.type.Type;
import xtc.type.Type.Tag;
import xtc.type.UnionT;
import xtc.type.VariableT;
import xtc.type.VoidT;
import xtc.util.SymbolTable;
import xtc.util.SymbolTable.Scope;
import xtc.util.SingletonIterator;
import xtc.util.Utilities;
import xtc.lang.cpp.PresenceConditionManager.PresenceCondition;
import xtc.lang.cpp.ForkMergeParser.StackFrame;
import java.util.ArrayList;
import java.util.List;
import org.sat4j.core.VecInt;
import org.sat4j.minisat.SolverFactory;
import org.sat4j.specs.ContradictionException;
import org.sat4j.specs.IConstr;
import org.sat4j.specs.IProblem;
import org.sat4j.specs.ISolver;
import org.sat4j.specs.TimeoutException;
import org.sat4j.tools.ModelIterator;
/**
* This class is generated from grammar annotations and provides semantic
* action support.
*/
public class CActions implements SemanticActions {
/** The instance of this class */
private static CActions ref;
/** Get the instance of this class */
public static CActions getInstance() {
if (null == ref) {
ref = new CActions();
}
return ref;
}
public Object action(int production, Subparser subparser, Object value) {
switch (production) {
case 12:
{ ReenterScope(subparser); }
break;
case 13:
{ ExitScope(subparser); }
break;
case 15:
{ ReenterScope(subparser); }
break;
case 16:
{ ExitScope(subparser); }
break;
case 19:
{ bindFunDef(subparser, null, getNodeAt(subparser, 1)); }
break;
case 20:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindFunDef(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 21:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindFunDef(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 22:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindFunDef(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 23:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindFunDef(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 24:
{ bindFunDef(subparser, null, getNodeAt(subparser, 1)); }
break;
case 25:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindFunDef(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 26:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindFunDef(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 27:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindFunDef(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 28:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindFunDef(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 29:
{ bindFunDef(subparser, null, getNodeAt(subparser, 1)); }
break;
case 30:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindFunDef(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 31:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindFunDef(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 32:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindFunDef(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 33:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindFunDef(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 34:
{ ReenterScope(subparser); }
break;
case 35:
{ ExitScope(subparser); }
break;
case 37:
{ ReenterScope(subparser); }
break;
case 38:
{ ExitScope(subparser); }
break;
case 40:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindFunDef(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 41:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindFunDef(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 42:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindFunDef(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 43:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindFunDef(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 44:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindFunDef(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 45:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindFunDef(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 46:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindFunDef(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 47:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindFunDef(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 48:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindFunDef(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 49:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindFunDef(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 50:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindFunDef(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 51:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindFunDef(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 54:
{ KillReentrantScope(subparser); }
break;
case 56:
{ KillReentrantScope(subparser); }
break;
case 58:
{ KillReentrantScope(subparser); }
break;
case 60:
{ KillReentrantScope(subparser); }
break;
case 62:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindIdent(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 64:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindIdent(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 66:
{
// reuses saved base type
bindIdent(subparser, getNodeAt(subparser, 4), getNodeAt(subparser, 1));
}
break;
case 68:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindIdent(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 70:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindIdent(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 72:
{
// reuses saved base type
bindIdent(subparser, getNodeAt(subparser, 4), getNodeAt(subparser, 1));
}
break;
case 84:
{
updateSpecs(subparser,
getSpecsAt(subparser, 1),
value);
}
break;
case 85:
{
updateSpecs(subparser,
getSpecsAt(subparser, 2),
getSpecsAt(subparser, 1),
value);
}
break;
case 86:
{
updateSpecs(subparser,
getSpecsAt(subparser, 2),
getSpecsAt(subparser, 1),
value);
}
break;
case 87:
{
updateSpecs(subparser,
getSpecsAt(subparser, 1),
value);
}
break;
case 88:
{
updateSpecs(subparser,
getSpecsAt(subparser, 2),
getSpecsAt(subparser, 1),
value);
}
break;
case 91:
{
getSpecsAt(subparser, 1).add(Constants.ATT_CONSTANT);
updateSpecs(subparser,
getSpecsAt(subparser, 1),
value);
}
break;
case 92:
{
getSpecsAt(subparser, 1).add(Constants.ATT_VOLATILE);
updateSpecs(subparser,
getSpecsAt(subparser, 1),
value);
}
break;
case 93:
{
getSpecsAt(subparser, 1).add(Constants.ATT_RESTRICT);
updateSpecs(subparser,
getSpecsAt(subparser, 1),
value);
}
break;
case 94:
{
/* TODO AttributeSpecifier */
updateSpecs(subparser,
getSpecsAt(subparser, 1),
value);
}
break;
case 95:
{
getSpecsAt(subparser, 1).add(Constants.ATT_INLINE);
updateSpecs(subparser,
getSpecsAt(subparser, 1),
value);
}
break;
case 108:
{
updateSpecs(subparser,
getSpecsAt(subparser, 2),
getSpecsAt(subparser, 1),
value);
}
break;
case 109:
{
updateSpecs(subparser,
getSpecsAt(subparser, 2),
getSpecsAt(subparser, 1),
value);
}
break;
case 110:
{
updateSpecs(subparser,
getSpecsAt(subparser, 2),
getSpecsAt(subparser, 1),
value);
}
break;
case 111:
{
updateSpecs(subparser,
getSpecsAt(subparser, 2),
getSpecsAt(subparser, 1),
value);
}
break;
case 112:
{ /* Arithmetic or void */
updateSpecs(subparser,
getSpecsAt(subparser, 1),
value);
}
break;
case 113:
{
updateSpecs(subparser,
getSpecsAt(subparser, 2),
getSpecsAt(subparser, 1),
value);
}
break;
case 114:
{
updateSpecs(subparser,
getSpecsAt(subparser, 2),
getSpecsAt(subparser, 1),
value);
}
break;
case 115:
{
updateSpecs(subparser,
getSpecsAt(subparser, 2),
getSpecsAt(subparser, 1),
value);
}
break;
case 141:
{
updateSpecs(subparser,
getSpecsAt(subparser, 2),
getSpecsAt(subparser, 1),
value);
}
break;
case 142:
{
updateSpecs(subparser,
getSpecsAt(subparser, 2),
getSpecsAt(subparser, 1),
value);
}
break;
case 143:
{
updateSpecs(subparser,
getSpecsAt(subparser, 2),
getSpecsAt(subparser, 1),
value);
}
break;
case 144:
{
updateSpecs(subparser,
getSpecsAt(subparser, 2),
getSpecsAt(subparser, 1),
value);
}
break;
case 145:
{
updateSpecs(subparser,
getSpecsAt(subparser, 1),
value);
}
break;
case 146:
{
updateSpecs(subparser,
getSpecsAt(subparser, 2),
getSpecsAt(subparser, 1),
value);
}
break;
case 147:
{
updateSpecs(subparser,
getSpecsAt(subparser, 2),
getSpecsAt(subparser, 1),
value);
}
break;
case 148:
{
updateSpecs(subparser,
getSpecsAt(subparser, 2),
getSpecsAt(subparser, 1),
value);
}
break;
case 149:
{ getSpecsAt(subparser, 1).type = InternalT.VA_LIST; }
break;
case 150:
{ getSpecsAt(subparser, 1).storage = Constants.ATT_STORAGE_TYPEDEF; }
break;
case 151:
{ getSpecsAt(subparser, 1).storage = Constants.ATT_STORAGE_EXTERN; }
break;
case 152:
{ getSpecsAt(subparser, 1).storage = Constants.ATT_STORAGE_STATIC; }
break;
case 153:
{ getSpecsAt(subparser, 1).storage = Constants.ATT_STORAGE_AUTO; }
break;
case 154:
{ getSpecsAt(subparser, 1).storage = Constants.ATT_STORAGE_REGISTER; }
break;
case 155:
{ getSpecsAt(subparser, 1).type = VoidT.TYPE; }
break;
case 156:
{ getSpecsAt(subparser, 1).seenChar = true; }
break;
case 157:
{ getSpecsAt(subparser, 1).seenShort = true; }
break;
case 158:
{ getSpecsAt(subparser, 1).seenInt = true; }
break;
case 159:
{ getSpecsAt(subparser, 1).seenInt = true; }
break;
case 160:
{ getSpecsAt(subparser, 1).longCount++; }
break;
case 161:
{ getSpecsAt(subparser, 1).seenFloat = true; }
break;
case 162:
{ getSpecsAt(subparser, 1).seenDouble = true; }
break;
case 163:
{ getSpecsAt(subparser, 1).seenSigned = true; }
break;
case 164:
{ getSpecsAt(subparser, 1).seenUnsigned = true; }
break;
case 165:
{ getSpecsAt(subparser, 1).seenBool = true; }
break;
case 166:
{ getSpecsAt(subparser, 1).seenComplex = true; }
break;
case 175:
{ EnterScope(subparser); }
break;
case 176:
{ ExitScope(subparser); }
break;
case 177:
{
Node tag = null;
Node members = getNodeAt(subparser, 3);
Node attrs = null;
updateSpecs(subparser,
makeStructSpec(subparser, tag, members, attrs),
value);
}
break;
case 178:
{ EnterScope(subparser); }
break;
case 179:
{ ExitScope(subparser); }
break;
case 180:
{
Node tag = getNodeAt(subparser, 6);
Node members = getNodeAt(subparser, 3);
Node attrs = null;
updateSpecs(subparser,
makeStructSpec(subparser, tag, members, attrs),
value);
}
break;
case 182:
{ EnterScope(subparser); }
break;
case 183:
{ ExitScope(subparser); }
break;
case 184:
{
Node tag = null;
Node members = getNodeAt(subparser, 3);
Node attrs = getNodeAt(subparser, 6);
updateSpecs(subparser,
makeStructSpec(subparser, tag, members, attrs),
value);
}
break;
case 185:
{ EnterScope(subparser); }
break;
case 186:
{ ExitScope(subparser); }
break;
case 187:
{
Node tag = getNodeAt(subparser, 6);
Node members = getNodeAt(subparser, 3);
Node attrs = getNodeAt(subparser, 7);
updateSpecs(subparser,
makeStructSpec(subparser, tag, members, attrs),
value);
}
break;
case 189:
{ EnterScope(subparser); }
break;
case 190:
{ ExitScope(subparser); }
break;
case 192:
{ EnterScope(subparser); }
break;
case 193:
{ ExitScope(subparser); }
break;
case 196:
{ EnterScope(subparser); }
break;
case 197:
{ ExitScope(subparser); }
break;
case 199:
{ EnterScope(subparser); }
break;
case 200:
{ ExitScope(subparser); }
break;
case 203:
{
((Node) value).setProperty(SPECS, new Specifiers());
}
break;
case 204:
{
updateSpecs(subparser,
getSpecsAt(subparser, 2),
getSpecsAt(subparser, 1),
value);
}
break;
case 233:
{ BindEnum(subparser); }
break;
case 235:
{ BindEnum(subparser); }
break;
case 253:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindIdent(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 255:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindIdent(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 257:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindIdent(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 259:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindIdent(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 261:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindIdent(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 263:
{
saveBaseType(subparser, getNodeAt(subparser, 2));
bindIdent(subparser, getNodeAt(subparser, 2), getNodeAt(subparser, 1));
}
break;
case 267:
{ BindVar(subparser); }
break;
case 324:
{
/* setDecl(value, new PointerT(getDecl(getNodeAt(subparser, 1)))); */
/* copyName(subparser, value, 1); */
}
break;
case 325:
{
/* Specifiers spec = getSpecsAt(subparser, 2); */
/* Type baseType = getDecl(getNodeAt(subparser, 1));; */
/* Type result = spec.annotateBase(new PointerT(baseType).annotate()); */
/* setDecl(value, result); */
/* copyName(subparser, value, 1); */
}
break;
case 330:
{
/* copyDeclName(subparser, value, 2); */
}
break;
case 332:
{ EnterScope(subparser); }
break;
case 333:
{ ExitReentrantScope(subparser); }
break;
case 336:
{ /* copyDeclName(subparser, value, 1); */ }
break;
case 337:
{ /* copyDeclName(subparser, value, 2); */ }
break;
case 338:
{
/* setDecl(value, lastSeenType(subparser)); */
/* setName(value, getStringAt(subparser, 1)); */
}
break;
case 342:
{ EnterScope(subparser); }
break;
case 343:
{ ExitReentrantScope(subparser); }
break;
case 354:
{
/* setDecl(value, new ArrayT(getDecl(getNodeAt(subparser, 1)))); */
/* copyName(subparser, value, 1); */
}
break;
case 355:
{
/* setDecl(value, new ArrayT(getDecl())); */
/* copyName(subparser, value, 1); */
}
break;
case 420:
{ useIdent(subparser, getNodeAt(subparser, 1)); }
break;
case 422:
{ EnterScope(subparser); }
break;
case 423:
{ ExitScope(subparser); }
break;
case 434:
{ callFunction(subparser, getNodeAt(subparser, 3), null); }
break;
case 435:
{ callFunction(subparser, getNodeAt(subparser, 4), getNodeAt(subparser, 2)); }
break;
}
return value;
}
public void dispatch(int id, Subparser subparser) {
// no action productions
}
/* from c.epilogue */
/** True when statistics should be output. */
private boolean languageStatistics = false;
/** Turn on error reporting. */
private static boolean showErrors = false;
/** Turn on debugging messages. */
private static boolean debug = false;
/** Turn on checkers. */
private static boolean enableCheckers = false;
/** Turn on checkers. */
private static List<String> extraConstraints = null;
/** Turn on function analysis. */
private static boolean enableFunctionAnalysis = false;
/** A symbol table for analysis. */
private CContext.SymbolTable functionTable;
/** Turn on kconfig feature model clauses. */
private boolean hasClauses = false;
/** The clauses for the kconfig feature model. */
private Clauses featureClauses = null;
/** The kconfig feature model solver. */
private ISolver featureSolver;
/** The assumptions of the feature model, i.e., non-arch config vars. */
private VecInt modelAssumptions;
/**
* Turn language statistics collection on. Default is off.
*
* @param b True is on.
*/
public void collectStatistics(boolean b) {
languageStatistics = b;
}
/**
* Show errors.
*
* @param b True is on.
*/
public void showErrors(boolean b) {
showErrors = b;
}
/**
* Show debugging messages.
*
* @param b True is on.
*/
public void debug(boolean b) {
debug = b;
}
/**
* Enable checkers.
*
* @param b Enable checkers if true.
*/
public void enableCheckers(boolean b) {
this.enableCheckers(b, null);
}
/**
* Enable checkers.
*
* @param b Enable checkers if true.
* @param extraConstraints Extra constraints to SAT solver.
*/
public void enableCheckers(boolean b, List<String> extraConstraints) {
this.enableCheckers = b;
if (null == extraConstraints) {
// avoid having to check for null
extraConstraints = new ArrayList<String>();
}
this.extraConstraints = extraConstraints;
}
/**
* Enable function analysis.
*/
public void enableFunctionAnalysis() {
this.enableFunctionAnalysis = true;
this.functionTable = new CContext.SymbolTable();
}
/**
* Add kconfig feature model clauses.
*
* @param clauses The clauses.
*/
public void addClauses(Clauses clauses, int[] assumptions) {
if (null != assumptions) {
this.modelAssumptions = new VecInt(assumptions);
} else {
this.modelAssumptions = new VecInt(new int[0]);
}
if (null != clauses) {
this.hasClauses = true;
this.featureClauses = clauses;
this.featureSolver = SolverFactory.newDefault();
this.featureSolver.newVar(clauses.getNumVars());
this.featureSolver.setExpectedNumberOfClauses(clauses.size());
try {
for (List<Integer> clause : clauses) {
int[] cint = new int[clause.size()];
int i = 0;
for (Integer val : clause) {
cint[i++] = val;
}
this.featureSolver.addClause(new VecInt(cint));
}
} catch (ContradictionException e) {
e.printStackTrace();
System.exit(1);
}
} else {
this.hasClauses = false;
this.featureClauses = null;
}
}
/**
* Get the checker symbol table.
*
* @return The checker symbol table.
*/
public CContext.SymbolTable getFunctionTable() {
return this.functionTable;
}
/**
* A helper function to get the value of a node on the stack, which
* corresponds to the value of the component of a production. Unlike
* bison, this is numbered by the stack, i.e., the closest component
* to the action has the lowest number, starting with 1.
*
* @param subparser The reference to the subparser.
* @param number The component number, where 1 is the component to the
* left of the action, and increasing in number while going towards
* the beginning of the production.
* @return The node value of the component.
*/
private static Node getNodeAt(Subparser subparser, int component) {
return (Node) (subparser.stack.get(component).value);
}
private static String getStringAt(Subparser subparser, int component) {
return ((Syntax) getNodeAt(subparser, component)).toLanguage().getTokenText();
}
/**
* A helper function to set the type property of the given node. The
* given value will be first cast to a Node.
*
* @param value A node object.
* @param type The type to set.
*/
private static void setType(Object value, Type type) {
((Node) value).setProperty(Constants.TYPE, type);
}
private static void error(String msg) {
if (showErrors) {
System.err.println("error: " + msg);
}
/* System.exit(1); */
}
// ---------- Parsing-only context
/**
* Compute and store the base type indicated by the specifications
* property of the given node.
*/
public void saveBaseType(Subparser subparser, Node typespec) {
if (typespec.getProperty(SPECS) == null) {
if (showErrors) {
System.err.println("error: no specs available");
}
return;
}
((CContext) subparser.scope).lastSeenType =
((Specifiers) typespec.getProperty(SPECS)).getType();
}
/**
* Return the last seen type.
*/
public Type lastSeenType(Subparser subparser) {
return ((CContext) subparser.scope).lastSeenType;
}
private static class Binding {
public Language ident;
public Type type;
public Binding(Language ident, Type type) {
this.ident = ident;
this.type = type;
}
}
private boolean findToken(Object n, CTag tag) {
if (n instanceof Language && ((Language) n).tag() == tag) {
return true;
} else if (n instanceof Syntax) {
return ((Syntax) n).getTokenText().equals(tag.getText());
} else if (n instanceof Node) {
boolean b = false;
for (Object o : ((Node) n)) {
b |= findToken(o, tag);
if (b) return true;
}
return false;
} else if (n instanceof PresenceCondition) {
// ignore
return false;
} else {
System.err.println(n.getClass().getSimpleName());
return false;
}
}
public void bindFunDef(Subparser subparser, Node typespec, Node declarator) {
boolean static_function;
if (getident(declarator).equals("ERR_PTR")) {
System.err.println(typespec);
System.err.println(declarator);
}
if (null == typespec) {
// only static with static keyword
static_function = false;
} else if (typespec.getName().equals("DeclarationSpecifier") ||
typespec.getName().equals("DeclarationQualifierList")) {
// the declaration keyword can only appear in these kinds of
// specifiers
if (typespec.getProperty(SPECS) != null) {
static_function = ((Specifiers) typespec.getProperty(SPECS)).storage ==
Constants.ATT_STORAGE_STATIC;
} else {
// traverse subtree looking for static until checkers are finished
static_function = findToken(typespec, CTag.STATIC);
}
} else {
// the declaration keyword can only appear in these kinds of
// specifiers
if (typespec.getProperty(SPECS) != null) {
static_function = ((Specifiers) typespec.getProperty(SPECS)).storage ==
Constants.ATT_STORAGE_STATIC;
} else {
// traverse subtree looking for static until checkers are finished
static_function = findToken(typespec, CTag.STATIC);
}
}
if (static_function) {
bindIdent(subparser, typespec, declarator, STField.STATIC_FUNDEF);
} else {
bindIdent(subparser, typespec, declarator, STField.GLOBAL_FUNDEF);
}
}
public void bindIdent(Subparser subparser, Node typespec, Node declarator) {
bindIdent(subparser, typespec, declarator, null);
}
/** typespec might be null for declarations and definitions without a
* type spec; alsoSet is used to set another symbol table bit and
* might be null.
*/
public void bindIdent(Subparser subparser, Node typespec, Node declarator, STField alsoSet) {
StackFrame stack = subparser.stack;
PresenceConditionManager.PresenceCondition presenceCondition = subparser.getPresenceCondition();
CContext scope = (CContext) subparser.scope;
// TODO need to hoist conditionals from typespec and declarator
// around entire declaration by combining with each other
// TODO causing an infinite loop on 3.12 init/main.c
/* if (typespec.getProperty(SPECS) == null) { */
/* System.err.println("error: no specs available"); */
/* } else { */
/* Type baseType = ((Specifiers) typespec.getProperty(SPECS)).getType(); */
/* Binding binding = grokdeclarator(declarator, baseType); */
/* Type type = binding.type; */
/* Language ident = binding.ident; */
/* System.err.println(ident + " = " + type); */
/* } */
// TODO replace old-style typedef checking by using specs above
Language ident = getident(declarator);
// Check whether the declaration is a typedef. This assumes that
// the typedef keyword is the first token of the declaration.
boolean typedef = false;
if (null != typespec) {
Object a = typespec;
while (true) {
if ( ! (a instanceof Syntax)) {
Node n = (Node) a;
if (n.hasName(ForkMergeParser.CHOICE_NODE_NAME)) {
// When it's a conditional node, the first child is a
// presence condition, the second is the first AST child.
a = n.get(1);
} else {
a = n.get(0);
}
} else if (a instanceof Pair) {
a = ((Pair) a).head();
} else {
break;
}
}
Language t = (Language) a;
if (CTag.TYPEDEF == t.tag()) {
// Bind a typedef name.
typedef = true;
if (languageStatistics) {
if (typedef) {
Location location = subparser.lookahead.token.syntax.getLocation();
System.err.println(String.format("typedef %s %s", ident, location));
}
}
} else {
// Binding a variable name.
typedef = false;
}
}
if (showErrors) {
System.err.println("bind: " + ident.getTokenText() + " " + typedef);
}
if (debug) {
System.err.println("def: " + ident.getTokenText() + " " + alsoSet);
}
STField field = typedef ? STField.TYPEDEF : STField.IDENT;
scope.getSymbolTable().setbool(ident.getTokenText(), field, true, presenceCondition);
if (null != alsoSet) {
scope.getSymbolTable().setbool(ident.getTokenText(), alsoSet, true, presenceCondition);
}
/* if (typedef) { */
/* scope.getSymbolTable().setbool(ident.getTokenText(), STField.TYPEDEF, true, presenceCondition); */
/* } else { */
/* scope.getSymbolTable().setbool(ident.getTokenText(), STField.IDENT, true, presenceCondition); */
/* } */
/* scope.bind(ident.getTokenText(), typedef, presenceCondition); */
}
private static Binding grokdeclarator(Node declarator, Type type) {
Language ident = null;
while (null != declarator) {
if (declarator.getName().equals("SimpleDeclarator")) {
ident = ((Syntax) declarator.get(0)).toLanguage();
declarator = null;
} else if (declarator.getName().equals("ParenIdentifierDeclarator")) {
Node parenIdentDecl = null;
switch (declarator.size()) {
case 3:
parenIdentDecl = (Node) declarator.get(1);
break;
default:
error("unexpected grammar structure for " + declarator.getName());
break;
}
declarator = parenIdentDecl;
} else if (declarator.getName().equals("UnaryIdentifierDeclarator")) {
Node typeQual;
Node identDecl;
switch (declarator.size()) {
case 2:
typeQual = null;
identDecl = (Node) declarator.get(1);
break;
case 3:
typeQual = (Node) declarator.get(1);
identDecl = (Node) declarator.get(2);
break;
default:
typeQual = null;
identDecl = null;
error("unexpected grammar structure for " + declarator.getName());
break;
}
if (null != typeQual) {
Specifiers specs = (Specifiers) typeQual.getProperty(SPECS);
type = specs.annotateBase(new PointerT(type).annotate());
} else {
type = new PointerT(type);
}
declarator = identDecl;
} else if (declarator.getName().equals("ArrayDeclarator")) {
Node parenIdentDecl = (Node) declarator.get(0);
Node arrayAbsDecl = (Node) declarator.get(1);
type = grokabsdeclarator(arrayAbsDecl, type);
declarator = parenIdentDecl;
} else if (declarator.getName().equals("PostfixIdentifierDeclarator")) {
Node unaryIdentDecl = (Node) declarator.get(0);
Node postfixAbsDecl = (Node) declarator.get(1);
type = grokabsdeclarator(postfixAbsDecl, type);
declarator = unaryIdentDecl;
} else if (declarator.getName().equals("FunctionDeclarator")) {
Node parenIdentDecl = (Node) declarator.get(0);
Node postfixFuncDecl = (Node) declarator.get(1);
type = grokabsdeclarator(postfixFuncDecl, type);
declarator = parenIdentDecl;
} else {
if (debug) {
System.err.println("TODO support declarator " + declarator.getName());
}
declarator = null;
}
}
return new Binding(ident, type);
}
private static Type grokabsdeclarator(Node absdeclarator, Type type) {
if (absdeclarator.getName().equals("ArrayAbstractDeclarator")) {
while (null != absdeclarator) {
Node arraySize = null;
switch (absdeclarator.size()) {
case 0:
arraySize = null;
absdeclarator = null;
break;
case 1:
arraySize = (Node) absdeclarator.get(0);
absdeclarator = null;
break;
case 2:
arraySize = (Node) absdeclarator.get(1);
absdeclarator = (Node) absdeclarator.get(0);
break;
default:
error("unexpected grammar structure for " + absdeclarator.getName());
}
type = new ArrayT(type);
}
} else if (absdeclarator.getName().equals("PostfixingFunctionDeclarator")) {
Node parms = null;
switch (absdeclarator.size()) {
case 1:
parms = (Node) absdeclarator.get(0);
break;
default:
error("unexpected grammar structure for " + absdeclarator.getName());
break;
}
FunctionT function = getParameterTypes(parms);
function.setResult(type);
type = function;
} else {
if (debug) {
System.err.println("TODO support absdeclarator " + absdeclarator.getName());
}
}
return type;
}
private static FunctionT getParameterTypes(Node parms) {
// TODO flesh this out and do type checking
boolean varArgs = false;
ArrayList<Type> types = new ArrayList<Type>();
if (parms != null && parms.size() > 0) {
parms = (Node) parms.get(0);
/* System.err.println(parms); */
switch (parms.size()) {
case 2:
varArgs = true;
// fall through
case 1:
parms = (Node) parms.get(0);
break;
default:
error("unexpected grammar structure for " + parms.getName());
break;
}
// parms is now a list node containing ParameterDeclaration elements
if (parms.getName().equals("ParameterList")) {
for (Object o : parms) {
GNode n = (GNode) o;
if (n.getName().equals("Conditional")) {
boolean isCond = true;
for (Object o_parm : n) {
if (isCond) {
// TODO get presence condition
} else {
GNode parm = (GNode) o_parm;
Node typespec = (Node) parm.get(0);
// TODO remove once specs are done
if (typespec.getProperty(SPECS) == null) continue;
Type baseType = ((Specifiers) typespec.getProperty(SPECS)).getType();
if (parm.size() > 1) {
Node declarator = (Node) parm.get(1);
if (parm.getName().equals("ParameterIdentifierDeclaration")) {
Binding binding = grokdeclarator(declarator, baseType);
Language ident = binding.ident;
Type type = binding.type;
String name = binding.ident.getTokenText();
types.add(VariableT.newParam(type, name));
} else if (parm.getName().equals("ParameterAbstractDeclaration")) {
Type type = grokabsdeclarator(declarator, baseType);
types.add(type);
} else {
if (showErrors) {
System.err.println("unsupported parameter declaration " + parm.getName());
}
}
} else {
types.add(baseType);
}
}
isCond = isCond ? false : true;
}
} else {
if (showErrors) {
System.err.println("parameter is no conditional");
}
}
}
} else {
if (showErrors) {
System.err.println("unexpected parameter list node");
}
}
}
FunctionT function = new FunctionT(null, types, varArgs);
function.addAttribute(Constants.ATT_STYLE_NEW);
return function;
}
public void BindVar(Subparser subparser) {
StackFrame stack = subparser.stack;
PresenceConditionManager.PresenceCondition presenceCondition = subparser.getPresenceCondition();
CContext scope = (CContext) subparser.scope;
// Get the identifier in the declarator.
Object b = stack.get(1).value;
Language<?> ident = getident(b);
// Bind variable name.
scope.getSymbolTable().setbool(ident.getTokenText(), STField.IDENT, true, presenceCondition);
/* scope.bind(ident.getTokenText(), false, presenceCondition); */
}
public void BindEnum(Subparser subparser) {
StackFrame stack = subparser.stack;
PresenceConditionManager.PresenceCondition presenceCondition = subparser.getPresenceCondition();
CContext scope = (CContext) subparser.scope;
// Get the identifier in the declarator. The identifier must
// occur after an IdentifierOrTypedefName token.
Object b = stack.get(1).value;
String ident = getident(b).getTokenText();
// Bind variable name.
scope.getSymbolTable().setbool(ident, STField.IDENT, true, presenceCondition);
/* scope.bind(ident, false, presenceCondition); */
}
public void useIdent(Subparser subparser, Node ident) {
CContext scope = (CContext) subparser.scope;
String name = ident.getTokenText();
if (debug) {
System.err.println("use: " + name);
}
if (enableCheckers) {
PresenceCondition identPresenceCond = scope.symbolPresenceCond(name, STField.IDENT);
if (null != identPresenceCond && ! identPresenceCond.isFalse()) {
PresenceCondition not = identPresenceCond.not();
PresenceCondition andnot = subparser.getPresenceCondition().and(not);
/* not.delRef(); */
if (! andnot.isFalse()) {
boolean satWithKconfig = true;
boolean contradiction = false;
int[] model = null;
// check andnot against kconfig feature model
if (this.hasClauses) {
// use double negation to get andnot in cnf form
PresenceCondition notandnot = andnot.not();
/* System.err.println(notandnot); */
List allsat = (List) notandnot.getBDD().allsat();
ArrayList<ArrayList<Integer>> bugClauses =
new ArrayList<ArrayList<Integer>>();
for (Object o : allsat) {
byte[] sat = (byte[]) o;
ArrayList<Integer> clause = new ArrayList<Integer>();
for (int i = 0; i < sat.length; i++) {
// convert to solver's varnum
// look up i in variable manager
// if varname exists in clauses, then add to clause
int sign = 1;
switch (sat[i]) {
case 1:
// negate again
sign = -1;
case 0:
String varname = notandnot.presenceConditionManager().getVariableManager().getName(i);
if (varname.startsWith("(defined ")) {
varname = varname.substring(9, varname.length() - 1);
/* System.err.println(varname); */
if (this.featureClauses.getVarmap().containsKey(varname)) {
int var = this.featureClauses.getVarmap().get(varname);
var = sign * var;
clause.add(var);
}
}
break;
}
}
if (clause.size() > 0) {
/* System.err.println(clause); */
bugClauses.add(clause);
}
}
// add extra constraints
for (String extraConstraint : extraConstraints) {
this.featureClauses.addClauses(extraConstraint);
}
// remove them to avoid adding them again the next check
extraConstraints.clear();
try {
ISolver featureSolver = SolverFactory.newDefault();
featureSolver.newVar(this.featureClauses.getNumVars());
/* featureSolver.setExpectedNumberOfClauses(this.featureClauses.size() + bugClauses.size()); */
for (List<Integer> clause : this.featureClauses) {
int[] cint = new int[clause.size()];
int i = 0;
for (Integer val : clause) {
cint[i++] = val;
}
featureSolver.addClause(new VecInt(cint));
}
for (List<Integer> clause : bugClauses) {
int[] cint = new int[clause.size()];
int i = 0;
for (Integer val : clause) {
cint[i++] = val;
}
IConstr curConstr =
featureSolver.addClause(new VecInt(cint));
}
ISolver bugSolver = SolverFactory.newDefault();
bugSolver.newVar(this.featureClauses.getNumVars());
bugSolver.setExpectedNumberOfClauses(bugClauses.size());
for (List<Integer> clause : bugClauses) {
int[] cint = new int[clause.size()];
int i = 0;
for (Integer val : clause) {
cint[i++] = val;
}
IConstr curConstr =
bugSolver.addClause(new VecInt(cint));
}
IProblem simpleProblem = new ModelIterator(bugSolver);
boolean satWithoutKconfig = simpleProblem.isSatisfiable();
/* IProblem problem = featureSolver; */
IProblem problem = new ModelIterator(featureSolver);
if (problem.isSatisfiable(modelAssumptions)) {
satWithKconfig = true;
if (debug) {
System.err.println("computing model");
}
model = problem.model();
} else {
satWithKconfig = false;
if (satWithoutKconfig) {
System.err.print("invalid config invalidated by kconfig ");
} else {
System.err.print("invalid config invalidated by bug clauses alone ");
}
System.err.println(name + " at " + ident.getLocation());
}
} catch (ContradictionException e) {
contradiction = true;
} catch (TimeoutException e) {
e.printStackTrace();
/* System.exit(1); */
}
notandnot.delRef();
}
if (contradiction) {
System.err.print("invalid config invalidated by contradiction " + name + " at " + ident.getLocation());
} else if (satWithKconfig) {
PresenceCondition sat = andnot.satOne();
if (null != scope.symbolPresenceCond(name, STField.GLOBAL_FUNDEF) || null != scope.symbolPresenceCond(name, STField.STATIC_FUNDEF)) {
System.err.println("found for function def");
}
System.err.println("found invalid configuration on "
+ name + " at " + ident.getLocation());
/* System.err.println("config " + andnot); */
/* System.err.println("identPresenceCond: " + identPresenceCond); */
/* /\* System.err.println("undefined under " + not); *\/ */
/* /\* System.err.println("used under " + subparser.getPresenceCondition()); *\/ */
/* if (this.showExample) { */
if (true) {
if (null != model) {
System.err.print("model: ");
String delim = "[";
for (int i = 0; i < model.length; i++) {
if (model[i] > 0) {
System.err.print(delim + featureClauses.getVarName(model[i]));
delim = ",";
}
}
System.err.println("]");
}
}
sat.delRef();
}
} else {
if (debug) {
System.err.println("valid function call " + name + " at " + ident.getLocation());
/* System.err.println("not: " + not); */
/* System.err.println("subparser.getPresenceCondition() " + subparser.getPresenceCondition()); */
}
}
not.delRef();
andnot.delRef();
/* PresenceCondition and = subparser.getPresenceCondition().and(identPresenceCond); */
/* if (and.isFalse()) { */
/* System.err.println("found infeasible configuration on " + name + " at " + ident.getLocation() + " defined in " + identPresenceCond); */
/* } */
/* and.delRef(); */
// update configurations the identifier is used in
scope.getSymbolTable().setbool(name, STField.USED, true, subparser.getPresenceCondition());
} else {
if (debug) {
System.err.println("not an identifier in any config " + name + " at " + ident.getLocation());
}
}
}
}
public void callFunction(Subparser subparser, Node fun, Node parms) {
if (fun.getName().equals("PrimaryIdentifier") && enableFunctionAnalysis) {
/* CContext scope = (CContext) subparser.scope; */
/* String name = ((Language<?>) fun.get(0)).getTokenText(); */
/* scope.getSymbolTable().setbool(name, STField.FUNCALL, true, subparser.getPresenceCondition()); */
String name = ((Language<?>) fun.get(0)).getTokenText();
functionTable.setbool(name, STField.FUNCALL, true, subparser.getPresenceCondition());
return;
}
// TODO do later
if (true) {
return;
}
String name = ((Syntax) fun.get(0)).getTokenText();
CContext scope = (CContext) subparser.scope;
if (debug) {
System.err.println("function call: " + name);
}
if (enableCheckers) {
PresenceCondition funPresenceCond = scope.symbolPresenceCond(name, STField.GLOBAL_FUNDEF).or(scope.symbolPresenceCond(name, STField.STATIC_FUNDEF));
if (null != funPresenceCond && ! funPresenceCond.isFalse()) {
PresenceCondition not = funPresenceCond.not();
PresenceCondition andnot = subparser.getPresenceCondition().and(not);
not.delRef();
if (! andnot.isFalse()) {
PresenceCondition sat = andnot.satOne();
System.err.println("found invalid configuration on function call " + name + " at " + fun.getLocation() + " config " + sat); sat.delRef();
}
andnot.delRef();
PresenceCondition and = subparser.getPresenceCondition().and(funPresenceCond);
if (and.isFalse()) {
System.err.println("found infeasible configuration on function call " + name + " at " + fun.getLocation() + " defined in " + funPresenceCond);
}
and.delRef();
// update configurations the function is used in
scope.getSymbolTable().setbool(name, STField.USED, true, subparser.getPresenceCondition());
} else {
if (debug) {
System.err.println("checker error: " + name + " not a function in any configuration");
}
}
funPresenceCond.delRef();
}
}
public void EnterScope(Subparser subparser) {
PresenceConditionManager.PresenceCondition presenceCondition = subparser.getPresenceCondition();
subparser.scope = ((CContext) subparser.scope).enterScope(presenceCondition);
}
public void ExitScope(Subparser subparser) {
PresenceConditionManager.PresenceCondition presenceCondition = subparser.getPresenceCondition();
subparser.scope = ((CContext) subparser.scope).exitScope(presenceCondition);
}
public void ExitReentrantScope(Subparser subparser) {
PresenceConditionManager.PresenceCondition presenceCondition = subparser.getPresenceCondition();
subparser.scope
= ((CContext) subparser.scope).exitReentrantScope(presenceCondition);
}
public void ReenterScope(Subparser subparser) {
PresenceConditionManager.PresenceCondition presenceCondition = subparser.getPresenceCondition();
subparser.scope
= ((CContext) subparser.scope).reenterScope(presenceCondition);
}
public void KillReentrantScope(Subparser subparser) {
PresenceConditionManager.PresenceCondition presenceCondition = subparser.getPresenceCondition();
subparser.scope
= ((CContext) subparser.scope).killReentrantScope(presenceCondition);
}
/**
* Find the identifier or typedef name in a declarator. Assume
* the first identifier in the subtree is the var or typedef name.
*
* @param o The semantic value.
* @return The first identifier in the subtree or null if there is
* none.
*/
private static Language getident(Object o) {
if (o instanceof Language) {
Language token = ((Language) o);
if (CTag.IDENTIFIER == token.tag()
|| CTag.TYPEDEFname == token.tag()) {
return token;
} else {
return null;
}
} else if (o instanceof Pair) {
Pair<?> b = (Pair<?>) o;
while (b != Pair.empty()) {
Object child = b.head();
if (null != child) {
Language ident = getident(child);
if (null != ident) {
return ident;
}
}
b = b.tail();
}
return null;
} else if (o instanceof PresenceConditionManager.PresenceCondition) {
return null;
} else if (o instanceof Error) {
return null;
} else {
Node b = (Node) o;
for (int i = 0; i < b.size(); i++) {
Object child = b.get(i);
if (null != child) {
Language ident = getident(child);
if (null != ident) {
return ident;
}
}
}
return null;
}
}
// ---------- Specifiers
private static String SPECS = "xtc.lang.cpp.Specifiers";
private static class Specifiers {
/** Presence condition. */
public PresenceCondition pc;
/** True if there is a type error. */
public boolean error;
/** The type-error message. */
public String error_message;
/** The flag for whether a tag reference is a declaration. */
public boolean refIsDecl;
/** The type, if any. */
public Type type;
/** The storage class attribute, if any. */
public Attribute storage;
/** The thread-local attribute, if any. */
public Attribute threadlocal;
/** The inline attribute, if any. */
public Attribute function;
/** Any other attributes. */
public List<Attribute> attributes;
// The internal state for tracking type specifiers.
public boolean seenSigned;
public boolean seenUnsigned;
public boolean seenBool;
public boolean seenChar;
public boolean seenShort;
public boolean seenInt;
public int longCount;
public boolean seenFloat;
public boolean seenDouble;
public boolean seenComplex;
public Specifiers() {
}
/* public Specifiers(PresenceCondition pc) { */
/* this.pc = pc.addRef(); */
/* } */
public Specifiers(PresenceCondition pc, Specifiers s) {
/* this(pc); */
this.error = s.error;
this.error_message = s.error_message;
this.refIsDecl = s.refIsDecl;
this.type = s.type;
this.storage = s.storage;
this.threadlocal = s.threadlocal;
this.function = s.function;
this.attributes = s.attributes;
this.seenSigned = s.seenSigned;
this.seenUnsigned = s.seenUnsigned;
this.seenBool = s.seenBool;
this.seenChar = s.seenChar;
this.seenShort = s.seenShort;
this.seenInt = s.seenInt;
this.longCount = s.longCount;
this.seenFloat = s.seenFloat;
this.seenDouble = s.seenDouble;
this.seenComplex = s.seenComplex;
}
/**
* Add given specs to this set of specs. Adds in-place and returns
* this updated specs object.
**/
public Specifiers addSpecs(Specifiers other) {
if (other.error) {
this.setError(other.error_message);
return this;
}
if (null != other.type) {
if (null != this.type) {
/* System.err.println("1"); */
this.multipleTypes();
} else {
this.type = other.type;
}
}
if (other.seenChar) {
if (this.hasType()) {
/* System.err.println("2"); */
this.multipleTypes();
} else {
this.seenChar = true;
}
}
if (other.seenShort) {
if (this.seenBool || this.seenChar || this.seenShort || (0 < this.longCount) ||
this.seenFloat || this.seenDouble || this.seenComplex ||
(null != this.type)) {
/* System.err.println("3"); */
this.multipleTypes();
} else {
this.seenShort = true;
}
}
if (other.seenInt) {
if (this.seenBool || this.seenChar || this.seenInt ||
this.seenFloat || this.seenDouble || this.seenComplex ||
(null != this.type)) {
/* System.err.println("4"); */
this.multipleTypes();
} else {
this.seenInt = true;
}
}
for (int i = 0; i < other.longCount; i++) {
if (this.seenBool || this.seenChar || this.seenShort || (1 < this.longCount) ||
this.seenFloat ||
((this.seenDouble || this.seenComplex) &&
(0 < this.longCount)) ||
(null != this.type)) {
/* System.err.println("5"); */
this.multipleTypes();
} else {
this.longCount++;
}
}
if (other.seenFloat) {
if (this.seenBool || this.seenChar || this.seenShort || this.seenInt || (0 < this.longCount) ||
this.seenDouble ||
(null != this.type)) {
/* System.err.println("6"); */
this.multipleTypes();
} else {
this.seenFloat = true;
}
}
if (other.seenDouble) {
if (this.seenBool || this.seenChar || this.seenShort || this.seenInt || (1 < this.longCount) ||
this.seenFloat ||
(null != this.type)) {
/* System.err.println("7"); */
this.multipleTypes();
} else {
this.seenDouble = true;
}
}
if (other.seenSigned) {
if (this.seenUnsigned) {
this.seenSigned = true;
this.setError("both 'signed' and 'unsigned' in declaration specifiers");
} else if (this.seenSigned) {
this.setError("duplicate 'signed'");
} else {
this.seenSigned = true;
}
}
if (other.seenUnsigned) {
if (this.seenSigned) {
this.seenUnsigned = true;
this.setError("both 'signed' and 'unsigned' in declaration specifiers");
} else if (this.seenUnsigned) {
this.setError("duplicate 'unsigned'");
} else {
this.seenUnsigned = true;
}
}
if (other.seenBool) {
if (this.hasType()) {
/* System.err.println("8"); */
this.multipleTypes();
} else {
this.seenBool = true;
}
}
if (null != other.storage) {
if (null == this.storage) {
this.storage = other.storage;
} else if (this.storage.equals(other.storage)) {
this.setError("duplicate storage class");
} else {
this.setError("multiple storage classes in declaration specifiers");
}
}
return this;
}
/**
* Annotate the specified base type. This method annotates the
* specified type with all attributes besides the storage class,
* thread-local specifier, and function specifier attributes.
*
* @param base The base type.
* @return The annnotated base type.
*/
public Type annotateBase(Type base) {
return (null != attributes)? base.attribute(attributes) : base;
}
/**
* Get the resulting type.
*/
public Type getType() {
Type type;
if (seenBool) {
type = BooleanT.TYPE;
} else if (seenChar) {
if (seenUnsigned) {
type = NumberT.U_CHAR;
} else if (seenSigned) {
type = NumberT.S_CHAR;
} else {
type = NumberT.CHAR;
}
} else if (seenShort) {
if (seenUnsigned) {
type = NumberT.U_SHORT;
} else {
type = NumberT.SHORT;
}
} else if (seenFloat) {
if (seenComplex) {
type = NumberT.FLOAT_COMPLEX;
} else {
type = NumberT.FLOAT;
}
} else if (seenDouble) {
if (0 < longCount) {
if (seenComplex) {
type = NumberT.LONG_DOUBLE_COMPLEX;
} else {
type = NumberT.LONG_DOUBLE;
}
} else {
if (seenComplex) {
type = NumberT.DOUBLE_COMPLEX;
} else {
type = NumberT.DOUBLE;
}
}
} else if (1 == longCount) {
if (seenUnsigned) {
type = NumberT.U_LONG;
} else {
type = NumberT.LONG;
}
} else if (1 < longCount) {
if (seenUnsigned) {
type = NumberT.U_LONG_LONG;
} else {
type = NumberT.LONG_LONG;
}
} else if (seenUnsigned) {
type = NumberT.U_INT;
} else if (seenSigned) {
type = NumberT.S_INT;
} else if (seenInt) {
type = NumberT.INT;
} else {
type = C.IMPLICIT;
}
// Annotate the type.
if ((! type.hasError()) && (null != attributes)) {
type = type.annotate().attribute(attributes);
}
return type;
}
/** Test for previous type. */
protected boolean hasType() {
return
(seenBool || seenChar || seenShort || seenInt || (0 < longCount) ||
seenFloat || seenDouble || seenComplex ||
(null != type));
}
/** Report error indicating multiple types. */
protected void multipleTypes() {
this.setError("multiple data types in declaration specifiers");
}
/** Add the specified attribute. */
protected void add(Attribute att) {
if (null == attributes) {
attributes = new ArrayList<Attribute>();
attributes.add(att);
} else if (! attributes.contains(att)) {
attributes.add(att);
}
}
public void setError(String msg) {
this.error = true;
this.error_message = msg;
type = ErrorT.TYPE;
if (showErrors) { // showErrors is true
System.err.println("error in specifiers: " + msg);
}
}
// Get specs. Gets list of specifiers, checking for type errors.
// Also need to hoist conditionals around complete type
// specifiers. Is it possible to make a hoisting tree-walker?
// Walk tree, when encountering conditional, fork the spec state
// and walk both. No need for merge, since there are two
// different declarations.
}
/**
* A helper function to get the specifiers of the value of a component
* node from the stack.
*
* @param subparser The reference to the subparser.
* @param number The component number.
* @return The specifiers for the component.
*/
private static Specifiers getSpecsAt(Subparser subparser, int component) {
Node n = getNodeAt(subparser, component);
if (n.hasProperty(SPECS)) {
return (Specifiers) n.getProperty(SPECS);
} else {
Specifiers specs = new Specifiers();
n.setProperty(SPECS, specs);
return specs;
}
}
private static void updateSpecs(Subparser subparser,
Specifiers new_specs,
Object value) {
updateSpecs(subparser, null, new_specs, value);
}
private static void updateSpecs(Subparser subparser,
Specifiers specs,
Specifiers new_specs,
Object value) {
if (null == specs) {
specs = new_specs;
} else {
specs = specs.addSpecs(new_specs);
}
((CContext) subparser.scope).lastSeenType = specs.getType();
((Node) value).setProperty(SPECS, specs);
}
private static Specifiers makeUnionSpec(Subparser subparser,
Node tagNode,
Node membersNode,
Node attrsNode) {
Specifiers specs = new Specifiers();
return specs;
}
private static Specifiers makeStructSpec(Subparser subparser,
Node tagNode,
Node membersNode,
Node attrsNode) {
String tag;
String name;
if (null == tagNode) {
// TODO struct tag creation
/* tag = table.freshName("tag"); */
tag = "tag(untagged)";
name = tag;
} else {
// TODO check for conditional here
/* tag = ((Syntax) tagNode.get(0)).toLanguage().getTokenText(); */
/* name = SymbolTable.toTagName(tag); */
}
// TODO remove this once above code is complete
tag = "tag(untagged)";
name = tag;
Type type;
// TODO struct tag is defined
/* if (table.current().isDefinedLocally(name)) { */
/* final Type t = (Type)table.current().lookupLocally(name); */
/* if (! t.isStruct()) { */
/* runtime.error("'" + tag + "' defined as wrong kind of tag", n); */
/* reportPreviousTag(t); */
/* type = ErrorT.TYPE; */
/* return; */
/* } else if (null != t.toTagged().getMembers()) { */
/* runtime.error("redefinition of 'struct " + tag + "'", n); */
/* reportPreviousTag(t); */
/* type = ErrorT.TYPE; */
/* return; */
/* } else if (t.hasAttribute(Constants.ATT_DEFINED)) { */
/* runtime.error("nested redefinition of 'struct " + tag + "'", n); */
/* type = ErrorT.TYPE; */
/* return; */
/* } else { */
/* type = t; */
/* } */
/* } else { */
// TODO checkNotParameter
/* checkNotParameter(n, "struct"); */
// Declare the struct so that members can reference it.
type = new StructT(tag);
/* table.current().define(name, type); */
/* } */
// TODO location
/* // Update the location. */
/* type.setLocation(n); */
// TODO struct attributes
/* // Update the GCC attributes. */
/* for (Attribute a : toAttributeList(n.getGeneric(0))) { */
/* type.addAttribute(a); */
/* } */
/* for (Attribute a : toAttributeList(n.getGeneric(3))) { */
/* type.addAttribute(a); */
/* } */
// Process the members and update the struct declaration. Use
// defined attribute to protect against nested redefinition.
type.addAttribute(Constants.ATT_DEFINED);
// TODO struct members
/* List<VariableT> members = processMembers(n.getGeneric(2), true); */
List<VariableT> members = null;
type.toStruct().setMembers(members);
type.removeAttribute(Constants.ATT_DEFINED);
Specifiers specs = new Specifiers();
specs.type = type;
return specs;
}
/**
* Check that the tag declaration is not located within a
* parameter list. If the declaration is located within a
* parameter list, this method prints the appropriate warning.
*
* @param node The node.
* @param kind The kind of tag.
*/
private void checkNotParameter(Node node, String kind) {
// TODO checkNotParameter implementation
/* if (TMP_SCOPE.equals(table.current().getName())) { */
/* final String tag = node.getString(1); */
/* final String msg; */
/* if (null == tag) { */
/* msg = "anonymous " + kind + " declared inside parameter list"; */
/* } else { */
/* msg = "'" + kind + " " + tag + "' declared inside parameter list"; */
/* } */
/* runtime.warning(msg, node); */
/* } */
}
// ---------- Declarators
/* private static String DECL = "xtc.lang.cpp.Declarator"; */
/* private static String NAME = "xtc.lang.cpp.Name"; */
/* private static void setDecl(Object n, Type type) { */
/* ((Node) n).setProperty(DECL, type); */
/* } */
/* private static Type getDecl(Object n) { */
/* return ((Type) ((Node) n).getProperty(DECL)); */
/* } */
/* private static void setName(Object n, String name) { */
/* ((Node) n).setProperty(NAME, name); */
/* } */
/* private static String getName(Object n) { */
/* return ((String) ((Node) n).getProperty(NAME)); */
/* } */
/* private static void setDecl(Object n, Type type, String name) { */
/* setDecl(n, type); */
/* setName(n, name); */
/* } */
/* private static void copyDecl(Subparser subparser, Object value, int from) { */
/* setDecl(value, (Type) (getNodeAt(subparser, from).getProperty(DECL))); */
/* } */
/* private static void copyName(Subparser subparser, Object value, int from) { */
/* setName(value, (String) (getNodeAt(subparser, from).getProperty(NAME))); */
/* } */
/* private static void copyDeclName(Subparser subparser, Object value, int from){ */
/* copyDecl(subparser, value, from); */
/* copyName(subparser, value, from); */
/* } */
}