void ClassCheck::checkInterfaceVars( const ClassDefPtr& pClassDef, const InterfaceDefPtr& pInterfaceDef, const StaticContextPtr& pRootCtx, const LogPtr& pLog) const { const list<VariableDeclDefPtr>& classVars = pClassDef->getVariableDecls(); const list<VariableDeclDefPtr>& ifaceVars = pInterfaceDef->getVariableDecls(); map<const wstring, VariableDeclDefPtr> classVarsMap; map<const wstring, VariableDeclDefPtr>::const_iterator mit; list<VariableDeclDefPtr>::const_iterator cit; for (cit = classVars.begin(); cit != classVars.end(); cit++) { const VariableDeclDefPtr& pVariableDecl = *cit; classVarsMap[pVariableDecl->getName()] = pVariableDecl; } list<VariableDeclDefPtr>::const_iterator iit; for (iit = ifaceVars.begin(); iit != ifaceVars.end(); iit++) { const VariableDeclDefPtr& pIfaceVariableDecl = *iit; const wstring& variableName = pIfaceVariableDecl->getName(); if ((mit = classVarsMap.find(variableName)) == classVarsMap.end()) { boost::wformat f(L"Variable %1% defined on interface %2% not found in class."); f % variableName % pInterfaceDef->getClassName(); pLog->log(*pClassDef, msg::ErrAnaClassDef_MissingIfaceVar, f.str()); continue; } const VariableDeclDefPtr& pClassVariableDecl = (*mit).second; if (pIfaceVariableDecl->isStatic() != pClassVariableDecl->isStatic()) { boost::wformat f(L"Variable %1% has invalid scope. See interface %2%"); f % variableName % pInterfaceDef->getClassName(); pLog->log(*pClassVariableDecl, msg::ErrAnaClassDef_IfaceVarWrongScope, f.str()); continue; } if (!SemanticAnalysis::isTypeAssignableFrom( pClassVariableDecl->getDeclaredType(), pIfaceVariableDecl->getDeclaredType(), pRootCtx)) { boost::wformat f(L"Can't convert from %1% to %2% at class variable %3% defined on interface %4%"); f % pIfaceVariableDecl->getDeclaredType()->toString()% pClassVariableDecl->getDeclaredType()->toString() % variableName % pInterfaceDef->getClassName(); pLog->log(*pClassVariableDecl, msg::ErrAnaClassDef_IfaceVarIncompTypes, f.str()); continue; } } }
void ClassCheck::doCheck( const StaticContextPtr& pRootCtx, const ASTNodePtr& pNode, const LogPtr& pLog) const { if (pNode->getASTNodeType() != ASTN_CLASS) { return; } ClassDefPtr pClassDef = boost::static_pointer_cast<ClassDef>(pNode); const list<const wstring>& ifaces = pClassDef->getImplementedInterfaces(); list<const wstring>::const_iterator it; for (it = ifaces.begin(); it != ifaces.end(); it++) { const wstring& ifaceName = *it; CStaticContextEntryPtr pEntry; InterfaceDefPtr pInterfaceDef; if (!pRootCtx->lookup(ifaceName, pEntry)) { boost::wformat f(L"Interface %1% not found."); f % ifaceName; pLog->log(*pClassDef, msg::ErrAnaClassDef_IfaceNotFound, f.str()); continue; } else if (!pEntry->getInterface(pInterfaceDef)) { boost::wformat f(L"%1% is not an interface."); f % ifaceName; pLog->log(*pClassDef, msg::ErrAnaClassDef_NotAnIface, f.str()); continue; } checkInterfaceParams(pClassDef, pInterfaceDef, pRootCtx, pLog); checkInterfaceVars(pClassDef, pInterfaceDef, pRootCtx, pLog); } const list<VariableDeclDefPtr>& vars = pClassDef->getVariableDecls(); list<VariableDeclDefPtr>::const_iterator vit; for (vit = vars.begin(); vit != vars.end(); vit++) { const VariableDeclDefPtr& pVar = *vit; if (pVar->getValue().get() == NULL) { boost::wformat f(L"Unassigned class variable %1%."); f % pVar->getName(); pLog->log(*pClassDef, msg::ErrAnaClassDef_UnassignedClassVar, f.str()); continue; } } }
bool TypeInference::followPathElement( const Type& currentType, const StaticContext& rootCtx, const wstring& pathElement, TypePtr& pNextType) { boolean isObject = false; switch (currentType.getBasicType()) { case FLOAT_B_TYPE: case INTEGER_B_TYPE: case STRING_B_TYPE: case ARRAY_B_TYPE: { return false; } case OBJECT_B_TYPE: case CLASS_B_TYPE: { const ReferenceType& refType = static_cast<const ReferenceType&>(currentType); const wstring& className = refType.getReferenceTypeName(); CStaticContextEntryPtr pEntry; if (!rootCtx.lookup(className, pEntry)) { return false; } list<VariableDeclDefPtr> varsDecls; if (pEntry->getStaticEntryType() == CLASS_DEF_CTX_ENTRY) { ClassDefPtr pClassDefEntry; pEntry->getClass(pClassDefEntry); varsDecls = pClassDefEntry->getVariableDecls(); } else if (pEntry->getStaticEntryType() == INTERFACE_DEF_CTX_ENTRY) { InterfaceDefPtr pInterfaceDefEntry; pEntry->getInterface(pInterfaceDefEntry); varsDecls = pInterfaceDefEntry->getVariableDecls(); } else { return false; } bool isObject = (refType.getBasicType() == OBJECT_REF_TYPE); list<VariableDeclDefPtr>::const_iterator it; for (it = varsDecls.begin(); it != varsDecls.end(); it++) { VariableDeclDefPtr varDecl = *it; if (varDecl->getName() == pathElement) { if (isObject && varDecl->isStatic()) { return false; } else if (!isObject && !varDecl->isStatic()) { return false; } pNextType = varDecl->getDeclaredType(); return true; } } } break; default: assert(false); } return false; }