diff --git a/TestSuite/attributes5.pas b/TestSuite/attributes5.pas new file mode 100644 index 000000000..022379f84 --- /dev/null +++ b/TestSuite/attributes5.pas @@ -0,0 +1,17 @@ +uses System; + +type + [AttributeUsage(AttributeTargets.Field or AttributeTargets.Property) ] + myattr = class (Attribute) end; + + TClass = class + [myattr] + a: integer; + + [myattr] + property prop: integer read a; + + end; + +begin +end. \ No newline at end of file diff --git a/TestSuite/errors/err0518_attributes.pas b/TestSuite/errors/err0518_attributes.pas new file mode 100644 index 000000000..ebe30ec9d --- /dev/null +++ b/TestSuite/errors/err0518_attributes.pas @@ -0,0 +1,23 @@ +//!Атрибут myattr неприменим к методам +uses System; + +type + [AttributeUsage(AttributeTargets.Field or AttributeTargets.Property) ] + myattr = class (Attribute) end; + + TClass = class + [myattr] + a: integer; + + [myattr] + property prop: integer read a; + + [myattr] + procedure Test; + begin + + end; + end; + +begin +end. diff --git a/TreeConverter/SystemLib/static_executors.cs b/TreeConverter/SystemLib/static_executors.cs index 711f2ce1a..5ec026e62 100644 --- a/TreeConverter/SystemLib/static_executors.cs +++ b/TreeConverter/SystemLib/static_executors.cs @@ -5019,6 +5019,75 @@ namespace PascalABCCompiler.SystemLibrary return new string_const_node(left.constant_value.ToString() + right.constant_value.ToString(), call_location); } + public static expression_node enum_or_executor(location call_location, params expression_node[] parameters) + { + enum_const_node left = parameters[0] as enum_const_node; + if (left == null && parameters[0] is static_compiled_variable_reference) + { + static_compiled_variable_reference cvr = parameters[0] as static_compiled_variable_reference; + if (cvr.var.IsLiteral) + left = new enum_const_node((int)cvr.var.compiled_field.GetRawConstantValue(), parameters[0].type, parameters[0].location); + } + if (left == null) + return null; + enum_const_node right = parameters[1] as enum_const_node; + if (right == null && parameters[1] is static_compiled_variable_reference) + { + static_compiled_variable_reference cvr = parameters[1] as static_compiled_variable_reference; + if (cvr.var.IsLiteral) + right = new enum_const_node((int)cvr.var.compiled_field.GetRawConstantValue(), parameters[1].type, parameters[1].location); + } + if (right == null) + return null; + + return new enum_const_node(left.constant_value | right.constant_value, left.type, call_location); + } + + public static expression_node enum_and_executor(location call_location, params expression_node[] parameters) + { + enum_const_node left = parameters[0] as enum_const_node; + if (left == null && parameters[0] is static_compiled_variable_reference) + { + static_compiled_variable_reference cvr = parameters[0] as static_compiled_variable_reference; + if (cvr.var.IsLiteral) + left = new enum_const_node((int)cvr.var.compiled_field.GetRawConstantValue(), parameters[0].type, parameters[0].location); + } + if (left == null) + return null; + enum_const_node right = parameters[1] as enum_const_node; + if (right == null && parameters[1] is static_compiled_variable_reference) + { + static_compiled_variable_reference cvr = parameters[1] as static_compiled_variable_reference; + if (cvr.var.IsLiteral) + right = new enum_const_node((int)cvr.var.compiled_field.GetRawConstantValue(), parameters[1].type, parameters[1].location); + } + if (right == null) + return null; + return new enum_const_node(left.constant_value & right.constant_value, left.type, call_location); + } + + public static expression_node enum_xor_executor(location call_location, params expression_node[] parameters) + { + enum_const_node left = parameters[0] as enum_const_node; + if (left == null && parameters[0] is static_compiled_variable_reference) + { + static_compiled_variable_reference cvr = parameters[0] as static_compiled_variable_reference; + if (cvr.var.IsLiteral) + left = new enum_const_node((int)cvr.var.compiled_field.GetRawConstantValue(), parameters[0].type, parameters[0].location); + } + if (left == null) + return null; + enum_const_node right = parameters[1] as enum_const_node; + if (right == null && parameters[1] is static_compiled_variable_reference) + { + static_compiled_variable_reference cvr = parameters[1] as static_compiled_variable_reference; + if (cvr.var.IsLiteral) + right = new enum_const_node((int)cvr.var.compiled_field.GetRawConstantValue(), parameters[1].type, parameters[1].location); + } + if (right == null) + return null; + return new enum_const_node(left.constant_value ^ right.constant_value, left.type, call_location); + } } } diff --git a/TreeConverter/TreeConversion/syntax_tree_visitor.cs b/TreeConverter/TreeConversion/syntax_tree_visitor.cs index 8f15ebdae..343662df7 100644 --- a/TreeConverter/TreeConversion/syntax_tree_visitor.cs +++ b/TreeConverter/TreeConversion/syntax_tree_visitor.cs @@ -12496,6 +12496,8 @@ namespace PascalABCCompiler.TreeConverter for (int i = 0; i < cnstr_args.expressions.Count; i++) { constant_node cn = convert_strong_to_constant_node(cnstr_args.expressions[i]); + if (cn is basic_function_call_as_constant && (cn as basic_function_call_as_constant).method_call.function_node.compile_time_executor != null) + cn = (cn as basic_function_call_as_constant).method_call.function_node.compile_time_executor(cn.location, (cn as basic_function_call_as_constant).method_call.parameters.ToArray()) as constant_node; check_for_strong_constant(cn, get_location(cnstr_args.expressions[i])); args.AddElement(cn); } diff --git a/TreeConverter/TreeRealization/types.cs b/TreeConverter/TreeRealization/types.cs index 252eb2fbb..73f227261 100644 --- a/TreeConverter/TreeRealization/types.cs +++ b/TreeConverter/TreeRealization/types.cs @@ -3340,8 +3340,11 @@ namespace PascalABCCompiler.TreeRealization { if (ctn.compiled_type.GetCustomAttributes(typeof(FlagsAttribute), true).Length == 0) return; basic_function_node _int_and = SystemLibrary.SystemLibrary.make_binary_operator(compiler_string_consts.and_name, ctn, SemanticTree.basic_function_type.iand); + _int_and.compile_time_executor = SystemLibrary.static_executors.enum_and_executor; basic_function_node _int_or = SystemLibrary.SystemLibrary.make_binary_operator(compiler_string_consts.or_name, ctn, SemanticTree.basic_function_type.ior); + _int_or.compile_time_executor = SystemLibrary.static_executors.enum_or_executor; basic_function_node _int_xor = SystemLibrary.SystemLibrary.make_binary_operator(compiler_string_consts.xor_name, ctn, SemanticTree.basic_function_type.ixor); + _int_xor.compile_time_executor = SystemLibrary.static_executors.enum_xor_executor; if (ctn.scope != null) { ctn.scope.AddSymbol(compiler_string_consts.and_name, new SymbolInfo(_int_and));