NodeQuerySynthesizedAttributeType querySolverGrammarElementFromVariantVector ( SgNode * astNode, VariantVector targetVariantVector ) { // This function extracts type nodes that would not be traversed so that they can // accumulated to a list. The specific nodes collected into the list is controlled // by targetVariantVector. ROSE_ASSERT (astNode != NULL); NodeQuerySynthesizedAttributeType returnNodeList; Rose_STL_Container<SgNode*> nodesToVisitTraverseOnlyOnce; pushNewNode (&returnNodeList,targetVariantVector,astNode); vector<SgNode*> succContainer = astNode->get_traversalSuccessorContainer(); vector<pair<SgNode*,string> > allNodesInSubtree = astNode->returnDataMemberPointers(); if( succContainer.size() != allNodesInSubtree.size() ) for(vector<pair<SgNode*,string> >::iterator iItr = allNodesInSubtree.begin(); iItr!= allNodesInSubtree.end(); ++iItr ) if( isSgType(iItr->first) != NULL ) if(std::find(succContainer.begin(),succContainer.end(),iItr->first) == succContainer.end() ) pushNewNode (&returnNodeList,targetVariantVector,iItr->first); return returnNodeList; } /* End function querySolverUnionFields() */
//--------------------------------------------------------------------------------- // // Parse RBBI rules. The state machine for rules parsing is here. // The state tables are hand-written in the file rbbirpt.txt, // and converted to the form used here by a perl // script rbbicst.pl // //--------------------------------------------------------------------------------- void RBBIRuleScanner::parse() { uint16_t state; const RBBIRuleTableEl *tableEl; if (U_FAILURE(*fRB->fStatus)) { return; } state = 1; nextChar(fC); // // Main loop for the rule parsing state machine. // Runs once per state transition. // Each time through optionally performs, depending on the state table, // - an advance to the the next input char // - an action to be performed. // - pushing or popping a state to/from the local state return stack. // for (;;) { // Bail out if anything has gone wrong. // RBBI rule file parsing stops on the first error encountered. if (U_FAILURE(*fRB->fStatus)) { break; } // Quit if state == 0. This is the normal way to exit the state machine. // if (state == 0) { break; } // Find the state table element that matches the input char from the rule, or the // class of the input character. Start with the first table row for this // state, then linearly scan forward until we find a row that matches the // character. The last row for each state always matches all characters, so // the search will stop there, if not before. // tableEl = &gRuleParseStateTable[state]; #ifdef RBBI_DEBUG if (fRB->fDebugEnv && uprv_strstr(fRB->fDebugEnv, "scan")) { RBBIDebugPrintf("char, line, col = (\'%c\', %d, %d) state=%s ", fC.fChar, fLineNum, fCharNum, RBBIRuleStateNames[state]); } #endif for (;;) { #ifdef RBBI_DEBUG if (fRB->fDebugEnv && uprv_strstr(fRB->fDebugEnv, "scan")) { RBBIDebugPrintf("."); } #endif if (tableEl->fCharClass < 127 && fC.fEscaped == FALSE && tableEl->fCharClass == fC.fChar) { // Table row specified an individual character, not a set, and // the input character is not escaped, and // the input character matched it. break; } if (tableEl->fCharClass == 255) { // Table row specified default, match anything character class. break; } if (tableEl->fCharClass == 254 && fC.fEscaped) { // Table row specified "escaped" and the char was escaped. break; } if (tableEl->fCharClass == 253 && fC.fEscaped && (fC.fChar == 0x50 || fC.fChar == 0x70 )) { // Table row specified "escaped P" and the char is either 'p' or 'P'. break; } if (tableEl->fCharClass == 252 && fC.fChar == (UChar32)-1) { // Table row specified eof and we hit eof on the input. break; } if (tableEl->fCharClass >= 128 && tableEl->fCharClass < 240 && // Table specs a char class && fC.fEscaped == FALSE && // char is not escaped && fC.fChar != (UChar32)-1) { // char is not EOF UnicodeSet *uniset = fRuleSets[tableEl->fCharClass-128]; if (uniset->contains(fC.fChar)) { // Table row specified a character class, or set of characters, // and the current char matches it. break; } } // No match on this row, advance to the next row for this state, tableEl++; } if (fRB->fDebugEnv && uprv_strstr(fRB->fDebugEnv, "scan")) { RBBIDebugPuts(""); } // // We've found the row of the state table that matches the current input // character from the rules string. // Perform any action specified by this row in the state table. if (doParseActions((EParseAction)tableEl->fAction) == FALSE) { // Break out of the state machine loop if the // the action signalled some kind of error, or // the action was to exit, occurs on normal end-of-rules-input. break; } if (tableEl->fPushState != 0) { fStackPtr++; if (fStackPtr >= kStackSize) { error(U_BRK_INTERNAL_ERROR); RBBIDebugPuts("RBBIRuleScanner::parse() - state stack overflow."); fStackPtr--; } fStack[fStackPtr] = tableEl->fPushState; } if (tableEl->fNextChar) { nextChar(fC); } // Get the next state from the table entry, or from the // state stack if the next state was specified as "pop". if (tableEl->fNextState != 255) { state = tableEl->fNextState; } else { state = fStack[fStackPtr]; fStackPtr--; if (fStackPtr < 0) { error(U_BRK_INTERNAL_ERROR); RBBIDebugPuts("RBBIRuleScanner::parse() - state stack underflow."); fStackPtr++; } } } // // If there were NO user specified reverse rules, set up the equivalent of ".*;" // if (fRB->fReverseTree == NULL) { fRB->fReverseTree = pushNewNode(RBBINode::opStar); RBBINode *operand = pushNewNode(RBBINode::setRef); findSetFor(kAny, operand); fRB->fReverseTree->fLeftChild = operand; operand->fParent = fRB->fReverseTree; fNodeStackPtr -= 2; } // // Parsing of the input RBBI rules is complete. // We now have a parse tree for the rule expressions // and a list of all UnicodeSets that are referenced. // #ifdef RBBI_DEBUG if (fRB->fDebugEnv && uprv_strstr(fRB->fDebugEnv, "symbols")) { fSymbolTable->rbbiSymtablePrint(); } if (fRB->fDebugEnv && uprv_strstr(fRB->fDebugEnv, "ptree")) { RBBIDebugPrintf("Completed Forward Rules Parse Tree...\n"); fRB->fForwardTree->printTree(TRUE); RBBIDebugPrintf("\nCompleted Reverse Rules Parse Tree...\n"); fRB->fReverseTree->printTree(TRUE); RBBIDebugPrintf("\nCompleted Safe Point Forward Rules Parse Tree...\n"); fRB->fSafeFwdTree->printTree(TRUE); RBBIDebugPrintf("\nCompleted Safe Point Reverse Rules Parse Tree...\n"); fRB->fSafeRevTree->printTree(TRUE); } #endif }
//---------------------------------------------------------------------------------------- // // doParseAction Do some action during rule parsing. // Called by the parse state machine. // Actions build the parse tree and Unicode Sets, // and maintain the parse stack for nested expressions. // // TODO: unify EParseAction and RBBI_RuleParseAction enum types. // They represent exactly the same thing. They're separate // only to work around enum forward declaration restrictions // in some compilers, while at the same time avoiding multiple // definitions problems. I'm sure that there's a better way. // //---------------------------------------------------------------------------------------- UBool RBBIRuleScanner::doParseActions(EParseAction action) { RBBINode *n = NULL; UBool returnVal = TRUE; switch ((RBBI_RuleParseAction)action) { case doExprStart: pushNewNode(RBBINode::opStart); fRuleNum++; break; case doExprOrOperator: { fixOpStack(RBBINode::precOpCat); RBBINode *operandNode = fNodeStack[fNodeStackPtr--]; RBBINode *orNode = pushNewNode(RBBINode::opOr); orNode->fLeftChild = operandNode; operandNode->fParent = orNode; } break; case doExprCatOperator: // concatenation operator. // For the implicit concatenation of adjacent terms in an expression that are // not separated by any other operator. Action is invoked between the // actions for the two terms. { fixOpStack(RBBINode::precOpCat); RBBINode *operandNode = fNodeStack[fNodeStackPtr--]; RBBINode *catNode = pushNewNode(RBBINode::opCat); catNode->fLeftChild = operandNode; operandNode->fParent = catNode; } break; case doLParen: // Open Paren. // The openParen node is a dummy operation type with a low precedence, // which has the affect of ensuring that any real binary op that // follows within the parens binds more tightly to the operands than // stuff outside of the parens. pushNewNode(RBBINode::opLParen); break; case doExprRParen: fixOpStack(RBBINode::precLParen); break; case doNOP: break; case doStartAssign: // We've just scanned "$variable = " // The top of the node stack has the $variable ref node. // Save the start position of the RHS text in the StartExpression node // that precedes the $variableReference node on the stack. // This will eventually be used when saving the full $variable replacement // text as a string. n = fNodeStack[fNodeStackPtr-1]; n->fFirstPos = fNextIndex; // move past the '=' // Push a new start-of-expression node; needed to keep parse of the // RHS expression happy. pushNewNode(RBBINode::opStart); break; case doEndAssign: { // We have reached the end of an assignement statement. // Current scan char is the ';' that terminates the assignment. // Terminate expression, leaves expression parse tree rooted in TOS node. fixOpStack(RBBINode::precStart); RBBINode *startExprNode = fNodeStack[fNodeStackPtr-2]; RBBINode *varRefNode = fNodeStack[fNodeStackPtr-1]; RBBINode *RHSExprNode = fNodeStack[fNodeStackPtr]; // Save original text of right side of assignment, excluding the terminating ';' // in the root of the node for the right-hand-side expression. RHSExprNode->fFirstPos = startExprNode->fFirstPos; RHSExprNode->fLastPos = fScanIndex; fRB->fRules.extractBetween(RHSExprNode->fFirstPos, RHSExprNode->fLastPos, RHSExprNode->fText); // Expression parse tree becomes l. child of the $variable reference node. varRefNode->fLeftChild = RHSExprNode; RHSExprNode->fParent = varRefNode; // Make a symbol table entry for the $variableRef node. fSymbolTable->addEntry(varRefNode->fText, varRefNode, *fRB->fStatus); if (U_FAILURE(*fRB->fStatus)) { // This is a round-about way to get the parse position set // so that duplicate symbols error messages include a line number. UErrorCode t = *fRB->fStatus; *fRB->fStatus = U_ZERO_ERROR; error(t); } // Clean up the stack. delete startExprNode; fNodeStackPtr-=3; break; } case doEndOfRule: { fixOpStack(RBBINode::precStart); // Terminate expression, leaves expression if (U_FAILURE(*fRB->fStatus)) { // parse tree rooted in TOS node. break; } #ifdef RBBI_DEBUG if (fRB->fDebugEnv && uprv_strstr(fRB->fDebugEnv, "rtree")) { printNodeStack("end of rule"); } #endif U_ASSERT(fNodeStackPtr == 1); // If this rule includes a look-ahead '/', add a endMark node to the // expression tree. if (fLookAheadRule) { RBBINode *thisRule = fNodeStack[fNodeStackPtr]; RBBINode *endNode = pushNewNode(RBBINode::endMark); RBBINode *catNode = pushNewNode(RBBINode::opCat); fNodeStackPtr -= 2; catNode->fLeftChild = thisRule; catNode->fRightChild = endNode; fNodeStack[fNodeStackPtr] = catNode; endNode->fVal = fRuleNum; endNode->fLookAheadEnd = TRUE; } // All rule expressions are ORed together. // The ';' that terminates an expression really just functions as a '|' with // a low operator prededence. // // Each of the four sets of rules are collected separately. // (forward, reverse, safe_forward, safe_reverse) // OR this rule into the appropriate group of them. // RBBINode **destRules = (fReverseRule? &fRB->fReverseTree : fRB->fDefaultTree); if (*destRules != NULL) { // This is not the first rule encounted. // OR previous stuff (from *destRules) // with the current rule expression (on the Node Stack) // with the resulting OR expression going to *destRules // RBBINode *thisRule = fNodeStack[fNodeStackPtr]; RBBINode *prevRules = *destRules; RBBINode *orNode = pushNewNode(RBBINode::opOr); orNode->fLeftChild = prevRules; prevRules->fParent = orNode; orNode->fRightChild = thisRule; thisRule->fParent = orNode; *destRules = orNode; } else { // This is the first rule encountered (for this direction). // Just move its parse tree from the stack to *destRules. *destRules = fNodeStack[fNodeStackPtr]; } fReverseRule = FALSE; // in preparation for the next rule. fLookAheadRule = FALSE; fNodeStackPtr = 0; } break; case doRuleError: error(U_BRK_RULE_SYNTAX); returnVal = FALSE; break; case doVariableNameExpectedErr: error(U_BRK_RULE_SYNTAX); break; // // Unary operands + ? * // These all appear after the operand to which they apply. // When we hit one, the operand (may be a whole sub expression) // will be on the top of the stack. // Unary Operator becomes TOS, with the old TOS as its one child. case doUnaryOpPlus: { RBBINode *operandNode = fNodeStack[fNodeStackPtr--]; RBBINode *plusNode = pushNewNode(RBBINode::opPlus); plusNode->fLeftChild = operandNode; operandNode->fParent = plusNode; } break; case doUnaryOpQuestion: { RBBINode *operandNode = fNodeStack[fNodeStackPtr--]; RBBINode *qNode = pushNewNode(RBBINode::opQuestion); qNode->fLeftChild = operandNode; operandNode->fParent = qNode; } break; case doUnaryOpStar: { RBBINode *operandNode = fNodeStack[fNodeStackPtr--]; RBBINode *starNode = pushNewNode(RBBINode::opStar); starNode->fLeftChild = operandNode; operandNode->fParent = starNode; } break; case doRuleChar: // A "Rule Character" is any single character that is a literal part // of the regular expression. Like a, b and c in the expression "(abc*) | [:L:]" // These are pretty uncommon in break rules; the terms are more commonly // sets. To keep things uniform, treat these characters like as // sets that just happen to contain only one character. { n = pushNewNode(RBBINode::setRef); findSetFor(fC.fChar, n); n->fFirstPos = fScanIndex; n->fLastPos = fNextIndex; fRB->fRules.extractBetween(n->fFirstPos, n->fLastPos, n->fText); break; } case doDotAny: // scanned a ".", meaning match any single character. { n = pushNewNode(RBBINode::setRef); findSetFor(kAny, n); n->fFirstPos = fScanIndex; n->fLastPos = fNextIndex; fRB->fRules.extractBetween(n->fFirstPos, n->fLastPos, n->fText); break; } case doSlash: // Scanned a '/', which identifies a look-ahead break position in a rule. n = pushNewNode(RBBINode::lookAhead); n->fVal = fRuleNum; n->fFirstPos = fScanIndex; n->fLastPos = fNextIndex; fRB->fRules.extractBetween(n->fFirstPos, n->fLastPos, n->fText); fLookAheadRule = TRUE; break; case doStartTagValue: // Scanned a '{', the opening delimiter for a tag value within a rule. n = pushNewNode(RBBINode::tag); n->fVal = 0; n->fFirstPos = fScanIndex; n->fLastPos = fNextIndex; break; case doTagDigit: // Just scanned a decimal digit that's part of a tag value { n = fNodeStack[fNodeStackPtr]; uint32_t v = u_charDigitValue(fC.fChar); U_ASSERT(v < 10); n->fVal = n->fVal*10 + v; break; } case doTagValue: n = fNodeStack[fNodeStackPtr]; n->fLastPos = fNextIndex; fRB->fRules.extractBetween(n->fFirstPos, n->fLastPos, n->fText); break; case doTagExpectedError: error(U_BRK_MALFORMED_RULE_TAG); returnVal = FALSE; break; case doOptionStart: // Scanning a !!option. At the start of string. fOptionStart = fScanIndex; break; case doOptionEnd: { UnicodeString opt(fRB->fRules, fOptionStart, fScanIndex-fOptionStart); if (opt == UNICODE_STRING("chain", 5)) { fRB->fChainRules = TRUE; } else if (opt == UNICODE_STRING("LBCMNoChain", 11)) { fRB->fLBCMNoChain = TRUE; } else if (opt == UNICODE_STRING("forward", 7)) { fRB->fDefaultTree = &fRB->fForwardTree; } else if (opt == UNICODE_STRING("reverse", 7)) { fRB->fDefaultTree = &fRB->fReverseTree; } else if (opt == UNICODE_STRING("safe_forward", 12)) { fRB->fDefaultTree = &fRB->fSafeFwdTree; } else if (opt == UNICODE_STRING("safe_reverse", 12)) { fRB->fDefaultTree = &fRB->fSafeRevTree; } else if (opt == UNICODE_STRING("lookAheadHardBreak", 18)) { fRB->fLookAheadHardBreak = TRUE; } else { error(U_BRK_UNRECOGNIZED_OPTION); } } break; case doReverseDir: fReverseRule = TRUE; break; case doStartVariableName: n = pushNewNode(RBBINode::varRef); if (U_FAILURE(*fRB->fStatus)) { break; } n->fFirstPos = fScanIndex; break; case doEndVariableName: n = fNodeStack[fNodeStackPtr]; if (n==NULL || n->fType != RBBINode::varRef) { error(U_BRK_INTERNAL_ERROR); break; } n->fLastPos = fScanIndex; fRB->fRules.extractBetween(n->fFirstPos+1, n->fLastPos, n->fText); // Look the newly scanned name up in the symbol table // If there's an entry, set the l. child of the var ref to the replacement expression. // (We also pass through here when scanning assignments, but no harm is done, other // than a slight wasted effort that seems hard to avoid. Lookup will be null) n->fLeftChild = fSymbolTable->lookupNode(n->fText); break; case doCheckVarDef: n = fNodeStack[fNodeStackPtr]; if (n->fLeftChild == NULL) { error(U_BRK_UNDEFINED_VARIABLE); returnVal = FALSE; } break; case doExprFinished: break; case doRuleErrorAssignExpr: error(U_BRK_ASSIGN_ERROR); returnVal = FALSE; break; case doExit: returnVal = FALSE; break; case doScanUnicodeSet: scanSet(); break; default: error(U_BRK_INTERNAL_ERROR); returnVal = FALSE; break; } return returnVal; }
//--------------------------------------------------------------------------------- // // scanSet Construct a UnicodeSet from the text at the current scan // position. Advance the scan position to the first character // after the set. // // A new RBBI setref node referring to the set is pushed onto the node // stack. // // The scan position is normally under the control of the state machine // that controls rule parsing. UnicodeSets, however, are parsed by // the UnicodeSet constructor, not by the RBBI rule parser. // //--------------------------------------------------------------------------------- void RBBIRuleScanner::scanSet() { UnicodeSet *uset; ParsePosition pos; int startPos; int i; if (U_FAILURE(*fRB->fStatus)) { return; } pos.setIndex(fScanIndex); startPos = fScanIndex; UErrorCode localStatus = U_ZERO_ERROR; uset = new UnicodeSet(fRB->fRules, pos, USET_IGNORE_SPACE, fSymbolTable, localStatus); if (U_FAILURE(localStatus)) { // TODO: Get more accurate position of the error from UnicodeSet's return info. // UnicodeSet appears to not be reporting correctly at this time. #ifdef RBBI_DEBUG RBBIDebugPrintf("UnicodeSet parse postion.ErrorIndex = %d\n", pos.getIndex()); #endif error(localStatus); delete uset; return; } // Verify that the set contains at least one code point. // if (uset->isEmpty()) { // This set is empty. // Make it an error, because it almost certainly is not what the user wanted. // Also, avoids having to think about corner cases in the tree manipulation code // that occurs later on. error(U_BRK_RULE_EMPTY_SET); delete uset; return; } // Advance the RBBI parse postion over the UnicodeSet pattern. // Don't just set fScanIndex because the line/char positions maintained // for error reporting would be thrown off. i = pos.getIndex(); for (;;) { if (fNextIndex >= i) { break; } nextCharLL(); } if (U_SUCCESS(*fRB->fStatus)) { RBBINode *n; n = pushNewNode(RBBINode::setRef); n->fFirstPos = startPos; n->fLastPos = fNextIndex; fRB->fRules.extractBetween(n->fFirstPos, n->fLastPos, n->fText); // findSetFor() serves several purposes here: // - Adopts storage for the UnicodeSet, will be responsible for deleting. // - Mantains collection of all sets in use, needed later for establishing // character categories for run time engine. // - Eliminates mulitiple instances of the same set. // - Creates a new uset node if necessary (if this isn't a duplicate.) findSetFor(n->fText, n, uset); } }
// DQ (4/7/2004): Added to support more general lookup of data in the AST (vector of variants) void* querySolverGrammarElementFromVariantVector ( SgNode * astNode, VariantVector targetVariantVector, NodeQuerySynthesizedAttributeType* returnNodeList ) { // This function extracts type nodes that would not be traversed so that they can // accumulated to a list. The specific nodes collected into the list is controlled // by targetVariantVector. ROSE_ASSERT (astNode != NULL); #if 0 printf ("Inside of void* querySolverGrammarElementFromVariantVector() astNode = %p = %s \n",astNode,astNode->class_name().c_str()); #endif Rose_STL_Container<SgNode*> nodesToVisitTraverseOnlyOnce; pushNewNode (returnNodeList,targetVariantVector,astNode); vector<SgNode*> succContainer = astNode->get_traversalSuccessorContainer(); vector<pair<SgNode*,string> > allNodesInSubtree = astNode->returnDataMemberPointers(); #if 0 printf ("succContainer.size() = %zu \n",succContainer.size()); printf ("allNodesInSubtree.size() = %zu \n",allNodesInSubtree.size()); #endif if ( succContainer.size() != allNodesInSubtree.size() ) { for (vector<pair<SgNode*,string> >::iterator iItr = allNodesInSubtree.begin(); iItr!= allNodesInSubtree.end(); ++iItr ) { #if 0 if ( iItr->first != NULL ) { // printf ("iItr->first = %p = %s \n",iItr->first,iItr->first->class_name().c_str()); printf ("iItr->first = %p \n",iItr->first); printf ("iItr->first = %p = %s \n",iItr->first,iItr->first->class_name().c_str()); } #endif // DQ (7/27/2014): Check if this is always non-NULL. // ROSE_ASSERT(iItr->first != NULL); #if 0 if (iItr->first != NULL) { // printf ("In querySolverGrammarElementFromVariantVector(): iItr->first->variantT() = %d class_name = %s \n",iItr->first->variantT(),iItr->first->class_name().c_str()); printf ("In querySolverGrammarElementFromVariantVector(): iItr->first = %p \n",iItr->first); printf ("In querySolverGrammarElementFromVariantVector(): iItr->first->class_name = %s \n",iItr->first->class_name().c_str()); printf ("In querySolverGrammarElementFromVariantVector(): iItr->first->variantT() = %d \n",(int)iItr->first->variantT()); } else { printf ("In querySolverGrammarElementFromVariantVector(): iItr->first == NULL \n"); } #endif SgType* type = isSgType(iItr->first); if ( type != NULL ) { // DQ (1/13/2011): If we have not already seen this entry then we have to chase down possible nested types. // if (std::find(succContainer.begin(),succContainer.end(),iItr->first) == succContainer.end() ) if (std::find(succContainer.begin(),succContainer.end(),type) == succContainer.end() ) { // DQ (1/30/2010): Push the current type onto the list first, then any internal types... pushNewNode (returnNodeList,targetVariantVector,type); // Are there any other places where nested types can be found...? // if ( isSgPointerType(iItr->first) != NULL || isSgArrayType(iItr->first) != NULL || isSgReferenceType(iItr->first) != NULL || isSgTypedefType(iItr->first) != NULL || isSgFunctionType(iItr->first) != NULL || isSgModifierType(iItr->first) != NULL) // if (type->containsInternalTypes() == true) if (type->containsInternalTypes() == true) { #if 0 printf ("If we have not already seen this entry then we have to chase down possible nested types. \n"); // ROSE_ASSERT(false); #endif Rose_STL_Container<SgType*> typeVector = type->getInternalTypes(); #if 0 printf ("----- typeVector.size() = %zu \n",typeVector.size()); #endif Rose_STL_Container<SgType*>::iterator i = typeVector.begin(); while(i != typeVector.end()) { #if 0 printf ("----- internal type = %s \n",(*i)->class_name().c_str()); #endif // DQ (1/16/2011): This causes a test in tests/roseTests/programAnalysisTests/variableLivenessTests // to fail with error "Error :: Number of nodes = 37 should be : 36" // Add this type to the return list of types. pushNewNode (returnNodeList,targetVariantVector,*i); i++; } } // DQ (1/30/2010): Move this code to the top of the basic block. // pushNewNode (returnNodeList,targetVariantVector,iItr->first); // pushNewNode (returnNodeList,targetVariantVector,type); } } } } #if 0 // This code cannot be put here. Since the same SgVarRefExp will also be found during variable substitution phase. // We don't want to replace the original SgVarRefExp!! // Liao 1/19/2011. query the dim_info of SgArrayType associated with SgPntrArrRefExp // e.g. assuming a subtree has a reference to an array, then the variables used to declare the array dimensions should also be treated as referenced/used by the subtree // even though the reference is indirect. // AST should look like: // SgPntrArrRefExp -> SgVarRefExp (lhs) -> SgVariableSymbol(symbol) -> SgInitializedName -> SgArrayType (typeptr) -> SgExprListExp (dim_info) // AST outlining needs to find indirect use of a variable to work properly if (std::find(targetVariantVector.begin(), targetVariantVector.end(), V_SgVarRefExp) != targetVariantVector.end()) // Only do this if SgVarRefExp is of interest { if (SgPntrArrRefExp * arr_exp = isSgPntrArrRefExp(astNode)) { printf("Debug: queryVariant.C Found SgPntrArrRefExp :%p\n", arr_exp); Rose_STL_Container<SgNode*> refList = NodeQuery::querySubTree(arr_exp->get_lhs_operand(),V_SgVarRefExp); // find the array reference from the lhs operand, which could be a complex arithmetic expression SgVarRefExp* array_ref = NULL; for (Rose_STL_Container<SgNode*>::iterator iter = refList.begin(); iter !=refList.end(); iter ++) { SgVarRefExp* cur_ref = isSgVarRefExp(*iter); ROSE_ASSERT (cur_ref != NULL); SgVariableSymbol * sym = cur_ref->get_symbol(); ROSE_ASSERT (sym != NULL); SgInitializedName * i_name = sym->get_declaration(); ROSE_ASSERT (i_name != NULL); SgArrayType * a_type = isSgArrayType(i_name->get_typeptr()); if (a_type) { Rose_STL_Container<SgNode*> dim_ref_list = NodeQuery::querySubTree(a_type->get_dim_info(),V_SgVarRefExp); for (Rose_STL_Container<SgNode*>::iterator iter2 = dim_ref_list.begin(); iter2 != dim_ref_list.end(); iter2++) { SgVarRefExp* dim_ref = isSgVarRefExp(*iter2); printf("Debug: queryVariant.C Found indirect SgVarRefExp as part of array dimension declaration:%s\n", dim_ref->get_symbol()->get_name().str()); pushNewNode (returnNodeList, targetVariantVector, *iter2); } } } } // end if SgPntrArrRefExp } // end if find() #endif return NULL; } /* End function querySolverUnionFields() */