예제 #1
0
	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;
			}
		}
	}
예제 #2
0
	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;
			}
		}
	}
예제 #3
0
	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;
	}