// Traverse VAR DECL bool SuperastCPP::TraverseVarDecl(clang::VarDecl* var) { const std::string varName = var->getName().str(); rapidjson::Value varValue(rapidjson::kObjectType); addId(varValue); addPos(varValue, var); // Variable Declaration if it is not a parameter of a function if (!clang::dyn_cast<clang::ParmVarDecl>(var)) { varValue.AddMember("type", "variable-declaration", allocator); } varValue.AddMember("name", rapidjson::Value().SetString(varName.c_str(), varName.size(), allocator), allocator); // NonLValueExpr to remove LValueExpression for references. // There are more options clang::QualType qualType = var->getType().getNonLValueExprType(*context); const clang::Type* type = qualType.getTypePtr(); bool isConst = var->getType().isConstQualified() | qualType.isConstQualified(); //std::cerr << " type: " << type->getCanonicalTypeInternal().getAsString(); varValue.AddMember("data-type", createTypeValue(type), allocator); varValue.AddMember("is-reference", var->getType()->isReferenceType(), allocator); varValue.AddMember("is-const", isConst, allocator); if (var->hasInit() && !type->isStructureType() && !isSTLVectorType(type->getCanonicalTypeInternal())) { rapidjson::Value exprValue(rapidjson::kObjectType); TRY_TO(TraverseStmt(var->getInit())); clang::VarDecl::InitializationStyle initStyle = var->getInitStyle(); switch (initStyle) { case clang::VarDecl::CInit: case clang::VarDecl::CallInit: // We don't distinguis between these two initializations if (!sonValue.IsNull()) { varValue.AddMember("init", sonValue, allocator); } // Call style initializer (int x(1)) break; case clang::VarDecl::ListInit: // C++11 Initializer list. Not supported by us. break; } } sonValue = varValue; return true; }
// IF STATEMENT bool SuperastCPP::TraverseIfStmt(clang::IfStmt* ifs) { rapidjson::Value ifValue(rapidjson::kObjectType); addId(ifValue); addPos(ifValue, ifs); ifValue.AddMember("type", "conditional", allocator); // Check if the condition contains a var declaration if (ifs->getConditionVariable()) { ifValue.AddMember("condition", createMessageValue(ifs->getConditionVariable(), "error", "condition-variable", "Variable declarations are not allowed in if conditions"), allocator); } else { // condition part TRY_TO(TraverseStmt(ifs->getCond())); rapidjson::Value conditionValue; conditionValue = sonValue; ifValue.AddMember("condition", conditionValue, allocator); } // then part TRY_TO(TraverseStmt(ifs->getThen())); // Now sonValue contains the arrayValue ensureSonIsArray(); rapidjson::Value blockValue = createBlockValue(sonValue); ifValue.AddMember("then", blockValue, allocator); // if has else, print if (ifs->getElse()) { TRY_TO(TraverseStmt(ifs->getElse())); // sonValue contains the arrayValue ensureSonIsArray(); blockValue = createBlockValue(sonValue); ifValue.AddMember("else", blockValue, allocator); } sonValue = ifValue; return true; }
bool SuperastCPP::TraverseFunctionDecl(clang::FunctionDecl* functionDecl) { const std::string functionName = functionDecl->getNameInfo().getAsString(); rapidjson::Value functionValue(rapidjson::kObjectType); addId(functionValue); addPos(functionValue, functionDecl); functionValue.AddMember("type", "function-declaration", allocator); // Add the name functionValue.AddMember( "name", rapidjson::Value().SetString(functionName.c_str(), functionName.size(), allocator), allocator); // Add the return type clang::QualType qualType = functionDecl->getCallResultType().getNonLValueExprType(*context); functionValue.AddMember("return-type", createTypeValue((qualType.getTypePtr())), allocator); // Array of parameters rapidjson::Value parametersValue(rapidjson::kArrayType); // Traverse parameters for (unsigned int i = 0; i < functionDecl->param_size(); ++i) { TRY_TO(TraverseDecl(functionDecl->getParamDecl(i))); // Add the parameter to array parametersValue.PushBack(sonValue, allocator); } // Add parameters to functionValue functionValue.AddMember("parameters", parametersValue, allocator); // If this is a function definition, traverse definition. if (functionDecl->isThisDeclarationADefinition()) { TRY_TO(TraverseStmt(functionDecl->getBody())); ensureSonIsArray(); rapidjson::Value blockValue = createBlockValue(sonValue); functionValue.AddMember("block", blockValue, allocator); } else { // If not definition, add empty block rapidjson::Value emptyArray(rapidjson::kArrayType); functionValue.AddMember("block", createBlockValue(emptyArray), allocator); } // END BODY TRAVERSE sonValue = functionValue; return true; }
// RETURN STATEMENT bool SuperastCPP::TraverseReturnStmt(clang::ReturnStmt* ret) { rapidjson::Value returnValue(rapidjson::kObjectType); addId(returnValue); addPos(returnValue, ret); TRY_TO(TraverseStmt(ret->getRetValue())); returnValue.AddMember("type", "return", allocator); returnValue.AddMember("expression", sonValue, allocator); sonValue = returnValue; return true; }
// COMPOUND STATEMENTS, A block of statements in clangAST bool SuperastCPP::TraverseCompoundStmt(clang::CompoundStmt* compoundStmt) { rapidjson::Value arrayValue(rapidjson::kArrayType); // Traverse each statement and append it to the array for (clang::Stmt* stmt : compoundStmt->body()) { TRY_TO(TraverseStmt(stmt)); if (sonValue.IsArray()) { addElemsToArray(arrayValue, sonValue); } else { arrayValue.PushBack(sonValue, allocator); } } sonValue = arrayValue; return true; }
bool DoTraverseStmt(clang::Stmt *S) { if (auto const E = llvm::dyn_cast<clang::CallExpr>(S)) { // If this is a direct function call, don't bother showing the nodes for // the DeclRefExpr and function to pointer decay - just show arg nodes. if (E->getDirectCallee()) { for (auto const &Arg : seec::range(E->arg_begin(), E->arg_end())) { if (!TraverseStmt(Arg)) return false; } return true; } } return clang::RecursiveASTVisitor<DepthRecorder>::TraverseStmt(S); }
void VarCollector::HandleDirective(PragmaDirectiveMap *Directives, DirectiveList *FullDirectives, FullDirective *FD) { this->Directives = Directives; this->FullDirectives = FullDirectives; FullDirectives->ResetStack(); FullDirectives->Push(FD->Directive, FD->Header, FD->S, *(FD->CI)); CompilerInstanceStack.push_back(FD->CI); TraverseStmt(FD->S); CompilerInstanceStack.pop_back(); }
void Fix(CompoundStmt* CS) { if (!CS->size()) return; typedef llvm::SmallVector<Stmt*, 32> Statements; Statements Stmts; Stmts.append(CS->body_begin(), CS->body_end()); for (Statements::iterator I = Stmts.begin(); I != Stmts.end(); ++I) { if (!TraverseStmt(*I) && !m_HandledDecls.count(m_FoundDRE->getDecl())) { Sema::DeclGroupPtrTy VDPtrTy = m_Sema->ConvertDeclToDeclGroup(m_FoundDRE->getDecl()); StmtResult DS = m_Sema->ActOnDeclStmt(VDPtrTy, m_FoundDRE->getLocStart(), m_FoundDRE->getLocEnd()); assert(!DS.isInvalid() && "Invalid DeclStmt."); I = Stmts.insert(I, DS.take()); m_HandledDecls.insert(m_FoundDRE->getDecl()); } } CS->setStmts(m_Sema->getASTContext(), Stmts.data(), Stmts.size()); }
bool VarCollector::VisitCallExpr(CallExpr *e) { FunctionCall * FC = FullDirectives->Push(e); if (!FC) { CompilerInstance &CI = *(CompilerInstanceStack.back()); DiagnosticsEngine &Diags = CI.getDiagnostics(); unsigned DiagID = Diags.getCustomDiagID(DiagnosticsEngine::Warning, "Call to function '%0' does not have a " "definition, hence cannot be checked for safety"); Diags.Report(e->getLocStart(), DiagID) << e->getDirectCallee()->getName(); } else { CompilerInstanceStack.push_back(FC->CI); TraverseStmt(FC->S); CompilerInstanceStack.pop_back(); } return true; }
bool findBreak(SwitchCase *switchCaseStmt) { return !TraverseStmt(switchCaseStmt); }
bool SuperastCPP::TraverseCXXOperatorCallExpr(clang::CXXOperatorCallExpr* operatorCallExpr) { // IF THERE IS A PRINT auto decl = llvm::dyn_cast<clang::FunctionDecl>(operatorCallExpr->getCalleeDecl()); if (!decl) { std::cerr << "Unknown function in CXXOperatorCallExpr" << std::endl; return true; } const std::string functionName = decl->getNameInfo().getAsString(); if (functionName == PRINT_NAME || functionName == READ_NAME) { bool isFirst = false; if (!iofunctionStarted) { isFirst = true; iofunctionStarted = true; } rapidjson::Value arrayValue(rapidjson::kArrayType); for (unsigned i = 0; i < operatorCallExpr->getNumArgs(); ++i) { TRY_TO(TraverseStmt(operatorCallExpr->getArg(i))); if (i == 0) { // If sonValue is not an array, is because it reached the begin of // call, which is the cout/cerr/stream class if (sonValue.IsArray()) { arrayValue = sonValue; } } else { arrayValue.PushBack(sonValue, allocator); } } if (!isFirst) { sonValue = arrayValue; } else { iofunctionStarted = false; rapidjson::Value functionValue(rapidjson::kObjectType); addId(functionValue); addPos(functionValue, operatorCallExpr); functionValue.AddMember("type", "function-call", allocator); if (functionName == PRINT_NAME) functionValue.AddMember("name", "print", allocator); else functionValue.AddMember("name", "read", allocator); functionValue.AddMember("arguments", arrayValue, allocator); sonValue = functionValue; } } else if (functionName == VECTOR_POS_NAME) { // Operator [] TRY_TO(TraverseStmt(operatorCallExpr->getArg(0))); rapidjson::Value leftValue(rapidjson::kObjectType); leftValue = sonValue; TRY_TO(TraverseStmt(operatorCallExpr->getArg(1))); rapidjson::Value rightValue(rapidjson::kObjectType); rightValue = sonValue; sonValue = createBinOpValue("[]", leftValue, rightValue); } else { std::cerr << "Operator call not defined: " << functionName << std::endl; } return true; }
StatementVisitor(const clang::Stmt *const stmt) : stmt_{stmt} { TraverseStmt(const_cast<clang::Stmt *>(stmt_)); }
void DeclReferencer::Traverse(Loc loc, Scope *sc, clang::Stmt *S) { this->loc = loc; this->sc = sc; TraverseStmt(S); }
void extract(ObjCAtFinallyStmt *finallyStmt, vector<ObjCMessageExpr*> *raisers) { _raisers = raisers; (void) /* explicitly ignore the return of this function */ TraverseStmt(finallyStmt); }
void extract(ObjCAtFinallyStmt *finallyStmt, vector<ObjCAtThrowStmt*> *throws) { _throws = throws; (void) /* explicitly ignore the return of this function */ TraverseStmt(finallyStmt); }
void Fix(CompoundStmt* CS) { TraverseStmt(CS); }