void ProBoundsPointerArithmeticCheck::registerMatchers(MatchFinder *Finder) { if (!getLangOpts().CPlusPlus) return; // Flag all operators +, -, +=, -=, ++, -- that result in a pointer Finder->addMatcher( binaryOperator( anyOf(hasOperatorName("+"), hasOperatorName("-"), hasOperatorName("+="), hasOperatorName("-=")), hasType(pointerType()), unless(hasLHS(ignoringImpCasts(declRefExpr(to(isImplicit())))))) .bind("expr"), this); Finder->addMatcher( unaryOperator(anyOf(hasOperatorName("++"), hasOperatorName("--")), hasType(pointerType())) .bind("expr"), this); // Array subscript on a pointer (not an array) is also pointer arithmetic Finder->addMatcher( arraySubscriptExpr( hasBase(ignoringImpCasts( anyOf(hasType(pointerType()), hasType(decayedType(hasDecayedType(pointerType()))))))) .bind("expr"), this); }
void RedundantVoidArgCheck::registerMatchers(MatchFinder *Finder) { Finder->addMatcher(functionDecl(parameterCountIs(0), unless(isImplicit()), unless(isExternC())) .bind(FunctionId), this); Finder->addMatcher(typedefNameDecl().bind(TypedefId), this); auto ParenFunctionType = parenType(innerType(functionType())); auto PointerToFunctionType = pointee(ParenFunctionType); auto FunctionOrMemberPointer = anyOf(hasType(pointerType(PointerToFunctionType)), hasType(memberPointerType(PointerToFunctionType))); Finder->addMatcher(fieldDecl(FunctionOrMemberPointer).bind(FieldId), this); Finder->addMatcher(varDecl(FunctionOrMemberPointer).bind(VarId), this); auto CastDestinationIsFunction = hasDestinationType(pointsTo(ParenFunctionType)); Finder->addMatcher( cStyleCastExpr(CastDestinationIsFunction).bind(CStyleCastId), this); Finder->addMatcher( cxxStaticCastExpr(CastDestinationIsFunction).bind(NamedCastId), this); Finder->addMatcher( cxxReinterpretCastExpr(CastDestinationIsFunction).bind(NamedCastId), this); Finder->addMatcher( cxxConstCastExpr(CastDestinationIsFunction).bind(NamedCastId), this); Finder->addMatcher(lambdaExpr().bind(LambdaId), this); }
Type Value::typeFor(Opcode opcode, Value* firstChild) { switch (opcode) { case Identity: case Add: case Sub: case Mul: case Div: case ChillDiv: case Mod: case BitAnd: case BitOr: case BitXor: case Shl: case SShr: case ZShr: case CheckAdd: case CheckSub: case CheckMul: return firstChild->type(); case FramePointer: return pointerType(); case SExt8: case SExt16: case Trunc: case DToI32: case Equal: case NotEqual: case LessThan: case GreaterThan: case LessEqual: case GreaterEqual: case Above: case Below: case AboveEqual: case BelowEqual: return Int32; case SExt32: case ZExt32: return Int64; case FRound: case IToD: return Double; case BitwiseCast: if (firstChild->type() == Int64) return Double; if (firstChild->type() == Double) return Int64; ASSERT_NOT_REACHED(); return Void; case Nop: return Void; default: RELEASE_ASSERT_NOT_REACHED(); } }
void PointerAndIntegralOperationCheck::registerMatchers(MatchFinder *Finder) { const auto PointerExpr = expr(hasType(pointerType())); const auto BoolExpr = ignoringParenImpCasts(hasType(booleanType())); const auto CharExpr = ignoringParenImpCasts(hasType(isAnyCharacter())); const auto BinOpWithPointerExpr = binaryOperator(unless(anyOf(hasOperatorName(","), hasOperatorName("="))), hasEitherOperand(PointerExpr)); const auto AssignToPointerExpr = binaryOperator(hasOperatorName("="), hasLHS(PointerExpr)); const auto CompareToPointerExpr = binaryOperator(matchers::isRelationalOperator(), hasEitherOperand(PointerExpr)); // Detect expression like: ptr = (x != y); Finder->addMatcher(binaryOperator(AssignToPointerExpr, hasRHS(BoolExpr)) .bind("assign-bool-to-pointer"), this); // Detect expression like: ptr = A[i]; where A is char*. Finder->addMatcher(binaryOperator(AssignToPointerExpr, hasRHS(CharExpr)) .bind("assign-char-to-pointer"), this); // Detect expression like: ptr < false; Finder->addMatcher( binaryOperator(BinOpWithPointerExpr, hasEitherOperand(ignoringParenImpCasts(cxxBoolLiteral()))) .bind("pointer-and-bool-literal"), this); // Detect expression like: ptr < 'a'; Finder->addMatcher(binaryOperator(BinOpWithPointerExpr, hasEitherOperand(ignoringParenImpCasts( characterLiteral()))) .bind("pointer-and-char-literal"), this); // Detect expression like: ptr < 0; Finder->addMatcher(binaryOperator(CompareToPointerExpr, hasEitherOperand(ignoringParenImpCasts( integerLiteral(equals(0))))) .bind("compare-pointer-to-zero"), this); // Detect expression like: ptr < nullptr; Finder->addMatcher(binaryOperator(CompareToPointerExpr, hasEitherOperand(ignoringParenImpCasts( cxxNullPtrLiteralExpr()))) .bind("compare-pointer-to-null"), this); }
// Generate the code for a method call (save base and return label and call // method). void genMethodCall( FILE* yyout, Method* method, int reg ) { int newLabel_ = newLabel(); int totalSize = method->argumentsSize; int freg = -1; // Save base fprintf( yyout, "\tP(R7+4) = R6;\t// Save base\n" ); // Save return label fprintf( yyout, "\tP(R7) = %i;\t// Save return label\n", newLabel_ ); // Call method fprintf( yyout, "\tGT(%i);\t// Call method\n", method->label ); // Set return label fprintf( yyout, "L %i:\n", newLabel_ ); if(method->returnType){ if(!isFloat(method->returnType)){ // Save return value fprintf( yyout, "\tR%d = %c(R7+%d); // Get return value\n", reg, pointerType(method->returnType), totalSize); }else{ // Save return value fprintf( yyout, "\tRR%d = %c(R7+%d); // Get return value\n", reg, pointerType(method->returnType), totalSize); freg = reg; reg = -1; } totalSize += ((Type*)(method->returnType->info))->size; } // Free arguments memory fprintf( yyout,"\tR7 = R7 + %d;\t// Free memory for arguments and return value\n", totalSize ); // Load the used registers from the stack loadRegisters(yyout, reg, freg); // Print a comment to indicate the method call's end. fprintf( yyout, "\t/* Call to procedure - end */\n\n" ); }
SymbolInfo* genArrayContent( FILE* yyout, SymbolInfo* leftSide, Symbol* literalInfo, SymbolInfo* arrayInfo ) { Symbol* varSymbol = leftSide->varSymbol; int position = arrayInfo->info; int address = ((Variable*)(varSymbol->info))->address; int nRegister = ((ExtraInfo*)(literalInfo->info))->nRegister; int elementSize = ((Type*)(((Type*)(((Variable*)(varSymbol->info))->type->info))->arrayInfo->type->info))->size; int isFloat_ = isFloat(leftSide->varSymbol); cstr regStr = getRegStr( isFloat_ ); switch(varSymbol->symType) { case SYM_GLOBAL: fprintf(yyout,"\t%c(0x%x + %d) = %s%d; //Initializing %s array\n",pointerType(varSymbol), address, elementSize*position, regStr, nRegister, varSymbol->name); break; case SYM_VARIABLE: if(((Variable*)(varSymbol->info))->symSubtype == SYM_LOCAL){ fprintf(yyout,"\t%c(R6 + %d) = %s%d; //Initializing %s array\n",pointerType(varSymbol), elementSize*position - address, regStr, nRegister, varSymbol->name); }else{ fprintf(yyout,"\t%c(R6 - %d) = %s%d; //Initializing %s array\n",pointerType(varSymbol), elementSize*position + address, regStr, nRegister, varSymbol->name); } break; case SYM_CONSTANT: break; default: //Error printf("Error in array content\n"); break; } arrayInfo->info++; freeRegister( ((ExtraInfo*)(literalInfo->info))->nRegister, isFloat_ ); freeSymbol(literalInfo); return arrayInfo; }
// Generate the code for a parameter pass. Arguments: // - iRegister - index of register with the argument's value. // - method - called method symbol. // - iArgument - argument index. void genArgumentPass( FILE* yyout, Symbol* argumentSymbol, Symbol* method, int iArgument ) { Symbol* argument = getMethodArgument( method, iArgument ); int iRegister = ((ExtraInfo*)(argumentSymbol->info))->nRegister; int address = ((Variable*)( argument->info ) )->address; int isFloat_ = isFloat( argumentSymbol ); cstr regStr = getRegStr( isFloat_ ); // Get parameter. fprintf( yyout,"\t%c(R7+%d) = %s%d;\t// %iº Argument\n", pointerType( argument ), address, regStr, iRegister, iArgument+1 ); freeRegister( iRegister, isFloat_ ); freeSymbol(argumentSymbol); }
Output::Output(CompilerState& state) : m_state(state) , m_repo(state.m_context, state.m_module) , m_builder(nullptr) , m_stackMapsId(1) , m_currentBlockTerminated(false) { m_argType = pointerType(arrayType(repo().intPtr, state.m_platformDesc.m_contextSize / sizeof(intptr_t))); state.m_function = addFunction( state.m_module, "main", functionType(repo().voidType, m_argType)); llvmAPI->SetFunctionCallConv(state.m_function, LLVMFastCallConv); m_builder = llvmAPI->CreateBuilderInContext(state.m_context); m_prologue = appendBasicBlock("Prologue"); positionToBBEnd(m_prologue); buildGetArg(); }
void MoveConstructorInitCheck::registerMatchers(MatchFinder *Finder) { // Only register the matchers for C++11; the functionality currently does not // provide any benefit to other languages, despite being benign. if (!getLangOpts().CPlusPlus11) return; Finder->addMatcher( cxxConstructorDecl( unless(isImplicit()), allOf(isMoveConstructor(), hasAnyConstructorInitializer( cxxCtorInitializer( withInitializer(cxxConstructExpr(hasDeclaration( cxxConstructorDecl(isCopyConstructor()) .bind("ctor"))))) .bind("move-init")))), this); auto NonConstValueMovableAndExpensiveToCopy = qualType(allOf(unless(pointerType()), unless(isConstQualified()), hasDeclaration(cxxRecordDecl(hasMethod(cxxConstructorDecl( isMoveConstructor(), unless(isDeleted()))))), matchers::isExpensiveToCopy())); // This checker is also used to implement cert-oop11-cpp, but when using that // form of the checker, we do not want to diagnose movable parameters. if (!UseCERTSemantics) { Finder->addMatcher( cxxConstructorDecl( allOf( unless(isMoveConstructor()), hasAnyConstructorInitializer(withInitializer(cxxConstructExpr( hasDeclaration(cxxConstructorDecl(isCopyConstructor())), hasArgument( 0, declRefExpr( to(parmVarDecl( hasType( NonConstValueMovableAndExpensiveToCopy)) .bind("movable-param"))) .bind("init-arg"))))))) .bind("ctor-decl"), this); } }
DataType TypeParser::applyTypePostfixes(const DataType& originalType, bool genericParam) { DataType type(originalType); if (_helper->nextIf(Token::Type::OperatorNot)) { type.setAccess(DataType::Access::ReadWrite); } if (_helper->nextIf(Token::Type::OperatorQuestionMark)) { DataType::Kind kind = genericParam ? DataType::Kind::GenericNullablePointer : DataType::Kind::NullablePointer; DataType pointerType(kind); pointerType.addSubtype(type); type = pointerType; } return type; }
CommonValues::CommonValues(LContext context) : voidType(FTL::voidType(context)) , boolean(int1Type(context)) , int8(int8Type(context)) , int16(int16Type(context)) , int32(int32Type(context)) , int64(int64Type(context)) , intPtr(intPtrType(context)) , floatType(FTL::floatType(context)) , doubleType(FTL::doubleType(context)) , ref8(pointerType(int8)) , ref16(pointerType(int16)) , ref32(pointerType(int32)) , ref64(pointerType(int64)) , refPtr(pointerType(intPtr)) , refFloat(pointerType(floatType)) , refDouble(pointerType(doubleType)) , booleanTrue(constInt(boolean, true, ZeroExtend)) , booleanFalse(constInt(boolean, false, ZeroExtend)) , int8Zero(constInt(int8, 0, SignExtend)) , int32Zero(constInt(int32, 0, SignExtend)) , int32One(constInt(int32, 1, SignExtend)) , int64Zero(constInt(int64, 0, SignExtend)) , intPtrZero(constInt(intPtr, 0, SignExtend)) , intPtrOne(constInt(intPtr, 1, SignExtend)) , intPtrTwo(constInt(intPtr, 2, SignExtend)) , intPtrThree(constInt(intPtr, 3, SignExtend)) , intPtrFour(constInt(intPtr, 4, SignExtend)) , intPtrEight(constInt(intPtr, 8, SignExtend)) , intPtrPtr(constInt(intPtr, sizeof(void*), SignExtend)) , doubleZero(constReal(doubleType, 0)) , rangeKind(mdKindID(context, "range")) , profKind(mdKindID(context, "prof")) , branchWeights(mdString(context, "branch_weights")) , nonNegativeInt32(constInt(int32, 0, SignExtend), constInt(int32, 1ll << 31, SignExtend)) , m_context(context) , m_module(0) { }
void TabletWidget::paintEvent(QPaintEvent *) { QPainter painter(this); QStringList eventInfo; QString typeString("Event type: "); switch (mType) { case QEvent::TabletEnterProximity: typeString += "QEvent::TabletEnterProximity"; break; case QEvent::TabletLeaveProximity: typeString += "QEvent::TabletLeaveProximity"; break; case QEvent::TabletMove: typeString += "QEvent::TabletMove"; break; case QEvent::TabletPress: typeString += "QEvent::TabletPress"; break; case QEvent::TabletRelease: typeString += "QEvent::TabletRelease"; break; case QEvent::MouseMove: typeString += "QEvent::MouseMove"; break; } eventInfo << typeString; eventInfo << QString("Global position: %1 %2").arg(QString::number(mGPos.x()), QString::number(mGPos.y())); eventInfo << QString("Local position: %1 %2").arg(QString::number(mPos.x()), QString::number(mPos.y())); if (mType == QEvent::TabletEnterProximity || mType == QEvent::TabletLeaveProximity || mType == QEvent::TabletMove || mType == QEvent::TabletPress || mType == QEvent::TabletRelease) { eventInfo << QString("High res global position: %1 %2").arg(QString::number(mHiResGlobalPos.x()), QString::number(mHiResGlobalPos.y())); QString pointerType("Pointer type: "); switch (mPointerType) { case QTabletEvent::UnknownPointer: pointerType += "QTabletEvent::UnknownPointer"; break; case QTabletEvent::Pen: pointerType += "QTabletEvent::Pen"; break; case QTabletEvent::Cursor: pointerType += "QTabletEvent::Cursor"; break; case QTabletEvent::Eraser: pointerType += "QTabletEvent::Eraser"; break; } eventInfo << pointerType; QString deviceString = "Device type: "; switch (mDev) { case QTabletEvent::NoDevice: deviceString += "QTabletEvent::NoDevice"; break; case QTabletEvent::Puck: deviceString += "QTabletEvent::Puck"; break; case QTabletEvent::Stylus: deviceString += "QTabletEvent::Stylus"; break; case QTabletEvent::Airbrush: deviceString += "QTabletEvent::Airbrush"; break; case QTabletEvent::FourDMouse: deviceString += "QTabletEvent::FourDMouse"; break; case QTabletEvent::RotationStylus: deviceString += "QTabletEvent::RotationStylus"; break; } eventInfo << deviceString; eventInfo << QString("Button: %1 (0x%2)").arg(buttonToString(mButton)).arg(mButton, 0, 16); eventInfo << QString("Buttons currently pressed: %1 (0x%2)").arg(buttonsToString(mButtons)).arg(mButtons, 0, 16); eventInfo << QString("Pressure: %1").arg(QString::number(mPress)); eventInfo << QString("Tangential pressure: %1").arg(QString::number(mTangential)); eventInfo << QString("Rotation: %1").arg(QString::number(mRot)); eventInfo << QString("xTilt: %1").arg(QString::number(mXT)); eventInfo << QString("yTilt: %1").arg(QString::number(mYT)); eventInfo << QString("z: %1").arg(QString::number(mZ)); eventInfo << QString("Unique Id: %1").arg(QString::number(mUnique)); } QString text = eventInfo.join("\n"); painter.drawText(rect(), text); }
static const llvm::Type *makeLLVMType(TypePtr t) { switch (t->typeKind) { case BOOL_TYPE : return llvmIntType(8); case INTEGER_TYPE : { IntegerType *x = (IntegerType *)t.ptr(); return llvmIntType(x->bits); } case FLOAT_TYPE : { FloatType *x = (FloatType *)t.ptr(); return llvmFloatType(x->bits); } case POINTER_TYPE : { PointerType *x = (PointerType *)t.ptr(); return llvmPointerType(x->pointeeType); } case CODE_POINTER_TYPE : { CodePointerType *x = (CodePointerType *)t.ptr(); vector<const llvm::Type *> llArgTypes; for (unsigned i = 0; i < x->argTypes.size(); ++i) llArgTypes.push_back(llvmPointerType(x->argTypes[i])); for (unsigned i = 0; i < x->returnTypes.size(); ++i) { TypePtr t = x->returnTypes[i]; if (x->returnIsRef[i]) llArgTypes.push_back(llvmPointerType(pointerType(t))); else llArgTypes.push_back(llvmPointerType(t)); } llvm::FunctionType *llFuncType = llvm::FunctionType::get(llvmIntType(32), llArgTypes, false); return llvm::PointerType::getUnqual(llFuncType); } case CCODE_POINTER_TYPE : { CCodePointerType *x = (CCodePointerType *)t.ptr(); vector<const llvm::Type *> llArgTypes; for (unsigned i = 0; i < x->argTypes.size(); ++i) llArgTypes.push_back(llvmType(x->argTypes[i])); const llvm::Type *llReturnType = x->returnType.ptr() ? llvmType(x->returnType) : llvmVoidType(); llvm::FunctionType *llFuncType = llvm::FunctionType::get(llReturnType, llArgTypes, x->hasVarArgs); return llvm::PointerType::getUnqual(llFuncType); } case ARRAY_TYPE : { ArrayType *x = (ArrayType *)t.ptr(); return llvmArrayType(x->elementType, x->size); } case VEC_TYPE : { VecType *x = (VecType *)t.ptr(); return llvm::VectorType::get(llvmType(x->elementType), x->size); } case TUPLE_TYPE : { TupleType *x = (TupleType *)t.ptr(); vector<const llvm::Type *> llTypes; vector<TypePtr>::iterator i, end; for (i = x->elementTypes.begin(), end = x->elementTypes.end(); i != end; ++i) llTypes.push_back(llvmType(*i)); if (x->elementTypes.empty()) llTypes.push_back(llvmIntType(8)); return llvm::StructType::get(llvm::getGlobalContext(), llTypes); } case UNION_TYPE : { UnionType *x = (UnionType *)t.ptr(); const llvm::Type *maxAlignType = NULL; size_t maxAlign = 0; size_t maxAlignSize = 0; size_t maxSize = 0; for (unsigned i = 0; i < x->memberTypes.size(); ++i) { const llvm::Type *llt = makeLLVMApproximateType(x->memberTypes[i]); size_t align = llvmTargetData->getABITypeAlignment(llt); size_t size = llvmTargetData->getTypeAllocSize(llt); if (align > maxAlign) { maxAlign = align; maxAlignType = llt; maxAlignSize = size; } if (size > maxSize) maxSize = size; } if (!maxAlignType) { maxAlignType = llvmIntType(8); maxAlign = 1; } vector<const llvm::Type *> llTypes; llTypes.push_back(maxAlignType); if (maxSize > maxAlignSize) { const llvm::Type *padding = llvm::ArrayType::get(llvmIntType(8), maxSize-maxAlignSize); llTypes.push_back(padding); } return llvm::StructType::get(llvm::getGlobalContext(), llTypes); } case RECORD_TYPE : { RecordType *x = (RecordType *)t.ptr(); const vector<TypePtr> &fieldTypes = recordFieldTypes(x); vector<const llvm::Type *> llTypes; vector<TypePtr>::const_iterator i, end; for (i = fieldTypes.begin(), end = fieldTypes.end(); i != end; ++i) llTypes.push_back(llvmType(*i)); if (fieldTypes.empty()) llTypes.push_back(llvmIntType(8)); return llvm::StructType::get(llvm::getGlobalContext(), llTypes); } case VARIANT_TYPE : { VariantType *x = (VariantType *)t.ptr(); return llvmType(variantReprType(x)); } case STATIC_TYPE : { vector<const llvm::Type *> llTypes; llTypes.push_back(llvmIntType(8)); return llvm::StructType::get(llvm::getGlobalContext(), llTypes); } case ENUM_TYPE : { return llvmType(cIntType); } default : assert(false); return NULL; } }
#include "ASTUtility.h" StatementMatcher FuncStmtMatcher = compoundStmt( hasParent(functionDecl(returns(pointerType())).bind("functiondecl")), hasDescendant(returnStmt( hasDescendant(declRefExpr().bind("decl")))) ).bind("funcstmt"); class ReturnChecker : public MatchFinder::MatchCallback { public: virtual void run(const MatchFinder::MatchResult &Result) { clang::ASTContext *Context = Result.Context; const clang::CompoundStmt *cs = Result.Nodes.getNodeAs<clang::CompoundStmt>("funcstmt"); const clang::FunctionDecl *fd = Result.Nodes.getNodeAs<clang::FunctionDecl>("functiondecl"); const clang::DeclRefExpr *decl = Result.Nodes.getNodeAs<clang::DeclRefExpr>("decl"); if(!cs || !fd || !decl || ASTUtility::IsStmtInSTDFile(cs, Context)) return; if (!clang::VarDecl::classof(decl -> getDecl())) return; const clang::VarDecl *var = static_cast<const clang::VarDecl*>(decl -> getDecl()); if (var -> hasLocalStorage()) ASTUtility::Print(decl, Context, "Rule65"); } }; //@TestNeed static llvm::cl::OptionCategory MyToolCategory("options");
#include "ASTUtility.h" // int *x = NULL or int *x = 0 DeclarationMatcher nullPointerMatcher = varDecl(hasType(pointerType()), hasInitializer(implicitCastExpr().bind("cast"))).bind("var"); // x == NULL or x == 0 StatementMatcher biOpMatcher1 = binaryOperator(hasRHS(implicitCastExpr().bind("castR1")), hasOperatorName("==")).bind("bo1"); // x != NULL or x != 0 StatementMatcher biOpMatcher2 = binaryOperator(hasRHS(implicitCastExpr().bind("castR2")), hasOperatorName("!=")).bind("bo2"); // x != NULL or x != 0 StatementMatcher biOpMatcher3 = binaryOperator(hasRHS(implicitCastExpr().bind("castR3")), hasOperatorName("=")).bind("bo3"); class NullPointerPrinter : public MatchFinder::MatchCallback { public: virtual void run(const MatchFinder::MatchResult &Result) { //get the node clang::ASTContext *Context = Result.Context; const clang::ImplicitCastExpr *cast = Result.Nodes.getNodeAs<clang::ImplicitCastExpr>("cast"); const clang::ImplicitCastExpr *castR1 = Result.Nodes.getNodeAs<clang::ImplicitCastExpr>("castR1"); const clang::ImplicitCastExpr *castR2 = Result.Nodes.getNodeAs<clang::ImplicitCastExpr>("castR2"); const clang::ImplicitCastExpr *castR3 = Result.Nodes.getNodeAs<clang::ImplicitCastExpr>("castR3"); const clang::BinaryOperator *bo1 = Result.Nodes.getNodeAs<clang::BinaryOperator>("bo1"); const clang::BinaryOperator *bo2 = Result.Nodes.getNodeAs<clang::BinaryOperator>("bo2"); const clang::BinaryOperator *bo3 = Result.Nodes.getNodeAs<clang::BinaryOperator>("bo3");
void CanRunScriptChecker::registerMatchers(MatchFinder *AstMatcher) { auto InvalidArg = // We want to find any expression, ignoreTrivials(expr( // which has a refcounted pointer type, hasType(pointerType( pointee(hasDeclaration(cxxRecordDecl(isRefCounted()))))), // and which is not this, unless(cxxThisExpr()), // and which is not a method call on a smart ptr, unless(cxxMemberCallExpr(on(hasType(isSmartPtrToRefCounted())))), // and which is not a parameter of the parent function, unless(declRefExpr(to(parmVarDecl()))), // and which is not a MOZ_KnownLive wrapped value. unless(callExpr(callee(functionDecl(hasName("MOZ_KnownLive"))))), expr().bind("invalidArg"))); auto OptionalInvalidExplicitArg = anyOf( // We want to find any argument which is invalid. hasAnyArgument(InvalidArg), // This makes this matcher optional. anything()); // Please not that the hasCanRunScriptAnnotation() matchers are not present // directly in the cxxMemberCallExpr, callExpr and constructExpr matchers // because we check that the corresponding functions can run script later in // the checker code. AstMatcher->addMatcher( expr( anyOf( // We want to match a method call expression, cxxMemberCallExpr( // which optionally has an invalid arg, OptionalInvalidExplicitArg, // or which optionally has an invalid implicit this argument, anyOf( // which derefs into an invalid arg, on(cxxOperatorCallExpr( anyOf(hasAnyArgument(InvalidArg), anything()))), // or is an invalid arg. on(InvalidArg), anything()), expr().bind("callExpr")), // or a regular call expression, callExpr( // which optionally has an invalid arg. OptionalInvalidExplicitArg, expr().bind("callExpr")), // or a construct expression, cxxConstructExpr( // which optionally has an invalid arg. OptionalInvalidExplicitArg, expr().bind("constructExpr"))), anyOf( // We want to match the parent function. forFunction(functionDecl().bind("nonCanRunScriptParentFunction")), // ... optionally. anything())), this); }
void DanglingOnTemporaryChecker::registerMatchers(MatchFinder *AstMatcher) { //////////////////////////////////////// // Quick annotation conflict checkers // //////////////////////////////////////// AstMatcher->addMatcher( // This is a matcher on a method declaration, cxxMethodDecl( // which is marked as no dangling on temporaries, noDanglingOnTemporaries(), // and which is && ref-qualified. isRValueRefQualified(), decl().bind("invalidMethodRefQualified")), this); AstMatcher->addMatcher( // This is a matcher on a method declaration, cxxMethodDecl( // which is marked as no dangling on temporaries, noDanglingOnTemporaries(), // which returns a primitive type, returns(builtinType()), // and which doesn't return a pointer. unless(returns(pointerType())), decl().bind("invalidMethodPointer")), this); ////////////////// // Main checker // ////////////////// auto hasParentCall = hasParent(expr(anyOf( cxxOperatorCallExpr( // If we're in a lamda, we may have an operator call expression // ancestor in the AST, but the temporary we're matching // against is not going to have the same lifetime as the // constructor call. unless(has(expr(ignoreTrivials(lambdaExpr())))), expr().bind("parentOperatorCallExpr")), callExpr( // If we're in a lamda, we may have a call expression // ancestor in the AST, but the temporary we're matching // against is not going to have the same lifetime as the // function call. unless(has(expr(ignoreTrivials(lambdaExpr())))), expr().bind("parentCallExpr")), objcMessageExpr( // If we're in a lamda, we may have an objc message expression // ancestor in the AST, but the temporary we're matching // against is not going to have the same lifetime as the // function call. unless(has(expr(ignoreTrivials(lambdaExpr())))), expr().bind("parentObjCMessageExpr")), cxxConstructExpr( // If we're in a lamda, we may have a construct expression // ancestor in the AST, but the temporary we're matching // against is not going to have the same lifetime as the // constructor call. unless(has(expr(ignoreTrivials(lambdaExpr())))), expr().bind("parentConstructExpr"))))); AstMatcher->addMatcher( // This is a matcher on a method call, cxxMemberCallExpr( // which is in first party code, isFirstParty(), // and which is performed on a temporary, on(allOf( unless(hasType(pointerType())), isTemporary(), // but which is not `this`. unless(cxxThisExpr()))), // and which is marked as no dangling on temporaries. callee(cxxMethodDecl(noDanglingOnTemporaries())), expr().bind("memberCallExpr"), // We optionally match a parent call expression or a parent construct // expression because using a temporary inside a call is fine as long // as the pointer doesn't escape the function call. anyOf( // This is the case where the call is the direct parent, so we // know that the member call expression is the argument. allOf(hasParentCall, expr().bind("parentCallArg")), // This is the case where the call is not the direct parent, so we // get its child to know in which argument tree we are. hasAncestor(expr( hasParentCall, expr().bind("parentCallArg"))), // To make it optional. anything())), this); }
Symbol* genAccessVariable(FILE* yyout,cstr name, int symType, SymbolInfo* atribute) { Symbol* variable = searchVariable(symType, name); int isFloat_ = isFloat( variable ); int reg; int height = returnVariableHeight( symType, name ); //When trying to access an array variable outside a block //we can use expression register so we do not have to assign a new one if( atribute->info == TYPE_ARRAY && !isFloat_ && height == 0 ){ reg = ((ExtraInfo*)(atribute->exprSymbol->info))->nRegister; }else{ reg = assignRegisters( isFloat_ ); } cstr regStr = getRegStr( isFloat_ ); int elementSize = 0; if (isFloat_ == 0) reg = checkOverflow(yyout, reg, TYPE_INTEGER); else reg = checkOverflow(yyout, reg, TYPE_FLOAT); Symbol* returnSymbol = createExtraInfoSymbol(reg, isFloat_); ExtraInfo* aux = (ExtraInfo*)(returnSymbol->info); aux->nRegister = reg; aux->variable = variable; if(atribute->info == SYM_CLASS_VARIABLE){ //varSymbol gets the Symbol of the variable aux->variable = getClassVar(aux->variable,atribute->name); } if( atribute->info == TYPE_ARRAY ){ elementSize = ((Type*)(((Type*)(((Variable*)(aux->variable->info))->type->info))->arrayInfo->type->info))->size; } if( symType == SYM_VARIABLE ) { int accessRegister = genFrameAccess( yyout, height, reg, isFloat_ ); if(((Variable*)(aux->variable->info))->symSubtype == SYM_LOCAL){ if( atribute->info == TYPE_ARRAY ){ int expReg = ((ExtraInfo*)(atribute->exprSymbol->info))->nRegister; fprintf(yyout, "\tR%d = R%d * %d; //Calculate array %s position\n",expReg, expReg, elementSize, aux->variable->name); fprintf(yyout, "\tR%d = R%d - %d; //Calculate local %s position\n",expReg, expReg, returnAddress(symType,aux->variable->name), aux->variable->name); fprintf(yyout,"\t%s%d = %c(R%d + R%d); //%s[expr] = expr\n",regStr, reg, pointerType(aux->variable), accessRegister, expReg, aux->variable->name); if( !(atribute->info == TYPE_ARRAY && !isFloat_ && height == 0) ){ freeRegister( expReg, 0 ); } freeSymbol(atribute->exprSymbol); }else{ fprintf(yyout,"\t%s%d = %c(R%d - %d); //Loading value of var %s\n",regStr, reg, pointerType(aux->variable), accessRegister, returnAddress(symType,aux->variable->name), aux->variable->name); } }else{ if( atribute->info == TYPE_ARRAY ){ int expReg = ((ExtraInfo*)(atribute->exprSymbol->info))->nRegister; fprintf(yyout, "\tR%d = R%d * %d; //Calculate array %s position\n",expReg, expReg, elementSize, aux->variable->name); fprintf(yyout, "\tR%d = R%d + %d; //Calculate local %s position\n",expReg, expReg, returnAddress(symType,aux->variable->name), aux->variable->name); fprintf(yyout,"\t%s%d = %c(R%d + R%d); //%s[expr] = expr\n",regStr, reg, pointerType(aux->variable), accessRegister, expReg, aux->variable->name); if( !(atribute->info == TYPE_ARRAY && !isFloat_ && height == 0) ){ freeRegister( expReg, 0 ); } freeSymbol(atribute->exprSymbol); }else{ fprintf(yyout,"\t%s%d = %c(R%d + %d); //Loading value of var %s\n",regStr,reg, pointerType(aux->variable), accessRegister, returnAddress(symType,aux->variable->name), aux->variable->name); } } if( accessRegister != 6 ){ freeRegister( accessRegister, 0 ); } }else{ if( symType == SYM_GLOBAL ) { if( atribute->info == TYPE_ARRAY ){ int expReg = ((ExtraInfo*)(atribute->exprSymbol->info))->nRegister; fprintf(yyout, "\tR%d = R%d * %d; //Calculate array %s position\n",expReg, expReg, elementSize, aux->variable->name); fprintf(yyout,"\t%s%d = %c(0x%x + R%d); //Loading value of var %s[expr]\n",regStr, reg, pointerType(aux->variable), returnAddress(symType,aux->variable->name), expReg, aux->variable->name); if( !(atribute->info == TYPE_ARRAY && !isFloat_ && height == 0) ){ freeRegister( expReg, 0 ); } freeSymbol(atribute->exprSymbol); }else{ fprintf(yyout,"\t%s%d = %c(0x%x); //Loading value of var %s\n", regStr, reg, pointerType(aux->variable), returnAddress(symType,aux->variable->name), aux->variable->name); } //FIXME Las constantes van aqui }else{ } } freeSymbolInfo(atribute); return returnSymbol; }
//StatementMatcher callExprMatcher = callExpr().bind("callexpr"); StatementMatcher mallocMatcher = callExpr(callee(functionDecl(hasName("malloc")).bind("m"))).bind("mallocCall"); StatementMatcher freeMatcher = callExpr(callee(functionDecl(hasName("free")).bind("f"))).bind("freeCall"); StatementMatcher reallocMatcher = callExpr(callee(functionDecl(hasName("realloc")).bind("r"))).bind("reallocCall"); //memcpy arrayType non-builtin = pointer or user-defined StatementMatcher memcpyAryMatcher = callExpr( callee(functionDecl(hasName("memcpy")).bind("cpy")), hasAnyArgument(ignoringImpCasts(declRefExpr( to(declaratorDecl(hasType(arrayType( unless(hasElementType(builtinType()))).bind("cpyParm"))))))) ).bind("memcpyCall"); StatementMatcher memcpyPtrMatcher = callExpr( callee(functionDecl(hasName("memcpy")).bind("cpy")), hasAnyArgument(ignoringImpCasts(declRefExpr( to(declaratorDecl(hasType(pointerType( pointee(unless(builtinType()))).bind("cpyParmPtr"))))))) ).bind("memcpyCall"); StatementMatcher memcmpAryMatcher = callExpr( callee(functionDecl(hasName("memcmp")).bind("cmp")), hasAnyArgument(ignoringImpCasts(declRefExpr( to(declaratorDecl(hasType(arrayType( unless(hasElementType(builtinType()))).bind("cmpParm"))))))) ).bind("memcmpCall"); StatementMatcher memcmpPtrMatcher = callExpr( callee(functionDecl(hasName("memcmp")).bind("cmp")), hasAnyArgument(ignoringImpCasts(declRefExpr( to(declaratorDecl(hasType(pointerType( pointee(unless(builtinType()))).bind("cmpParmPtr"))))))) ).bind("memcmpCall");
Type Value::typeFor(Opcode opcode, Value* firstChild, Value* secondChild) { switch (opcode) { case Identity: case Add: case Sub: case Mul: case Div: case Mod: case Neg: case ChillDiv: case ChillMod: case BitAnd: case BitOr: case BitXor: case Shl: case SShr: case ZShr: case Clz: case Abs: case Ceil: case Sqrt: case CheckAdd: case CheckSub: case CheckMul: return firstChild->type(); case FramePointer: return pointerType(); case SExt8: case SExt16: case Trunc: case Equal: case NotEqual: case LessThan: case GreaterThan: case LessEqual: case GreaterEqual: case Above: case Below: case AboveEqual: case BelowEqual: case EqualOrUnordered: return Int32; case SExt32: case ZExt32: return Int64; case FloatToDouble: case IToD: return Double; case DoubleToFloat: return Float; case BitwiseCast: switch (firstChild->type()) { case Int64: return Double; case Double: return Int64; case Int32: return Float; case Float: return Int32; case Void: ASSERT_NOT_REACHED(); } return Void; case Nop: return Void; case Select: ASSERT(secondChild); return secondChild->type(); default: RELEASE_ASSERT_NOT_REACHED(); } }
static void initializeLambdaWithFreeVars(LambdaPtr x, EnvPtr env, string const &closureDataName, string const &lname) { RecordPtr r = new Record(PRIVATE); r->location = x->location; r->name = new Identifier(lname); r->env = env; x->lambdaRecord = r; r->lambda = x; vector<RecordFieldPtr> fields; CallPtr converted = new Call(NULL, new ExprList()); for (unsigned i = 0; i < x->freeVars.size(); ++i) { IdentifierPtr ident = new Identifier(x->freeVars[i]); NameRefPtr nameRef = new NameRef(ident); TypePtr type; ObjectPtr obj = safeLookupEnv(env, ident); switch (obj->objKind) { case PVALUE : case CVALUE : { type = typeOfValue(obj); if (x->captureByRef) { type = pointerType(type); vector<int> ops; ops.push_back(ADDRESS_OF); ExprPtr addr = new VariadicOp(ops, new ExprList(nameRef.ptr())); converted->parenArgs->add(addr); } else { converted->parenArgs->add(nameRef.ptr()); } break; } case MULTI_PVALUE : case MULTI_CVALUE : { vector<TypePtr> types = typesOfValues(obj); vector<TypePtr> elementTypes; for (unsigned j = 0; j < types.size(); ++j) { TypePtr t = types[j]; if (x->captureByRef) t = pointerType(t); elementTypes.push_back(t); } type = tupleType(elementTypes); if (x->captureByRef) { ExprPtr e = operator_expr_packMultiValuedFreeVarByRef(); CallPtr call = new Call(e, new ExprList()); call->parenArgs->add(new Unpack(nameRef.ptr())); converted->parenArgs->add(call.ptr()); } else { ExprPtr e = operator_expr_packMultiValuedFreeVar(); CallPtr call = new Call(e, new ExprList()); call->parenArgs->add(new Unpack(nameRef.ptr())); converted->parenArgs->add(call.ptr()); } break; } default : assert(false); } ExprPtr fieldType = new ObjectExpr(type.ptr()); RecordFieldPtr field = new RecordField(ident, fieldType); fields.push_back(field); } r->body = new RecordBody(fields); TypePtr t = recordType(r, vector<ObjectPtr>()); x->lambdaType = t; ExprPtr typeExpr = new ObjectExpr(t.ptr()); converted->expr = typeExpr; x->converted = converted.ptr(); CodePtr code = new Code(); code->location = x->location; IdentifierPtr closureDataIdent = new Identifier(closureDataName); FormalArgPtr closureDataArg = new FormalArg(closureDataIdent, typeExpr); code->formalArgs.push_back(closureDataArg.ptr()); for (unsigned i = 0; i < x->formalArgs.size(); ++i) { code->formalArgs.push_back(x->formalArgs[i]); } if (x->formalVarArg.ptr()) { code->formalVarArg = x->formalVarArg; } code->body = x->body; OverloadPtr overload = new Overload( operator_expr_call(), code, false, false ); overload->env = env; overload->location = x->location; ObjectPtr obj = operator_call(); if (obj->objKind != PROCEDURE) error("'call' operator not found!"); Procedure *callObj = (Procedure *)obj.ptr(); callObj->overloads.insert(callObj->overloads.begin(), overload); }
Symbol* genAssignement(FILE* yyout, SymbolInfo* leftSide, Symbol* rightSide, int insideIfLoop) { ExtraInfo* rightInfo = (ExtraInfo*)(rightSide->info); Variable* leftInfo = (Variable*)(leftSide->varSymbol->info); int i, arraySize, elementSize; if( rightInfo->assignmentType == TYPE_ARRAY || leftSide->info == TYPE_ARRAY ){ arraySize = ((Type*)(leftInfo->type->info))->arrayInfo->nElements; elementSize = ((Type*)(((Type*)(leftInfo->type->info))->arrayInfo->type->info))->size; } int isFloat_ = isFloat(leftSide->varSymbol); cstr regStr = getRegStr( isFloat_ ); int height = returnVariableHeight( leftSide->varSymbol->symType, leftSide->varSymbol->name ); //Left side is a global variable if (leftSide->varSymbol->symType == SYM_GLOBAL){ //Aquí no afecta el derramado porque la asignacion se hace directamente a memoria. //var = Array / Class if( rightInfo->assignmentType == LOAD_ADDRESS ){ //FIXME Aqui deberiamos cargar la direccion de la variable, para arrays y clases }else{ //Right side is Array.new if( rightInfo->assignmentType == TYPE_ARRAY ){ for( i = 0; i < arraySize; i++ ){ fprintf(yyout,"\t%c(0x%x + %d) = %s%d; //Initializing %s array",pointerType(leftSide->varSymbol), leftInfo->address, elementSize*i, regStr, rightInfo->nRegister, leftSide->varSymbol->name); } }else{ //Assignement $var[expression] = expression if( leftSide->info == TYPE_ARRAY ){ int reg = ((ExtraInfo*)(leftSide->exprSymbol->info))->nRegister; fprintf(yyout, "\tR%d = R%d * %d; //Calculate array %s position\n",reg, reg, elementSize, leftSide->varSymbol->name); fprintf(yyout,"\t%c(0x%x + R%d) = %s%d; //%s[expr] = expr\n",pointerType(leftSide->varSymbol), leftInfo->address, reg, regStr, rightInfo->nRegister, leftSide->varSymbol->name ); freeRegister( reg, 0 ); freeSymbol(leftSide->exprSymbol); //Assignement $var = expression }else{ fprintf(yyout,"\t%c(0x%x) = %s%d; //%s = expr\n",pointerType(leftSide->varSymbol), leftInfo->address, regStr, rightInfo->nRegister, leftSide->varSymbol->name, isFloat_); } } } //Left side not a global varialbe }else if (leftSide->varSymbol->symType == SYM_VARIABLE){ //Obtenemos la direccion con el desplazamiento y almacenamos if( rightInfo->assignmentType == LOAD_ADDRESS ){ //FIXME Aqui deberiamos cargar la direccion de la variable, para arrays y clases }else{ int accessRegister = genFrameAccess( yyout, height, -1, 1 ); //Left side is a local variable if(((Variable*)(leftSide->varSymbol->info))->symSubtype == SYM_LOCAL){ //Right side is Array.new or [e,e,..,e] if( rightInfo->assignmentType == TYPE_ARRAY ){ for( i = 0; i < arraySize; i++ ){ fprintf(yyout,"\t%c(R%d - %d) = %s%d; //Initializing %s array\n",pointerType(leftSide->varSymbol), accessRegister,leftInfo->address - elementSize*i, regStr, rightInfo->nRegister, leftSide->varSymbol->name); } }else{ //Assignement var[expression] = expression if( leftSide->info == TYPE_ARRAY ){ int reg = ((ExtraInfo*)(leftSide->exprSymbol->info))->nRegister; fprintf(yyout, "\tR%d = R%d * %d; //Calculate array %s position\n",reg, reg, elementSize, leftSide->varSymbol->name); fprintf(yyout, "\tR%d = R%d - %d; //Calculate local %s position\n",reg, reg, leftInfo->address, leftSide->varSymbol->name); fprintf(yyout,"\t%c(R%d + R%d) = %s%d; //%s[expr] = expr (2)\n",pointerType(leftSide->varSymbol), accessRegister, reg, regStr, rightInfo->nRegister, leftSide->varSymbol->name); freeRegister( reg, 0 ); freeSymbol(leftSide->exprSymbol); //Assignement var = expression }else{ fprintf(yyout,"\t%c(R%d - %d) = %s%d; //%s = expr\n",pointerType(leftSide->varSymbol), accessRegister, leftInfo->address, regStr, rightInfo->nRegister, leftSide->varSymbol->name); } } } //Left side is an argument variable else{ //Right side is Array.new or [e,e,..,e] if( rightInfo->assignmentType == TYPE_ARRAY ){ for( i = 0; i < arraySize; i++ ){ fprintf(yyout,"\t%c(R%d + %d) = %s%d; //Initializing %s array\n",pointerType(leftSide->varSymbol), accessRegister, leftInfo->address + elementSize*i, regStr, rightInfo->nRegister, leftSide->varSymbol->name); } }else{ //Assignement var[expression] = expression if( leftSide->info == TYPE_ARRAY ){ int reg = ((ExtraInfo*)(leftSide->exprSymbol->info))->nRegister; fprintf(yyout, "\tR%d = R%d * %d; //Calculate array %s position\n",reg, reg, elementSize, leftSide->varSymbol->name); fprintf(yyout, "\tR%d = R%d - %d; //Calculate local %s position\n",reg, reg, leftInfo->address, leftSide->varSymbol->name); fprintf(yyout,"\t%c(R%d - R%d) = %s%d; //%s[expr] = expr\n",pointerType(leftSide->varSymbol), accessRegister, reg, regStr, rightInfo->nRegister, leftSide->varSymbol->name); freeRegister( reg, 0 ); freeSymbol(leftSide->exprSymbol); //Assignement var = expression }else{ fprintf(yyout,"\t%c(R%d + %d) = %s%d; //%s = expr\n",pointerType(leftSide->varSymbol), accessRegister, leftInfo->address, regStr, rightInfo->nRegister, leftSide->varSymbol->name); } } } if( accessRegister != 6 ){ freeRegister( accessRegister, 0 ); } } } if(!insideIfLoop){ int reg = rightInfo->nRegister; Method* method = getCurrentScope(); if(method->returnType){ int size = method->argumentsSize; if(!isFloat(method->returnType) && !isFloat_){ fprintf(yyout,"\t%c(R6 + %d) = R%d; //Store return value\n", pointerType(method->returnType), size, reg); }else{ if(isFloat(method->returnType) && isFloat_){ fprintf(yyout,"\t%c(R6 + %d) = RR%d; //Store return value\n", pointerType(method->returnType), size, reg); } } } } freeRegister( rightInfo->nRegister, isFloat_ ); freeSymbolInfo(leftSide); return rightSide; }