// Note: Callgrind sometimes gives different IDs for same file // (when references to same source file come from different ELF objects) TraceFile* CachegrindLoader::compressedFile(const QString& name) { if ((name[0] != '(') || !name[1].isDigit()) return _data->file(checkUnknown(name)); // compressed format using _fileVector int p = name.indexOf(')'); if (p<2) { error(QStringLiteral("Invalid compressed file ('%1')").arg(name)); return 0; } int index = name.midRef(1, p-1).toUInt(); TraceFile* f = 0; p++; while((name.length()>p) && name.at(p).isSpace()) p++; if (name.length()>p) { if (_fileVector.size() <= index) { int newSize = index * 2; #if TRACE_LOADER qDebug() << " CachegrindLoader::fileVector enlarged to " << newSize; #endif _fileVector.resize(newSize); } QString realName = checkUnknown(name.mid(p)); f = (TraceFile*) _fileVector.at(index); if (f && (f->name() != realName)) { error(QStringLiteral("Redefinition of compressed file index %1 (was '%2') to %3") .arg(index).arg(f->name()).arg(realName)); } f = _data->file(realName); _fileVector.replace(index, f); } else { if ((_fileVector.size() <= index) || ( (f=(TraceFile*)_fileVector.at(index)) == 0)) { error(QStringLiteral("Undefined compressed file index %1").arg(index)); return 0; } } return f; }
TraceObject* CachegrindLoader::compressedObject(const QString& name) { if ((name[0] != '(') || !name[1].isDigit()) return _data->object(checkUnknown(name)); // compressed format using _objectVector int p = name.indexOf(')'); if (p<2) { error(QStringLiteral("Invalid compressed ELF object ('%1')").arg(name)); return 0; } int index = name.midRef(1, p-1).toInt(); TraceObject* o = 0; p++; while((name.length()>p) && name.at(p).isSpace()) p++; if (name.length()>p) { if (_objectVector.size() <= index) { int newSize = index * 2; #if TRACE_LOADER qDebug() << " CachegrindLoader: objectVector enlarged to " << newSize; #endif _objectVector.resize(newSize); } QString realName = checkUnknown(name.mid(p)); o = (TraceObject*) _objectVector.at(index); if (o && (o->name() != realName)) { error(QStringLiteral("Redefinition of compressed ELF object index %1 (was '%2') to %3") .arg(index).arg(o->name()).arg(realName)); } o = _data->object(realName); _objectVector.replace(index, o); } else { if ((_objectVector.size() <= index) || ( (o=(TraceObject*)_objectVector.at(index)) == 0)) { error(QStringLiteral("Undefined compressed ELF object index %1").arg(index)); return 0; } } return o; }
void SymbolCheckVisitor::visit(ASTLocalVariable& ast) { ASTVariable& var = ast.getVariable(); checkUnknown(var.getType()); checkVarInit(var); mpFunction->addLocal(var.getType().clone()); ScopeVariable* pvariable = ScopeVariable::fromVariable(ast.getVariable()); mScopeStack.add(pvariable); }
void SymbolCheckVisitor::checkReturn(const ASTFunction& function) { checkUnknown(function.getType()); if ( !function.getType().isVoid() ) { // ensure that we have a return statement bool hasunreachablecode = false; if ( !function.getBody().hasReturn(hasunreachablecode) ) { error(E0045, UTEXT("Function ") + function.getName() + UTEXT(" should return a value of type ") + function.getType().toString(), function.getPosition()); } else if ( hasunreachablecode ) { warning(W0003, UTEXT("Unreachable code in ") + function.getName(), function.getPosition()); } } }
void SymbolCheckVisitor::visit(ASTInstanceOf& ast) { mCurrentType.clear(); checkUnknown(ast.getInstanceType()); ast.getObject().accept(*this); if ( !(mCurrentType.isObject() || mCurrentType.isArray()) ) { error(E0027, UTEXT("Operator instanceof can only be called against objects/arrays."), ast); } else if ( !mCurrentType.isDerivedFrom(ast.getInstanceType()) ) { error(E0028, UTEXT("Instanceof operator can never be true for ") + mCurrentType.toString() + UTEXT(" and ") + ast.getInstanceType().toString(), ast); } mCurrentType = ASTType(ASTType::eBoolean); }
// Note: Callgrind gives different IDs even for same function // when parts of the function are from different source files. // Thus, it is no error when multiple indexes map to same function. TraceFunction* CachegrindLoader::compressedFunction(const QString& name, TraceFile* file, TraceObject* object) { if ((name[0] != '(') || !name[1].isDigit()) return _data->function(checkUnknown(name), file, object); // compressed format using _functionVector int p = name.indexOf(')'); if (p<2) { error(QStringLiteral("Invalid compressed function ('%1')").arg(name)); return 0; } int index = name.midRef(1, p-1).toUInt(); TraceFunction* f = 0; p++; while((name.length()>p) && name.at(p).isSpace()) p++; if (name.length()>p) { if (_functionVector.size() <= index) { int newSize = index * 2; #if TRACE_LOADER qDebug() << " CachegrindLoader::functionVector enlarged to " << newSize; #endif _functionVector.resize(newSize); } QString realName = checkUnknown(name.mid(p)); f = (TraceFunction*) _functionVector.at(index); if (f && (f->name() != realName)) { error(QStringLiteral("Redefinition of compressed function index %1 (was '%2') to %3") .arg(index).arg(f->name()).arg(realName)); } f = _data->function(realName, file, object); _functionVector.replace(index, f); #if TRACE_LOADER qDebug() << "compressedFunction: Inserted at Index " << index << "\n " << f->fullName() << "\n in " << f->cls()->fullName() << "\n in " << f->file()->fullName() << "\n in " << f->object()->fullName(); #endif } else { if ((_functionVector.size() <= index) || ( (f=(TraceFunction*)_functionVector.at(index)) == 0)) { error(QStringLiteral("Undefined compressed function index %1").arg(index)); return 0; } // there was a check if the used function (returned from KCachegrinds // model) has the same object and file as here given to us, but that was wrong: // that holds only if we make this assumption on the model... } return f; }
void SymbolCheckVisitor::visit(ASTNew& ast) { switch ( ast.getKind() ) { case ASTNew::eObject: { ASTType before = mCurrentType; ASTSignature signature; ASTNodes& arguments = ast.getArguments(); for ( int index = 0; index < arguments.size(); index++ ) { ASTExpression& expr = dynamic_cast<ASTExpression&>(arguments[index]); expr.accept(*this); signature.append(mCurrentType.clone()); } checkUnknown(ast.getType()); if ( ast.getType().hasObjectClass() ) { const ASTClass& newclass = ast.getType().getObjectClass(); const ASTFunction* pfunction = newclass.findBestMatch(newclass.getName(), signature, before.getTypeArguments()); if ( pfunction == NULL ) { String arguments = UTEXT("(") + signature.toString() + ')'; error(E0029, UTEXT("No matching constructor ") + newclass.getFullName() + arguments + UTEXT(" defined."), ast); } else { ast.setConstructor(*pfunction); } } mCurrentType = ast.getType(); } break; case ASTNew::eArray: { ASTNodes& arguments = ast.getArguments(); for ( int index = 0; index < arguments.size(); index++ ) { ASTExpression& expr = dynamic_cast<ASTExpression&>(arguments[index]); expr.accept(*this); if ( !mCurrentType.isInt() ) { error(E0030, UTEXT("Array size expression should be of type int."), ast); } } mCurrentType = ast.getType(); } break; case ASTNew::eInvalid: error(E0001, UTEXT("Invalid compiler state!"), ast); break; } }
void SymbolCheckVisitor::visit(ASTProperty& ast) { checkUnknown(ast.getType()); }
void SymbolCheckVisitor::visit(ASTField& ast) { ASTVariable& var = ast.getVariable(); checkUnknown(var.getType()); checkVarInit(var); }