Typer extends ScopeTrackingVisitor { @Override public void visitMemberLookupExpr(MemberLookupExpr memberLookupExpr) { super.visitMemberLookupExpr(memberLookupExpr); final Type structureType = lookupType(memberLookupExpr.getStructure()); assert structureType != null; if (BasicType.allVectorTypes().contains(structureType.getWithoutQualifiers())) { BasicType vecType = (BasicType) structureType.getWithoutQualifiers(); for (int i = 0; i < memberLookupExpr.getMember().length(); i++) { assert ("xyzw" + "rgba" + "stpq") .contains(String.valueOf(memberLookupExpr.getMember().charAt(i))); } types.put(memberLookupExpr, BasicType .makeVectorType(vecType.getElementType(), memberLookupExpr.getMember().length())); } if (structureType.getWithoutQualifiers() instanceof StructNameType) { types.put(memberLookupExpr, structDeclarationMap.get(structureType.getWithoutQualifiers()) .getFieldType(memberLookupExpr.getMember())); } if (structureType.getWithoutQualifiers() instanceof StructDefinitionType) { types.put(memberLookupExpr, ((StructDefinitionType) structureType.getWithoutQualifiers()) .getFieldType(memberLookupExpr.getMember())); } if (structureType.getWithoutQualifiers() instanceof BasicType) { BasicType vecType = (BasicType) structureType.getWithoutQualifiers(); for (int i = 0; i < memberLookupExpr.getMember().length(); i++) { assert ("xyzw" + "rgba" + "stpq") .contains(String.valueOf(memberLookupExpr.getMember().charAt(i))); } final BasicType v = BasicType.makeVectorType(vecType.getElementType(), memberLookupExpr.getMember().length()); types.put(memberLookupExpr, v); } } Typer(TranslationUnit tu); @Override void visitParenExpr(ParenExpr parenExpr); @Override void visitFunctionPrototype(FunctionPrototype functionPrototype); @Override void visitFunctionDefinition(FunctionDefinition functionDefinition); @Override void visitFunctionCallExpr(FunctionCallExpr functionCallExpr); boolean prototypeMatches(FunctionPrototype prototype, FunctionCallExpr functionCallExpr); @Override void visitVariableIdentifierExpr(VariableIdentifierExpr variableIdentifierExpr); @Override void visitTypeConstructorExpr(TypeConstructorExpr typeConstructorExpr); @Override void visitUnaryExpr(UnaryExpr unaryExpr); @Override void visitTernaryExpr(TernaryExpr ternaryExpr); @Override void visitBinaryExpr(BinaryExpr binaryExpr); @Override void visitBoolConstantExpr(BoolConstantExpr boolConstantExpr); @Override void visitIntConstantExpr(IntConstantExpr intConstantExpr); @Override void visitUIntConstantExpr(UIntConstantExpr uintConstantExpr); @Override void visitFloatConstantExpr(FloatConstantExpr floatConstantExpr); @Override void visitMemberLookupExpr(MemberLookupExpr memberLookupExpr); @Override void visitArrayConstructorExpr(ArrayConstructorExpr arrayConstructorExpr); Type lookupType(Expr expr); boolean hasType(Expr expr); Set<FunctionPrototype> getPrototypes(String name); @Override void visitStructDefinitionType(StructDefinitionType structDefinitionType); @Override void visitArrayIndexExpr(ArrayIndexExpr arrayIndexExpr); @Override void visitInterfaceBlock(InterfaceBlock interfaceBlock); static Optional<Type> maybeGetTypeOfBuiltinVariable(String name); static ImmutablePair<Type, ArrayInfo> getBaseTypeArrayInfo(Type type); static Type combineBaseTypeAndArrayInfo(Type type, ArrayInfo arrayInfo);  }
@Test public void visitMemberLookupExpr() throws Exception { String prog = "#version 100\n" + "struct S { float a; float b; };\n" + "struct T { S s; float c; };\n" + "void main() {\n" + " T myT = T(S(1.0, 2.0), 3.0);\n" + " myT.s.a = myT.c;\n" + "}"; TranslationUnit tu = ParseHelper.parse(prog); int actualCount = new NullCheckTyper(tu) { private int count; private int getCount() { return count; } @Override public void visitMemberLookupExpr(MemberLookupExpr memberLookupExpr) { super.visitMemberLookupExpr(memberLookupExpr); assertNotNull(lookupType(memberLookupExpr)); count++; } }.getCount(); assertEquals(3, actualCount); }