[llvm-branch-commits] [cfe-branch] r111418 [1/2] - in /cfe/branches/Apple/williamson: include/clang/Basic/DiagnosticSemaKinds.td.orig include/clang/Driver/CC1Options.td.orig lib/Analysis/CFG.cpp.orig lib/Basic/Targets.cpp.orig lib/Checker/AnalysisConsumer.cpp.orig lib/Checker/GRExprEngine.cpp.orig lib/CodeGen/CGObjCMac.cpp.orig lib/Frontend/CompilerInvocation.cpp.orig lib/Sema/SemaExpr.cpp.orig
Daniel Dunbar
daniel at zuster.org
Wed Aug 18 13:34:30 PDT 2010
Author: ddunbar
Date: Wed Aug 18 15:34:30 2010
New Revision: 111418
URL: http://llvm.org/viewvc/llvm-project?rev=111418&view=rev
Log:
Remove stray merge files.
Removed:
cfe/branches/Apple/williamson/include/clang/Basic/DiagnosticSemaKinds.td.orig
cfe/branches/Apple/williamson/include/clang/Driver/CC1Options.td.orig
cfe/branches/Apple/williamson/lib/Analysis/CFG.cpp.orig
cfe/branches/Apple/williamson/lib/Basic/Targets.cpp.orig
cfe/branches/Apple/williamson/lib/Checker/AnalysisConsumer.cpp.orig
cfe/branches/Apple/williamson/lib/Checker/GRExprEngine.cpp.orig
cfe/branches/Apple/williamson/lib/CodeGen/CGObjCMac.cpp.orig
cfe/branches/Apple/williamson/lib/Frontend/CompilerInvocation.cpp.orig
cfe/branches/Apple/williamson/lib/Sema/SemaExpr.cpp.orig
Removed: cfe/branches/Apple/williamson/include/clang/Basic/DiagnosticSemaKinds.td.orig
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/williamson/include/clang/Basic/DiagnosticSemaKinds.td.orig?rev=111417&view=auto
==============================================================================
--- cfe/branches/Apple/williamson/include/clang/Basic/DiagnosticSemaKinds.td.orig (original)
+++ cfe/branches/Apple/williamson/include/clang/Basic/DiagnosticSemaKinds.td.orig (removed)
@@ -1,3242 +0,0 @@
-//==--- DiagnosticSemaKinds.td - libsema diagnostics ----------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-//===----------------------------------------------------------------------===//
-// Semantic Analysis
-//===----------------------------------------------------------------------===//
-
-let Component = "Sema" in {
-let CategoryName = "Semantic Issue" in {
-
-// Constant expressions
-def err_expr_not_ice : Error<
- "expression is not an integer constant expression">;
-def ext_expr_not_ice : Extension<
- "expression is not integer constant expression "
- "(but is allowed as an extension)">;
-
-// Semantic analysis of constant literals.
-def ext_predef_outside_function : Warning<
- "predefined identifier is only valid inside function">;
-def warn_float_overflow : Warning<
- "magnitude of floating-point constant too large for type %0; maximum is %1">,
- InGroup<LiteralRange>;
-def warn_float_underflow : Warning<
- "magnitude of floating-point constant too small for type %0; minimum is %1">,
- InGroup<LiteralRange>;
-
-// C99 variable-length arrays
-def ext_vla : Extension<
- "variable length arrays are a C99 feature, accepted as an extension">,
- InGroup<VLA>;
-def err_vla_non_pod : Error<"variable length array of non-POD element type %0">;
-def err_vla_in_sfinae : Error<
- "variable length array cannot be formed during template argument deduction">;
-def err_array_star_in_function_definition : Error<
- "variable length array must be bound in function definition">;
-def err_vla_decl_in_file_scope : Error<
- "variable length array declaration not allowed at file scope">;
-def err_vla_decl_has_static_storage : Error<
- "variable length array declaration can not have 'static' storage duration">;
-def err_vla_decl_has_extern_linkage : Error<
- "variable length array declaration can not have 'extern' linkage">;
-
-// C99 variably modified types
-def err_variably_modified_template_arg : Error<
- "variably modified type %0 cannot be used as a template argument">;
-def err_variably_modified_nontype_template_param : Error<
- "non-type template parameter of variably modified type %0">;
-
-// C99 Designated Initializers
-def err_array_designator_negative : Error<
- "array designator value '%0' is negative">;
-def err_array_designator_empty_range : Error<
- "array designator range [%0, %1] is empty">;
-def err_array_designator_non_array : Error<
- "array designator cannot initialize non-array type %0">;
-def err_array_designator_too_large : Error<
- "array designator index (%0) exceeds array bounds (%1)">;
-def err_field_designator_non_aggr : Error<
- "field designator cannot initialize a "
- "%select{non-struct, non-union|non-class}0 type %1">;
-def err_field_designator_unknown : Error<
- "field designator %0 does not refer to any field in type %1">;
-def err_field_designator_nonfield : Error<
- "field designator %0 does not refer to a non-static data member">;
-def note_field_designator_found : Note<"field designator refers here">;
-def err_designator_for_scalar_init : Error<
- "designator in initializer for scalar type %0">;
-def warn_subobject_initializer_overrides : Warning<
- "subobject initialization overrides initialization of other fields "
- "within its enclosing subobject">, InGroup<InitializerOverrides>;
-def warn_initializer_overrides : Warning<
- "initializer overrides prior initialization of this subobject">,
- InGroup<InitializerOverrides>;
-def note_previous_initializer : Note<
- "previous initialization %select{|with side effects }0is here"
- "%select{| (side effects may not occur at run time)}0">;
-def err_designator_into_flexible_array_member : Error<
- "designator into flexible array member subobject">;
-def note_flexible_array_member : Note<
- "initialized flexible array member %0 is here">;
-def ext_flexible_array_init : Extension<
- "flexible array initialization is a GNU extension">, InGroup<GNU>;
-
-// Declarations.
-def ext_anon_param_requires_type_specifier : Extension<
- "type specifier required for unnamed parameter, defaults to int">;
-def err_bad_variable_name : Error<
- "'%0' cannot be the name of a variable or data member">;
-def err_parameter_name_omitted : Error<"parameter name omitted">;
-def warn_unused_parameter : Warning<"unused parameter %0">,
- InGroup<UnusedParameter>, DefaultIgnore;
-def warn_unused_variable : Warning<"unused variable %0">,
- InGroup<UnusedVariable>, DefaultIgnore;
-def warn_unused_exception_param : Warning<"unused exception parameter %0">,
- InGroup<UnusedExceptionParameter>, DefaultIgnore;
-def warn_decl_in_param_list : Warning<
- "declaration of %0 will not be visible outside of this function">;
-def warn_unused_function : Warning<"unused function %0">,
- InGroup<UnusedFunction>, DefaultIgnore;
-
-def warn_implicit_function_decl : Warning<
- "implicit declaration of function %0">,
- InGroup<ImplicitFunctionDeclare>, DefaultIgnore;
-def ext_implicit_function_decl : ExtWarn<
- "implicit declaration of function %0 is invalid in C99">,
- InGroup<ImplicitFunctionDeclare>;
-
-def err_ellipsis_first_arg : Error<
- "ISO C requires a named argument before '...'">;
-def err_declarator_need_ident : Error<"declarator requires an identifier">;
-def err_bad_language : Error<"unknown linkage language">;
-def warn_use_out_of_scope_declaration : Warning<
- "use of out-of-scope declaration of %0">;
-def err_inline_non_function : Error<
- "'inline' can only appear on functions">;
-def warn_qual_return_type : Warning<
- "'%0' type qualifier%s1 on return type %plural{1:has|:have}1 no effect">,
- InGroup<IgnoredQualifiers>, DefaultIgnore;
-
-def warn_decl_shadow :
- Warning<"declaration shadows a %select{"
- "local variable|"
- "variable in %2|"
- "static data member of %2|"
- "field of %2}1">,
- InGroup<Shadow>, DefaultIgnore;
-
-// C++ using declarations
-def err_using_requires_qualname : Error<
- "using declaration requires a qualified name">;
-def err_using_typename_non_type : Error<
- "'typename' keyword used on a non-type">;
-def err_using_dependent_value_is_type : Error<
- "dependent using declaration resolved to type without 'typename'">;
-def err_using_decl_nested_name_specifier_is_not_class : Error<
- "using declaration in class refers into '%0', which is not a class">;
-def err_using_decl_nested_name_specifier_is_current_class : Error<
- "using declaration refers to its own class">;
-def err_using_decl_nested_name_specifier_is_not_base_class : Error<
- "using declaration refers into '%0', which is not a base class of %1">;
-def err_using_decl_can_not_refer_to_class_member : Error<
- "using declaration can not refer to class member">;
-def err_using_decl_can_not_refer_to_namespace : Error<
- "using declaration can not refer to namespace">;
-def err_using_decl_constructor : Error<
- "using declaration can not refer to a constructor">;
-def err_using_decl_destructor : Error<
- "using declaration can not refer to a destructor">;
-def err_using_decl_template_id : Error<
- "using declaration can not refer to a template specialization">;
-def note_using_decl_target : Note<"target of using declaration">;
-def note_using_decl_conflict : Note<"conflicting declaration">;
-def err_using_decl_redeclaration : Error<"redeclaration of using decl">;
-def err_using_decl_conflict : Error<
- "target of using declaration conflicts with declaration already in scope">;
-def err_using_decl_conflict_reverse : Error<
- "declaration conflicts with target of using declaration already in scope">;
-def note_using_decl : Note<"%select{|previous }0using declaration">;
-
-def warn_access_decl_deprecated : Warning<
- "access declarations are deprecated; use using declarations instead">,
- InGroup<Deprecated>;
-
-def err_invalid_thread : Error<
- "'__thread' is only allowed on variable declarations">;
-def err_thread_non_global : Error<
- "'__thread' variables must have global storage">;
-def err_thread_unsupported : Error<
- "thread-local storage is unsupported for the current target">;
-
-def warn_maybe_falloff_nonvoid_function : Warning<
- "control may reach end of non-void function">,
- InGroup<ReturnType>;
-def warn_falloff_nonvoid_function : Warning<
- "control reaches end of non-void function">,
- InGroup<ReturnType>;
-def err_maybe_falloff_nonvoid_block : Error<
- "control may reach end of non-void block">;
-def err_falloff_nonvoid_block : Error<
- "control reaches end of non-void block">;
-def warn_suggest_noreturn_function : Warning<
- "function could be attribute 'noreturn'">,
- InGroup<DiagGroup<"missing-noreturn">>, DefaultIgnore;
-def warn_suggest_noreturn_block : Warning<
- "block could be attribute 'noreturn'">,
- InGroup<DiagGroup<"missing-noreturn">>, DefaultIgnore;
-def warn_unreachable : Warning<"will never be executed">,
- InGroup<DiagGroup<"unreachable-code">>, DefaultIgnore;
-
-/// Built-in functions.
-def ext_implicit_lib_function_decl : ExtWarn<
- "implicitly declaring C library function '%0' with type %1">;
-def note_please_include_header : Note<
- "please include the header <%0> or explicitly provide a "
- "declaration for '%1'">;
-def note_previous_builtin_declaration : Note<"%0 is a builtin with type %1">;
-def err_implicit_decl_requires_stdio : Error<
- "implicit declaration of '%0' requires inclusion of the header <stdio.h>">;
-def err_implicit_decl_requires_setjmp : Error<
- "implicit declaration of '%0' requires inclusion of the header <setjmp.h>">;
-def warn_redecl_library_builtin : Warning<
- "incompatible redeclaration of library function %0">;
-def err_builtin_definition : Error<"definition of builtin function %0">;
-def err_types_compatible_p_in_cplusplus : Error<
- "__builtin_types_compatible_p is not valid in C++">;
-def warn_builtin_unknown : Warning<"use of unknown builtin %0">, DefaultError;
-
-/// main()
-// static/inline main() are not errors in C, just in C++.
-def warn_unusual_main_decl : Warning<"'main' should not be declared "
- "%select{static|inline|static or inline}0">;
-def err_unusual_main_decl : Error<"'main' is not allowed to be declared "
- "%select{static|inline|static or inline}0">;
-def err_main_returns_nonint : Error<"'main' must return 'int'">;
-def err_main_surplus_args : Error<"too many parameters (%0) for 'main': "
- "must be 0, 2, or 3">;
-def warn_main_one_arg : Warning<"only one parameter on 'main' declaration">;
-def err_main_arg_wrong : Error<"%select{first|second|third|fourth}0 "
- "parameter of 'main' (%select{argument count|argument array|environment|"
- "platform-specific data}0) must be of type %1">;
-
-/// parser diagnostics
-def ext_typedef_without_a_name : ExtWarn<"typedef requires a name">,
- InGroup<MissingDeclarations>;
-def err_typedef_not_identifier : Error<"typedef name must be an identifier">;
-def err_statically_allocated_object : Error<
- "interface type cannot be statically allocated">;
-def err_object_cannot_be_passed_returned_by_value : Error<
- "interface type %1 cannot be %select{returned|passed}0 by value"
- "; did you forget * in %1">;
-def warn_enum_value_overflow : Warning<"overflow in enumeration value">;
-def warn_pragma_options_align_unsupported_option : Warning<
- "unsupported alignment option in '#pragma options align'">;
-def warn_pragma_options_align_reset_failed : Warning<
- "#pragma options align=reset failed: %0">;
-def err_pragma_options_align_mac68k_target_unsupported : Error<
- "mac68k alignment pragma is not supported on this target">;
-def warn_pragma_pack_invalid_alignment : Warning<
- "expected #pragma pack parameter to be '1', '2', '4', '8', or '16'">;
-// Follow the MSVC implementation.
-def warn_pragma_pack_show : Warning<"value of #pragma pack(show) == %0">;
-def warn_pragma_pack_pop_identifer_and_alignment : Warning<
- "specifying both a name and alignment to 'pop' is undefined">;
-def warn_pragma_pack_pop_failed : Warning<"#pragma pack(pop, ...) failed: %0">;
-
-def warn_pragma_unused_undeclared_var : Warning<
- "undeclared variable %0 used as an argument for '#pragma unused'">;
-def warn_pragma_unused_expected_localvar : Warning<
- "only local variables can be arguments to '#pragma unused'">;
-def err_unsupported_pragma_weak : Error<
- "using '#pragma weak' to refer to an undeclared identifier is not yet supported">;
-
-/// Objective-C parser diagnostics
-def err_duplicate_class_def : Error<
- "duplicate interface definition for class %0">;
-def err_undef_superclass : Error<
- "cannot find interface declaration for %0, superclass of %1">;
-def err_no_nsconstant_string_class : Error<
- "cannot find interface declaration for %0">;
-def err_recursive_superclass : Error<
- "trying to recursively use %0 as superclass of %1">;
-def warn_previous_alias_decl : Warning<"previously declared alias is ignored">;
-def err_conflicting_aliasing_type : Error<"conflicting types for alias %0">;
-def warn_undef_interface : Warning<"cannot find interface declaration for %0">;
-def warn_duplicate_protocol_def : Warning<"duplicate protocol definition of %0 is ignored">;
-def err_protocol_has_circular_dependency : Error<
- "protocol has circular dependency">;
-def err_undeclared_protocol : Error<"cannot find protocol declaration for %0">;
-def warn_undef_protocolref : Warning<"cannot find protocol definition for %0">;
-def warn_readonly_property : Warning<
- "attribute 'readonly' of property %0 restricts attribute "
- "'readwrite' of property inherited from %1">;
-
-def warn_property_attribute : Warning<
- "property %0 '%1' attribute does not match the property inherited from %2">;
-def warn_property_types_are_incompatible : Warning<
- "property type %0 is incompatible with type %1 inherited from %2">;
-def err_undef_interface : Error<"cannot find interface declaration for %0">;
-def err_class_extension_after_impl : Error<
- "cannot declare class extension for %0 after class implementation">;
-def note_implementation_declared : Note<
- "class implementation is declared here">;
-def warn_dup_category_def : Warning<
- "duplicate definition of category %1 on interface %0">;
-def err_conflicting_super_class : Error<"conflicting super class name %0">;
-def err_dup_implementation_class : Error<"reimplementation of class %0">;
-def err_dup_implementation_category : Error<
- "reimplementation of category %1 for class %0">;
-def err_conflicting_ivar_type : Error<
- "instance variable %0 has conflicting type: %1 vs %2">;
-def err_duplicate_ivar_declaration : Error<
- "instance variable is already declared">;
-def warn_on_superclass_use : Warning<
- "class implementation may not have super class">;
-def err_conflicting_ivar_bitwidth : Error<
- "instance variable %0 has conflicting bit-field width">;
-def err_conflicting_ivar_name : Error<
- "conflicting instance variable names: %0 vs %1">;
-def err_inconsistant_ivar_count : Error<
- "inconsistent number of instance variables specified">;
-def warn_incomplete_impl : Warning<"incomplete implementation">;
-def note_undef_method_impl : Note<"method definition for %0 not found">;
-def note_required_for_protocol_at :
- Note<"required for direct or indirect protocol %0">;
-
-def warn_conflicting_ret_types : Warning<
- "conflicting return type in implementation of %0: %1 vs %2">;
-
-def warn_conflicting_param_types : Warning<
- "conflicting parameter types in implementation of %0: %1 vs %2">;
-def warn_conflicting_variadic :Warning<
- "conflicting variadic declaration of method and its implementation">;
-
-def warn_implements_nscopying : Warning<
-"default assign attribute on property %0 which implements "
-"NSCopying protocol is not appropriate with -fobjc-gc[-only]">;
-
-def warn_multiple_method_decl : Warning<"multiple methods named %0 found">;
-def warn_accessor_property_type_mismatch : Warning<
- "type of property %0 does not match type of accessor %1">;
-def note_declared_at : Note<"declared here">;
-def err_setter_type_void : Error<"type of setter must be void">;
-def err_duplicate_method_decl : Error<"duplicate declaration of method %0">;
-def warn_missing_atend : Warning<"'@end' is missing in implementation context">;
-def err_objc_var_decl_inclass :
- Error<"cannot declare variable inside @interface or @protocol">;
-def error_missing_method_context : Error<
- "missing context for method declaration">;
-def err_objc_property_attr_mutually_exclusive : Error<
- "property attributes '%0' and '%1' are mutually exclusive">;
-def err_objc_property_requires_object : Error<
- "property with '%0' attribute must be of object type">;
-def warn_objc_property_no_assignment_attribute : Warning<
- "no 'assign', 'retain', or 'copy' attribute is specified - "
- "'assign' is assumed">;
-def warn_objc_property_default_assign_on_object : Warning<
- "default property attribute 'assign' not appropriate for non-gc object">;
-def warn_property_attr_mismatch : Warning<
- "property attribute in continuation class does not match the primary class">;
-def warn_objc_property_copy_missing_on_block : Warning<
- "'copy' attribute must be specified for the block property "
- "when -fobjc-gc-only is specified">;
-def warn_atomic_property_rule : Warning<
- "writable atomic property %0 cannot pair a synthesized setter/getter "
- "with a user defined setter/getter">;
-def err_use_continuation_class : Error<
- "illegal declaration of property in continuation class %0"
- ": attribute must be readwrite, while its primary must be readonly">;
-def err_continuation_class : Error<"continuation class has no primary class">;
-def err_property_type : Error<"property cannot have array or function type %0">;
-def error_missing_property_context : Error<
- "missing context for property implementation declaration">;
-def error_bad_property_decl : Error<
- "property implementation must have its declaration in interface %0">;
-def error_category_property : Error<
- "property declared in category %0 cannot be implemented in "
- "class implementation">;
-def note_property_declare : Note<
- "property declared here">;
-def error_synthesize_category_decl : Error<
- "@synthesize not allowed in a category's implementation">;
-def error_reference_property : Error<
- "property of reference type is not supported">;
-def error_missing_property_interface : Error<
- "property implementation in a category with no category declaration">;
-def error_bad_category_property_decl : Error<
- "property implementation must have its declaration in the category %0">;
-def error_bad_property_context : Error<
- "property implementation must be in a class or category implementation">;
-def error_missing_property_ivar_decl : Error<
- "synthesized property %0 must either be named the same as a compatible"
- " ivar or must explicitly name an ivar">;
-
-def error_synthesized_ivar_yet_not_supported : Error<
- "instance variable synthesis not yet supported"
- " (need to declare %0 explicitly)">;
-
-def error_property_ivar_type : Error<
- "type of property %0 (%1) does not match type of ivar %2 (%3)">;
-def error_ivar_in_superclass_use : Error<
- "property %0 attempting to use ivar %1 declared in super class %2">;
-def error_weak_property : Error<
- "existing ivar %1 for __weak property %0 must be __weak">;
-def error_strong_property : Error<
- "existing ivar %1 for a __strong property %0 must be garbage collectable">;
-def error_dynamic_property_ivar_decl : Error<
- "dynamic property can not have ivar specification">;
-def error_duplicate_ivar_use : Error<
- "synthesized properties %0 and %1 both claim ivar %2">;
-def error_property_implemented : Error<"property %0 is already implemented">;
-def warn_objc_property_attr_mutually_exclusive : Warning<
- "property attributes '%0' and '%1' are mutually exclusive">,
- InGroup<ReadOnlySetterAttrs>, DefaultIgnore;
-def warn_undeclared_selector : Warning<
- "undeclared selector %0">, InGroup<UndeclaredSelector>, DefaultIgnore;
-def warn_unimplemented_selector: Warning<
- "unimplemented selector %0">, InGroup<Selector>, DefaultIgnore;
-def warn_unimplemented_protocol_method : Warning<
- "method in protocol not implemented">, InGroup<Protocol>;
-
-// C++ declarations
-def err_static_assert_expression_is_not_constant : Error<
- "static_assert expression is not an integral constant expression">;
-def err_static_assert_failed : Error<"static_assert failed \"%0\"">;
-
-def err_unexpected_friend : Error<
- "friends can only be classes or functions">;
-def ext_enum_friend : ExtWarn<
- "enumeration type %0 cannot be a friend">;
-def ext_nonclass_type_friend : ExtWarn<
- "non-class type %0 cannot be a friend">;
-def err_friend_is_member : Error<
- "friends cannot be members of the declaring class">;
-def ext_unelaborated_friend_type : ExtWarn<
- "must specify '%select{struct|union|class|enum}0' to befriend %1">;
-def err_qualified_friend_not_found : Error<
- "no function named %0 with type %1 was found in the specified scope">;
-def err_introducing_special_friend : Error<
- "must use a qualified name when declaring a %select{constructor|"
- "destructor|conversion operator}0 as a friend">;
-def err_tagless_friend_type_template : Error<
- "friend type templates must use an elaborated type">;
-
-def err_abstract_type_in_decl : Error<
- "%select{return|parameter|variable|field}0 type %1 is an abstract class">;
-def err_allocation_of_abstract_type : Error<
- "allocation of an object of abstract type %0">;
-def err_throw_abstract_type : Error<
- "cannot throw an object of abstract type %0">;
-def err_array_of_abstract_type : Error<"array of abstract class type %0">;
-
-def err_multiple_final_overriders : Error<
- "virtual function %q0 has more than one final overrider in %1">;
-def note_final_overrider : Note<"final overrider of %q0 in %1">;
-
-def err_type_defined_in_type_specifier : Error<
- "%0 can not be defined in a type specifier">;
-def err_type_defined_in_result_type : Error<
- "%0 can not be defined in the result type of a function">;
-def err_type_defined_in_param_type : Error<
- "%0 can not be defined in a parameter type">;
-
-def note_pure_virtual_function : Note<
- "pure virtual function %0">;
-
-def err_deleted_non_function : Error<
- "only functions can have deleted definitions">;
-def err_deleted_decl_not_first : Error<
- "deleted definition must be first declaration">;
-
-def warn_weak_vtable : Warning<
- "%0 has no out-of-line virtual method definitions; its vtable will be "
- "emitted in every translation unit">,
- InGroup<DiagGroup<"weak-vtables">>, DefaultIgnore;
-
-def ext_using_undefined_std : ExtWarn<
- "using directive refers to implicitly-defined namespace 'std'">;
-
-// C++ exception specifications
-def err_exception_spec_in_typedef : Error<
- "exception specifications are not allowed in typedefs">;
-def err_distant_exception_spec : Error<
- "exception specifications are not allowed beyond a single level "
- "of indirection">;
-def err_incomplete_in_exception_spec : Error<
- "%select{|pointer to |reference to }0incomplete type %1 is not allowed "
- "in exception specification">;
-def err_mismatched_exception_spec : Error<
- "exception specification in declaration does not match previous declaration">;
-def err_override_exception_spec : Error<
- "exception specification of overriding function is more lax than "
- "base version">;
-def err_incompatible_exception_specs : Error<
- "target exception specification is not superset of source">;
-def err_deep_exception_specs_differ : Error<
- "exception specifications of %select{return|argument}0 types differ">;
-def warn_missing_exception_specification : Warning<
- "%0 is missing exception specification '%1'">;
-
-// C++ access checking
-def err_class_redeclared_with_different_access : Error<
- "%0 redeclared with '%1' access">;
-def err_access : Error<
- "%1 is a %select{private|protected}0 member of %3">, NoSFINAE;
-def err_access_ctor : Error<
- "calling a %select{private|protected}0 constructor of class %2">, NoSFINAE;
-def ext_rvalue_to_reference_access_ctor : ExtWarn<
- "C++98 requires an accessible copy constructor for class %2 when binding "
- "a reference to a temporary; was %select{private|protected}0">,
- NoSFINAE, InGroup<BindToTemporaryCopy>;
-def err_access_base : Error<
- "%select{base class|inherited virtual base class}0 %1 has %select{private|"
- "protected}3 %select{constructor|copy constructor|copy assignment operator|"
- "destructor}2">, NoSFINAE;
-def err_access_field: Error<
- "field of type %0 has %select{private|protected}2 %select{constructor|copy "
- "constructor|copy assignment operator|destructor}1">, NoSFINAE;
-
-def err_access_ctor_field :
- Error<"field of type %1 has %select{private|protected}2 constructor">,
- NoSFINAE;
-def err_access_dtor_base :
- Error<"base class %0 has %select{private|protected}1 destructor">,
- NoSFINAE;
-def err_access_dtor_vbase :
- Error<"inherited virtual base class %0 has "
- "%select{private|protected}1 destructor">,
- NoSFINAE;
-def err_access_dtor_temp :
- Error<"temporary of type %0 has %select{private|protected}1 destructor">,
- NoSFINAE;
-def err_access_dtor_exception :
- Error<"exception object of type %0 has %select{private|protected}1 "
- "destructor">, NoSFINAE;
-def err_access_dtor_field :
- Error<"field of type %1 has %select{private|protected}2 destructor">,
- NoSFINAE;
-def err_access_dtor_var :
- Error<"variable of type %1 has %select{private|protected}2 destructor">,
- NoSFINAE;
-def err_access_assign_field :
- Error<"field of type %1 has %select{private|protected}2 copy assignment"
- " operator">,
- NoSFINAE;
-def err_access_assign_base :
- Error<"base class %0 has %select{private|protected}1 copy assignment"
- " operator">,
- NoSFINAE;
-def err_access_copy_field :
- Error<"field of type %1 has %select{private|protected}2 copy constructor">,
- NoSFINAE;
-def err_access_copy_base :
- Error<"base class %0 has %select{private|protected}1 copy constructor">,
- NoSFINAE;
-def err_access_dtor_ivar :
- Error<"instance variable of type %0 has %select{private|protected}1 "
- "destructor">,
- NoSFINAE;
-def note_previous_access_declaration : Note<
- "previously declared '%1' here">;
-def err_access_outside_class : Error<
- "access to %select{private|protected}0 member outside any class context">;
-def note_access_natural : Note<
- "%select{|implicitly }1declared %select{private|protected}0 here">;
-def note_access_constrained_by_path : Note<
- "constrained by %select{|implicitly }1%select{private|protected}0"
- " inheritance here">;
-
-// C++ name lookup
-def err_incomplete_nested_name_spec : Error<
- "incomplete type %0 named in nested name specifier">;
-def err_dependent_nested_name_spec : Error<
- "nested name specifier for a declaration cannot depend on a template "
- "parameter">;
-def err_nested_name_member_ref_lookup_ambiguous : Error<
- "lookup of %0 in member access expression is ambiguous">;
-def ext_nested_name_member_ref_lookup_ambiguous : ExtWarn<
- "lookup of %0 in member access expression is ambiguous; using member of %1">,
- InGroup<AmbigMemberTemplate>;
-def note_ambig_member_ref_object_type : Note<
- "lookup in the object type %0 refers here">;
-def note_ambig_member_ref_scope : Note<
- "lookup from the current scope refers here">;
-def err_qualified_member_nonclass : Error<
- "qualified member access refers to a member in %0">;
-def err_incomplete_member_access : Error<
- "member access into incomplete type %0">;
-def err_incomplete_type : Error<
- "incomplete type %0 where a complete type is required">;
-
-// C++ class members
-def err_storageclass_invalid_for_member : Error<
- "storage class specified for a member declaration">;
-def err_mutable_function : Error<"'mutable' cannot be applied to functions">;
-def err_mutable_reference : Error<"'mutable' cannot be applied to references">;
-def err_mutable_const : Error<"'mutable' and 'const' cannot be mixed">;
-def err_mutable_nonmember : Error<
- "'mutable' can only be applied to member variables">;
-def err_virtual_non_function : Error<
- "'virtual' can only appear on non-static member functions">;
-def err_virtual_out_of_class : Error<
- "'virtual' can only be specified inside the class definition">;
-def err_explicit_non_function : Error<
- "'explicit' can only appear on non-static member functions">;
-def err_explicit_out_of_class : Error<
- "'explicit' can only be specified inside the class definition">;
-def err_explicit_non_ctor_or_conv_function : Error<
- "'explicit' can only be applied to a constructor or conversion function">;
-def err_static_not_bitfield : Error<"static member %0 cannot be a bit-field">;
-def err_static_out_of_line : Error<
- "'static' can only be specified inside the class definition">;
-def err_typedef_not_bitfield : Error<"typedef member %0 cannot be a bit-field">;
-def err_not_integral_type_bitfield : Error<
- "bit-field %0 has non-integral type %1">;
-def err_not_integral_type_anon_bitfield : Error<
- "anonymous bit-field has non-integral type %0">;
-def err_member_initialization : Error<
- "%0 can only be initialized if it is a static const integral data member">;
-def err_member_function_initialization : Error<
- "initializer on function does not look like a pure-specifier">;
-def err_non_virtual_pure : Error<
- "%0 is not virtual and cannot be declared pure">;
-def err_implicit_object_parameter_init : Error<
- "cannot initialize object parameter of type %0 with an expression "
- "of type %1">;
-def err_qualified_member_of_unrelated : Error<
- "%q0 is not a member of class %1">;
-
-def note_field_decl : Note<"member is declared here">;
-def note_ivar_decl : Note<"ivar is declared here">;
-def note_bitfield_decl : Note<"bit-field is declared here">;
-def note_previous_decl : Note<"%0 declared here">;
-def note_member_synthesized_at : Note<
- "implicit default %select{constructor|copy constructor|"
- "copy assignment operator|destructor}0 for %1 first required here">;
-def err_missing_default_ctor : Error<
- "%select{|implicit default }0constructor for %1 must explicitly initialize "
- "the %select{base class|member}2 %3 which does not have a default "
- "constructor">;
-def err_illegal_union_member : Error<
- "union member %0 has a non-trivial %select{constructor|"
- "copy constructor|copy assignment operator|destructor}1">;
-def note_nontrivial_has_virtual : Note<
- "because type %0 has a virtual %select{member function|base class}1">;
-def note_nontrivial_has_nontrivial : Note<
- "because type %0 has a %select{member|base class}1 with a non-trivial "
- "%select{constructor|copy constructor|copy assignment operator|destructor}2">;
-def note_nontrivial_user_defined : Note<
- "because type %0 has a user-declared %select{constructor|copy constructor|"
- "copy assignment operator|destructor}1">;
-
-def err_different_return_type_for_overriding_virtual_function : Error<
- "virtual function %0 has a different return type (%1) than the "
- "function it overrides (which has return type %2)">;
-def note_overridden_virtual_function : Note<
- "overridden virtual function is here">;
-
-def err_covariant_return_inaccessible_base : Error<
- "invalid covariant return for virtual function: %1 is a "
- "%select{private|protected}2 base class of %0">, NoSFINAE;
-def err_covariant_return_ambiguous_derived_to_base_conv : Error<
- "return type of virtual function %3 is not covariant with the return type of "
- "the function it overrides (ambiguous conversion from derived class "
- "%0 to base class %1:%2)">;
-def err_covariant_return_not_derived : Error<
- "return type of virtual function %0 is not covariant with the return type of "
- "the function it overrides (%1 is not derived from %2)">;
-def err_covariant_return_incomplete : Error<
- "return type of virtual function %0 is not covariant with the return type of "
- "the function it overrides (%1 is incomplete)">;
-def err_covariant_return_type_different_qualifications : Error<
- "return type of virtual function %0 is not covariant with the return type of "
- "the function it overrides (%1 has different qualifiers than %2)">;
-def err_covariant_return_type_class_type_more_qualified : Error<
- "return type of virtual function %0 is not covariant with the return type of "
- "the function it overrides (class type %1 is more qualified than class "
- "type %2">;
-
-// C++ constructors
-def err_constructor_cannot_be : Error<"constructor cannot be declared '%0'">;
-def err_invalid_qualified_constructor : Error<
- "'%0' qualifier is not allowed on a constructor">;
-def err_constructor_return_type : Error<
- "constructor cannot have a return type">;
-def err_constructor_redeclared : Error<"constructor cannot be redeclared">;
-def err_constructor_byvalue_arg : Error<
- "copy constructor must pass its first argument by reference">;
-def warn_no_constructor_for_refconst : Warning<
- "%select{struct|union|class|enum}0 %1 does not declare any constructor to "
- "initialize its non-modifiable members">;
-def note_refconst_member_not_initialized : Note<
- "%select{const|reference}0 member %1 will never be initialized">;
-
-// C++ destructors
-def err_destructor_not_member : Error<
- "destructor must be a non-static member function">;
-def err_destructor_cannot_be : Error<"destructor cannot be declared '%0'">;
-def err_invalid_qualified_destructor : Error<
- "'%0' qualifier is not allowed on a destructor">;
-def err_destructor_return_type : Error<"destructor cannot have a return type">;
-def err_destructor_redeclared : Error<"destructor cannot be redeclared">;
-def err_destructor_with_params : Error<"destructor cannot have any parameters">;
-def err_destructor_variadic : Error<"destructor cannot be variadic">;
-def err_destructor_typedef_name : Error<
- "destructor cannot be declared using a typedef %0 of the class name">;
-def err_destructor_name : Error<
- "expected the class name after '~' to name the enclosing class">;
-def err_destructor_class_name : Error<
- "expected the class name after '~' to name a destructor">;
-def err_ident_in_pseudo_dtor_not_a_type : Error<
- "identifier %0 in pseudo-destructor expression does not name a type">;
-
-// C++ initialization
-def err_init_conversion_failed : Error<
- "cannot initialize %select{a variable|a parameter|return object|an "
- "exception object|a member subobject|an array element|a new value|a value|a "
- "base class|a vector element}0 of type %1 with an %select{rvalue|lvalue}2 of "
- "type %3">;
-
-def err_lvalue_to_rvalue_ref : Error<"rvalue reference cannot bind to lvalue">;
-def err_invalid_initialization : Error<
-"invalid initialization of reference of type %0 from expression of type %1">;
-def err_lvalue_to_rvalue_ambig_ref : Error<"rvalue reference cannot bind to lvalue "
- "due to multiple conversion functions">;
-def err_not_reference_to_const_init : Error<
- "%select{non-const|volatile}0 lvalue reference to type %1 cannot be "
- "initialized with a %select{value|temporary}2 of type %3">;
-def err_lvalue_reference_bind_to_temporary : Error<
- "%select{non-const|volatile}0 lvalue reference to type %1 cannot bind to a "
- "temporary of type %2">;
-def err_lvalue_reference_bind_to_unrelated : Error<
- "%select{non-const|volatile}0 lvalue reference to type %1 cannot bind to a "
- "value of unrelated type %2">;
-def err_reference_bind_drops_quals : Error<
- "binding of reference to type %0 to a value of type %1 drops qualifiers">;
-def err_reference_bind_failed : Error<
- "reference to type %0 could not bind to an %select{rvalue|lvalue}1 of type "
- "%2">;
-def err_reference_bind_init_list : Error<
- "reference to type %0 cannot bind to an initializer list">;
-def err_init_list_bad_dest_type : Error<
- "%select{|non-aggregate }0type %1 cannot be initialized with an initializer "
- "list">;
-
-def err_reference_init_drops_quals : Error<
- "initialization of reference to type %0 with a %select{value|temporary}1 of type %2 drops "
- "qualifiers">;
-def err_reference_bind_to_bitfield : Error<
- "%select{non-const|volatile}0 reference cannot bind to bit-field %1">;
-def err_reference_bind_to_vector_element : Error<
- "%select{non-const|volatile}0 reference cannot bind to vector element">;
-def err_reference_var_requires_init : Error<
- "declaration of reference variable %0 requires an initializer">;
-def err_const_var_requires_init : Error<
- "declaration of const variable '%0' requires an initializer">;
-def err_reference_without_init : Error<
- "reference to type %0 requires an initializer">;
-def err_reference_has_multiple_inits : Error<
- "reference cannot be initialized with multiple values">;
-def err_init_non_aggr_init_list : Error<
- "initialization of non-aggregate type %0 with an initializer list">;
-def err_init_reference_member_uninitialized : Error<
- "reference member of type %0 uninitialized">;
-def note_uninit_reference_member : Note<
- "uninitialized reference member is here">;
-def warn_field_is_uninit : Warning<"field is uninitialized when used here">,
- InGroup<DiagGroup<"uninitialized">>;
-def err_init_incomplete_type : Error<"initialization of incomplete type %0">;
-
-def err_temp_copy_no_viable : Error<
- "no viable constructor %select{copying variable|copying parameter|"
- "returning object|throwing object|copying member subobject|copying array "
- "element|allocating object|copying temporary|initializing base subobject|"
- "initializing vector element}0 of type %1">;
-def ext_rvalue_to_reference_temp_copy_no_viable : ExtWarn<
- "no viable constructor %select{copying variable|copying parameter|"
- "returning object|throwing object|copying member subobject|copying array "
- "element|allocating object|copying temporary|initializing base subobject|"
- "initializing vector element}0 of type %1; C++98 requires a copy "
- "constructor when binding a reference to a temporary">,
- InGroup<BindToTemporaryCopy>;
-def err_temp_copy_ambiguous : Error<
- "ambiguous constructor call when %select{copying variable|copying "
- "parameter|returning object|throwing object|copying member subobject|copying "
- "array element|allocating object|copying temporary|initializing base subobject|"
- "initializing vector element}0 of type %1">;
-def err_temp_copy_deleted : Error<
- "%select{copying variable|copying parameter|returning object|throwing "
- "object|copying member subobject|copying array element|allocating object|"
- "copying temporary|initializing base subobject|initializing vector element}0 "
- "of type %1 invokes deleted constructor">;
-def err_temp_copy_incomplete : Error<
- "copying a temporary object of incomplete type %0">;
-
-// C++0x decltype
-def err_cannot_determine_declared_type_of_overloaded_function : Error<
- "cannot determine the %select{type|declared type}0 of an overloaded "
- "function">;
-
-// C++0x auto
-def err_auto_variable_cannot_appear_in_own_initializer : Error<
- "variable %0 declared with 'auto' type cannot appear in its own initializer">;
-def err_illegal_decl_array_of_auto : Error<
- "'%0' declared as array of 'auto'">;
-def err_auto_not_allowed : Error<
- "'auto' not allowed in %select{function prototype|struct member|union member"
- "|class member|exception declaration|template parameter|block literal}0">;
-def err_auto_var_requires_init : Error<
- "declaration of variable %0 with type %1 requires an initializer">;
-
-// C++0x attributes
-def err_repeat_attribute : Error<"'%0' attribute cannot be repeated">;
-
-// C++0x [[final]]
-def err_final_function_overridden : Error<
- "declaration of %0 overrides a 'final' function">;
-def err_final_base : Error<
- "derivation from 'final' %0">;
-
-// Objective-C++
-def err_objc_decls_may_only_appear_in_global_scope : Error<
- "Objective-C declarations may only appear in global scope">;
-def err_nsobject_attribute : Error<
- "__attribute ((NSObject)) is for pointer types only">;
-
-// Attributes
-def err_attribute_can_be_applied_only_to_symbol_declaration : Error<
- "%0 attribute can be applied only to symbol declaration">;
-def err_attributes_are_not_compatible : Error<
- "%0 and %1 attributes are not compatible">;
-def err_attribute_wrong_number_arguments : Error<
- "attribute requires %0 argument(s)">;
-def err_attribute_missing_parameter_name : Error<
- "attribute requires unquoted parameter">;
-def err_attribute_invalid_vector_type : Error<"invalid vector element type %0">;
-def err_attribute_argument_not_int : Error<
- "'%0' attribute requires integer constant">;
-def err_attribute_argument_outof_range : Error<
- "init_priority attribute requires integer constant between "
- "101 and 65535 inclusive">;
-def err_init_priority_object_attr : Error<
- "can only use âinit_priorityâ attribute on file-scope definitions "
- "of objects of class type">;
-def err_attribute_argument_n_not_int : Error<
- "'%0' attribute requires parameter %1 to be an integer constant">;
-def err_attribute_argument_n_not_string : Error<
- "'%0' attribute requires parameter %1 to be a string">;
-def err_attribute_argument_out_of_bounds : Error<
- "'%0' attribute parameter %1 is out of bounds">;
-def err_attribute_requires_objc_interface : Error<
- "attribute may only be applied to an Objective-C interface">;
-def err_nonnull_pointers_only : Error<
- "nonnull attribute only applies to pointer arguments">;
-def err_format_strftime_third_parameter : Error<
- "strftime format attribute requires 3rd parameter to be 0">;
-def err_format_attribute_requires_variadic : Error<
- "format attribute requires variadic function">;
-def err_format_attribute_not : Error<"format argument not %0">;
-def err_format_attribute_result_not : Error<"function does not return %0">;
-def err_attribute_invalid_size : Error<
- "vector size not an integral multiple of component size">;
-def err_attribute_zero_size : Error<"zero vector size">;
-def err_typecheck_vector_not_convertable : Error<
- "can't convert between vector values of different size (%0 and %1)">;
-def err_typecheck_ext_vector_not_typedef : Error<
- "ext_vector_type only applies to types, not variables">;
-def err_unsupported_vector_size : Error<
- "unsupported type %0 for vector_size attribute, please use on typedef">;
-def err_ext_vector_component_exceeds_length : Error<
- "vector component access exceeds type %0">;
-def err_ext_vector_component_name_illegal : Error<
- "illegal vector component name '%0'">;
-def err_attribute_address_space_not_int : Error<
- "address space attribute requires an integer constant">;
-def err_attribute_address_space_negative : Error<
- "address space is negative">;
-def err_attribute_address_space_too_high : Error<
- "address space is larger than the maximum supported (%0)">;
-def err_attribute_address_multiple_qualifiers : Error<
- "multiple address spaces specified for type">;
-def err_implicit_pointer_address_space_cast : Error<
- "illegal implicit conversion between two pointers with different address "
- "spaces">;
-def err_as_qualified_auto_decl : Error<
- "automatic variable qualified with an address space">;
-def err_arg_with_address_space : Error<
- "parameter may not be qualified with an address space">;
-def err_attribute_not_string : Error<
- "argument to %0 attribute was not a string literal">;
-def err_attribute_section_invalid_for_target : Error<
- "argument to 'section' attribute is not valid for this target: %0">;
-def err_attribute_section_local_variable : Error<
- "'section' attribute is not valid on local variables">;
-def err_attribute_aligned_not_power_of_two : Error<
- "requested alignment is not a power of 2">;
-def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning<
- "'%0' redeclared without %1 attribute: previous %1 ignored">;
-def warn_attribute_ignored : Warning<"%0 attribute ignored">;
-def warn_unknown_attribute_ignored : Warning<
- "unknown attribute %0 ignored">, InGroup<UnknownAttributes>;
-def warn_attribute_precede_definition : Warning<
- "attribute declaration must precede definition">;
-def warn_attribute_void_function_method : Warning<
- "attribute %0 cannot be applied to "
- "%select{functions|Objective-C method}1 without return value">;
-def warn_attribute_weak_on_field : Warning<
- "__weak attribute cannot be specified on a field declaration">;
-def warn_attribute_weak_on_local : Warning<
- "__weak attribute cannot be specified on an automatic variable">;
-def warn_weak_identifier_undeclared : Warning<
- "weak identifier %0 never declared">;
-def err_attribute_weak_static : Error<
- "weak declaration of '%0' must be public">;
-def warn_attribute_weak_import_invalid_on_definition : Warning<
- "'weak_import' attribute cannot be specified on a definition">;
-def err_attribute_weakref_not_static : Error<
- "weakref declaration of '%0' must be static">;
-def err_attribute_weakref_not_global_context : Error<
- "weakref declaration of '%0' must be in a global context">;
-def err_attribute_weakref_without_alias : Error<
- "weakref declaration of '%0' must also have an alias attribute">;
-def warn_attribute_wrong_decl_type : Warning<
- "%0 attribute only applies to %select{function|union|"
- "variable and function|function or method|parameter|"
- "parameter or Objective-C method |function, method or block|"
- "virtual method or class|function, method, or parameter|class|virtual method"
- "|member}1 types">;
-def err_attribute_wrong_decl_type : Error<
- "%0 attribute only applies to %select{function|union|"
- "variable and function|function or method|parameter|"
- "parameter or Objective-C method |function, method or block|"
- "virtual method or class|function, method, or parameter|class|virtual method"
- "|member}1 types">;
-def warn_function_attribute_wrong_type : Warning<
- "%0 only applies to function types; type here is %1">;
-def warn_gnu_inline_attribute_requires_inline : Warning<
- "'gnu_inline' attribute requires function to be marked 'inline',"
- " attribute ignored">;
-def err_cconv_change : Error<
- "function declared '%0' here was previously declared "
- "%select{'%2'|without calling convention}1">;
-def err_cconv_knr : Error<
- "function with no prototype cannot use %0 calling convention">;
-def err_cconv_varargs : Error<
- "variadic function cannot use %0 calling convention">;
-def err_regparm_mismatch : Error<"function declared with with regparm(%0) "
- "attribute was previously declared %plural{0:without the regparm|1:"
- "with the regparm(1)|2:with the regparm(2)|3:with the regparm(3)|:with the"
- "regparm}1 attribute">;
-
-def warn_impcast_vector_scalar : Warning<
- "implicit conversion turns vector to scalar: %0 to %1">,
- InGroup<DiagGroup<"conversion">>, DefaultIgnore;
-def warn_impcast_complex_scalar : Warning<
- "implicit conversion discards imaginary component: %0 to %1">,
- InGroup<DiagGroup<"conversion">>, DefaultIgnore;
-def warn_impcast_float_precision : Warning<
- "implicit conversion loses floating-point precision: %0 to %1">,
- InGroup<DiagGroup<"conversion">>, DefaultIgnore;
-def warn_impcast_float_integer : Warning<
- "implicit conversion turns floating-point number into integer: %0 to %1">,
- InGroup<DiagGroup<"conversion">>, DefaultIgnore;
-def warn_impcast_integer_sign : Warning<
- "implicit conversion changes signedness: %0 to %1">,
- InGroup<DiagGroup<"conversion">>, DefaultIgnore;
-def warn_impcast_integer_sign_conditional : Warning<
- "operand of ? changes signedness: %0 to %1">,
- InGroup<DiagGroup<"conversion">>, DefaultIgnore;
-def warn_impcast_integer_precision : Warning<
- "implicit conversion loses integer precision: %0 to %1">,
- InGroup<DiagGroup<"conversion">>, DefaultIgnore;
-def warn_impcast_integer_64_32 : Warning<
- "implicit conversion loses integer precision: %0 to %1">,
- InGroup<DiagGroup<"shorten-64-to-32">>, DefaultIgnore;
-
-def warn_attribute_ignored_for_field_of_type : Warning<
- "%0 attribute ignored for field of type %1">;
-def warn_transparent_union_attribute_field_size_align : Warning<
- "%select{alignment|size}0 of field %1 (%2 bits) does not match the "
- "%select{alignment|size}0 of the first field in transparent union; "
- "transparent_union attribute ignored">;
-def note_transparent_union_first_field_size_align : Note<
- "%select{alignment|size}0 of first field is %1 bits">;
-def warn_transparent_union_attribute_not_definition : Warning<
- "transparent_union attribute can only be applied to a union definition; "
- "attribute ignored">;
-def warn_transparent_union_attribute_floating : Warning<
- "first field of a transparent union cannot have %select{floating point|"
- "vector}0 type %1; transparent_union attribute ignored">;
-def warn_transparent_union_attribute_zero_fields : Warning<
- "transparent union definition must contain at least one field; "
- "transparent_union attribute ignored">;
-def warn_attribute_type_not_supported : Warning<
- "'%0' attribute argument not supported: %1">;
-def warn_attribute_unknown_visibility : Warning<"unknown visibility '%1'">;
-def err_unknown_machine_mode : Error<"unknown machine mode %0">;
-def err_unsupported_machine_mode : Error<"unsupported machine mode %0">;
-def err_mode_not_primitive : Error<
- "mode attribute only supported for integer and floating-point types">;
-def err_mode_wrong_type : Error<
- "type of machine mode does not match type of base type">;
-def err_attr_wrong_decl : Error<
- "'%0' attribute invalid on this declaration, requires typedef or value">;
-def warn_attribute_nonnull_no_pointers : Warning<
- "'nonnull' attribute applied to function with no pointer arguments">;
-def warn_attribute_malloc_pointer_only : Warning<
- "'malloc' attribute only applies to functions returning a pointer type">;
-def warn_transparent_union_nonpointer : Warning<
- "'transparent_union' attribute support incomplete; only supported for "
- "pointer unions">;
-
-def warn_attribute_sentinel_named_arguments : Warning<
- "'sentinel' attribute requires named arguments">;
-def warn_attribute_sentinel_not_variadic : Warning<
- "'sentinel' attribute only supported for variadic %select{functions|blocks}0">;
-def err_attribute_sentinel_less_than_zero : Error<
- "'sentinel' parameter 1 less than zero">;
-def err_attribute_sentinel_not_zero_or_one : Error<
- "'sentinel' parameter 2 not 0 or 1">;
-def err_attribute_cleanup_arg_not_found : Error<
- "'cleanup' argument %0 not found">;
-def err_attribute_cleanup_arg_not_function : Error<
- "'cleanup' argument %0 is not a function">;
-def err_attribute_cleanup_func_must_take_one_arg : Error<
- "'cleanup' function %0 must take 1 parameter">;
-def err_attribute_cleanup_func_arg_incompatible_type : Error<
- "'cleanup' function %0 parameter has type %1 which is incompatible with "
- "type %2">;
-def err_attribute_regparm_wrong_platform : Error<
- "'regparm' is not valid on this platform">;
-def err_attribute_regparm_invalid_number : Error<
- "'regparm' parameter must be between 0 and %0 inclusive">;
-
-
-// Clang-Specific Attributes
-def err_attribute_iboutlet : Error<
- "%0 attribute can only be applied to instance variables or properties">;
-def err_attribute_ibaction: Error<
- "ibaction attribute can only be applied to Objective-C instance methods">;
-def err_attribute_overloadable_not_function : Error<
- "'overloadable' attribute can only be applied to a function">;
-def err_attribute_overloadable_missing : Error<
- "%select{overloaded function|redeclaration of}0 %1 must have the "
- "'overloadable' attribute">;
-def note_attribute_overloadable_prev_overload : Note<
- "previous overload of function is here">;
-def err_attribute_overloadable_no_prototype : Error<
- "'overloadable' function %0 must have a prototype">;
-def warn_ns_attribute_wrong_return_type : Warning<
- "%0 attribute only applies to functions or methods that "
- "return a pointer or Objective-C object">;
-
-// Function Parameter Semantic Analysis.
-def err_param_with_void_type : Error<"argument may not have 'void' type">;
-def err_void_only_param : Error<
- "'void' must be the first and only parameter if specified">;
-def err_void_param_qualified : Error<
- "'void' as parameter must not have type qualifiers">;
-def err_ident_list_in_fn_declaration : Error<
- "a parameter list without types is only allowed in a function definition">;
-def ext_param_not_declared : Extension<
- "parameter %0 was not declared, defaulting to type 'int'">;
-def err_param_typedef_of_void : Error<
- "empty parameter list defined with a typedef of 'void' not allowed in C++">;
-def err_param_default_argument : Error<
- "C does not support default arguments">;
-def err_param_default_argument_redefinition : Error<
- "redefinition of default argument">;
-def err_param_default_argument_missing : Error<
- "missing default argument on parameter">;
-def err_param_default_argument_missing_name : Error<
- "missing default argument on parameter %0">;
-def err_param_default_argument_references_param : Error<
- "default argument references parameter %0">;
-def err_param_default_argument_references_local : Error<
- "default argument references local variable %0 of enclosing function">;
-def err_param_default_argument_references_this : Error<
- "default argument references 'this'">;
-def err_param_default_argument_nonfunc : Error<
- "default arguments can only be specified for parameters in a function "
- "declaration">;
-def err_param_default_argument_template_redecl : Error<
- "default arguments cannot be added to a function template that has already "
- "been declared">;
-def err_param_default_argument_member_template_redecl : Error<
- "default arguments cannot be added to an out-of-line definition of a member "
- "of a %select{class template|class template partial specialization|nested "
- "class in a template}0">;
-def err_uninitialized_member_for_assign : Error<
- "cannot define the implicit default assignment operator for %0, because "
- "non-static %select{reference|const}1 member %2 can't use default "
- "assignment operator">;
-def note_first_required_here : Note<
- "synthesized method is first required here">;
-def err_uninitialized_member_in_ctor : Error<
- "%select{|implicit default }0constructor for %1 must explicitly initialize "
- "the %select{reference|const}2 member %3">;
-
-def err_use_of_default_argument_to_function_declared_later : Error<
- "use of default argument to function %0 that is declared later in class %1">;
-def note_default_argument_declared_here : Note<
- "default argument declared here">;
-
-def ext_param_promoted_not_compatible_with_prototype : ExtWarn<
- "promoted type %0 of K&R function parameter is not compatible with the "
- "parameter type %1 declared in a previous prototype">;
-
-
-// C++ Overloading Semantic Analysis.
-def err_ovl_diff_return_type : Error<
- "functions that differ only in their return type cannot be overloaded">;
-def err_ovl_static_nonstatic_member : Error<
- "static and non-static member functions with the same parameter types "
- "cannot be overloaded">;
-
-def err_ovl_no_viable_function_in_call : Error<
- "no matching function for call to %0">;
-def err_ovl_no_viable_member_function_in_call : Error<
- "no matching member function for call to %0">;
-def err_ovl_ambiguous_call : Error<
- "call to %0 is ambiguous">;
-def err_ovl_deleted_call : Error<
- "call to %select{unavailable|deleted}0 function %1">;
-def err_ovl_ambiguous_member_call : Error<
- "call to member function %0 is ambiguous">;
-def err_ovl_deleted_member_call : Error<
- "call to %select{unavailable|deleted}0 member function %1">;
-def note_ovl_too_many_candidates : Note<
- "remaining %0 candidate%s0 omitted; "
- "pass -fshow-overloads=all to show them">;
-def note_ovl_candidate : Note<"candidate "
- "%select{function|function|constructor|"
- "function |function |constructor |"
- "is the implicit default constructor|"
- "is the implicit copy constructor|"
- "is the implicit copy assignment operator}0%1">;
-
-def warn_init_pointer_from_false : Warning<
- "initialization of pointer of type %0 from literal 'false'">,
- InGroup<BoolConversions>;
-
-def note_ovl_candidate_bad_deduction : Note<
- "candidate template ignored: failed template argument deduction">;
-def note_ovl_candidate_incomplete_deduction : Note<"candidate template ignored: "
- "couldn't infer template argument %0">;
-def note_ovl_candidate_inconsistent_deduction : Note<
- "candidate template ignored: deduced conflicting %select{types|values|"
- "templates}0 for parameter %1 (%2 vs. %3)">;
-def note_ovl_candidate_explicit_arg_mismatch_named : Note<
- "candidate template ignored: invalid explicitly-specified argument "
- "for template parameter %0">;
-def note_ovl_candidate_explicit_arg_mismatch_unnamed : Note<
- "candidate template ignored: invalid explicitly-specified argument "
- "for %ordinal0 template parameter">;
-def note_ovl_candidate_instantiation_depth : Note<
- "candidate template ignored: substitution exceeded maximum template "
- "instantiation depth">;
-def note_ovl_candidate_substitution_failure : Note<
- "candidate template ignored: substitution failure %0">;
-
-// Note that we don't treat templates differently for this diagnostic.
-def note_ovl_candidate_arity : Note<"candidate "
- "%select{function|function|constructor|function|function|constructor|"
- "constructor (the implicit default constructor)|"
- "constructor (the implicit copy constructor)|"
- "function (the implicit copy assignment operator)}0 %select{|template }1"
- "not viable: requires%select{ at least| at most|}2 %3 argument%s3, but %4 "
- "%plural{1:was|:were}4 provided">;
-
-def note_ovl_candidate_deleted : Note<
- "candidate %select{function|function|constructor|"
- "function |function |constructor |||}0%1 "
- "has been explicitly %select{made unavailable|deleted}2">;
-
-// Giving the index of the bad argument really clutters this message, and
-// it's relatively unimportant because 1) it's generally obvious which
-// argument(s) are of the given object type and 2) the fix is usually
-// to complete the type, which doesn't involve changes to the call line
-// anyway. If people complain, we can change it.
-def note_ovl_candidate_bad_conv_incomplete : Note<"candidate "
- "%select{function|function|constructor|"
- "function |function |constructor |"
- "constructor (the implicit default constructor)|"
- "constructor (the implicit copy constructor)|"
- "function (the implicit copy assignment operator)}0%1 "
- "not viable: cannot convert argument of incomplete type %2 to %3">;
-def note_ovl_candidate_bad_overload : Note<"candidate "
- "%select{function|function|constructor|"
- "function |function |constructor |"
- "constructor (the implicit default constructor)|"
- "constructor (the implicit copy constructor)|"
- "function (the implicit copy assignment operator)}0%1"
- " not viable: no overload of %3 matching %2 for %ordinal4 argument">;
-def note_ovl_candidate_bad_conv : Note<"candidate "
- "%select{function|function|constructor|"
- "function |function |constructor |"
- "constructor (the implicit default constructor)|"
- "constructor (the implicit copy constructor)|"
- "function (the implicit copy assignment operator)}0%1"
- " not viable: no known conversion from %2 to %3 for "
- "%select{%ordinal5 argument|object argument}4">;
-def note_ovl_candidate_bad_addrspace : Note<"candidate "
- "%select{function|function|constructor|"
- "function |function |constructor |"
- "constructor (the implicit default constructor)|"
- "constructor (the implicit copy constructor)|"
- "function (the implicit copy assignment operator)}0%1 not viable: "
- "%select{%ordinal6|'this'}5 argument (%2) is in "
- "address space %3, but parameter must be in address space %4">;
-def note_ovl_candidate_bad_cvr_this : Note<"candidate "
- "%select{|function|||function||||"
- "function (the implicit copy assignment operator)}0 not viable: "
- "'this' argument has type %2, but method is not marked "
- "%select{const|volatile|const or volatile|restrict|const or restrict|"
- "volatile or restrict|const, volatile, or restrict}3">;
-def note_ovl_candidate_bad_cvr : Note<"candidate "
- "%select{function|function|constructor|"
- "function |function |constructor |"
- "constructor (the implicit default constructor)|"
- "constructor (the implicit copy constructor)|"
- "function (the implicit copy assignment operator)}0%1 not viable: "
- "%ordinal4 argument (%2) would lose "
- "%select{const|volatile|const and volatile|restrict|const and restrict|"
- "volatile and restrict|const, volatile, and restrict}3 qualifier"
- "%select{||s||s|s|s}3">;
-def note_ovl_candidate_bad_base_to_derived_conv : Note<"candidate "
- "%select{function|function|constructor|"
- "function |function |constructor |"
- "constructor (the implicit default constructor)|"
- "constructor (the implicit copy constructor)|"
- "function (the implicit copy assignment operator)}0%1"
- " not viable: cannot %select{convert from|convert from|bind}2 "
- "%select{base class pointer|superclass|base class object of type}2 %3 to "
- "%select{derived class pointer|subclass|derived class reference}2 %4 for "
- "%ordinal5 argument">;
-
-def note_ambiguous_type_conversion: Note<
- "because of ambiguity in conversion of %0 to %1">;
-def note_ovl_builtin_binary_candidate : Note<
- "built-in candidate %0">;
-def note_ovl_builtin_unary_candidate : Note<
- "built-in candidate %0">;
-def err_ovl_no_viable_function_in_init : Error<
- "no matching constructor for initialization of %0">;
-def err_ovl_ambiguous_init : Error<"call to constructor of %0 is ambiguous">;
-def err_ref_init_ambiguous : Error<
- "reference initialization of type %0 with initializer of type %1 is ambiguous">;
-def err_ovl_deleted_init : Error<
- "call to %select{unavailable|deleted}0 constructor of %1">;
-def err_ovl_ambiguous_oper : Error<
- "use of overloaded operator '%0' is ambiguous">;
-def err_ovl_no_viable_oper : Error<"no viable overloaded '%0'">;
-def err_ovl_deleted_oper : Error<
- "overload resolution selected %select{unavailable|deleted}0 operator '%1'">;
-def err_ovl_no_viable_subscript :
- Error<"no viable overloaded operator[] for type %0">;
-def err_ovl_no_oper :
- Error<"type %0 does not provide a %select{subscript|call}1 operator">;
-
-def err_ovl_no_viable_object_call : Error<
- "no matching function for call to object of type %0">;
-def err_ovl_ambiguous_object_call : Error<
- "call to object of type %0 is ambiguous">;
-def err_ovl_deleted_object_call : Error<
- "call to %select{unavailable|deleted}0 function call operator in type %1">;
-def note_ovl_surrogate_cand : Note<"conversion candidate of type %0">;
-def err_member_call_without_object : Error<
- "call to non-static member function without an object argument">;
-
-// C++ Address of Overloaded Function
-def err_addr_ovl_no_viable : Error<
- "address of overloaded function %0 does not match required type %1">;
-def err_addr_ovl_ambiguous : Error<
- "address of overloaded function %0 is ambiguous">;
-def err_addr_ovl_not_func_ptrref : Error<
- "address of overloaded function %0 cannot be converted to type %1">;
-
-// C++ Template Declarations
-def err_template_param_shadow : Error<
- "declaration of %0 shadows template parameter">;
-def note_template_param_here : Note<"template parameter is declared here">;
-def warn_template_export_unsupported : Warning<
- "exported templates are unsupported">;
-def err_template_outside_namespace_or_class_scope : Error<
- "templates can only be declared in namespace or class scope">;
-def err_template_linkage : Error<"templates must have C++ linkage">;
-def err_template_typedef : Error<"a typedef cannot be a template">;
-def err_template_unnamed_class : Error<
- "cannot declare a class template with no name">;
-def err_template_param_list_different_arity : Error<
- "%select{too few|too many}0 template parameters in template "
- "%select{|template parameter }1redeclaration">;
-def note_template_param_list_different_arity : Note<
- "%select{too few|too many}0 template parameters in template template "
- "argument">;
-def note_template_prev_declaration : Note<
- "previous template %select{declaration|template parameter}0 is here">;
-def err_template_param_different_kind : Error<
- "template parameter has a different kind in template "
- "%select{|template parameter }0redeclaration">;
-def note_template_param_different_kind : Note<
- "template parameter has a different kind in template argument">;
-
-def err_template_nontype_parm_different_type : Error<
- "template non-type parameter has a different type %0 in template "
- "%select{|template parameter }1redeclaration">;
-
-def note_template_nontype_parm_different_type : Note<
- "template non-type parameter has a different type %0 in template argument">;
-def note_template_nontype_parm_prev_declaration : Note<
- "previous non-type template parameter with type %0 is here">;
-def err_template_nontype_parm_bad_type : Error<
- "a non-type template parameter cannot have type %0">;
-def err_template_param_default_arg_redefinition : Error<
- "template parameter redefines default argument">;
-def note_template_param_prev_default_arg : Note<
- "previous default template argument defined here">;
-def err_template_param_default_arg_missing : Error<
- "template parameter missing a default argument">;
-def err_template_parameter_default_in_function_template : Error<
- "a template parameter of a function template cannot have a default argument "
- "in C++98">;
-def err_template_parameter_default_template_member : Error<
- "cannot add a default template argument to the definition of a member of a "
- "class template">;
-def err_template_parameter_default_friend_template : Error<
- "default template argument not permitted on a friend template">;
-
-def err_template_variable : Error<"variable %0 declared as a template">;
-def err_template_variable_noparams : Error<
- "extraneous 'template<>' in declaration of variable %0">;
-def err_template_tag_noparams : Error<
- "extraneous 'template<>' in declaration of %0 %1">;
-def err_template_decl_ref : Error<
- "cannot refer to class template %0 without a template argument list">;
-
-// C++ Template Argument Lists
-def err_template_missing_args : Error<
- "use of class template %0 requires template arguments">;
-def err_template_arg_list_different_arity : Error<
- "%select{too few|too many}0 template arguments for "
- "%select{class template|function template|template template parameter"
- "|template}1 %2">;
-def note_template_decl_here : Note<"template is declared here">;
-def note_member_of_template_here : Note<"member is declared here">;
-def err_template_arg_must_be_type : Error<
- "template argument for template type parameter must be a type">;
-def err_template_arg_must_be_expr : Error<
- "template argument for non-type template parameter must be an expression">;
-def err_template_arg_nontype_ambig : Error<
- "template argument for non-type template parameter is treated as type %0">;
-def err_template_arg_must_be_template : Error<
- "template argument for template template parameter must be a class template">;
-def err_template_arg_local_type : Error<"template argument uses local type %0">;
-def err_template_arg_unnamed_type : Error<
- "template argument uses unnamed type">;
-def note_template_unnamed_type_here : Note<
- "unnamed type used in template argument was declared here">;
-def err_template_arg_overload_type : Error<
- "template argument is the type of an unresolved overloaded function">;
-def err_template_arg_not_class_template : Error<
- "template argument does not refer to a class template or template "
- "template parameter">;
-def note_template_arg_refers_here_func : Note<
- "template argument refers to function template %0, here">;
-def err_template_arg_template_params_mismatch : Error<
- "template template argument has different template parameters than its "
- "corresponding template template parameter">;
-def err_template_arg_not_integral_or_enumeral : Error<
- "non-type template argument of type %0 must have an integral or enumeration"
- " type">;
-def err_template_arg_not_ice : Error<
- "non-type template argument of type %0 is not an integral constant "
- "expression">;
-def err_deduced_non_type_template_arg_type_mismatch : Error<
- "deduced non-type template argument does not have the same type as the "
- "its corresponding template parameter (%0 vs %1)">;
-def err_template_arg_not_convertible : Error<
- "non-type template argument of type %0 cannot be converted to a value "
- "of type %1">;
-def warn_template_arg_negative : Warning<
- "non-type template argument with value '%0' converted to '%1' for unsigned "
- "template parameter of type %2">;
-def warn_template_arg_too_large : Warning<
- "non-type template argument value '%0' truncated to '%1' for "
- "template parameter of type %2">;
-def err_template_arg_no_ref_bind : Error<
- "non-type template parameter of reference type %0 cannot bind to template "
- "argument of type %1">;
-def err_template_arg_ref_bind_ignores_quals : Error<
- "reference binding of non-type template parameter of type %0 to template "
- "argument of type %1 ignores qualifiers">;
-def err_template_arg_not_decl_ref : Error<
- "non-type template argument does not refer to any declaration">;
-def err_template_arg_not_object_or_func_form : Error<
- "non-type template argument does not directly refer to an object or "
- "function">;
-def err_template_arg_not_address_of : Error<
- "non-type template argument for template parameter of pointer type %0 must "
- "have its address taken">;
-def err_template_arg_address_of_non_pointer : Error<
- "address taken in non-type template argument for template parameter of "
- "reference type %0">;
-def err_template_arg_reference_var : Error<
- "non-type template argument of reference type %0 is not an object">;
-def err_template_arg_field : Error<
- "non-type template argument refers to non-static data member %0">;
-def err_template_arg_method : Error<
- "non-type template argument refers to non-static member function %0">;
-def err_template_arg_function_not_extern : Error<
- "non-template argument refers to function %0 with internal linkage">;
-def err_template_arg_object_not_extern : Error<
- "non-template argument refers to object %0 that does not have external "
- "linkage">;
-def note_template_arg_internal_object : Note<
- "non-template argument refers to %select{function|object}0 here">;
-def note_template_arg_refers_here : Note<"non-template argument refers here">;
-def err_template_arg_not_object_or_func : Error<
- "non-type template argument does not refer to an object or function">;
-def err_template_arg_not_pointer_to_member_form : Error<
- "non-type template argument is not a pointer to member constant">;
-def err_template_arg_extra_parens : Error<
- "non-type template argument cannot be surrounded by parentheses">;
-def err_pointer_to_member_type : Error<
- "invalid use of pointer to member type after %select{.*|->*}0">;
-
-// C++ template specialization
-def err_template_spec_unknown_kind : Error<
- "can only provide an explicit specialization for a class template, function "
- "template, or a member function, static data member, or member class of a "
- "class template">;
-def note_specialized_entity : Note<
- "explicitly specialized declaration is here">;
-def err_template_spec_decl_function_scope : Error<
- "explicit specialization of %0 in function scope">;
-def err_template_spec_decl_class_scope : Error<
- "explicit specialization of %0 in class scope">;
-def err_template_spec_decl_friend : Error<
- "cannot declare an explicit specialization in a friend">;
-def err_template_spec_decl_out_of_scope_global : Error<
- "%select{class template|class template partial|function template|member "
- "function|static data member|member class}0 specialization of %1 must "
- "originally be declared in the global scope">;
-def err_template_spec_decl_out_of_scope : Error<
- "%select{class template|class template partial|function template|member "
- "function|static data member|member class}0 specialization of %1 must "
- "originally be declared in namespace %2">;
-def err_template_spec_redecl_out_of_scope : Error<
- "%select{class template|class template partial|function template|member "
- "function|static data member|member class}0 specialization of %1 not in a "
- "namespace enclosing %2">;
-def err_template_spec_redecl_global_scope : Error<
- "%select{class template|class template partial|function template|member "
- "function|static data member|member class}0 specialization of %1 must occur "
- "at global scope">;
-def err_spec_member_not_instantiated : Error<
- "specialization of member %q0 does not specialize an instantiated member">;
-def note_specialized_decl : Note<"attempt to specialize declaration here">;
-def err_specialization_after_instantiation : Error<
- "explicit specialization of %0 after instantiation">;
-def note_instantiation_required_here : Note<
- "%select{implicit|explicit}0 instantiation first required here">;
-def err_template_spec_friend : Error<
- "template specialization declaration cannot be a friend">;
-def err_template_spec_default_arg : Error<
- "default argument not permitted on an explicit "
- "%select{instantiation|specialization}0 of function %1">;
-def err_not_class_template_specialization : Error<
- "cannot specialize a %select{dependent template|template template "
- "parameter}0">;
-
-// C++ class template specializations and out-of-line definitions
-def err_template_spec_needs_header : Error<
- "template specialization requires 'template<>'">;
-def err_template_spec_needs_template_parameters : Error<
- "template specialization or definition requires a template parameter list "
- "corresponding to the nested type %0">;
-def err_template_param_list_matches_nontemplate : Error<
- "template parameter list matching the non-templated nested type %0 should "
- "be empty ('template<>')">;
-def err_template_spec_extra_headers : Error<
- "extraneous template parameter list in template specialization or "
- "out-of-line template definition">;
-def warn_template_spec_extra_headers : Warning<
- "extraneous template parameter list in template specialization">;
-def note_explicit_template_spec_does_not_need_header : Note<
- "'template<>' header not required for explicitly-specialized class %0 "
- "declared here">;
-def err_template_qualified_declarator_no_match : Error<
- "nested name specifier '%0' for declaration does not refer into a class, "
- "class template or class template partial specialization">;
-
-// C++ Class Template Partial Specialization
-def err_default_arg_in_partial_spec : Error<
- "default template argument in a class template partial specialization">;
-def err_dependent_non_type_arg_in_partial_spec : Error<
- "non-type template argument depends on a template parameter of the "
- "partial specialization">;
-def err_dependent_typed_non_type_arg_in_partial_spec : Error<
- "non-type template argument specializes a template parameter with "
- "dependent type %0">;
-def err_partial_spec_args_match_primary_template : Error<
- "class template partial specialization does not specialize any template "
- "argument; to %select{declare|define}0 the primary template, remove the "
- "template argument list">;
-def warn_partial_specs_not_deducible : Warning<
- "class template partial specialization contains "
- "%select{a template parameter|template parameters}0 that can not be "
- "deduced; this partial specialization will never be used">;
-def note_partial_spec_unused_parameter : Note<
- "non-deducible template parameter %0">;
-def err_partial_spec_ordering_ambiguous : Error<
- "ambiguous partial specializations of %0">;
-def note_partial_spec_match : Note<"partial specialization matches %0">;
-def err_partial_spec_redeclared : Error<
- "class template partial specialization %0 cannot be redeclared">;
-def note_prev_partial_spec_here : Note<
- "previous declaration of class template partial specialization %0 is here">;
-def err_partial_spec_fully_specialized : Error<
- "partial specialization of %0 does not use any of its template parameters">;
-
-// C++ Function template specializations
-def err_function_template_spec_no_match : Error<
- "no function template matches function template specialization %0">;
-def err_function_template_spec_ambiguous : Error<
- "function template specialization %0 ambiguously refers to more than one "
- "function template; explicitly specify%select{|additional }1 template "
- "arguments to identify a particular function template">;
-def note_function_template_spec_matched : Note<
- "function template matches specialization %0">;
-
-// C++ Template Instantiation
-def err_template_recursion_depth_exceeded : Error<
- "recursive template instantiation exceeded maximum depth of %0">,
- DefaultFatal, NoSFINAE;
-def note_template_recursion_depth : Note<
- "use -ftemplate-depth-N to increase recursive template instantiation depth">;
-
-def err_template_instantiate_undefined : Error<
- "%select{implicit|explicit}0 instantiation of undefined template %1">;
-def err_implicit_instantiate_member_undefined : Error<
- "implicit instantiation of undefined member %0">;
-def note_template_class_instantiation_here : Note<
- "in instantiation of template class %0 requested here">;
-def note_template_member_class_here : Note<
- "in instantiation of member class %0 requested here">;
-def note_template_member_function_here : Note<
- "in instantiation of member function %q0 requested here">;
-def note_function_template_spec_here : Note<
- "in instantiation of function template specialization %q0 requested here">;
-def note_template_static_data_member_def_here : Note<
- "in instantiation of static data member %q0 requested here">;
-
-def note_default_arg_instantiation_here : Note<
- "in instantiation of default argument for '%0' required here">;
-def note_default_function_arg_instantiation_here : Note<
- "in instantiation of default function argument expression "
- "for '%0' required here">;
-def note_explicit_template_arg_substitution_here : Note<
- "while substituting explicitly-specified template arguments into function "
- "template %0 %1">;
-def note_function_template_deduction_instantiation_here : Note<
- "while substituting deduced template arguments into function template %0 "
- "%1">;
-def note_partial_spec_deduct_instantiation_here : Note<
- "during template argument deduction for class template partial "
- "specialization %0 %1">;
-def note_prior_template_arg_substitution : Note<
- "while substituting prior template arguments into %select{non-type|template}0"
- " template parameter%1 %2">;
-def note_template_default_arg_checking : Note<
- "while checking a default template argument used here">;
-def note_instantiation_contexts_suppressed : Note<
- "(skipping %0 context%s0 in backtrace; use -ftemplate-backtrace-limit=0 to "
- "see all)">;
-
-def err_field_instantiates_to_function : Error<
- "data member instantiated with function type %0">;
-def err_nested_name_spec_non_tag : Error<
- "type %0 cannot be used prior to '::' because it has no members">;
-
-// C++ Explicit Instantiation
-def err_explicit_instantiation_duplicate : Error<
- "duplicate explicit instantiation of %0">;
-def note_previous_explicit_instantiation : Note<
- "previous explicit instantiation is here">;
-def ext_explicit_instantiation_after_specialization : Extension<
- "explicit instantiation of %0 that occurs after an explicit "
- "specialization will be ignored (C++0x extension)">;
-def note_previous_template_specialization : Note<
- "previous template specialization is here">;
-def err_explicit_instantiation_enum : Error<
- "explicit instantiation of enumeration type %0">;
-def err_explicit_instantiation_nontemplate_type : Error<
- "explicit instantiation of non-templated type %0">;
-def note_nontemplate_decl_here : Note<
- "non-templated declaration is here">;
-def err_explicit_instantiation_in_class : Error<
- "explicit instantiation of %0 in class scope">;
-def err_explicit_instantiation_out_of_scope : Error<
- "explicit instantiation of %0 not in a namespace enclosing %1">;
-def err_explicit_instantiation_must_be_global : Error<
- "explicit instantiation of %0 must occur at global scope">;
-def warn_explicit_instantiation_out_of_scope_0x : Warning<
- "explicit instantiation of %0 not in a namespace enclosing %1">,
- InGroup<DiagGroup<"-Wc++0x-compat"> >;
-def warn_explicit_instantiation_must_be_global_0x : Warning<
- "explicit instantiation of %0 must occur at global scope">,
- InGroup<DiagGroup<"-Wc++0x-compat"> >;
-
-def err_explicit_instantiation_requires_name : Error<
- "explicit instantiation declaration requires a name">;
-def err_explicit_instantiation_of_typedef : Error<
- "explicit instantiation of typedef %0">;
-def err_explicit_instantiation_not_known : Error<
- "explicit instantiation of %0 does not refer to a function template, member "
- "function, member class, or static data member">;
-def note_explicit_instantiation_here : Note<
- "explicit instantiation refers here">;
-def err_explicit_instantiation_data_member_not_instantiated : Error<
- "explicit instantiation refers to static data member %q0 that is not an "
- "instantiation">;
-def err_explicit_instantiation_member_function_not_instantiated : Error<
- "explicit instantiation refers to member function %q0 that is not an "
- "instantiation">;
-def err_explicit_instantiation_ambiguous : Error<
- "partial ordering for explicit instantiation of %0 is ambiguous">;
-def note_explicit_instantiation_candidate : Note<
- "explicit instantiation candidate function template here %0">;
-def err_explicit_instantiation_inline : Error<
- "explicit instantiation cannot be 'inline'">;
-def ext_explicit_instantiation_without_qualified_id : ExtWarn<
- "qualifier in explicit instantiation of %q0 requires a template-id "
- "(a typedef is not permitted)">;
-def err_explicit_instantiation_unqualified_wrong_namespace : Error<
- "explicit instantiation of %q0 must occur in %1">;
-def warn_explicit_instantiation_unqualified_wrong_namespace_0x : Warning<
- "explicit instantiation of %q0 must occur in %1">,
- InGroup<DiagGroup<"c++0x-compat"> >;
-def err_explicit_instantiation_undefined_member : Error<
- "explicit instantiation of undefined %select{member class|member function|"
- "static data member}0 %1 of class template %2">;
-def err_explicit_instantiation_undefined_func_template : Error<
- "explicit instantiation of undefined function template %0">;
-def err_explicit_instantiation_declaration_after_definition : Error<
- "explicit instantiation declaration (with 'extern') follows explicit "
- "instantiation definition (without 'extern')">;
-def note_explicit_instantiation_definition_here : Note<
- "explicit instantiation definition is here">;
-
-// C++ typename-specifiers
-def err_typename_nested_not_found : Error<"no type named %0 in %1">;
-def err_typename_nested_not_type : Error<
- "typename specifier refers to non-type member %0 in %1">;
-def note_typename_refers_here : Note<
- "referenced member %0 is declared here">;
-def err_typename_missing : Error<
- "missing 'typename' prior to dependent type name '%0%1'">;
-def ext_typename_outside_of_template : ExtWarn<
- "'typename' occurs outside of a template">;
-
-def err_template_kw_refers_to_non_template : Error<
- "%0 following the 'template' keyword does not refer to a template">;
-def err_template_kw_refers_to_function_template : Error<
- "%0 following the 'template' keyword refers to a function template">;
-def err_template_kw_refers_to_class_template : Error<
- "'%0%1' instantiated to a class template, not a function template">;
-def note_referenced_class_template : Error<
- "class template declared here">;
-def err_template_kw_missing : Error<
- "missing 'template' keyword prior to dependent template name '%0%1'">;
-def ext_template_outside_of_template : ExtWarn<
- "'template' keyword outside of a template">;
-
-// C++0x Variadic Templates
-def err_template_param_pack_default_arg : Error<
- "template parameter pack cannot have a default argument">;
-def err_template_param_pack_must_be_last_template_parameter : Error<
- "template parameter pack must be the last template parameter">;
-
-def err_template_parameter_pack_non_pack : Error<
- "template %select{type|non-type|template}0 parameter%select{| pack}1 "
- "conflicts with previous template %select{type|non-type|template}0 "
- "parameter%select{ pack|}1">;
-def note_template_parameter_pack_non_pack : Note<
- "template %select{type|non-type|template}0 parameter%select{| pack}1 "
- "does not match template %select{type|non-type|template}0 "
- "parameter%select{ pack|}1 in template argument">;
-def note_template_parameter_pack_here : Note<
- "previous template %select{type|non-type|template}0 "
- "parameter%select{| pack}1 declared here">;
-
-def err_unexpected_typedef : Error<
- "unexpected type name %0: expected expression">;
-def err_unexpected_namespace : Error<
- "unexpected namespace name %0: expected expression">;
-def err_undeclared_var_use : Error<"use of undeclared identifier %0">;
-def note_dependent_var_use : Note<"must qualify identifier to find this "
- "declaration in dependent base class">;
-def err_undeclared_use : Error<"use of undeclared %0">;
-def warn_deprecated : Warning<"%0 is deprecated">,
- InGroup<DeprecatedDeclarations>;
-def err_unavailable : Error<"%0 is unavailable">;
-def note_unavailable_here : Note<
- "function has been explicitly marked %select{unavailable|deleted}0 here">;
-def warn_not_enough_argument : Warning<
- "not enough variable arguments in %0 declaration to fit a sentinel">;
-def warn_missing_sentinel : Warning <
- "missing sentinel in %select{function call|method dispatch|block call}0">;
-def note_sentinel_here : Note<
- "%select{function|method|block}0 has been explicitly marked sentinel here">;
-def warn_missing_prototype : Warning<
- "no previous prototype for function %0">,
- InGroup<DiagGroup<"missing-prototypes">>, DefaultIgnore;
-def err_redefinition : Error<"redefinition of %0">;
-def err_definition_of_implicitly_declared_member : Error<
- "definition of implicitly declared %select{constructor|copy constructor|"
- "copy assignment operator|destructor}1">;
-
-def warn_redefinition_of_typedef : Warning<
- "redefinition of typedef %0 is invalid in C">,
- InGroup<DiagGroup<"typedef-redefinition"> >, DefaultError;
-
-def err_static_non_static : Error<
- "static declaration of %0 follows non-static declaration">;
-def err_non_static_static : Error<
- "non-static declaration of %0 follows static declaration">;
-def err_non_thread_thread : Error<
- "non-thread-local declaration of %0 follows thread-local declaration">;
-def err_thread_non_thread : Error<
- "thread-local declaration of %0 follows non-thread-local declaration">;
-def err_redefinition_different_type : Error<
- "redefinition of %0 with a different type">;
-def err_redefinition_different_kind : Error<
- "redefinition of %0 as different kind of symbol">;
-def err_redefinition_different_typedef : Error<
- "typedef redefinition with different types (%0 vs %1)">;
-def err_tag_reference_non_tag : Error<
- "elaborated type refers to %select{a non-tag type|a typedef|a template}0">;
-def err_tag_reference_conflict : Error<
- "implicit declaration introduced by elaborated type conflicts with "
- "%select{a declaration|a typedef|a template}0 of the same name">;
-def err_dependent_tag_decl : Error<
- "%select{declaration|definition}0 of %select{struct|union|class|enum}1 "
- "in a dependent scope">;
-def err_tag_definition_of_typedef : Error<
- "definition of type %0 conflicts with typedef of the same name">;
-def err_conflicting_types : Error<"conflicting types for %0">;
-def err_nested_redefinition : Error<"nested redefinition of %0">;
-def err_use_with_wrong_tag : Error<
- "use of %0 with tag type that does not match previous declaration">;
-def warn_struct_class_tag_mismatch : Warning<
- "%select{struct|class}0 %select{|template}1 %2 was previously declared "
- "as a %select{class|struct}0 %select{|template}1">,
- InGroup<MismatchedTags>, DefaultIgnore;
-def ext_forward_ref_enum : Extension<
- "ISO C forbids forward references to 'enum' types">;
-def err_forward_ref_enum : Error<
- "ISO C++ forbids forward references to 'enum' types">;
-def ext_forward_ref_enum_def : Extension<
- "redeclaration of already-defined enum %0 is a GNU extension">, InGroup<GNU>;
-
-def err_redefinition_of_enumerator : Error<"redefinition of enumerator %0">;
-def err_duplicate_member : Error<"duplicate member %0">;
-def err_misplaced_ivar : Error<
- "ivars may not be placed in %select{categories|class extension}0">;
-def ext_enum_value_not_int : Extension<
- "ISO C restricts enumerator values to range of 'int' (%0 is too "
- "%select{small|large}1)">;
-def warn_enum_too_large : Warning<
- "enumeration values exceed range of largest integer">;
-def warn_enumerator_too_large : Warning<
- "enumerator value %0 is not representable in the largest integer type">;
-
-def warn_illegal_constant_array_size : Extension<
- "size of static array must be an integer constant expression">;
-def err_vm_decl_in_file_scope : Error<
- "variably modified type declaration not allowed at file scope">;
-def err_vm_decl_has_extern_linkage : Error<
- "variably modified type declaration can not have 'extern' linkage">;
-def err_typecheck_field_variable_size : Error<
- "fields must have a constant size: 'variable length array in structure' "
- "extension will never be supported">;
-def err_vm_func_decl : Error<
- "function declaration cannot have variably modified type">;
-
-def err_typecheck_negative_array_size : Error<"array size is negative">;
-def warn_typecheck_function_qualifiers : Warning<
- "qualifier on function type %0 has unspecified behavior">;
-def err_typecheck_invalid_restrict_not_pointer : Error<
- "restrict requires a pointer or reference (%0 is invalid)">;
-def err_typecheck_invalid_restrict_not_pointer_noarg : Error<
- "restrict requires a pointer or reference">;
-def err_typecheck_invalid_restrict_invalid_pointee : Error<
- "pointer to function type %0 may not be 'restrict' qualified">;
-def ext_typecheck_zero_array_size : Extension<
- "zero size arrays are an extension">;
-def err_typecheck_zero_array_size : Error<
- "zero-length arrays are not permitted in C++">;
-def err_at_least_one_initializer_needed_to_size_array : Error<
- "at least one initializer value required to size array">;
-def err_array_size_non_int : Error<"size of array has non-integer type %0">;
-def err_init_element_not_constant : Error<
- "initializer element is not a compile-time constant">;
-def err_block_extern_cant_init : Error<
- "'extern' variable cannot have an initializer">;
-def warn_extern_init : Warning<"'extern' variable has an initializer">;
-def err_variable_object_no_init : Error<
- "variable-sized object may not be initialized">;
-def err_array_init_list_required : Error<
- "initialization with '{...}' expected for array">;
-def err_excess_initializers : Error<
- "excess elements in %select{array|vector|scalar|union|struct}0 initializer">;
-def warn_excess_initializers : ExtWarn<
- "excess elements in %select{array|vector|scalar|union|struct}0 initializer">;
-def err_excess_initializers_in_char_array_initializer : Error<
- "excess elements in char array initializer">;
-def warn_excess_initializers_in_char_array_initializer : ExtWarn<
- "excess elements in char array initializer">;
-def warn_initializer_string_for_char_array_too_long : ExtWarn<
- "initializer-string for char array is too long">;
-def warn_missing_field_initializers : Warning<
- "missing field '%0' initializer">,
- InGroup<MissingFieldInitializers>, DefaultIgnore;
-def warn_braces_around_scalar_init : Warning<
- "braces around scalar initializer">;
-def err_many_braces_around_scalar_init : Error<
- "too many braces around scalar initializer">;
-def err_empty_scalar_initializer : Error<"scalar initializer cannot be empty">;
-def err_illegal_initializer : Error<
- "illegal initializer (only variables can be initialized)">;
-def err_illegal_initializer_type : Error<"illegal initializer type %0">;
-def err_init_objc_class : Error<
- "cannot initialize Objective-C class type %0">;
-def err_implicit_empty_initializer : Error<
- "initializer for aggregate with no elements requires explicit braces">;
-def err_bitfield_has_negative_width : Error<
- "bit-field %0 has negative width (%1)">;
-def err_anon_bitfield_has_negative_width : Error<
- "anonymous bit-field has negative width (%0)">;
-def err_bitfield_has_zero_width : Error<"named bit-field %0 has zero width">;
-def err_bitfield_width_exceeds_type_size : Error<
- "size of bit-field %0 (%1 bits) exceeds size of its type (%2 bits)">;
-def err_anon_bitfield_width_exceeds_type_size : Error<
- "size of anonymous bit-field (%0 bits) exceeds size of its type (%1 bits)">;
-
-// Used by C++ which allows bit-fields that are wider than the type.
-def warn_bitfield_width_exceeds_type_size: Warning<
- "size of bit-field %0 (%1 bits) exceeds the size of its type; value will be "
- "truncated to %2 bits">;
-def warn_anon_bitfield_width_exceeds_type_size : Warning<
- "size of anonymous bit-field (%0 bits) exceeds size of its type; value will "
- "be truncated to %1 bits">;
-
-def warn_missing_braces : Warning<
- "suggest braces around initialization of subobject">,
- InGroup<DiagGroup<"missing-braces">>, DefaultIgnore;
-
-def err_redefinition_of_label : Error<"redefinition of label '%0'">;
-def err_undeclared_label_use : Error<"use of undeclared label '%0'">;
-
-def err_goto_into_protected_scope : Error<"illegal goto into protected scope">;
-def err_switch_into_protected_scope : Error<
- "illegal switch case into protected scope">;
-def err_indirect_goto_without_addrlabel : Error<
- "indirect goto in function with no address-of-label expressions">;
-def warn_indirect_goto_in_protected_scope : Warning<
- "indirect goto might cross protected scopes">,
- InGroup<DiagGroup<"label-address-scope">>;
-def note_indirect_goto_target : Note<"possible target of indirect goto">;
-def note_protected_by_variable_init : Note<
- "jump bypasses variable initialization">;
-def note_protected_by_cleanup : Note<
- "jump bypasses initialization of variable with __attribute__((cleanup))">;
-def note_protected_by_vla_typedef : Note<
- "jump bypasses initialization of VLA typedef">;
-def note_protected_by_vla : Note<
- "jump bypasses initialization of variable length array">;
-def note_protected_by_objc_try : Note<
- "jump bypasses initialization of @try block">;
-def note_protected_by_objc_catch : Note<
- "jump bypasses initialization of @catch block">;
-def note_protected_by_objc_finally : Note<
- "jump bypasses initialization of @finally block">;
-def note_protected_by_objc_synchronized : Note<
- "jump bypasses initialization of @synchronized block">;
-def note_protected_by_cxx_try : Note<
- "jump bypasses initialization of try block">;
-def note_protected_by_cxx_catch : Note<
- "jump bypasses initialization of catch block">;
-def note_protected_by___block : Note<
- "jump bypasses setup of __block variable">;
-
-def note_exits_cleanup : Note<
- "jump exits scope of variable with __attribute__((cleanup))">;
-def note_exits_dtor : Note<
- "jump exits scope of variable with non-trivial destructor">;
-def note_exits___block : Note<
- "jump exits scope of __block variable">;
-def note_exits_objc_try : Note<
- "jump exits @try block">;
-def note_exits_objc_catch : Note<
- "jump exits @catch block">;
-def note_exits_objc_finally : Note<
- "jump exits @finally block">;
-def note_exits_objc_synchronized : Note<
- "jump exits @synchronized block">;
-def note_exits_cxx_try : Note<
- "jump exits try block">;
-def note_exits_cxx_catch : Note<
- "jump exits catch block">;
-
-def err_func_returning_array_function : Error<
- "function cannot return %select{array|function}0 type %1">;
-def err_field_declared_as_function : Error<"field %0 declared as a function">;
-def err_field_incomplete : Error<"field has incomplete type %0">;
-def ext_variable_sized_type_in_struct : ExtWarn<
- "field %0 with variable sized type %1 not at the end of a struct or class is"
- " a GNU extension">, InGroup<GNU>;
-
-def err_flexible_array_empty_struct : Error<
- "flexible array %0 not allowed in otherwise empty struct">;
-def err_flexible_array_has_nonpod_type : Error<
- "flexible array member %0 of non-POD element type %1">;
-def ext_flexible_array_in_struct : Extension<
- "%0 may not be nested in a struct due to flexible array member">;
-def ext_flexible_array_in_array : Extension<
- "%0 may not be used as an array element due to flexible array member">;
-def err_flexible_array_init_nonempty : Error<
- "non-empty initialization of flexible array member inside subobject">;
-def err_flexible_array_init_needs_braces : Error<
- "flexible array requires brace-enclosed initializer">;
-def err_illegal_decl_array_of_functions : Error<
- "'%0' declared as array of functions of type %1">;
-def err_illegal_decl_array_incomplete_type : Error<
- "array has incomplete element type %0">;
-def err_illegal_message_expr_incomplete_type : Error<
- "objective-c message has incomplete result type %0">;
-def err_illegal_decl_array_of_references : Error<
- "'%0' declared as array of references of type %1">;
-def err_array_star_outside_prototype : Error<
- "star modifier used outside of function prototype">;
-def err_illegal_decl_pointer_to_reference : Error<
- "'%0' declared as a pointer to a reference of type %1">;
-def err_illegal_decl_mempointer_to_reference : Error<
- "'%0' declared as a member pointer to a reference of type %1">;
-def err_illegal_decl_mempointer_to_void : Error<
- "'%0' declared as a member pointer to void">;
-def err_illegal_decl_mempointer_in_nonclass : Error<
- "'%0' does not point into a class">;
-def err_mempointer_in_nonclass_type : Error<
- "member pointer refers into non-class type %0">;
-def err_reference_to_void : Error<"cannot form a reference to 'void'">;
-def err_qualified_block_pointer_type : Error<
- "qualifier specification on block pointer type not allowed">;
-def err_nonfunction_block_type : Error<
- "block pointer to non-function type is invalid">;
-def err_return_block_has_expr : Error<"void block should not return a value">;
-def err_block_return_missing_expr : Error<
- "non-void block should return a value">;
-def err_block_with_return_type_requires_args : Error<
- "block with explicit return type requires argument list">;
-def err_func_def_incomplete_result : Error<
- "incomplete result type %0 in function definition">;
-
-// Expressions.
-def ext_sizeof_function_type : Extension<
- "invalid application of 'sizeof' to a function type">, InGroup<PointerArith>;
-def err_sizeof_alignof_overloaded_function_type : Error<
- "invalid application of '%select{sizeof|__alignof}0' to an overloaded "
- "function">;
-def ext_sizeof_void_type : Extension<
- "invalid application of '%0' to a void type">, InGroup<PointerArith>;
-def err_sizeof_alignof_incomplete_type : Error<
- "invalid application of '%select{sizeof|__alignof}0' to an incomplete type %1">;
-def err_sizeof_alignof_bitfield : Error<
- "invalid application of '%select{sizeof|__alignof}0' to bit-field">;
-def err_offsetof_incomplete_type : Error<
- "offsetof of incomplete type %0">;
-def err_offsetof_record_type : Error<
- "offsetof requires struct, union, or class type, %0 invalid">;
-def err_offsetof_array_type : Error<"offsetof requires array type, %0 invalid">;
-def ext_offsetof_extended_field_designator : Extension<
- "using extended field designator is an extension">;
-def warn_offsetof_non_pod_type : ExtWarn<"offset of on non-POD type %0">,
- InGroup<InvalidOffsetof>;
-def err_offsetof_bitfield : Error<"cannot compute offset of bit-field %0">;
-
-def warn_floatingpoint_eq : Warning<
- "comparing floating point with == or != is unsafe">,
- InGroup<DiagGroup<"float-equal">>, DefaultIgnore;
-
-def warn_division_by_zero : Warning<"division by zero is undefined">;
-def warn_remainder_by_zero : Warning<"remainder by zero is undefined">;
-def warn_shift_negative : Warning<"shift count is negative">;
-def warn_shift_gt_typewidth : Warning<"shift count >= width of type">;
-
-def warn_precedence_bitwise_rel : Warning<
- "%0 has lower precedence than %1; %1 will be evaluated first">,
- InGroup<Parentheses>;
-def note_precedence_bitwise_first : Note<
- "place parentheses around the %0 expression to evaluate it first">;
-def note_precedence_bitwise_silence : Note<
- "place parentheses around the %0 expression to silence this warning">;
-
-def warn_logical_instead_of_bitwise : Warning<
- "use of logical %0 with constant operand; switch to bitwise %1 or "
- "remove constant">, InGroup<DiagGroup<"constant-logical-operand">>;
-
-def err_sizeof_nonfragile_interface : Error<
- "invalid application of '%select{alignof|sizeof}1' to interface %0 in "
- "non-fragile ABI">;
-def err_atdef_nonfragile_interface : Error<
- "invalid application of @defs in non-fragile ABI">;
-def err_subscript_nonfragile_interface : Error<
- "subscript requires size of interface %0, which is not constant in "
- "non-fragile ABI">;
-
-def err_arithmetic_nonfragile_interface : Error<
- "arithmetic on pointer to interface %0, which is not a constant size in "
- "non-fragile ABI">;
-
-
-def ext_subscript_non_lvalue : Extension<
- "ISO C90 does not allow subscripting non-lvalue array">;
-def err_typecheck_subscript_value : Error<
- "subscripted value is not an array, pointer, or vector">;
-def err_typecheck_subscript_not_integer : Error<
- "array subscript is not an integer">;
-def err_subscript_function_type : Error<
- "subscript of pointer to function type %0">;
-def err_subscript_incomplete_type : Error<
- "subscript of pointer to incomplete type %0">;
-def err_typecheck_member_reference_struct_union : Error<
- "member reference base type %0 is not a structure or union">;
-def err_typecheck_member_reference_ivar : Error<
- "%0 does not have a member named %1">;
-def err_typecheck_member_reference_arrow : Error<
- "member reference type %0 is not a pointer">;
-def err_typecheck_member_reference_suggestion : Error<
- "member reference type %0 is %select{a|not a}1 pointer; maybe you meant to use '%select{->|.}1'?">;
-def err_typecheck_member_reference_type : Error<
- "cannot refer to type member %0 in %1 with '%select{.|->}2'">;
-def err_typecheck_member_reference_unknown : Error<
- "cannot refer to member %0 in %1 with '%select{.|->}2'">;
-def err_member_reference_needs_call : Error<
- "base of member reference has function type %0; perhaps you meant to call "
- "this function with '()'?">;
-def warn_subscript_is_char : Warning<"array subscript is of type 'char'">,
- InGroup<CharSubscript>, DefaultIgnore;
-
-def err_typecheck_incomplete_tag : Error<"incomplete definition of type %0">;
-def err_no_member : Error<"no member named %0 in %1">;
-
-def err_member_redeclared : Error<"class member cannot be redeclared">;
-def err_member_def_undefined_record : Error<
- "out-of-line definition of %0 from class %1 without definition">;
-def err_member_def_does_not_match : Error<
- "out-of-line definition of %0 does not match any declaration in %1">;
-def err_nonstatic_member_out_of_line : Error<
- "non-static data member defined out-of-line">;
-def err_qualified_typedef_declarator : Error<
- "typedef declarator cannot be qualified">;
-def err_qualified_param_declarator : Error<
- "parameter declarator cannot be qualified">;
-def ext_out_of_line_declaration : ExtWarn<
- "out-of-line declaration of a member must be a definition">,
- InGroup<OutOfLineDeclaration>, DefaultError;
-def note_member_def_close_match : Note<"member declaration nearly matches">;
-def err_typecheck_ivar_variable_size : Error<
- "instance variables must have a constant size">;
-def err_ivar_reference_type : Error<
- "instance variables cannot be of reference type">;
-def err_typecheck_illegal_increment_decrement : Error<
- "cannot %select{decrement|increment}1 value of type %0">;
-def err_typecheck_arithmetic_incomplete_type : Error<
- "arithmetic on pointer to incomplete type %0">;
-def err_typecheck_pointer_arith_function_type : Error<
- "arithmetic on pointer to function type %0">;
-def err_typecheck_pointer_arith_void_type : Error<
- "arithmetic on pointer to void type">;
-def err_typecheck_decl_incomplete_type : Error<
- "variable has incomplete type %0">;
-def ext_typecheck_decl_incomplete_type : ExtWarn<
- "tentative definition of variable with internal linkage has incomplete non-array type %0">;
-def err_tentative_def_incomplete_type : Error<
- "tentative definition has type %0 that is never completed">;
-def err_tentative_def_incomplete_type_arr : Error<
- "tentative definition has array of type %0 that is never completed">;
-def warn_tentative_incomplete_array : Warning<
- "tentative array definition assumed to have one element">;
-def err_typecheck_incomplete_array_needs_initializer : Error<
- "definition of variable with array type needs an explicit size "
- "or an initializer">;
-def err_array_init_not_init_list : Error<
- "array initializer must be an initializer "
- "list%select{| or string literal}0">;
-def warn_deprecated_string_literal_conversion : Warning<
- "conversion from string literal to %0 is deprecated">, InGroup<Deprecated>;
-def err_realimag_invalid_type : Error<"invalid type %0 to %1 operator">;
-def err_typecheck_sclass_fscope : Error<
- "illegal storage class on file-scoped variable">;
-def err_unsupported_global_register : Error<
- "global register variables are not supported">;
-def err_typecheck_sclass_func : Error<"illegal storage class on function">;
-def err_static_block_func : Error<
- "function declared in block scope cannot have 'static' storage class">;
-def err_typecheck_address_of : Error<"address of %0 requested">;
-def ext_typecheck_addrof_void : Extension<
- "ISO C forbids taking the address of an expression of type 'void'">;
-def err_unqualified_pointer_member_function : Error<
- "must explicitly qualify member function %0 when taking its address">;
-def err_typecheck_invalid_lvalue_addrof : Error<
- "address expression must be an lvalue or a function designator">;
-def ext_typecheck_addrof_class_temporary : ExtWarn<
- "taking the address of a temporary object of type %0">,
- InGroup<DiagGroup<"address-of-temporary">>, DefaultError;
-def err_typecheck_addrof_class_temporary : Error<
- "taking the address of a temporary object of type %0">;
-def err_typecheck_unary_expr : Error<
- "invalid argument type %0 to unary expression">;
-def err_typecheck_indirection_requires_pointer : Error<
- "indirection requires pointer operand (%0 invalid)">;
-def warn_indirection_through_null : Warning<
- "indirection of non-volatile null pointer will be deleted, not trap">;
-def note_indirection_through_null : Note<
- "consider using __builtin_trap() or qualifying pointer with 'volatile'">;
-
-def err_indirection_requires_nonfragile_object : Error<
- "indirection cannot be to an interface in non-fragile ABI (%0 invalid)">;
-def err_direct_interface_unsupported : Error<
- "indirection to an interface is not supported (%0 invalid)">;
-def err_typecheck_invalid_operands : Error<
- "invalid operands to binary expression (%0 and %1)">;
-def err_typecheck_sub_ptr_object : Error<
- "subtraction of pointer %0 requires pointee to be a complete object type">;
-def err_typecheck_sub_ptr_compatible : Error<
- "%0 and %1 are not pointers to compatible types">;
-def ext_typecheck_ordered_comparison_of_pointer_integer : ExtWarn<
- "ordered comparison between pointer and integer (%0 and %1)">;
-def ext_typecheck_ordered_comparison_of_pointer_and_zero : Extension<
- "ordered comparison between pointer and zero (%0 and %1) is an extension">;
-def ext_typecheck_ordered_comparison_of_function_pointers : ExtWarn<
- "ordered comparison of function pointers (%0 and %1)">;
-def ext_typecheck_comparison_of_fptr_to_void : Extension<
- "equality comparison between function pointer and void pointer (%0 and %1)">;
-def err_typecheck_comparison_of_fptr_to_void : Error<
- "equality comparison between function pointer and void pointer (%0 and %1)">;
-def ext_typecheck_comparison_of_pointer_integer : ExtWarn<
- "comparison between pointer and integer (%0 and %1)">;
-def err_typecheck_comparison_of_pointer_integer : Error<
- "comparison between pointer and integer (%0 and %1)">;
-def ext_typecheck_comparison_of_distinct_pointers : ExtWarn<
- "comparison of distinct pointer types (%0 and %1)">;
-def ext_typecheck_cond_incompatible_operands : ExtWarn<
- "incompatible operand types (%0 and %1)">;
-def err_typecheck_comparison_of_distinct_pointers : Error<
- "comparison of distinct pointer types (%0 and %1)">;
-def ext_typecheck_comparison_of_distinct_pointers_nonstandard : ExtWarn<
- "comparison of distinct pointer types (%0 and %1) uses non-standard "
- "composite pointer type %2">;
-def err_typecheck_vector_comparison : Error<
- "comparison of vector types (%0 and %1) not supported yet">;
-def err_typecheck_assign_const : Error<"read-only variable is not assignable">;
-def err_stmtexpr_file_scope : Error<
- "statement expression not allowed at file scope">;
-def warn_mixed_sign_comparison : Warning<
- "comparison of integers of different signs: %0 and %1">,
- InGroup<SignCompare>, DefaultIgnore;
-def warn_mixed_sign_conditional : Warning<
- "operands of ? are integers of different signs: %0 and %1">,
- InGroup<SignCompare>, DefaultIgnore;
-def warn_lunsigned_always_true_comparison : Warning<
- "comparison of unsigned expression %0 is always %1">,
- InGroup<SignCompare>, DefaultIgnore;
-def warn_runsigned_always_true_comparison : Warning<
- "comparison of %0 unsigned expression is always %1">,
- InGroup<SignCompare>, DefaultIgnore;
-
-def err_invalid_this_use : Error<
- "invalid use of 'this' outside of a nonstatic member function">;
-def err_invalid_member_use_in_static_method : Error<
- "invalid use of member %0 in static member function">;
-def err_invalid_qualified_function_type : Error<
- "type qualifier is not allowed on this function">;
-def err_invalid_qualified_function_pointer : Error<
- "type qualifier is not allowed on this function %select{pointer|reference}0">;
-def err_invalid_qualified_typedef_function_type_use : Error<
- "a qualified function type cannot be used to declare a "
- "%select{static member|nonmember}0 function">;
-
-def err_invalid_non_static_member_use : Error<
- "invalid use of nonstatic data member %0">;
-def err_invalid_incomplete_type_use : Error<
- "invalid use of incomplete type %0">;
-def err_builtin_func_cast_more_than_one_arg : Error<
- "function-style cast to a builtin type can only take one argument">;
-def err_builtin_direct_init_more_than_one_arg : Error<
- "initializer of a builtin type can only take one argument">;
-def err_value_init_for_array_type : Error<
- "array types cannot be value-initialized">;
-def warn_format_nonliteral_noargs : Warning<
- "format string is not a string literal (potentially insecure)">,
- InGroup<FormatSecurity>;
-def warn_format_nonliteral : Warning<
- "format string is not a string literal">,
- InGroup<FormatNonLiteral>, DefaultIgnore;
-
-def err_unexpected_interface : Error<
- "unexpected interface name %0: expected expression">;
-def err_ref_non_value : Error<"%0 does not refer to a value">;
-def err_ref_vm_type : Error<
- "cannot refer to declaration with a variably modified type inside block">;
-def err_ref_array_type : Error<
- "cannot refer to declaration with an array type inside block">;
-def err_property_not_found : Error<
- "property %0 not found on object of type %1">;
-def err_duplicate_property : Error<
- "property has a previous declaration">;
-def ext_gnu_void_ptr : Extension<
- "use of GNU void* extension">, InGroup<PointerArith>;
-def ext_gnu_ptr_func_arith : Extension<
- "arithmetic on pointer to function type %0 is a GNU extension">,
- InGroup<PointerArith>;
-def error_readonly_property_assignment : Error<
- "assigning to property with 'readonly' attribute not allowed">;
-def ext_integer_increment_complex : Extension<
- "ISO C does not support '++'/'--' on complex integer type %0">;
-def ext_integer_complement_complex : Extension<
- "ISO C does not support '~' for complex conjugation of %0">;
-def error_nosetter_property_assignment : Error<
- "setter method is needed to assign to object using property" " assignment syntax">;
-def error_no_subobject_property_setting : Error<
- "expression is not assignable using property assignment syntax">;
-
-def ext_freestanding_complex : Extension<
- "complex numbers are an extension in a freestanding C99 implementation">;
-
-
-// Obj-c expressions
-def warn_root_inst_method_not_found : Warning<
- "instance method %0 is being used on 'Class' which is not in the root class">;
-def warn_class_method_not_found : Warning<
- "method %objcclass0 not found (return type defaults to 'id')">;
-def warn_inst_method_not_found : Warning<
- "method %objcinstance0 not found (return type defaults to 'id')">;
-def error_no_super_class_message : Error<
- "no @interface declaration found in class messaging of %0">;
-def error_no_super_class : Error<
- "no super class declared in @interface for %0">;
-def err_invalid_receiver_to_message : Error<
- "invalid receiver to message expression">;
-def err_invalid_receiver_to_message_super : Error<
- "'super' is only valid in a method body">;
-def err_invalid_receiver_class_message : Error<
- "receiver type %0 is not an Objective-C class">;
-def warn_bad_receiver_type : Warning<
- "receiver type %0 is not 'id' or interface pointer, consider "
- "casting it to 'id'">;
-def err_bad_receiver_type : Error<"bad receiver type %0">;
-def err_unknown_receiver_suggest : Error<
- "unknown receiver %0; did you mean %1?">;
-def error_objc_throw_expects_object : Error<
- "@throw requires an Objective-C object type (%0 invalid)">;
-def error_objc_synchronized_expects_object : Error<
- "@synchronized requires an Objective-C object type (%0 invalid)">;
-def error_rethrow_used_outside_catch : Error<
- "@throw (rethrow) used outside of a @catch block">;
-def err_attribute_multiple_objc_gc : Error<
- "multiple garbage collection attributes specified for type">;
-def err_catch_param_not_objc_type : Error<
- "@catch parameter is not a pointer to an interface type">;
-def err_illegal_qualifiers_on_catch_parm : Error<
- "illegal qualifiers on @catch parameter">;
-def err_storage_spec_on_catch_parm : Error<
- "@catch parameter cannot have storage specifier %select{|'typedef'|'extern'|"
- "'static'|'auto'|'register'|'__private_extern__'|'mutable'}0">;
-def warn_register_objc_catch_parm : Warning<
- "'register' storage specifier on @catch parameter will be ignored">;
-def err_qualified_objc_catch_parm : Error<
- "@catch parameter declarator cannot be qualified">;
-def err_objc_pointer_cxx_catch_gnu : Error<
- "can't catch Objective C exceptions in C++ in the GNU runtime">;
-def err_objc_pointer_cxx_catch_fragile : Error<
- "can't catch Objective C exceptions in C++ in the non-unified "
- "exception model">;
-def err_objc_object_catch : Error<
- "can't catch an Objective C object by value">;
-
-def warn_setter_getter_impl_required : Warning<
- "property %0 requires method %1 to be defined - "
- "use @synthesize, @dynamic or provide a method implementation">;
-def warn_setter_getter_impl_required_in_category : Warning<
- "property %0 requires method %1 to be defined - "
- "use @dynamic or provide a method implementation in category">;
-def note_property_impl_required : Note<
- "implementation is here">;
-def note_parameter_named_here : Note<
- "passing argument to parameter %0 here">;
-def note_parameter_here : Note<
- "passing argument to parameter here">;
-
-// C++ casts
-// These messages adhere to the TryCast pattern: %0 is an int specifying the
-// cast type, %1 is the source type, %2 is the destination type.
-def err_bad_cxx_cast_generic : Error<
- "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|"
- "functional-style cast}0 from %1 to %2 is not allowed">;
-def err_bad_cxx_cast_rvalue : Error<
- "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|"
- "functional-style cast}0 from rvalue to reference type %2">;
-def err_bad_cxx_cast_const_away : Error<
- "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|"
- "functional-style cast}0 from %1 to %2 casts away constness">;
-def err_bad_const_cast_dest : Error<
- "%select{const_cast||||C-style cast|functional-style cast}0 to %2, "
- "which is not a reference, pointer-to-object, or pointer-to-data-member">;
-def ext_cast_fn_obj : Extension<
- "cast between pointer-to-function and pointer-to-object is an extension">;
-def err_bad_reinterpret_cast_small_int : Error<
- "cast from pointer to smaller type %2 loses information">;
-def err_bad_cxx_cast_vector_to_scalar_different_size : Error<
- "%select{||reinterpret_cast||C-style cast|}0 from vector %1 "
- "to scalar %2 of different size">;
-def err_bad_cxx_cast_scalar_to_vector_different_size : Error<
- "%select{||reinterpret_cast||C-style cast|}0 from scalar %1 "
- "to vector %2 of different size">;
-def err_bad_cxx_cast_vector_to_vector_different_size : Error<
- "%select{||reinterpret_cast||C-style cast|}0 from vector %1 "
- "to vector %2 of different size">;
-def err_bad_lvalue_to_rvalue_cast : Error<
- "cannot cast from lvalue of type %1 to rvalue reference type %2; types are "
- "not compatible">;
-def err_bad_static_cast_pointer_nonpointer : Error<
- "cannot cast from type %1 to pointer type %2">;
-def err_bad_static_cast_member_pointer_nonmp : Error<
- "cannot cast from type %1 to member pointer type %2">;
-def err_bad_static_cast_incomplete : Error<"%0 is an incomplete type">;
-
-// These messages don't adhere to the pattern.
-// FIXME: Display the path somehow better.
-def err_ambiguous_base_to_derived_cast : Error<
- "ambiguous cast from base %0 to derived %1:%2">;
-def err_static_downcast_via_virtual : Error<
- "cannot cast %0 to %1 via virtual base %2">;
-def err_downcast_from_inaccessible_base : Error<
- "cannot cast %select{private|protected}2 base class %1 to %0">;
-def err_upcast_to_inaccessible_base : Error<
- "cannot cast %0 to its %select{private|protected}2 base class %1">;
-def err_bad_dynamic_cast_not_ref_or_ptr : Error<
- "%0 is not a reference or pointer">;
-def err_bad_dynamic_cast_not_class : Error<"%0 is not a class">;
-def err_bad_dynamic_cast_incomplete : Error<"%0 is an incomplete type">;
-def err_bad_dynamic_cast_not_ptr : Error<"%0 is not a pointer">;
-def err_bad_dynamic_cast_not_polymorphic : Error<"%0 is not polymorphic">;
-
-// Other C++ expressions
-def err_need_header_before_typeid : Error<
- "you need to include <typeinfo> before using the 'typeid' operator">;
-def err_incomplete_typeid : Error<"'typeid' of incomplete type %0">;
-def err_static_illegal_in_new : Error<
- "the 'static' modifier for the array size is not legal in new expressions">;
-def err_array_new_needs_size : Error<
- "array size must be specified in new expressions">;
-def err_bad_new_type : Error<
- "cannot allocate %select{function|reference}1 type %0 with new">;
-def err_new_incomplete_type : Error<
- "allocation of incomplete type %0">;
-def err_new_array_nonconst : Error<
- "only the first dimension of an allocated array may have dynamic size">;
-def err_new_array_init_args : Error<
- "array 'new' cannot have initialization arguments">;
-def ext_new_paren_array_nonconst : ExtWarn<
- "when type is in parentheses, array cannot have dynamic size">;
-def err_placement_new_non_placement_delete : Error<
- "'new' expression with placement arguments refers to non-placement "
- "'operator delete'">;
-def err_array_size_not_integral : Error<
- "array size expression must have integral or enumerated type, not %0">;
-def err_array_size_incomplete_type : Error<
- "array size expression has incomplete class type %0">;
-def err_array_size_explicit_conversion : Error<
- "array size expression of type %0 requires explicit conversion to type %1">;
-def note_array_size_conversion : Note<
- "conversion to %select{integral|enumeration}0 type %1 declared here">;
-def err_array_size_ambiguous_conversion : Error<
- "ambiguous conversion of array size expression of type %0 to an integral or "
- "enumeration type">;
-def ext_array_size_conversion : Extension<
- "implicit conversion from array size expression of type %0 to "
- "%select{integral|enumeration}1 type %2 is a C++0x extension">;
-
-def err_default_init_const : Error<
- "default initialization of an object of const type %0"
- "%select{| requires a user-provided default constructor}1">;
-def err_delete_operand : Error<"cannot delete expression of type %0">;
-def ext_delete_void_ptr_operand : ExtWarn<
- "cannot delete expression with pointer-to-'void' type %0">;
-def err_ambiguous_delete_operand : Error<"ambiguous conversion of delete "
- "expression of type %0 to a pointer">;
-def warn_delete_incomplete : Warning<
- "deleting pointer to incomplete type %0 may cause undefined behaviour">;
-def err_delete_incomplete_class_type : Warning<
- "deleting incomplete class type %0; no conversions to pointer type">;
-def err_no_suitable_delete_member_function_found : Error<
- "no suitable member %0 in %1">;
-def note_member_declared_here : Note<
- "member %0 declared here">;
-def err_decrement_bool : Error<"cannot decrement expression of type bool">;
-def warn_increment_bool : Warning<
- "incrementing expression of type bool is deprecated">, InGroup<Deprecated>;
-def ext_catch_incomplete_ptr : ExtWarn<
- "ISO C++ forbids catching a pointer to incomplete type %0">;
-def ext_catch_incomplete_ref : ExtWarn<
- "ISO C++ forbids catching a reference to incomplete type %0">;
-def err_catch_incomplete : Error<"cannot catch incomplete type %0">;
-def err_catch_rvalue_ref : Error<"cannot catch exceptions by rvalue reference">;
-def err_qualified_catch_declarator : Error<
- "exception declarator cannot be qualified">;
-def err_early_catch_all : Error<"catch-all handler must come last">;
-def err_bad_memptr_rhs : Error<
- "right hand operand to %0 has non pointer-to-member type %1">;
-def err_memptr_rhs_to_incomplete : Error<
- "cannot dereference pointer into incomplete class type %0">;
-def err_bad_memptr_lhs : Error<
- "left hand operand to %0 must be a %select{|pointer to }1class "
- "compatible with the right hand operand, but is %2">;
-def warn_exception_caught_by_earlier_handler : Warning<
- "exception of type %0 will be caught by earlier handler">;
-def note_previous_exception_handler : Note<"for type %0">;
-
-def err_conditional_void_nonvoid : Error<
- "%select{left|right}1 operand to ? is void, but %select{right|left}1 operand "
- "is of type %0">;
-def err_conditional_ambiguous : Error<
- "conditional expression is ambiguous; %0 can be converted to %1 "
- "and vice versa">;
-def err_conditional_ambiguous_ovl : Error<
- "conditional expression is ambiguous; %0 and %1 can be converted to several "
- "common types">;
-
-def err_throw_incomplete : Error<
- "cannot throw object of incomplete type %0">;
-def err_throw_incomplete_ptr : Error<
- "cannot throw pointer to object of incomplete type %0">;
-def err_return_in_constructor_handler : Error<
- "return in the catch of a function try block of a constructor is illegal">;
-
-def err_operator_arrow_circular : Error<
- "circular pointer delegation detected">;
-def err_pseudo_dtor_base_not_scalar : Error<
- "object expression of non-scalar type %0 cannot be used in a "
- "pseudo-destructor expression">;
-def err_pseudo_dtor_type_mismatch : Error<
- "the type of object expression (%0) does not match the type being destroyed "
- "(%1) in pseudo-destructor expression">;
-def err_pseudo_dtor_call_with_args : Error<
- "call to pseudo-destructor cannot have any arguments">;
-def err_dtor_expr_without_call : Error<
- "%select{destructor reference|pseudo-destructor expression}0 must be "
- "called immediately with '()'">;
-def err_pseudo_dtor_destructor_non_type : Error<
- "%0 does not refer to a type name in pseudo-destructor expression; expected "
- "the name of type %1">;
-def err_pseudo_dtor_template : Error<
- "specialization of template %0 does not refer to a scalar type in pseudo-"
- "destructor expression">;
-def err_invalid_use_of_function_type : Error<
- "a function type is not allowed here">;
-def err_invalid_use_of_array_type : Error<"an array type is not allowed here">;
-def err_type_defined_in_condition : Error<
- "types may not be defined in conditions">;
-def err_typecheck_bool_condition : Error<
- "value of type %0 is not contextually convertible to 'bool'">;
-def err_typecheck_ambiguous_condition : Error<
- "conversion from %0 to %1 is ambiguous">;
-def err_typecheck_nonviable_condition : Error<
- "no viable conversion from %0 to %1">;
-def err_typecheck_deleted_function : Error<
- "conversion function from %0 to %1 invokes a deleted function">;
-
-def err_expected_class_or_namespace : Error<"expected a class or namespace">;
-def err_missing_qualified_for_redecl : Error<
- "must qualify the name %0 to declare %q1 in this scope">;
-def err_invalid_declarator_scope : Error<
- "definition or redeclaration of %0 not in a namespace enclosing %1">;
-def err_invalid_declarator_global_scope : Error<
- "definition or redeclaration of %0 cannot name the global scope">;
-def err_invalid_declarator_in_function : Error<
- "definition or redeclaration of %0 not allowed inside a function">;
-def err_not_tag_in_scope : Error<
- "no %select{struct|union|class|enum}0 named %1 in %2">;
-
-def err_cannot_form_pointer_to_member_of_reference_type : Error<
- "cannot form a pointer-to-member to member %0 of reference type %1">;
-def err_incomplete_object_call : Error<
- "incomplete type in call to object of type %0">;
-def err_incomplete_pointer_to_member_return : Error<
- "incomplete return type %0 of pointer-to-member constant">;
-
-def warn_condition_is_assignment : Warning<"using the result of an "
- "assignment as a condition without parentheses">,
- InGroup<Parentheses>;
-// Completely identical except off by default.
-def warn_condition_is_idiomatic_assignment : Warning<"using the result "
- "of an assignment as a condition without parentheses">,
- InGroup<DiagGroup<"idiomatic-parentheses">>, DefaultIgnore;
-def note_condition_assign_to_comparison : Note<
- "use '==' to turn this assignment into an equality comparison">;
-def note_condition_assign_silence : Note<
- "place parentheses around the assignment to silence this warning">;
-
-def warn_value_always_zero : Warning<
- "%0 is always %select{zero|false|NULL}1 in this context">;
-
-def warn_ivar_variable_conflict : Warning<
- "%0 lookup will access the property ivar in nonfragile-abi2 mode">,
- InGroup<NonfragileAbi2>;
-
-// assignment related diagnostics (also for argument passing, returning, etc).
-// In most of these diagnostics the %2 is a value from the
-// Sema::AssignmentAction enumeration
-def err_typecheck_convert_incompatible : Error<
- "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
- " %0 "
- "%select{from incompatible type|to parameter of incompatible type|"
- "from a function with incompatible result type|to incompatible type|"
- "with an expression of incompatible type|to parameter of incompatible type|"
- "to incompatible type}2 %1">;
-def warn_incompatible_qualified_id : Warning<
- "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
- " %0 "
- "%select{from incompatible type|to parameter of incompatible type|"
- "from a function with incompatible result type|to incompatible type|"
- "with an expression of incompatible type|to parameter of incompatible type|"
- "to incompatible type}2 %1">;
-def ext_typecheck_convert_pointer_int : ExtWarn<
- "incompatible pointer to integer conversion "
- "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
- " %0 "
- "%select{from|to parameter of type|from a function with result type|to type|"
- "with an expression of type|to parameter of type|to type}2 %1">;
-def ext_typecheck_convert_int_pointer : ExtWarn<
- "incompatible integer to pointer conversion "
- "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
- " %0 "
- "%select{from|to parameter of type|from a function with result type|to type|"
- "with an expression of type|to parameter of type|to type}2 %1">;
-def ext_typecheck_convert_pointer_void_func : Extension<
- "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
- " %0 "
- "%select{from|to parameter of type|from a function with result type|to type|"
- "with an expression of type|to parameter of type|to type}2 %1 "
- "converts between void pointer and function pointer">;
-def ext_typecheck_convert_incompatible_pointer_sign : ExtWarn<
- "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
- " %0 "
- "%select{from|to parameter of type|from a function with result type|to type|"
- "with an expression of type|to parameter of type|to type}2 %1 "
- "converts between pointers to integer types with different sign">,
- InGroup<DiagGroup<"pointer-sign">>;
-def ext_typecheck_convert_incompatible_pointer : ExtWarn<
- "incompatible pointer types "
- "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
- " %0 "
- "%select{from|to parameter of type|from a function with result type|to type|"
- "with an expression of type|to parameter of type|to type}2 %1">;
-def ext_typecheck_convert_discards_qualifiers : ExtWarn<
- "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
- " %0 "
- "%select{from|to parameter of type|from a function with result type|to type|"
- "with an expression of type|to parameter of type|to type}2 %1 discards "
- "qualifiers">;
-def ext_nested_pointer_qualifier_mismatch : ExtWarn<
- "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
- " %0 "
- "%select{from|to parameter of type|from a function with result type|to type|"
- "with an expression of type|to parameter of type|to type}2 %1 discards "
- "qualifiers in nested pointer types">;
-def warn_incompatible_vectors : Warning<
- "incompatible vector types "
- "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
- " %0 "
- "%select{from|to parameter of type|from a function with result type|to type|"
- "with an expression of type|to parameter of type|to type}2 %1">,
- InGroup<VectorConversions>, DefaultIgnore;
-def err_int_to_block_pointer : Error<
- "invalid block pointer conversion "
- "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
- " %0 "
- "%select{from|to parameter of type|from a function with result type|to type|"
- "with an expression of type|to parameter of type|to type}2 %1">;
-def err_typecheck_convert_incompatible_block_pointer : Error<
- "incompatible block pointer types "
- "%select{assigning to|passing|returning|converting|initializing|sending|casting}2"
- " %0 "
- "%select{from|to parameter of type|from a function with result type|to type|"
- "with an expression of type|to parameter of type|to type}2 %1">;
-
-def err_typecheck_convert_ambiguous : Error<
- "ambiguity in initializing value of type %0 with initializer of type %1">;
-def err_cannot_initialize_decl_noname : Error<
- "cannot initialize a value of type %0 with an %select{rvalue|lvalue}1 "
- "of type %2">;
-def err_cannot_initialize_decl : Error<
- "cannot initialize %0 with an %select{rvalue|lvalue}1 of type %2">;
-def err_typecheck_comparison_of_distinct_blocks : Error<
- "comparison of distinct block types (%0 and %1)">;
-
-def err_typecheck_array_not_modifiable_lvalue : Error<
- "array type %0 is not assignable">;
-def err_typecheck_non_object_not_modifiable_lvalue : Error<
- "non-object type %0 is not assignable">;
-def err_typecheck_expression_not_modifiable_lvalue : Error<
- "expression is not assignable">;
-def err_typecheck_incomplete_type_not_modifiable_lvalue : Error<
- "incomplete type %0 is not assignable">;
-def err_typecheck_lvalue_casts_not_supported : Error<
- "assignment to cast is illegal, lvalue casts are not supported">;
-
-def err_typecheck_duplicate_vector_components_not_mlvalue : Error<
- "vector is not assignable (contains duplicate components)">;
-def err_block_decl_ref_not_modifiable_lvalue : Error<
- "variable is not assignable (missing __block type specifier)">;
-def err_typecheck_call_not_function : Error<
- "called object type %0 is not a function or function pointer">;
-def err_call_incomplete_return : Error<
- "calling function with incomplete return type %0">;
-def err_call_function_incomplete_return : Error<
- "calling %0 with incomplete return type %1">;
-def note_function_with_incomplete_return_type_declared_here : Note<
- "%0 declared here">;
-def err_call_incomplete_argument : Error<
- "argument type %0 is incomplete">;
-def err_typecheck_call_too_few_args : Error<
- "too few arguments to %select{function|block|method}0 call, "
- "expected %1, have %2">;
-def err_typecheck_call_too_few_args_at_least : Error<
- "too few arguments to %select{function|block|method}0 call, "
- "expected at least %1, have %2">;
-def err_typecheck_call_too_many_args : Error<
- "too many arguments to %select{function|block|method}0 call, "
- "expected %1, have %2">;
-def err_typecheck_call_too_many_args_at_most : Error<
- "too many arguments to %select{function|block|method}0 call, "
- "expected at most %1, have %2">;
-def warn_call_wrong_number_of_arguments : Warning<
- "too %select{few|many}0 arguments in call to %1">;
-def err_atomic_builtin_must_be_pointer : Error<
- "first argument to atomic builtin must be a pointer (%0 invalid)">;
-def err_atomic_builtin_must_be_pointer_intptr : Error<
- "first argument to atomic builtin must be a pointer to integer or pointer"
- " (%0 invalid)">;
-def err_atomic_builtin_pointer_size : Error<
- "first argument to atomic builtin must be a pointer to 1,2,4,8 or 16 byte "
- "type (%0 invalid)">;
-
-
-def err_deleted_function_use : Error<"attempt to use a deleted function">;
-
-def err_cannot_pass_objc_interface_to_vararg : Error<
- "cannot pass object with interface type %0 by-value through variadic "
- "%select{function|block|method}1">;
-
-def warn_cannot_pass_non_pod_arg_to_vararg : Warning<
- "cannot pass object of non-POD type %0 through variadic "
- "%select{function|block|method|constructor}1; call will abort at runtime">,
- InGroup<DiagGroup<"non-pod-varargs">>, DefaultError;
-
-def err_typecheck_call_invalid_ordered_compare : Error<
- "ordered compare requires two args of floating point type (%0 and %1)">;
-def err_typecheck_call_invalid_unary_fp : Error<
- "floating point classification requires argument of floating point type "
- "(passed in %0)">;
-def err_typecheck_cond_expect_scalar : Error<
- "used type %0 where arithmetic or pointer type is required">;
-def ext_typecheck_cond_one_void : Extension<
- "C99 forbids conditional expressions with only one void side">;
-def err_typecheck_cast_to_incomplete : Error<
- "cast to incomplete type %0">;
-def ext_typecheck_cast_nonscalar : Extension<
- "C99 forbids casting nonscalar type %0 to the same type">;
-def ext_typecheck_cast_to_union : Extension<"C99 forbids casts to union type">;
-def err_typecheck_cast_to_union_no_type : Error<
- "cast to union type from type %0 not present in union">;
-def err_cast_pointer_from_non_pointer_int : Error<
- "operand of type %0 cannot be cast to a pointer type">;
-def err_cast_pointer_to_non_pointer_int : Error<
- "pointer cannot be cast to type %0">;
-def err_typecheck_expect_scalar_operand : Error<
- "operand of type %0 where arithmetic or pointer type is required">;
-def err_typecheck_cond_incompatible_operands : Error<
- "incompatible operand types (%0 and %1)">;
-def ext_typecheck_cond_incompatible_operands_nonstandard : ExtWarn<
- "incompatible operand types (%0 and %1) use non-standard composite pointer "
- "type %2">;
-def err_cast_selector_expr : Error<
- "cannot type cast @selector expression">;
-def warn_typecheck_cond_incompatible_pointers : ExtWarn<
- "pointer type mismatch (%0 and %1)">;
-def warn_typecheck_cond_pointer_integer_mismatch : ExtWarn<
- "pointer/integer type mismatch in conditional expression (%0 and %1)">;
-def err_typecheck_choose_expr_requires_constant : Error<
- "'__builtin_choose_expr' requires a constant expression">;
-def ext_typecheck_expression_not_constant_but_accepted : Extension<
- "expression is not a constant, but is accepted as one by GNU extensions">,
- InGroup<GNU>;
-def warn_unused_expr : Warning<"expression result unused">,
- InGroup<UnusedValue>;
-def warn_unused_voidptr : Warning<
- "expression result unused; should this cast be to 'void'?">,
- InGroup<UnusedValue>;
-def warn_unused_property_expr : Warning<
- "property access result unused - getters should not be used for side effects">,
- InGroup<UnusedValue>;
-def warn_unused_call : Warning<
- "ignoring return value of function declared with %0 attribute">,
- InGroup<UnusedValue>;
-
-def err_incomplete_type_used_in_type_trait_expr : Error<
- "incomplete type %0 used in type trait expression">;
-def err_expected_ident_or_lparen : Error<"expected identifier or '('">;
-
-} // End of general sema category.
-
-// inline asm.
-let CategoryName = "Inline Assembly Issue" in {
- def err_asm_wide_character : Error<"wide string is invalid in 'asm'">;
- def err_asm_invalid_lvalue_in_output : Error<"invalid lvalue in asm output">;
- def err_asm_invalid_output_constraint : Error<
- "invalid output constraint '%0' in asm">;
- def err_asm_invalid_lvalue_in_input : Error<
- "invalid lvalue in asm input for constraint '%0'">;
- def err_asm_invalid_input_constraint : Error<
- "invalid input constraint '%0' in asm">;
- def err_asm_invalid_type_in_input : Error<
- "invalid type %0 in asm input for constraint '%1'">;
- def err_asm_tying_incompatible_types : Error<
- "unsupported inline asm: input with type %0 matching output with type %1">;
- def err_asm_unknown_register_name : Error<"unknown register name '%0' in asm">;
- def err_invalid_asm_cast_lvalue : Error<
- "invalid use of a cast in a inline asm context requiring an l-value: "
- "remove the cast or build with -fheinous-gnu-extensions">;
-
- def warn_invalid_asm_cast_lvalue : Warning<
- "invalid use of a cast in a inline asm context requiring an l-value: "
- "accepted due to -fheinous-gnu-extensions, but clang may remove support "
- "for this in the future">;
-}
-
-let CategoryName = "Semantic Issue" in {
-
-def err_invalid_conversion_between_vectors : Error<
- "invalid conversion between vector type %0 and %1 of different size">;
-def err_invalid_conversion_between_vector_and_integer : Error<
- "invalid conversion between vector type %0 and integer type %1 "
- "of different size">;
-
-def err_invalid_conversion_between_vector_and_scalar : Error<
- "invalid conversion between vector type %0 and scalar type %1">;
-def err_overload_expr_requires_non_zero_constant : Error<
- "overload requires a non-zero constant expression as first argument">;
-def err_overload_incorrect_fntype : Error<
- "argument is not a function, or has wrong number of parameters">;
-
-// C++ member initializers.
-def err_only_constructors_take_base_inits : Error<
- "only constructors take base initializers">;
-
-def err_multiple_mem_initialization : Error <
- "multiple initializations given for non-static member %0">;
-def err_multiple_mem_union_initialization : Error <
- "initializing multiple members of anonymous union">;
-def err_multiple_base_initialization : Error <
- "multiple initializations given for base %0">;
-
-def err_mem_init_not_member_or_class : Error<
- "member initializer %0 does not name a non-static data member or base "
- "class">;
-
-def warn_initializer_out_of_order : Warning<
- "%select{field|base class}0 %1 will be initialized after "
- "%select{field|base}2 %3">,
- InGroup<Reorder>, DefaultIgnore;
-
-def err_base_init_does_not_name_class : Error<
- "constructor initializer %0 does not name a class">;
-def err_base_init_direct_and_virtual : Error<
- "base class initializer %0 names both a direct base class and an "
- "inherited virtual base class">;
-def err_not_direct_base_or_virtual : Error<
- "type %0 is not a direct or virtual base of %1">;
-
-def err_in_class_initializer_non_integral_type : Error<
- "in-class initializer has non-integral, non-enumeration type %0">;
-def err_in_class_initializer_non_constant : Error<
- "in-class initializer is not an integral constant expression">;
-
-// C++ anonymous unions and GNU anonymous structs/unions
-def ext_anonymous_union : Extension<
- "anonymous unions are a GNU extension in C">, InGroup<GNU>;
-def ext_anonymous_struct : Extension<
- "anonymous structs are a GNU extension">, InGroup<GNU>;
-def err_anonymous_union_not_static : Error<
- "anonymous unions at namespace or global scope must be declared 'static'">;
-def err_anonymous_union_with_storage_spec : Error<
- "anonymous union at class scope must not have a storage specifier">;
-def err_anonymous_struct_not_member : Error<
- "anonymous %select{structs|structs and classes}0 must be "
- "%select{struct or union|class}0 members">;
-def err_anonymous_union_member_redecl : Error<
- "member of anonymous union redeclares %0">;
-def err_anonymous_struct_member_redecl : Error<
- "member of anonymous struct redeclares %0">;
-def err_anonymous_record_with_type : Error<
- "types cannot be declared in an anonymous %select{struct|union}0">;
-def err_anonymous_record_with_function : Error<
- "functions cannot be declared in an anonymous %select{struct|union}0">;
-def err_anonymous_record_with_static : Error<
- "static members cannot be declared in an anonymous %select{struct|union}0">;
-def err_anonymous_record_bad_member : Error<
- "anonymous %select{struct|union}0 can only contain non-static data members">;
-def err_anonymous_record_nonpublic_member : Error<
- "anonymous %select{struct|union}0 cannot contain a "
- "%select{private|protected}1 data member">;
-
-// C++ local classes
-def err_reference_to_local_var_in_enclosing_function : Error<
- "reference to local variable %0 declared in enclosed function %1">;
-def note_local_variable_declared_here : Note<
- "%0 declared here">;
-def err_static_data_member_not_allowed_in_local_class : Error<
- "static data member %0 not allowed in local class %1">;
-
-// C++ derived classes
-def err_base_clause_on_union : Error<"unions cannot have base classes">;
-def err_base_must_be_class : Error<"base specifier must name a class">;
-def err_union_as_base_class : Error<"unions cannot be base classes">;
-def err_incomplete_base_class : Error<"base class has incomplete type">;
-def err_duplicate_base_class : Error<
- "base class %0 specified more than once as a direct base class">;
-// FIXME: better way to display derivation? Pass entire thing into diagclient?
-def err_ambiguous_derived_to_base_conv : Error<
- "ambiguous conversion from derived class %0 to base class %1:%2">;
-def err_ambiguous_memptr_conv : Error<
- "ambiguous conversion from pointer to member of %select{base|derived}0 "
- "class %1 to pointer to member of %select{derived|base}0 class %2:%3">;
-
-def err_memptr_conv_via_virtual : Error<
- "conversion from pointer to member of class %0 to pointer to member "
- "of class %1 via virtual base %2 is not allowed">;
-
-// C++ access control
-def err_conv_to_inaccessible_base : Error<
- "conversion from %0 to inaccessible base class %1">, NoSFINAE;
-def note_inheritance_specifier_here : Note<
- "'%0' inheritance specifier here">;
-def note_inheritance_implicitly_private_here : Note<
- "inheritance is implicitly 'private'">;
-
-// C++ member name lookup
-def err_ambiguous_member_multiple_subobjects : Error<
- "non-static member %0 found in multiple base-class subobjects of type %1:%2">;
-def err_ambiguous_member_multiple_subobject_types : Error<
- "member %0 found in multiple base classes of different types">;
-def note_ambiguous_member_found : Note<"member found by ambiguous name lookup">;
-def err_ambiguous_reference : Error<"reference to %0 is ambiguous">;
-def note_ambiguous_candidate : Note<"candidate found by name lookup is %q0">;
-def err_ambiguous_tag_hiding : Error<"a type named %0 is hidden by a "
- "declaration in a different namespace">;
-def note_hidden_tag : Note<"type declaration hidden">;
-def note_hiding_object : Note<"declaration hides type">;
-
-// C++ operator overloading
-def err_operator_overload_needs_class_or_enum : Error<
- "overloaded %0 must have at least one parameter of class "
- "or enumeration type">;
-
-def err_operator_overload_variadic : Error<"overloaded %0 cannot be variadic">;
-def err_operator_overload_static : Error<
- "overloaded %0 cannot be a static member function">;
-def err_operator_overload_default_arg : Error<
- "parameter of overloaded %0 cannot have a default argument">;
-def err_operator_overload_must_be : Error<
- "overloaded %0 must be a %select{unary|binary|unary or binary}2 operator "
- "(has %1 parameter%s1)">;
-
-def err_operator_overload_must_be_member : Error<
- "overloaded %0 must be a non-static member function">;
-def err_operator_overload_post_incdec_must_be_int : Error<
- "parameter of overloaded post-%select{increment|decrement}1 operator must "
- "have type 'int' (not %0)">;
-
-// C++ allocation and deallocation functions.
-def err_operator_new_delete_declared_in_namespace : Error<
- "%0 cannot be declared inside a namespace">;
-def err_operator_new_delete_declared_static : Error<
- "%0 cannot be declared static in global scope">;
-def err_operator_new_delete_invalid_result_type : Error<
- "%0 must return type %1">;
-def err_operator_new_delete_dependent_result_type : Error<
- "%0 cannot have a dependent return type; use %1 instead">;
-def err_operator_new_delete_too_few_parameters : Error<
- "%0 must have at least one parameter.">;
-def err_operator_new_delete_template_too_few_parameters : Error<
- "%0 template must have at least two parameters.">;
-
-def err_operator_new_dependent_param_type : Error<
- "%0 cannot take a dependent type as first parameter; "
- "use size_t (%1) instead">;
-def err_operator_new_param_type : Error<
- "%0 takes type size_t (%1) as first parameter">;
-def err_operator_new_default_arg: Error<
- "parameter of %0 cannot have a default argument">;
-def err_operator_delete_dependent_param_type : Error<
- "%0 cannot take a dependent type as first parameter; use %1 instead">;
-def err_operator_delete_param_type : Error<
- "%0 takes type %1 as first parameter">;
-
-// C++ literal operators
-def err_literal_operator_outside_namespace : Error<
- "literal operator %0 must be in a namespace or global scope">;
-// FIXME: This diagnostic sucks
-def err_literal_operator_params : Error<
- "parameter declaration for literal operator %0 is not valid">;
-
-// C++ conversion functions
-def err_conv_function_not_member : Error<
- "conversion function must be a non-static member function">;
-def err_conv_function_return_type : Error<
- "conversion function cannot have a return type">;
-def err_conv_function_with_params : Error<
- "conversion function cannot have any parameters">;
-def err_conv_function_variadic : Error<
- "conversion function cannot be variadic">;
-def err_conv_function_to_array : Error<
- "conversion function cannot convert to an array type">;
-def err_conv_function_to_function : Error<
- "conversion function cannot convert to a function type">;
-def err_conv_function_with_complex_decl : Error<
- "must use a typedef to declare a conversion to %0">;
-def err_conv_function_redeclared : Error<
- "conversion function cannot be redeclared">;
-def warn_conv_to_self_not_used : Warning<
- "conversion function converting %0 to itself will never be used">;
-def warn_conv_to_base_not_used : Warning<
- "conversion function converting %0 to its base class %1 will never be used">;
-def warn_conv_to_void_not_used : Warning<
- "conversion function converting %0 to %1 will never be used">;
-
-def warn_not_compound_assign : Warning<
- "use of unary operator that may be intended as compound assignment (%0=)">;
-
-// C++0x explicit conversion operators
-def warn_explicit_conversion_functions : Warning<
- "explicit conversion functions are a C++0x extension">;
-
-def warn_printf_write_back : Warning<
- "use of '%%n' in format string discouraged (potentially insecure)">,
- InGroup<FormatSecurity>;
-def warn_printf_insufficient_data_args : Warning<
- "more '%%' conversions than data arguments">, InGroup<Format>;
-def warn_printf_data_arg_not_used : Warning<
- "data argument not used by format string">, InGroup<FormatExtraArgs>;
-def warn_format_invalid_conversion : Warning<
- "invalid conversion specifier '%0'">, InGroup<Format>;
-def warn_printf_incomplete_specifier : Warning<
- "incomplete format specifier">, InGroup<Format>;
-def warn_missing_format_string : Warning<
- "format string missing">, InGroup<Format>;
-def warn_scanf_nonzero_width : Warning<
- "zero field width in scanf format string is unused">,
- InGroup<Format>;
-def warn_printf_conversion_argument_type_mismatch : Warning<
- "conversion specifies type %0 but the argument has type %1">,
- InGroup<Format>;
-def warn_printf_positional_arg_exceeds_data_args : Warning <
- "data argument position '%0' exceeds the number of data arguments (%1)">,
- InGroup<Format>;
-def warn_format_zero_positional_specifier : Warning<
- "position arguments in format strings start counting at 1 (not 0)">,
- InGroup<Format>;
-def warn_format_invalid_positional_specifier : Warning<
- "invalid position specified for %select{field width|field precision}0">,
- InGroup<Format>;
-def warn_format_mix_positional_nonpositional_args : Warning<
- "cannot mix positional and non-positional arguments in format string">,
- InGroup<Format>;
-def warn_null_arg : Warning<
- "null passed to a callee which requires a non-null argument">,
- InGroup<NonNull>;
-def warn_empty_format_string : Warning<
- "format string is empty">, InGroup<FormatZeroLength>;
-def warn_format_string_is_wide_literal : Warning<
- "format string should not be a wide string">, InGroup<Format>;
-def warn_printf_format_string_contains_null_char : Warning<
- "format string contains '\\0' within the string body">, InGroup<Format>;
-def warn_printf_asterisk_missing_arg : Warning<
- "'%select{*|.*}0' specified field %select{width|precision}0 is missing a matching 'int' argument">;
-def warn_printf_asterisk_wrong_type : Warning<
- "field %select{width|precision}0 should have type %1, but argument has type %2">,
- InGroup<Format>;
-def warn_printf_nonsensical_optional_amount: Warning<
- "%select{field width|precision}0 used with '%1' conversion specifier, resulting in undefined behavior">,
- InGroup<Format>;
-def warn_printf_nonsensical_flag: Warning<
- "flag '%0' results in undefined behavior with '%1' conversion specifier">,
- InGroup<Format>;
-def warn_format_nonsensical_length: Warning<
- "length modifier '%0' results in undefined behavior or no effect with '%1' conversion specifier">,
- InGroup<Format>;
-def warn_printf_ignored_flag: Warning<
- "flag '%0' is ignored when flag '%1' is present">,
- InGroup<Format>;
-def warn_scanf_scanlist_incomplete : Warning<
- "no closing ']' for '%%[' in scanf format string">,
- InGroup<Format>;
-
-// CHECK: returning address/reference of stack memory
-def warn_ret_stack_addr : Warning<
- "address of stack memory associated with local variable %0 returned">;
-def warn_ret_stack_ref : Warning<
- "reference to stack memory associated with local variable %0 returned">;
-def warn_ret_addr_label : Warning<
- "returning address of label, which is local">;
-def err_ret_local_block : Error<
- "returning block that lives on the local stack">;
-
-
-// For non-floating point, expressions of the form x == x or x != x
-// should result in a warning, since these always evaluate to a constant.
-// Array comparisons have similar warnings
-def warn_comparison_always : Warning<
- "%select{self-|array }0comparison always evaluates to %select{false|true|a constant}1">,
- InGroup<DiagGroup<"tautological-compare">>;
-
-def warn_stringcompare : Warning<
- "result of comparison against %select{a string literal|@encode}0 is "
- "unspecified (use strncmp instead)">;
-
-
-
-// Blocks
-def err_blocks_disable : Error<"blocks support disabled - compile with -fblocks"
- " or pick a deployment target that supports them">;
-def err_expected_block_lbrace : Error<"expected '{' in block literal">;
-def err_return_in_block_expression : Error<
- "return not allowed in block expression literal">;
-def err_block_returns_array : Error<
- "block declared as returning an array">;
-
-
-// CFString checking
-def err_cfstring_literal_not_string_constant : Error<
- "CFString literal is not a string constant">;
-def warn_cfstring_literal_contains_nul_character : Warning<
- "CFString literal contains NUL character">;
-
-// Statements.
-def err_continue_not_in_loop : Error<
- "'continue' statement not in loop statement">;
-def err_break_not_in_loop_or_switch : Error<
- "'break' statement not in loop or switch statement">;
-def err_default_not_in_switch : Error<
- "'default' statement not in switch statement">;
-def err_case_not_in_switch : Error<"'case' statement not in switch statement">;
-def warn_bool_switch_condition : Warning<
- "switch condition has boolean value">;
-def warn_case_value_overflow : Warning<
- "overflow converting case value to switch condition type (%0 to %1)">,
- InGroup<DiagGroup<"switch">>;
-def err_duplicate_case : Error<"duplicate case value '%0'">;
-def warn_case_empty_range : Warning<"empty case range specified">;
-def warn_missing_case_for_condition :
- Warning<"no case matching constant switch condition '%0'">;
-def warn_missing_cases : Warning<"enumeration value %0 not handled in switch">,
- InGroup<DiagGroup<"switch-enum"> >;
-def warn_not_in_enum : Warning<"case value not in enumerated type %0">,
- InGroup<DiagGroup<"switch-enum"> >;
-def err_typecheck_statement_requires_scalar : Error<
- "statement requires expression of scalar type (%0 invalid)">;
-def err_typecheck_statement_requires_integer : Error<
- "statement requires expression of integer type (%0 invalid)">;
-def err_multiple_default_labels_defined : Error<
- "multiple default labels in one switch">;
-def err_switch_multiple_conversions : Error<
- "multiple conversions from switch condition type %0 to an integral or "
- "enumeration type">;
-def note_switch_conversion : Note<
- "conversion to %select{integral|enumeration}0 type %1">;
-def err_switch_explicit_conversion : Error<
- "switch condition type %0 requires explicit conversion to %1">;
-def err_switch_incomplete_class_type : Error<
- "switch condition has incomplete class type %0">;
-def warn_empty_if_body : Warning<
- "if statement has empty body">, InGroup<EmptyBody>;
-def err_va_start_used_in_non_variadic_function : Error<
- "'va_start' used in function with fixed args">;
-def warn_second_parameter_of_va_start_not_last_named_argument : Warning<
- "second parameter of 'va_start' not last named argument">;
-def err_first_argument_to_va_arg_not_of_type_va_list : Error<
- "first argument to 'va_arg' is of type %0 and not 'va_list'">;
-
-def warn_return_missing_expr : Warning<
- "non-void %select{function|method}1 %0 should return a value">, DefaultError,
- InGroup<ReturnType>;
-def ext_return_missing_expr : ExtWarn<
- "non-void %select{function|method}1 %0 should return a value">, DefaultError,
- InGroup<ReturnType>;
-def ext_return_has_expr : ExtWarn<
- "void %select{function|method}1 %0 should not return a value">, DefaultError,
- InGroup<ReturnType>;
-def ext_return_has_void_expr : Extension<
- "void %select{function|method}1 %0 should not return void expression">;
-def warn_noreturn_function_has_return_expr : Warning<
- "function %0 declared 'noreturn' should not return">,
- InGroup<DiagGroup<"invalid-noreturn">>;
-def warn_falloff_noreturn_function : Warning<
- "function declared 'noreturn' should not return">,
- InGroup<DiagGroup<"invalid-noreturn">>;
-def err_noreturn_block_has_return_expr : Error<
- "block declared 'noreturn' should not return">;
-def err_block_on_nonlocal : Error<
- "__block attribute not allowed, only allowed on local variables">;
-def err_block_on_vm : Error<
- "__block attribute not allowed on declaration with a variably modified type">;
-
-def err_shufflevector_non_vector : Error<
- "first two arguments to __builtin_shufflevector must be vectors">;
-def err_shufflevector_incompatible_vector : Error<
- "first two arguments to __builtin_shufflevector must have the same type">;
-def err_shufflevector_nonconstant_argument : Error<
- "index for __builtin_shufflevector must be a constant integer">;
-def err_shufflevector_argument_too_large : Error<
- "index for __builtin_shufflevector must be less than the total number "
- "of vector elements">;
-
-def err_vector_incorrect_num_initializers : Error<
- "%select{too many|too few}0 elements in vector initialization (expected %1 elements, have %2)">;
-def err_altivec_empty_initializer : Error<"expected initializer">;
-
-def err_invalid_neon_type_code : Error<
- "incompatible constant for this __builtin_neon function">;
-def err_argument_invalid_range : Error<
- "argument should be a value from %0 to %1">;
-
-def err_builtin_longjmp_invalid_val : Error<
- "argument to __builtin_longjmp must be a constant 1">;
-
-def err_constant_integer_arg_type : Error<
- "argument to %0 must be a constant integer">;
-
-def ext_mixed_decls_code : Extension<
- "ISO C90 forbids mixing declarations and code">,
- InGroup<DiagGroup<"declaration-after-statement">>;
-
-def err_non_variable_decl_in_for : Error<
- "declaration of non-local variable in 'for' loop">;
-def err_toomany_element_decls : Error<
- "only one element declaration is allowed">;
-def err_selector_element_not_lvalue : Error<
- "selector element is not a valid lvalue">;
-def err_selector_element_type : Error<
- "selector element type %0 is not a valid object">;
-def err_collection_expr_type : Error<
- "collection expression type %0 is not a valid object">;
-
-def err_invalid_conversion_between_ext_vectors : Error<
- "invalid conversion between ext-vector type %0 and %1">;
-
-// Type
-def ext_invalid_sign_spec : Extension<"'%0' cannot be signed or unsigned">;
-def warn_receiver_forward_class : Warning<
- "receiver %0 is a forward class and corresponding @interface may not exist">;
-def note_method_sent_forward_class : Note<"method %0 is used for the forward class">;
-def ext_missing_declspec : ExtWarn<
- "declaration specifier missing, defaulting to 'int'">;
-def ext_missing_type_specifier : ExtWarn<
- "type specifier missing, defaults to 'int'">,
- InGroup<ImplicitInt>;
-def err_decimal_unsupported : Error<
- "GNU decimal type extension not supported">;
-def err_missing_type_specifier : Error<
- "C++ requires a type specifier for all declarations">;
-def err_missing_param_declspec : Error<
- "parameter requires a declaration specifier">;
-def err_objc_array_of_interfaces : Error<
- "array of interface %0 is invalid (probably should be an array of pointers)">;
-def ext_c99_array_usage : Extension<
- "use of C99-specific array features, accepted as an extension">;
-def err_c99_array_usage_cxx : Error<
- "C99-specific array features are not permitted in C++">;
-
-def note_getter_unavailable : Note<
- "or because setter is declared here, but no getter method %0 is found">;
-def err_invalid_protocol_qualifiers : Error<
- "invalid protocol qualifiers on non-ObjC type">;
-def warn_ivar_use_hidden : Warning<
- "local declaration of %0 hides instance variable">;
-def error_ivar_use_in_class_method : Error<
- "instance variable %0 accessed in class method">;
-def error_private_ivar_access : Error<"instance variable %0 is private">,
- NoSFINAE;
-def error_protected_ivar_access : Error<"instance variable %0 is protected">,
- NoSFINAE;
-def warn_maynot_respond : Warning<"%0 may not respond to %1">;
-def warn_attribute_method_def : Warning<
- "method attribute can only be specified on method declarations">;
-def ext_typecheck_base_super : Warning<
- "method parameter type %0 does not match "
- "super class method parameter type %1">, InGroup<SuperSubClassMismatch>, DefaultIgnore;
-
-// Spell-checking diagnostics
-def err_unknown_typename_suggest : Error<
- "unknown type name %0; did you mean %1?">;
-def err_unknown_nested_typename_suggest : Error<
- "no type named %0 in %1; did you mean %2?">;
-def err_no_member_suggest : Error<"no member named %0 in %1; did you mean %2?">;
-def err_undeclared_use_suggest : Error<
- "use of undeclared %0; did you mean %1?">;
-def err_undeclared_var_use_suggest : Error<
- "use of undeclared identifier %0; did you mean %1?">;
-def err_no_template_suggest : Error<"no template named %0; did you mean %1?">;
-def err_no_member_template_suggest : Error<
- "no template named %0 in %1; did you mean %2?">;
-def err_mem_init_not_member_or_class_suggest : Error<
- "initializer %0 does not name a non-static data member or base "
- "class; did you mean the %select{base class|member}1 %2?">;
-def err_field_designator_unknown_suggest : Error<
- "field designator %0 does not refer to any field in type %1; did you mean "
- "%2?">;
-def err_typecheck_member_reference_ivar_suggest : Error<
- "%0 does not have a member named %1; did you mean %2?">;
-def err_property_not_found_suggest : Error<
- "property %0 not found on object of type %1; did you mean %2?">;
-def err_undef_interface_suggest : Error<
- "cannot find interface declaration for %0; did you mean %1?">;
-def warn_undef_interface_suggest : Warning<
- "cannot find interface declaration for %0; did you mean %1?">;
-def err_undef_superclass_suggest : Error<
- "cannot find interface declaration for %0, superclass of %1; did you mean "
- "%2?">;
-def err_undeclared_protocol_suggest : Error<
- "cannot find protocol declaration for %0; did you mean %1?">;
-def note_base_class_specified_here : Note<
- "base class %0 specified here">;
-def err_using_directive_suggest : Error<
- "no namespace named %0; did you mean %1?">;
-def err_using_directive_member_suggest : Error<
- "no namespace named %0 in %1; did you mean %2?">;
-def note_namespace_defined_here : Note<"namespace %0 defined here">;
-
-} // end of sema category
-} // end of sema component.
-
Removed: cfe/branches/Apple/williamson/include/clang/Driver/CC1Options.td.orig
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/williamson/include/clang/Driver/CC1Options.td.orig?rev=111417&view=auto
==============================================================================
--- cfe/branches/Apple/williamson/include/clang/Driver/CC1Options.td.orig (original)
+++ cfe/branches/Apple/williamson/include/clang/Driver/CC1Options.td.orig (removed)
@@ -1,535 +0,0 @@
-//===--- CC1Options.td - Options for clang -cc1 ---------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the options accepted by clang -cc1.
-//
-//===----------------------------------------------------------------------===//
-
-// Include the common option parsing interfaces.
-include "OptParser.td"
-
-//===----------------------------------------------------------------------===//
-// Target Options
-//===----------------------------------------------------------------------===//
-
-def cxx_abi : Separate<"-cxx-abi">,
- HelpText<"Target a particular C++ ABI type">;
-def target_abi : Separate<"-target-abi">,
- HelpText<"Target a particular ABI type">;
-def target_cpu : Separate<"-target-cpu">,
- HelpText<"Target a specific cpu type">;
-def target_feature : Separate<"-target-feature">,
- HelpText<"Target specific attributes">;
-def triple : Separate<"-triple">,
- HelpText<"Specify target triple (e.g. i686-apple-darwin9)">;
-def triple_EQ : Joined<"-triple=">, Alias<triple>;
-
-//===----------------------------------------------------------------------===//
-// Analyzer Options
-//===----------------------------------------------------------------------===//
-
-def analysis_CFGDump : Flag<"-cfg-dump">,
- HelpText<"Display Control-Flow Graphs">;
-def analysis_CFGView : Flag<"-cfg-view">,
- HelpText<"View Control-Flow Graphs using GraphViz">;
-def analysis_DisplayLiveVariables : Flag<"-dump-live-variables">,
- HelpText<"Print results of live variable analysis">;
-def analysis_LLVMConventionChecker : Flag<"-analyzer-check-llvm-conventions">,
- HelpText<"Check code for LLVM codebase conventions (domain-specific)">;
-def analysis_SecuritySyntacticChecks : Flag<"-analyzer-check-security-syntactic">,
- HelpText<"Perform quick security checks that require no data flow">;
-def analysis_WarnDeadStores : Flag<"-analyzer-check-dead-stores">,
- HelpText<"Warn about stores to dead variables">;
-def analysis_WarnUninitVals : Flag<"-warn-uninit-values">,
- HelpText<"Warn about uses of uninitialized variables">;
-def analysis_WarnObjCMethSigs : Flag<"-analyzer-check-objc-methodsigs">,
- HelpText<"Warn about Objective-C method signatures with type incompatibilities">;
-def analysis_WarnObjCDealloc : Flag<"-analyzer-check-objc-missing-dealloc">,
- HelpText<"Warn about Objective-C classes that lack a correct implementation of -dealloc">;
-def analysis_WarnObjCUnusedIvars : Flag<"-analyzer-check-objc-unused-ivars">,
- HelpText<"Warn about private ivars that are never used">;
-def analysis_ObjCMemChecker : Flag<"-analyzer-check-objc-mem">,
- HelpText<"Run the [Core] Foundation reference count checker">;
-def analysis_WarnSizeofPointer : Flag<"-warn-sizeof-pointer">,
- HelpText<"Warn about unintended use of sizeof() on pointer expressions">;
-
-def analyzer_store : Separate<"-analyzer-store">,
- HelpText<"Source Code Analysis - Abstract Memory Store Models">;
-def analyzer_store_EQ : Joined<"-analyzer-store=">, Alias<analyzer_store>;
-
-def analyzer_constraints : Separate<"-analyzer-constraints">,
- HelpText<"Source Code Analysis - Symbolic Constraint Engines">;
-def analyzer_constraints_EQ : Joined<"-analyzer-constraints=">,
- Alias<analyzer_constraints>;
-
-def analyzer_output : Separate<"-analyzer-output">,
- HelpText<"Source Code Analysis - Output Options">;
-def analyzer_output_EQ : Joined<"-analyzer-output=">,
- Alias<analyzer_output>;
-
-def analyzer_opt_analyze_headers : Flag<"-analyzer-opt-analyze-headers">,
- HelpText<"Force the static analyzer to analyze functions defined in header files">;
-def analyzer_opt_analyze_nested_blocks : Flag<"-analyzer-opt-analyze-nested-blocks">,
- HelpText<"Analyze the definitions of blocks in addition to functions">;
-def analyzer_display_progress : Flag<"-analyzer-display-progress">,
- HelpText<"Emit verbose output about the analyzer's progress">;
-def analyzer_experimental_checks : Flag<"-analyzer-experimental-checks">,
- HelpText<"Use experimental path-sensitive checks">;
-def analyzer_experimental_internal_checks :
- Flag<"-analyzer-experimental-internal-checks">,
- HelpText<"Use new default path-sensitive checks currently in testing">;
-def analyze_function : Separate<"-analyze-function">,
- HelpText<"Run analysis on specific function">;
-def analyze_function_EQ : Joined<"-analyze-function=">, Alias<analyze_function>;
-def analyzer_eagerly_assume : Flag<"-analyzer-eagerly-assume">,
- HelpText<"Eagerly assume the truth/falseness of some symbolic constraints">;
-def analyzer_no_purge_dead : Flag<"-analyzer-no-purge-dead">,
- HelpText<"Don't remove dead symbols, bindings, and constraints before processing a statement">;
-def trim_egraph : Flag<"-trim-egraph">,
- HelpText<"Only show error-related paths in the analysis graph">;
-def analyzer_viz_egraph_graphviz : Flag<"-analyzer-viz-egraph-graphviz">,
- HelpText<"Display exploded graph using GraphViz">;
-def analyzer_viz_egraph_ubigraph : Flag<"-analyzer-viz-egraph-ubigraph">,
- HelpText<"Display exploded graph using Ubigraph">;
-def analyzer_inline_call : Flag<"-analyzer-inline-call">,
- HelpText<"Experimental transfer function inlining callees when its definition is available.">;
-def analyzer_max_nodes : Separate<"-analyzer-max-nodes">,
- HelpText<"The maximum number of nodes the analyzer can generate">;
-def analyzer_max_loop : Separate<"-analyzer-max-loop">,
- HelpText<"The maximum number of times the analyzer will go through a loop">;
-
-//===----------------------------------------------------------------------===//
-// CodeGen Options
-//===----------------------------------------------------------------------===//
-
-def disable_llvm_optzns : Flag<"-disable-llvm-optzns">,
- HelpText<"Don't run LLVM optimization passes">;
-def disable_llvm_verifier : Flag<"-disable-llvm-verifier">,
- HelpText<"Don't run the LLVM IR verifier pass">;
-def disable_red_zone : Flag<"-disable-red-zone">,
- HelpText<"Do not emit code that uses the red zone.">;
-def dwarf_debug_flags : Separate<"-dwarf-debug-flags">,
- HelpText<"The string to embed in the Dwarf debug flags record.">;
-def g : Flag<"-g">, HelpText<"Generate source level debug information">;
-def fcatch_undefined_behavior : Flag<"-fcatch-undefined-behavior">,
- HelpText<"Generate runtime checks for undefined behavior.">;
-def fno_common : Flag<"-fno-common">,
- HelpText<"Compile common globals like normal definitions">;
-def no_implicit_float : Flag<"-no-implicit-float">,
- HelpText<"Don't generate implicit floating point instructions (x86-only)">;
-def finstrument_functions : Flag<"-finstrument-functions">,
- HelpText<"Generate calls to instrument function entry and exit">;
-def fno_merge_all_constants : Flag<"-fno-merge-all-constants">,
- HelpText<"Disallow merging of constants.">;
-def fno_threadsafe_statics : Flag<"-fno-threadsafe-statics">,
- HelpText<"Do not emit code to make initialization of local statics thread safe">;
-def fdump_vtable_layouts : Flag<"-fdump-vtable-layouts">,
- HelpText<"Dump the layouts of all vtables that will be emitted in a translation unit">;
-def ffunction_sections : Flag<"-ffunction-sections">,
- HelpText<"Place each function in its own section (ELF Only)">;
-def fdata_sections : Flag<"-fdata-sections">,
- HelpText<"Place each data in its own section (ELF Only)">;
-def masm_verbose : Flag<"-masm-verbose">,
- HelpText<"Generate verbose assembly output">;
-def mcode_model : Separate<"-mcode-model">,
- HelpText<"The code model to use">;
-def mdebug_pass : Separate<"-mdebug-pass">,
- HelpText<"Enable additional debug output">;
-def mdisable_fp_elim : Flag<"-mdisable-fp-elim">,
- HelpText<"Disable frame pointer elimination optimization">;
-def mfloat_abi : Separate<"-mfloat-abi">,
- HelpText<"The float ABI to use">;
-def mlimit_float_precision : Separate<"-mlimit-float-precision">,
- HelpText<"Limit float precision to the given value">;
-def mno_zero_initialized_in_bss : Flag<"-mno-zero-initialized-in-bss">,
- HelpText<"Do not put zero initialized data in the BSS">;
-def momit_leaf_frame_pointer : Flag<"-momit-leaf-frame-pointer">,
- HelpText<"Omit frame pointer setup for leaf functions.">;
-def msoft_float : Flag<"-msoft-float">,
- HelpText<"Use software floating point">;
-def mrelax_all : Flag<"-mrelax-all">,
- HelpText<"Relax all machine instructions">;
-def mrelocation_model : Separate<"-mrelocation-model">,
- HelpText<"The relocation model to use">;
-def munwind_tables : Flag<"-munwind-tables">,
- HelpText<"Generate unwinding tables for all functions">;
-def mconstructor_aliases : Flag<"-mconstructor-aliases">,
- HelpText<"Emit complete constructors and destructors as aliases when possible">;
-def O : Joined<"-O">, HelpText<"Optimization level">;
-def Os : Flag<"-Os">, HelpText<"Optimize for size">;
-
-//===----------------------------------------------------------------------===//
-// Dependency Output Options
-//===----------------------------------------------------------------------===//
-
-def dependency_file : Separate<"-dependency-file">,
- HelpText<"Filename (or -) to write dependency output to">;
-def sys_header_deps : Flag<"-sys-header-deps">,
- HelpText<"Include system headers in dependency output">;
-def MQ : Separate<"-MQ">, HelpText<"Specify target to quote for dependency">;
-def MT : Separate<"-MT">, HelpText<"Specify target for dependency">;
-def MP : Flag<"-MP">,
- HelpText<"Create phony target for each dependency (other than main file)">;
-
-//===----------------------------------------------------------------------===//
-// Diagnostic Options
-//===----------------------------------------------------------------------===//
-
-def dump_build_information : Separate<"-dump-build-information">,
- MetaVarName<"<filename>">,
- HelpText<"output a dump of some build information to a file">;
-def fno_show_column : Flag<"-fno-show-column">,
- HelpText<"Do not include column number on diagnostics">;
-def fno_show_source_location : Flag<"-fno-show-source-location">,
- HelpText<"Do not include source location information with diagnostics">;
-def fshow_overloads_EQ : Joined<"-fshow-overloads=">,
- HelpText<"Which overload candidates to show when overload resolution fails: "
- "best|all; defaults to all">;
-def fno_caret_diagnostics : Flag<"-fno-caret-diagnostics">,
- HelpText<"Do not include source line and caret with diagnostics">;
-def fno_diagnostics_fixit_info : Flag<"-fno-diagnostics-fixit-info">,
- HelpText<"Do not include fixit information in diagnostics">;
-def fdiagnostics_binary : Flag<"-fdiagnostics-binary">;
-def w : Flag<"-w">, HelpText<"Suppress all warnings">;
-def pedantic : Flag<"-pedantic">;
-def pedantic_errors : Flag<"-pedantic-errors">;
-
-// This gets all -W options, including -Werror, -W[no-]system-headers, etc. The
-// driver has stripped off -Wa,foo etc. The driver has also translated -W to
-// -Wextra, so we don't need to worry about it.
-def W : Joined<"-W">;
-
-def fdiagnostics_print_source_range_info : Flag<"-fdiagnostics-print-source-range-info">,
- HelpText<"Print source range spans in numeric form">;
-def fdiagnostics_show_option : Flag<"-fdiagnostics-show-option">,
- HelpText<"Print diagnostic name with mappable diagnostics">;
-def fdiagnostics_show_category : Separate<"-fdiagnostics-show-category">,
- HelpText<"Print diagnostic category">;
-
-def ftabstop : Separate<"-ftabstop">, MetaVarName<"<N>">,
- HelpText<"Set the tab stop distance.">;
-def ferror_limit : Separate<"-ferror-limit">, MetaVarName<"<N>">,
- HelpText<"Set the maximum number of errors to emit before stopping (0 = no limit).">;
-def fmacro_backtrace_limit : Separate<"-fmacro-backtrace-limit">, MetaVarName<"<N>">,
- HelpText<"Set the maximum number of entries to print in a macro instantiation backtrace (0 = no limit).">;
-def ftemplate_backtrace_limit : Separate<"-ftemplate-backtrace-limit">, MetaVarName<"<N>">,
- HelpText<"Set the maximum number of entries to print in a template instantiation backtrace (0 = no limit).">;
-def fmessage_length : Separate<"-fmessage-length">, MetaVarName<"<N>">,
- HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">;
-def fcolor_diagnostics : Flag<"-fcolor-diagnostics">,
- HelpText<"Use colors in diagnostics">;
-def Wno_rewrite_macros : Flag<"-Wno-rewrite-macros">,
- HelpText<"Silence ObjC rewriting warnings">;
-def Wwrite_strings : Flag<"-Wwrite-strings">,
- HelpText<"Add const qualifier to string literals">;
-def verify : Flag<"-verify">,
- HelpText<"Verify emitted diagnostics and warnings">;
-
-//===----------------------------------------------------------------------===//
-// Frontend Options
-//===----------------------------------------------------------------------===//
-
-// This isn't normally used, it is just here so we can parse a
-// CompilerInvocation out of a driver-derived argument vector.
-def cc1 : Flag<"-cc1">;
-
-def ast_merge : Separate<"-ast-merge">,
- MetaVarName<"<ast file>">,
- HelpText<"Merge the given AST file into the translation unit being compiled.">;
-def code_completion_at : Separate<"-code-completion-at">,
- MetaVarName<"<file>:<line>:<column>">,
- HelpText<"Dump code-completion information at a location">;
-def remap_file : Separate<"-remap-file">,
- MetaVarName<"<from>;<to>">,
- HelpText<"Replace the contents of the <from> file with the contents of the <to> file">;
-def code_completion_at_EQ : Joined<"-code-completion-at=">,
- Alias<code_completion_at>;
-def no_code_completion_debug_printer : Flag<"-no-code-completion-debug-printer">,
- HelpText<"Don't use the \"debug\" code-completion print">;
-def code_completion_macros : Flag<"-code-completion-macros">,
- HelpText<"Include macros in code-completion results">;
-def code_completion_patterns : Flag<"-code-completion-patterns">,
- HelpText<"Include code patterns in code-completion results">;
-def disable_free : Flag<"-disable-free">,
- HelpText<"Disable freeing of memory on exit">;
-def help : Flag<"-help">,
- HelpText<"Print this help text">;
-def _help : Flag<"--help">, Alias<help>;
-def x : Separate<"-x">, HelpText<"Input language type">;
-def cxx_inheritance_view : Separate<"-cxx-inheritance-view">,
- MetaVarName<"<class name>">,
- HelpText<"View C++ inheritance for a specified class">;
-def o : Separate<"-o">, MetaVarName<"<path>">, HelpText<"Specify output file">;
-def load : Separate<"-load">, MetaVarName<"<dsopath>">,
- HelpText<"Load the named plugin (dynamic shared object)">;
-def plugin : Separate<"-plugin">, MetaVarName<"<name>">,
- HelpText<"Use the named plugin action (use \"help\" to list available options)">;
-def plugin_arg : JoinedAndSeparate<"-plugin-arg-">,
- MetaVarName<"<name> <arg>">,
- HelpText<"Pass <arg> to plugin <name>">;
-def resource_dir : Separate<"-resource-dir">,
- HelpText<"The directory which holds the compiler resource files">;
-def version : Flag<"-version">,
- HelpText<"Print the compiler version">;
-def _version : Flag<"--version">, Alias<version>;
-
-def Action_Group : OptionGroup<"<action group>">;
-let Group = Action_Group in {
-
-def Eonly : Flag<"-Eonly">,
- HelpText<"Just run preprocessor, no output (for timings)">;
-def E : Flag<"-E">,
- HelpText<"Run preprocessor, emit preprocessed file">;
-def dump_raw_tokens : Flag<"-dump-raw-tokens">,
- HelpText<"Lex file in raw mode and dump raw tokens">;
-def analyze : Flag<"-analyze">,
- HelpText<"Run static analysis engine">;
-def dump_tokens : Flag<"-dump-tokens">,
- HelpText<"Run preprocessor, dump internal rep of tokens">;
-def init_only : Flag<"-init-only">,
- HelpText<"Only execute frontend initialization">;
-def fsyntax_only : Flag<"-fsyntax-only">,
- HelpText<"Run parser and perform semantic analysis">;
-def fixit : Flag<"-fixit">,
- HelpText<"Apply fix-it advice to the input source">;
-def fixit_EQ : Joined<"-fixit=">,
- HelpText<"Apply fix-it advice creating a file with the given suffix">;
-def print_preamble : Flag<"-print-preamble">,
- HelpText<"Print the \"preamble\" of a file, which is a candidate for implicit"
- " precompiled headers.">;
-def emit_html : Flag<"-emit-html">,
- HelpText<"Output input source as HTML">;
-def ast_print : Flag<"-ast-print">,
- HelpText<"Build ASTs and then pretty-print them">;
-def ast_print_xml : Flag<"-ast-print-xml">,
- HelpText<"Build ASTs and then print them in XML format">;
-def ast_dump : Flag<"-ast-dump">,
- HelpText<"Build ASTs and then debug dump them">;
-def ast_view : Flag<"-ast-view">,
- HelpText<"Build ASTs and view them with GraphViz">;
-def boostcon : Flag<"-boostcon">,
- HelpText<"BoostCon workshop mode">;
-def print_decl_contexts : Flag<"-print-decl-contexts">,
- HelpText<"Print DeclContexts and their Decls">;
-def emit_pth : Flag<"-emit-pth">,
- HelpText<"Generate pre-tokenized header file">;
-def emit_pch : Flag<"-emit-pch">,
- HelpText<"Generate pre-compiled header file">;
-def S : Flag<"-S">,
- HelpText<"Emit native assembly code">;
-def emit_llvm : Flag<"-emit-llvm">,
- HelpText<"Build ASTs then convert to LLVM, emit .ll file">;
-def emit_llvm_bc : Flag<"-emit-llvm-bc">,
- HelpText<"Build ASTs then convert to LLVM, emit .bc file">;
-def emit_llvm_only : Flag<"-emit-llvm-only">,
- HelpText<"Build ASTs and convert to LLVM, discarding output">;
-def emit_codegen_only : Flag<"-emit-codegen-only">,
- HelpText<"Generate machine code, but discard output">;
-def emit_obj : Flag<"-emit-obj">,
- HelpText<"Emit native object files">;
-def rewrite_test : Flag<"-rewrite-test">,
- HelpText<"Rewriter playground">;
-def rewrite_objc : Flag<"-rewrite-objc">,
- HelpText<"Rewrite ObjC into C (code rewriter example)">;
-def rewrite_macros : Flag<"-rewrite-macros">,
- HelpText<"Expand macros without full preprocessing">;
-
-}
-
-def relocatable_pch : Flag<"-relocatable-pch">,
- HelpText<"Whether to build a relocatable precompiled header">;
-def chained_pch : Flag<"-chained-pch">,
- HelpText<"Whether to chain the new precompiled header to the old one.">;
-def print_stats : Flag<"-print-stats">,
- HelpText<"Print performance metrics and statistics">;
-def ftime_report : Flag<"-ftime-report">,
- HelpText<"Print the amount of time each phase of compilation takes">;
-
-def fdump_record_layouts : Flag<"-fdump-record-layouts">,
- HelpText<"Dump record layout information">;
-
-// Generic forwarding to LLVM options. This should only be used for debugging
-// and experimental features.
-def mllvm : Separate<"-mllvm">,
- HelpText<"Additional arguments to forward to LLVM's option processing">;
-
-//===----------------------------------------------------------------------===//
-// Language Options
-//===----------------------------------------------------------------------===//
-
-def fno_builtin : Flag<"-fno-builtin">,
- HelpText<"Disable implicit builtin knowledge of functions">;
-def faltivec : Flag<"-faltivec">,
- HelpText<"Enable AltiVec vector initializer syntax">;
-def fno_access_control : Flag<"-fno-access-control">,
- HelpText<"Disable C++ access control">;
-def fno_assume_sane_operator_new : Flag<"-fno-assume-sane-operator-new">,
- HelpText<"Don't assume that C++'s global operator new can't alias any pointer">;
-def fgnu_keywords : Flag<"-fgnu-keywords">,
- HelpText<"Allow GNU-extension keywords regardless of language standard">;
-def fno_gnu_keywords : Flag<"-fno-gnu-keywords">,
- HelpText<"Disallow GNU-extension keywords regardless of language standard">;
-def fdollars_in_identifiers : Flag<"-fdollars-in-identifiers">,
- HelpText<"Allow '$' in identifiers">;
-def fno_dollars_in_identifiers : Flag<"-fno-dollars-in-identifiers">,
- HelpText<"Disallow '$' in identifiers">;
-def femit_all_decls : Flag<"-femit-all-decls">,
- HelpText<"Emit all declarations, even if unused">;
-def fblocks : Flag<"-fblocks">,
- HelpText<"enable the 'blocks' language feature">;
-def fheinous_gnu_extensions : Flag<"-fheinous-gnu-extensions">;
-def fexceptions : Flag<"-fexceptions">,
- HelpText<"Enable support for exception handling">;
-def fsjlj_exceptions : Flag<"-fsjlj-exceptions">,
- HelpText<"Use SjLj style exceptions">;
-def ffreestanding : Flag<"-ffreestanding">,
- HelpText<"Assert that the compilation takes place in a freestanding environment">;
-def fgnu_runtime : Flag<"-fgnu-runtime">,
- HelpText<"Generate output compatible with the standard GNU Objective-C runtime">;
-def std_EQ : Joined<"-std=">,
- HelpText<"Language standard to compile for">;
-def fmath_errno : Flag<"-fmath-errno">,
- HelpText<"Require math functions to indicate errors by setting errno">;
-def fms_extensions : Flag<"-fms-extensions">,
- HelpText<"Accept some non-standard constructs used in Microsoft header files ">;
-def main_file_name : Separate<"-main-file-name">,
- HelpText<"Main file name to use for debug info">;
-def fno_elide_constructors : Flag<"-fno-elide-constructors">,
- HelpText<"Disable C++ copy constructor elision">;
-def fno_lax_vector_conversions : Flag<"-fno-lax-vector-conversions">,
- HelpText<"Disallow implicit conversions between vectors with a different number of elements or different element types">;
-def fno_operator_names : Flag<"-fno-operator-names">,
- HelpText<"Do not treat C++ operator name keywords as synonyms for operators">;
-def fno_signed_char : Flag<"-fno-signed-char">,
- HelpText<"Char is unsigned">;
-def fno_spell_checking : Flag<"-fno-spell-checking">,
- HelpText<"Disable spell-checking">;
-def fno_use_cxa_atexit : Flag<"-fno-use-cxa-atexit">,
- HelpText<"Don't use __cxa_atexit for calling destructors">;
-def fconstant_string_class : Separate<"-fconstant-string-class">,
- MetaVarName<"<class name>">,
- HelpText<"Specify the class to use for constant Objective-C string objects.">;
-def fno_constant_cfstrings : Flag<"-fno-constant-cfstrings">,
- HelpText<"Enable creation of CodeFoundation-type constant strings">;
-def fobjc_gc : Flag<"-fobjc-gc">,
- HelpText<"Enable Objective-C garbage collection">;
-def fobjc_gc_only : Flag<"-fobjc-gc-only">,
- HelpText<"Use GC exclusively for Objective-C related memory management">;
-def fobjc_dispatch_method_EQ : Joined<"-fobjc-dispatch-method=">,
- HelpText<"Objective-C dispatch method to use">;
-def print_ivar_layout : Flag<"-print-ivar-layout">,
- HelpText<"Enable Objective-C Ivar layout bitmap print trace">;
-def fobjc_nonfragile_abi : Flag<"-fobjc-nonfragile-abi">,
- HelpText<"enable objective-c's nonfragile abi">;
-def fobjc_nonfragile_abi2 : Flag<"-fobjc-nonfragile-abi2">,
- HelpText<"enable objective-c's enhanced nonfragile abi">;
-def ftrapv : Flag<"-ftrapv">,
- HelpText<"Trap on integer overflow">;
-def fwrapv : Flag<"-fwrapv">,
- HelpText<"Treat signed integer overflow as two's complement">;
-def pic_level : Separate<"-pic-level">,
- HelpText<"Value for __PIC__">;
-def pthread : Flag<"-pthread">,
- HelpText<"Support POSIX threads in generated code">;
-def fpascal_strings : Flag<"-fpascal-strings">,
- HelpText<"Recognize and construct Pascal-style string literals">;
-def fno_rtti : Flag<"-fno-rtti">,
- HelpText<"Disable generation of rtti information">;
-def fno_validate_pch : Flag<"-fno-validate-pch">,
- HelpText<"Disable validation of precompiled headers">;
-def fshort_wchar : Flag<"-fshort-wchar">,
- HelpText<"Force wchar_t to be a short unsigned int">;
-def static_define : Flag<"-static-define">,
- HelpText<"Should __STATIC__ be defined">;
-def stack_protector : Separate<"-stack-protector">,
- HelpText<"Enable stack protectors">;
-def fvisibility : Separate<"-fvisibility">,
- HelpText<"Default symbol visibility">;
-def fvisibility_inlines_hidden : Flag<"-fvisibility-inlines-hidden">,
- HelpText<"Give inline C++ member functions default visibility by default">;
-def ftemplate_depth : Separate<"-ftemplate-depth">,
- HelpText<"Maximum depth of recursive template instantiation">;
-def trigraphs : Flag<"-trigraphs">,
- HelpText<"Process trigraph sequences">;
-def fwritable_strings : Flag<"-fwritable-strings">,
- HelpText<"Store string literals as writable data">;
-def fno_bitfield_type_align : Flag<"-fno-bitfield-type-align">,
- HelpText<"Ignore bit-field types when aligning structures">;
-
-//===----------------------------------------------------------------------===//
-// Header Search Options
-//===----------------------------------------------------------------------===//
-
-def nostdinc : Flag<"-nostdinc">,
- HelpText<"Disable standard #include directories">;
-def nostdincxx : Flag<"-nostdinc++">,
- HelpText<"Disable standard #include directories for the C++ standard library">;
-def nobuiltininc : Flag<"-nobuiltininc">,
- HelpText<"Disable builtin #include directories">;
-def F : JoinedOrSeparate<"-F">, MetaVarName<"<directory>">,
- HelpText<"Add directory to framework include search path">;
-def I : JoinedOrSeparate<"-I">, MetaVarName<"<directory>">,
- HelpText<"Add directory to include search path">;
-def idirafter : JoinedOrSeparate<"-idirafter">, MetaVarName<"<directory>">,
- HelpText<"Add directory to AFTER include search path">;
-def iquote : JoinedOrSeparate<"-iquote">, MetaVarName<"<directory>">,
- HelpText<"Add directory to QUOTE include search path">;
-def isystem : JoinedOrSeparate<"-isystem">, MetaVarName<"<directory>">,
- HelpText<"Add directory to SYSTEM include search path">;
-def iprefix : JoinedOrSeparate<"-iprefix">, MetaVarName<"<prefix>">,
- HelpText<"Set the -iwithprefix/-iwithprefixbefore prefix">;
-def iwithprefix : JoinedOrSeparate<"-iwithprefix">, MetaVarName<"<dir>">,
- HelpText<"Set directory to SYSTEM include search path with prefix">;
-def iwithprefixbefore : JoinedOrSeparate<"-iwithprefixbefore">,
- MetaVarName<"<dir>">,
- HelpText<"Set directory to include search path with prefix">;
-def isysroot : JoinedOrSeparate<"-isysroot">, MetaVarName<"<dir>">,
- HelpText<"Set the system root directory (usually /)">;
-def v : Flag<"-v">, HelpText<"Enable verbose output">;
-
-//===----------------------------------------------------------------------===//
-// Preprocessor Options
-//===----------------------------------------------------------------------===//
-
-def D : JoinedOrSeparate<"-D">, MetaVarName<"<macro>">,
- HelpText<"Predefine the specified macro">;
-def include_ : JoinedOrSeparate<"-include">, MetaVarName<"<file>">, EnumName<"include">,
- HelpText<"Include file before parsing">;
-def imacros : JoinedOrSeparate<"-imacros">, MetaVarName<"<file>">,
- HelpText<"Include macros from file before parsing">;
-def include_pch : Separate<"-include-pch">, MetaVarName<"<file>">,
- HelpText<"Include precompiled header file">;
-def include_pth : Separate<"-include-pth">, MetaVarName<"<file>">,
- HelpText<"Include file before parsing">;
-def preamble_bytes_EQ : Joined<"-preamble-bytes=">,
- HelpText<"Assume that the precompiled header is a precompiled preamble "
- "covering the first N bytes of the main file">;
-def token_cache : Separate<"-token-cache">, MetaVarName<"<path>">,
- HelpText<"Use specified token cache file">;
-def U : JoinedOrSeparate<"-U">, MetaVarName<"<macro>">,
- HelpText<"Undefine the specified macro">;
-def undef : Flag<"-undef">, MetaVarName<"<macro>">,
- HelpText<"undef all system defines">;
-def detailed_preprocessing_record : Flag<"-detailed-preprocessing-record">,
- HelpText<"include a detailed record of preprocessing actions">;
-
-//===----------------------------------------------------------------------===//
-// Preprocessed Output Options
-//===----------------------------------------------------------------------===//
-
-def P : Flag<"-P">,
- HelpText<"Disable linemarker output in -E mode">;
-def C : Flag<"-C">,
- HelpText<"Enable comment output in -E mode">;
-def CC : Flag<"-CC">,
- HelpText<"Enable comment output in -E mode, even from macro expansions">;
-def dM : Flag<"-dM">,
- HelpText<"Print macro definitions in -E mode instead of normal output">;
-def dD : Flag<"-dD">,
- HelpText<"Print macro definitions in -E mode in addition to normal output">;
Removed: cfe/branches/Apple/williamson/lib/Analysis/CFG.cpp.orig
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/williamson/lib/Analysis/CFG.cpp.orig?rev=111417&view=auto
==============================================================================
--- cfe/branches/Apple/williamson/lib/Analysis/CFG.cpp.orig (original)
+++ cfe/branches/Apple/williamson/lib/Analysis/CFG.cpp.orig (removed)
@@ -1,2393 +0,0 @@
-//===--- CFG.cpp - Classes for representing and building CFGs----*- C++ -*-===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines the CFG and CFGBuilder classes for representing and
-// building Control-Flow Graphs (CFGs) from ASTs.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Analysis/Support/SaveAndRestore.h"
-#include "clang/Analysis/CFG.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/StmtVisitor.h"
-#include "clang/AST/PrettyPrinter.h"
-#include "llvm/Support/GraphWriter.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Format.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/ADT/OwningPtr.h"
-
-using namespace clang;
-
-namespace {
-
-static SourceLocation GetEndLoc(Decl* D) {
- if (VarDecl* VD = dyn_cast<VarDecl>(D))
- if (Expr* Ex = VD->getInit())
- return Ex->getSourceRange().getEnd();
-
- return D->getLocation();
-}
-
-class AddStmtChoice {
-public:
- enum Kind { NotAlwaysAdd = 0,
- AlwaysAdd = 1,
- AsLValueNotAlwaysAdd = 2,
- AlwaysAddAsLValue = 3 };
-
- AddStmtChoice(Kind kind) : k(kind) {}
-
- bool alwaysAdd() const { return (unsigned)k & 0x1; }
- bool asLValue() const { return k >= AsLValueNotAlwaysAdd; }
-
-private:
- Kind k;
-};
-
-/// CFGBuilder - This class implements CFG construction from an AST.
-/// The builder is stateful: an instance of the builder should be used to only
-/// construct a single CFG.
-///
-/// Example usage:
-///
-/// CFGBuilder builder;
-/// CFG* cfg = builder.BuildAST(stmt1);
-///
-/// CFG construction is done via a recursive walk of an AST. We actually parse
-/// the AST in reverse order so that the successor of a basic block is
-/// constructed prior to its predecessor. This allows us to nicely capture
-/// implicit fall-throughs without extra basic blocks.
-///
-class CFGBuilder {
- ASTContext *Context;
- llvm::OwningPtr<CFG> cfg;
-
- CFGBlock* Block;
- CFGBlock* Succ;
- CFGBlock* ContinueTargetBlock;
- CFGBlock* BreakTargetBlock;
- CFGBlock* SwitchTerminatedBlock;
- CFGBlock* DefaultCaseBlock;
- CFGBlock* TryTerminatedBlock;
-
- // LabelMap records the mapping from Label expressions to their blocks.
- typedef llvm::DenseMap<LabelStmt*,CFGBlock*> LabelMapTy;
- LabelMapTy LabelMap;
-
- // A list of blocks that end with a "goto" that must be backpatched to their
- // resolved targets upon completion of CFG construction.
- typedef std::vector<CFGBlock*> BackpatchBlocksTy;
- BackpatchBlocksTy BackpatchBlocks;
-
- // A list of labels whose address has been taken (for indirect gotos).
- typedef llvm::SmallPtrSet<LabelStmt*,5> LabelSetTy;
- LabelSetTy AddressTakenLabels;
-
-public:
- explicit CFGBuilder() : cfg(new CFG()), // crew a new CFG
- Block(NULL), Succ(NULL),
- ContinueTargetBlock(NULL), BreakTargetBlock(NULL),
- SwitchTerminatedBlock(NULL), DefaultCaseBlock(NULL),
- TryTerminatedBlock(NULL) {}
-
- // buildCFG - Used by external clients to construct the CFG.
- CFG* buildCFG(const Decl *D, Stmt *Statement, ASTContext *C, bool AddEHEdges,
- bool AddScopes);
-
-private:
- // Visitors to walk an AST and construct the CFG.
- CFGBlock *VisitAddrLabelExpr(AddrLabelExpr *A, AddStmtChoice asc);
- CFGBlock *VisitBinaryOperator(BinaryOperator *B, AddStmtChoice asc);
- CFGBlock *VisitBlockExpr(BlockExpr* E, AddStmtChoice asc);
- CFGBlock *VisitBreakStmt(BreakStmt *B);
- CFGBlock *VisitCXXCatchStmt(CXXCatchStmt *S);
- CFGBlock *VisitCXXThrowExpr(CXXThrowExpr *T);
- CFGBlock *VisitCXXTryStmt(CXXTryStmt *S);
- CFGBlock *VisitCXXMemberCallExpr(CXXMemberCallExpr *C, AddStmtChoice asc);
- CFGBlock *VisitCallExpr(CallExpr *C, AddStmtChoice asc);
- CFGBlock *VisitCaseStmt(CaseStmt *C);
- CFGBlock *VisitChooseExpr(ChooseExpr *C, AddStmtChoice asc);
- CFGBlock *VisitCompoundStmt(CompoundStmt *C);
- CFGBlock *VisitConditionalOperator(ConditionalOperator *C, AddStmtChoice asc);
- CFGBlock *VisitContinueStmt(ContinueStmt *C);
- CFGBlock *VisitDeclStmt(DeclStmt *DS);
- CFGBlock *VisitDeclSubExpr(Decl* D);
- CFGBlock *VisitDefaultStmt(DefaultStmt *D);
- CFGBlock *VisitDoStmt(DoStmt *D);
- CFGBlock *VisitForStmt(ForStmt *F);
- CFGBlock *VisitGotoStmt(GotoStmt* G);
- CFGBlock *VisitIfStmt(IfStmt *I);
- CFGBlock *VisitIndirectGotoStmt(IndirectGotoStmt *I);
- CFGBlock *VisitLabelStmt(LabelStmt *L);
- CFGBlock *VisitMemberExpr(MemberExpr *M, AddStmtChoice asc);
- CFGBlock *VisitObjCAtCatchStmt(ObjCAtCatchStmt *S);
- CFGBlock *VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt *S);
- CFGBlock *VisitObjCAtThrowStmt(ObjCAtThrowStmt *S);
- CFGBlock *VisitObjCAtTryStmt(ObjCAtTryStmt *S);
- CFGBlock *VisitObjCForCollectionStmt(ObjCForCollectionStmt *S);
- CFGBlock *VisitReturnStmt(ReturnStmt* R);
- CFGBlock *VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E, AddStmtChoice asc);
- CFGBlock *VisitStmtExpr(StmtExpr *S, AddStmtChoice asc);
- CFGBlock *VisitSwitchStmt(SwitchStmt *S);
- CFGBlock *VisitWhileStmt(WhileStmt *W);
-
- CFGBlock *Visit(Stmt *S, AddStmtChoice asc = AddStmtChoice::NotAlwaysAdd);
- CFGBlock *VisitStmt(Stmt *S, AddStmtChoice asc);
- CFGBlock *VisitChildren(Stmt* S);
-
- // NYS == Not Yet Supported
- CFGBlock* NYS() {
- badCFG = true;
- return Block;
- }
-
- CFGBlock *StartScope(Stmt *S, CFGBlock *B) {
- if (!AddScopes)
- return B;
-
- if (B == 0)
- B = createBlock();
- B->StartScope(S, cfg->getBumpVectorContext());
- return B;
- }
-
- void EndScope(Stmt *S) {
- if (!AddScopes)
- return;
-
- if (Block == 0)
- Block = createBlock();
- Block->EndScope(S, cfg->getBumpVectorContext());
- }
-
- void autoCreateBlock() { if (!Block) Block = createBlock(); }
- CFGBlock *createBlock(bool add_successor = true);
- bool FinishBlock(CFGBlock* B);
- CFGBlock *addStmt(Stmt *S) {
- return Visit(S, AddStmtChoice::AlwaysAdd);
- }
-
- void AppendStmt(CFGBlock *B, Stmt *S,
- AddStmtChoice asc = AddStmtChoice::AlwaysAdd) {
- B->appendStmt(S, cfg->getBumpVectorContext(), asc.asLValue());
- }
-
- void AddSuccessor(CFGBlock *B, CFGBlock *S) {
- B->addSuccessor(S, cfg->getBumpVectorContext());
- }
-
- /// TryResult - a class representing a variant over the values
- /// 'true', 'false', or 'unknown'. This is returned by TryEvaluateBool,
- /// and is used by the CFGBuilder to decide if a branch condition
- /// can be decided up front during CFG construction.
- class TryResult {
- int X;
- public:
- TryResult(bool b) : X(b ? 1 : 0) {}
- TryResult() : X(-1) {}
-
- bool isTrue() const { return X == 1; }
- bool isFalse() const { return X == 0; }
- bool isKnown() const { return X >= 0; }
- void negate() {
- assert(isKnown());
- X ^= 0x1;
- }
- };
-
- /// TryEvaluateBool - Try and evaluate the Stmt and return 0 or 1
- /// if we can evaluate to a known value, otherwise return -1.
- TryResult TryEvaluateBool(Expr *S) {
- Expr::EvalResult Result;
- if (!S->isTypeDependent() && !S->isValueDependent() &&
- S->Evaluate(Result, *Context) && Result.Val.isInt())
- return Result.Val.getInt().getBoolValue();
-
- return TryResult();
- }
-
- bool badCFG;
-
- // True iff EH edges on CallExprs should be added to the CFG.
- bool AddEHEdges;
-
- // True iff scope start and scope end notes should be added to the CFG.
- bool AddScopes;
-};
-
-// FIXME: Add support for dependent-sized array types in C++?
-// Does it even make sense to build a CFG for an uninstantiated template?
-static VariableArrayType* FindVA(Type* t) {
- while (ArrayType* vt = dyn_cast<ArrayType>(t)) {
- if (VariableArrayType* vat = dyn_cast<VariableArrayType>(vt))
- if (vat->getSizeExpr())
- return vat;
-
- t = vt->getElementType().getTypePtr();
- }
-
- return 0;
-}
-
-/// BuildCFG - Constructs a CFG from an AST (a Stmt*). The AST can represent an
-/// arbitrary statement. Examples include a single expression or a function
-/// body (compound statement). The ownership of the returned CFG is
-/// transferred to the caller. If CFG construction fails, this method returns
-/// NULL.
-CFG* CFGBuilder::buildCFG(const Decl *D, Stmt* Statement, ASTContext* C,
- bool addehedges, bool AddScopes) {
- AddEHEdges = addehedges;
- Context = C;
- assert(cfg.get());
- if (!Statement)
- return NULL;
-
- this->AddScopes = AddScopes;
- badCFG = false;
-
- // Create an empty block that will serve as the exit block for the CFG. Since
- // this is the first block added to the CFG, it will be implicitly registered
- // as the exit block.
- Succ = createBlock();
- assert(Succ == &cfg->getExit());
- Block = NULL; // the EXIT block is empty. Create all other blocks lazily.
-
- // Visit the statements and create the CFG.
- CFGBlock* B = addStmt(Statement);
-
- if (const CXXConstructorDecl *CD = dyn_cast_or_null<CXXConstructorDecl>(D)) {
- // FIXME: Add code for base initializers and member initializers.
- (void)CD;
- }
- if (!B)
- B = Succ;
-
- if (B) {
- // Finalize the last constructed block. This usually involves reversing the
- // order of the statements in the block.
- if (Block) FinishBlock(B);
-
- // Backpatch the gotos whose label -> block mappings we didn't know when we
- // encountered them.
- for (BackpatchBlocksTy::iterator I = BackpatchBlocks.begin(),
- E = BackpatchBlocks.end(); I != E; ++I ) {
-
- CFGBlock* B = *I;
- GotoStmt* G = cast<GotoStmt>(B->getTerminator());
- LabelMapTy::iterator LI = LabelMap.find(G->getLabel());
-
- // If there is no target for the goto, then we are looking at an
- // incomplete AST. Handle this by not registering a successor.
- if (LI == LabelMap.end()) continue;
-
- AddSuccessor(B, LI->second);
- }
-
- // Add successors to the Indirect Goto Dispatch block (if we have one).
- if (CFGBlock* B = cfg->getIndirectGotoBlock())
- for (LabelSetTy::iterator I = AddressTakenLabels.begin(),
- E = AddressTakenLabels.end(); I != E; ++I ) {
-
- // Lookup the target block.
- LabelMapTy::iterator LI = LabelMap.find(*I);
-
- // If there is no target block that contains label, then we are looking
- // at an incomplete AST. Handle this by not registering a successor.
- if (LI == LabelMap.end()) continue;
-
- AddSuccessor(B, LI->second);
- }
-
- Succ = B;
- }
-
- // Create an empty entry block that has no predecessors.
- cfg->setEntry(createBlock());
-
- return badCFG ? NULL : cfg.take();
-}
-
-/// createBlock - Used to lazily create blocks that are connected
-/// to the current (global) succcessor.
-CFGBlock* CFGBuilder::createBlock(bool add_successor) {
- CFGBlock* B = cfg->createBlock();
- if (add_successor && Succ)
- AddSuccessor(B, Succ);
- return B;
-}
-
-/// FinishBlock - "Finalize" the block by checking if we have a bad CFG.
-bool CFGBuilder::FinishBlock(CFGBlock* B) {
- if (badCFG)
- return false;
-
- assert(B);
- return true;
-}
-
-/// Visit - Walk the subtree of a statement and add extra
-/// blocks for ternary operators, &&, and ||. We also process "," and
-/// DeclStmts (which may contain nested control-flow).
-CFGBlock* CFGBuilder::Visit(Stmt * S, AddStmtChoice asc) {
-tryAgain:
- if (!S) {
- badCFG = true;
- return 0;
- }
- switch (S->getStmtClass()) {
- default:
- return VisitStmt(S, asc);
-
- case Stmt::AddrLabelExprClass:
- return VisitAddrLabelExpr(cast<AddrLabelExpr>(S), asc);
-
- case Stmt::BinaryOperatorClass:
- return VisitBinaryOperator(cast<BinaryOperator>(S), asc);
-
- case Stmt::BlockExprClass:
- return VisitBlockExpr(cast<BlockExpr>(S), asc);
-
- case Stmt::BreakStmtClass:
- return VisitBreakStmt(cast<BreakStmt>(S));
-
- case Stmt::CallExprClass:
- return VisitCallExpr(cast<CallExpr>(S), asc);
-
- case Stmt::CaseStmtClass:
- return VisitCaseStmt(cast<CaseStmt>(S));
-
- case Stmt::ChooseExprClass:
- return VisitChooseExpr(cast<ChooseExpr>(S), asc);
-
- case Stmt::CompoundStmtClass:
- return VisitCompoundStmt(cast<CompoundStmt>(S));
-
- case Stmt::ConditionalOperatorClass:
- return VisitConditionalOperator(cast<ConditionalOperator>(S), asc);
-
- case Stmt::ContinueStmtClass:
- return VisitContinueStmt(cast<ContinueStmt>(S));
-
- case Stmt::CXXCatchStmtClass:
- return VisitCXXCatchStmt(cast<CXXCatchStmt>(S));
-
- case Stmt::CXXMemberCallExprClass:
- return VisitCXXMemberCallExpr(cast<CXXMemberCallExpr>(S), asc);
-
- case Stmt::CXXThrowExprClass:
- return VisitCXXThrowExpr(cast<CXXThrowExpr>(S));
-
- case Stmt::CXXTryStmtClass:
- return VisitCXXTryStmt(cast<CXXTryStmt>(S));
-
- case Stmt::DeclStmtClass:
- return VisitDeclStmt(cast<DeclStmt>(S));
-
- case Stmt::DefaultStmtClass:
- return VisitDefaultStmt(cast<DefaultStmt>(S));
-
- case Stmt::DoStmtClass:
- return VisitDoStmt(cast<DoStmt>(S));
-
- case Stmt::ForStmtClass:
- return VisitForStmt(cast<ForStmt>(S));
-
- case Stmt::GotoStmtClass:
- return VisitGotoStmt(cast<GotoStmt>(S));
-
- case Stmt::IfStmtClass:
- return VisitIfStmt(cast<IfStmt>(S));
-
- case Stmt::IndirectGotoStmtClass:
- return VisitIndirectGotoStmt(cast<IndirectGotoStmt>(S));
-
- case Stmt::LabelStmtClass:
- return VisitLabelStmt(cast<LabelStmt>(S));
-
- case Stmt::MemberExprClass:
- return VisitMemberExpr(cast<MemberExpr>(S), asc);
-
- case Stmt::ObjCAtCatchStmtClass:
- return VisitObjCAtCatchStmt(cast<ObjCAtCatchStmt>(S));
-
- case Stmt::ObjCAtSynchronizedStmtClass:
- return VisitObjCAtSynchronizedStmt(cast<ObjCAtSynchronizedStmt>(S));
-
- case Stmt::ObjCAtThrowStmtClass:
- return VisitObjCAtThrowStmt(cast<ObjCAtThrowStmt>(S));
-
- case Stmt::ObjCAtTryStmtClass:
- return VisitObjCAtTryStmt(cast<ObjCAtTryStmt>(S));
-
- case Stmt::ObjCForCollectionStmtClass:
- return VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S));
-
- case Stmt::ParenExprClass:
- S = cast<ParenExpr>(S)->getSubExpr();
- goto tryAgain;
-
- case Stmt::NullStmtClass:
- return Block;
-
- case Stmt::ReturnStmtClass:
- return VisitReturnStmt(cast<ReturnStmt>(S));
-
- case Stmt::SizeOfAlignOfExprClass:
- return VisitSizeOfAlignOfExpr(cast<SizeOfAlignOfExpr>(S), asc);
-
- case Stmt::StmtExprClass:
- return VisitStmtExpr(cast<StmtExpr>(S), asc);
-
- case Stmt::SwitchStmtClass:
- return VisitSwitchStmt(cast<SwitchStmt>(S));
-
- case Stmt::WhileStmtClass:
- return VisitWhileStmt(cast<WhileStmt>(S));
- }
-}
-
-CFGBlock *CFGBuilder::VisitStmt(Stmt *S, AddStmtChoice asc) {
- if (asc.alwaysAdd()) {
- autoCreateBlock();
- AppendStmt(Block, S, asc);
- }
-
- return VisitChildren(S);
-}
-
-/// VisitChildren - Visit the children of a Stmt.
-CFGBlock *CFGBuilder::VisitChildren(Stmt* Terminator) {
- CFGBlock *B = Block;
- for (Stmt::child_iterator I = Terminator->child_begin(),
- E = Terminator->child_end(); I != E; ++I) {
- if (*I) B = Visit(*I);
- }
- return B;
-}
-
-CFGBlock *CFGBuilder::VisitAddrLabelExpr(AddrLabelExpr *A,
- AddStmtChoice asc) {
- AddressTakenLabels.insert(A->getLabel());
-
- if (asc.alwaysAdd()) {
- autoCreateBlock();
- AppendStmt(Block, A, asc);
- }
-
- return Block;
-}
-
-CFGBlock *CFGBuilder::VisitBinaryOperator(BinaryOperator *B,
- AddStmtChoice asc) {
- if (B->isLogicalOp()) { // && or ||
- CFGBlock* ConfluenceBlock = Block ? Block : createBlock();
- AppendStmt(ConfluenceBlock, B, asc);
-
- if (!FinishBlock(ConfluenceBlock))
- return 0;
-
- // create the block evaluating the LHS
- CFGBlock* LHSBlock = createBlock(false);
- LHSBlock->setTerminator(B);
-
- // create the block evaluating the RHS
- Succ = ConfluenceBlock;
- Block = NULL;
- CFGBlock* RHSBlock = addStmt(B->getRHS());
-
- if (RHSBlock) {
- if (!FinishBlock(RHSBlock))
- return 0;
- }
- else {
- // Create an empty block for cases where the RHS doesn't require
- // any explicit statements in the CFG.
- RHSBlock = createBlock();
- }
-
- // See if this is a known constant.
- TryResult KnownVal = TryEvaluateBool(B->getLHS());
- if (KnownVal.isKnown() && (B->getOpcode() == BinaryOperator::LOr))
- KnownVal.negate();
-
- // Now link the LHSBlock with RHSBlock.
- if (B->getOpcode() == BinaryOperator::LOr) {
- AddSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock);
- AddSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock);
- } else {
- assert(B->getOpcode() == BinaryOperator::LAnd);
- AddSuccessor(LHSBlock, KnownVal.isFalse() ? NULL : RHSBlock);
- AddSuccessor(LHSBlock, KnownVal.isTrue() ? NULL : ConfluenceBlock);
- }
-
- // Generate the blocks for evaluating the LHS.
- Block = LHSBlock;
- return addStmt(B->getLHS());
- }
- else if (B->getOpcode() == BinaryOperator::Comma) { // ,
- autoCreateBlock();
- AppendStmt(Block, B, asc);
- addStmt(B->getRHS());
- return addStmt(B->getLHS());
- }
- else if (B->isAssignmentOp()) {
- if (asc.alwaysAdd()) {
- autoCreateBlock();
- AppendStmt(Block, B, asc);
- }
-
- Visit(B->getRHS());
- return Visit(B->getLHS(), AddStmtChoice::AsLValueNotAlwaysAdd);
- }
-
- return VisitStmt(B, asc);
-}
-
-CFGBlock *CFGBuilder::VisitBlockExpr(BlockExpr *E, AddStmtChoice asc) {
- if (asc.alwaysAdd()) {
- autoCreateBlock();
- AppendStmt(Block, E, asc);
- }
- return Block;
-}
-
-CFGBlock *CFGBuilder::VisitBreakStmt(BreakStmt *B) {
- // "break" is a control-flow statement. Thus we stop processing the current
- // block.
- if (Block && !FinishBlock(Block))
- return 0;
-
- // Now create a new block that ends with the break statement.
- Block = createBlock(false);
- Block->setTerminator(B);
-
- // If there is no target for the break, then we are looking at an incomplete
- // AST. This means that the CFG cannot be constructed.
- if (BreakTargetBlock)
- AddSuccessor(Block, BreakTargetBlock);
- else
- badCFG = true;
-
-
- return Block;
-}
-
-static bool CanThrow(Expr *E) {
- QualType Ty = E->getType();
- if (Ty->isFunctionPointerType())
- Ty = Ty->getAs<PointerType>()->getPointeeType();
- else if (Ty->isBlockPointerType())
- Ty = Ty->getAs<BlockPointerType>()->getPointeeType();
-
- const FunctionType *FT = Ty->getAs<FunctionType>();
- if (FT) {
- if (const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT))
- if (Proto->hasEmptyExceptionSpec())
- return false;
- }
- return true;
-}
-
-CFGBlock *CFGBuilder::VisitCallExpr(CallExpr *C, AddStmtChoice asc) {
- // If this is a call to a no-return function, this stops the block here.
- bool NoReturn = false;
- if (getFunctionExtInfo(*C->getCallee()->getType()).getNoReturn()) {
- NoReturn = true;
- }
-
- bool AddEHEdge = false;
-
- // Languages without exceptions are assumed to not throw.
- if (Context->getLangOptions().Exceptions) {
- if (AddEHEdges)
- AddEHEdge = true;
- }
-
- if (FunctionDecl *FD = C->getDirectCallee()) {
- if (FD->hasAttr<NoReturnAttr>())
- NoReturn = true;
- if (FD->hasAttr<NoThrowAttr>())
- AddEHEdge = false;
- }
-
- if (!CanThrow(C->getCallee()))
- AddEHEdge = false;
-
- if (!NoReturn && !AddEHEdge) {
- if (asc.asLValue())
- return VisitStmt(C, AddStmtChoice::AlwaysAddAsLValue);
- else
- return VisitStmt(C, AddStmtChoice::AlwaysAdd);
- }
-
- if (Block) {
- Succ = Block;
- if (!FinishBlock(Block))
- return 0;
- }
-
- Block = createBlock(!NoReturn);
- AppendStmt(Block, C, asc);
-
- if (NoReturn) {
- // Wire this to the exit block directly.
- AddSuccessor(Block, &cfg->getExit());
- }
- if (AddEHEdge) {
- // Add exceptional edges.
- if (TryTerminatedBlock)
- AddSuccessor(Block, TryTerminatedBlock);
- else
- AddSuccessor(Block, &cfg->getExit());
- }
-
- return VisitChildren(C);
-}
-
-CFGBlock *CFGBuilder::VisitChooseExpr(ChooseExpr *C,
- AddStmtChoice asc) {
- CFGBlock* ConfluenceBlock = Block ? Block : createBlock();
- AppendStmt(ConfluenceBlock, C, asc);
- if (!FinishBlock(ConfluenceBlock))
- return 0;
-
- asc = asc.asLValue() ? AddStmtChoice::AlwaysAddAsLValue
- : AddStmtChoice::AlwaysAdd;
-
- Succ = ConfluenceBlock;
- Block = NULL;
- CFGBlock* LHSBlock = Visit(C->getLHS(), asc);
- if (!FinishBlock(LHSBlock))
- return 0;
-
- Succ = ConfluenceBlock;
- Block = NULL;
- CFGBlock* RHSBlock = Visit(C->getRHS(), asc);
- if (!FinishBlock(RHSBlock))
- return 0;
-
- Block = createBlock(false);
- // See if this is a known constant.
- const TryResult& KnownVal = TryEvaluateBool(C->getCond());
- AddSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock);
- AddSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock);
- Block->setTerminator(C);
- return addStmt(C->getCond());
-}
-
-
-CFGBlock* CFGBuilder::VisitCompoundStmt(CompoundStmt* C) {
- EndScope(C);
-
- CFGBlock* LastBlock = Block;
-
- for (CompoundStmt::reverse_body_iterator I=C->body_rbegin(), E=C->body_rend();
- I != E; ++I ) {
- LastBlock = addStmt(*I);
-
- if (badCFG)
- return NULL;
- }
-
- LastBlock = StartScope(C, LastBlock);
-
- return LastBlock;
-}
-
-CFGBlock *CFGBuilder::VisitConditionalOperator(ConditionalOperator *C,
- AddStmtChoice asc) {
- // Create the confluence block that will "merge" the results of the ternary
- // expression.
- CFGBlock* ConfluenceBlock = Block ? Block : createBlock();
- AppendStmt(ConfluenceBlock, C, asc);
- if (!FinishBlock(ConfluenceBlock))
- return 0;
-
- asc = asc.asLValue() ? AddStmtChoice::AlwaysAddAsLValue
- : AddStmtChoice::AlwaysAdd;
-
- // Create a block for the LHS expression if there is an LHS expression. A
- // GCC extension allows LHS to be NULL, causing the condition to be the
- // value that is returned instead.
- // e.g: x ?: y is shorthand for: x ? x : y;
- Succ = ConfluenceBlock;
- Block = NULL;
- CFGBlock* LHSBlock = NULL;
- if (C->getLHS()) {
- LHSBlock = Visit(C->getLHS(), asc);
- if (!FinishBlock(LHSBlock))
- return 0;
- Block = NULL;
- }
-
- // Create the block for the RHS expression.
- Succ = ConfluenceBlock;
- CFGBlock* RHSBlock = Visit(C->getRHS(), asc);
- if (!FinishBlock(RHSBlock))
- return 0;
-
- // Create the block that will contain the condition.
- Block = createBlock(false);
-
- // See if this is a known constant.
- const TryResult& KnownVal = TryEvaluateBool(C->getCond());
- if (LHSBlock) {
- AddSuccessor(Block, KnownVal.isFalse() ? NULL : LHSBlock);
- } else {
- if (KnownVal.isFalse()) {
- // If we know the condition is false, add NULL as the successor for
- // the block containing the condition. In this case, the confluence
- // block will have just one predecessor.
- AddSuccessor(Block, 0);
- assert(ConfluenceBlock->pred_size() == 1);
- } else {
- // If we have no LHS expression, add the ConfluenceBlock as a direct
- // successor for the block containing the condition. Moreover, we need to
- // reverse the order of the predecessors in the ConfluenceBlock because
- // the RHSBlock will have been added to the succcessors already, and we
- // want the first predecessor to the the block containing the expression
- // for the case when the ternary expression evaluates to true.
- AddSuccessor(Block, ConfluenceBlock);
- assert(ConfluenceBlock->pred_size() == 2);
- std::reverse(ConfluenceBlock->pred_begin(),
- ConfluenceBlock->pred_end());
- }
- }
-
- AddSuccessor(Block, KnownVal.isTrue() ? NULL : RHSBlock);
- Block->setTerminator(C);
- return addStmt(C->getCond());
-}
-
-CFGBlock *CFGBuilder::VisitDeclStmt(DeclStmt *DS) {
- autoCreateBlock();
-
- if (DS->isSingleDecl()) {
- AppendStmt(Block, DS);
- return VisitDeclSubExpr(DS->getSingleDecl());
- }
-
- CFGBlock *B = 0;
-
- // FIXME: Add a reverse iterator for DeclStmt to avoid this extra copy.
- typedef llvm::SmallVector<Decl*,10> BufTy;
- BufTy Buf(DS->decl_begin(), DS->decl_end());
-
- for (BufTy::reverse_iterator I = Buf.rbegin(), E = Buf.rend(); I != E; ++I) {
- // Get the alignment of the new DeclStmt, padding out to >=8 bytes.
- unsigned A = llvm::AlignOf<DeclStmt>::Alignment < 8
- ? 8 : llvm::AlignOf<DeclStmt>::Alignment;
-
- // Allocate the DeclStmt using the BumpPtrAllocator. It will get
- // automatically freed with the CFG.
- DeclGroupRef DG(*I);
- Decl *D = *I;
- void *Mem = cfg->getAllocator().Allocate(sizeof(DeclStmt), A);
- DeclStmt *DSNew = new (Mem) DeclStmt(DG, D->getLocation(), GetEndLoc(D));
-
- // Append the fake DeclStmt to block.
- AppendStmt(Block, DSNew);
- B = VisitDeclSubExpr(D);
- }
-
- return B;
-}
-
-/// VisitDeclSubExpr - Utility method to add block-level expressions for
-/// initializers in Decls.
-CFGBlock *CFGBuilder::VisitDeclSubExpr(Decl* D) {
- assert(Block);
-
- VarDecl *VD = dyn_cast<VarDecl>(D);
-
- if (!VD)
- return Block;
-
- Expr *Init = VD->getInit();
-
- if (Init) {
- AddStmtChoice::Kind k =
- VD->getType()->isReferenceType() ? AddStmtChoice::AsLValueNotAlwaysAdd
- : AddStmtChoice::NotAlwaysAdd;
- Visit(Init, AddStmtChoice(k));
- }
-
- // If the type of VD is a VLA, then we must process its size expressions.
- for (VariableArrayType* VA = FindVA(VD->getType().getTypePtr()); VA != 0;
- VA = FindVA(VA->getElementType().getTypePtr()))
- Block = addStmt(VA->getSizeExpr());
-
- return Block;
-}
-
-CFGBlock* CFGBuilder::VisitIfStmt(IfStmt* I) {
- // We may see an if statement in the middle of a basic block, or it may be the
- // first statement we are processing. In either case, we create a new basic
- // block. First, we create the blocks for the then...else statements, and
- // then we create the block containing the if statement. If we were in the
- // middle of a block, we stop processing that block. That block is then the
- // implicit successor for the "then" and "else" clauses.
-
- // The block we were proccessing is now finished. Make it the successor
- // block.
- if (Block) {
- Succ = Block;
- if (!FinishBlock(Block))
- return 0;
- }
-
- // Process the false branch.
- CFGBlock* ElseBlock = Succ;
-
- if (Stmt* Else = I->getElse()) {
- SaveAndRestore<CFGBlock*> sv(Succ);
-
- // NULL out Block so that the recursive call to Visit will
- // create a new basic block.
- Block = NULL;
- ElseBlock = addStmt(Else);
-
- if (!ElseBlock) // Can occur when the Else body has all NullStmts.
- ElseBlock = sv.get();
- else if (Block) {
- if (!FinishBlock(ElseBlock))
- return 0;
- }
- }
-
- // Process the true branch.
- CFGBlock* ThenBlock;
- {
- Stmt* Then = I->getThen();
- assert(Then);
- SaveAndRestore<CFGBlock*> sv(Succ);
- Block = NULL;
- ThenBlock = addStmt(Then);
-
- if (!ThenBlock) {
- // We can reach here if the "then" body has all NullStmts.
- // Create an empty block so we can distinguish between true and false
- // branches in path-sensitive analyses.
- ThenBlock = createBlock(false);
- AddSuccessor(ThenBlock, sv.get());
- } else if (Block) {
- if (!FinishBlock(ThenBlock))
- return 0;
- }
- }
-
- // Now create a new block containing the if statement.
- Block = createBlock(false);
-
- // Set the terminator of the new block to the If statement.
- Block->setTerminator(I);
-
- // See if this is a known constant.
- const TryResult &KnownVal = TryEvaluateBool(I->getCond());
-
- // Now add the successors.
- AddSuccessor(Block, KnownVal.isFalse() ? NULL : ThenBlock);
- AddSuccessor(Block, KnownVal.isTrue()? NULL : ElseBlock);
-
- // Add the condition as the last statement in the new block. This may create
- // new blocks as the condition may contain control-flow. Any newly created
- // blocks will be pointed to be "Block".
- Block = addStmt(I->getCond());
-
- // Finally, if the IfStmt contains a condition variable, add both the IfStmt
- // and the condition variable initialization to the CFG.
- if (VarDecl *VD = I->getConditionVariable()) {
- if (Expr *Init = VD->getInit()) {
- autoCreateBlock();
- AppendStmt(Block, I, AddStmtChoice::AlwaysAdd);
- addStmt(Init);
- }
- }
-
- return Block;
-}
-
-
-CFGBlock* CFGBuilder::VisitReturnStmt(ReturnStmt* R) {
- // If we were in the middle of a block we stop processing that block.
- //
- // NOTE: If a "return" appears in the middle of a block, this means that the
- // code afterwards is DEAD (unreachable). We still keep a basic block
- // for that code; a simple "mark-and-sweep" from the entry block will be
- // able to report such dead blocks.
- if (Block)
- FinishBlock(Block);
-
- // Create the new block.
- Block = createBlock(false);
-
- // The Exit block is the only successor.
- AddSuccessor(Block, &cfg->getExit());
-
- // Add the return statement to the block. This may create new blocks if R
- // contains control-flow (short-circuit operations).
- return VisitStmt(R, AddStmtChoice::AlwaysAdd);
-}
-
-CFGBlock* CFGBuilder::VisitLabelStmt(LabelStmt* L) {
- // Get the block of the labeled statement. Add it to our map.
- addStmt(L->getSubStmt());
- CFGBlock* LabelBlock = Block;
-
- if (!LabelBlock) // This can happen when the body is empty, i.e.
- LabelBlock = createBlock(); // scopes that only contains NullStmts.
-
- assert(LabelMap.find(L) == LabelMap.end() && "label already in map");
- LabelMap[ L ] = LabelBlock;
-
- // Labels partition blocks, so this is the end of the basic block we were
- // processing (L is the block's label). Because this is label (and we have
- // already processed the substatement) there is no extra control-flow to worry
- // about.
- LabelBlock->setLabel(L);
- if (!FinishBlock(LabelBlock))
- return 0;
-
- // We set Block to NULL to allow lazy creation of a new block (if necessary);
- Block = NULL;
-
- // This block is now the implicit successor of other blocks.
- Succ = LabelBlock;
-
- return LabelBlock;
-}
-
-CFGBlock* CFGBuilder::VisitGotoStmt(GotoStmt* G) {
- // Goto is a control-flow statement. Thus we stop processing the current
- // block and create a new one.
- if (Block)
- FinishBlock(Block);
-
- Block = createBlock(false);
- Block->setTerminator(G);
-
- // If we already know the mapping to the label block add the successor now.
- LabelMapTy::iterator I = LabelMap.find(G->getLabel());
-
- if (I == LabelMap.end())
- // We will need to backpatch this block later.
- BackpatchBlocks.push_back(Block);
- else
- AddSuccessor(Block, I->second);
-
- return Block;
-}
-
-CFGBlock* CFGBuilder::VisitForStmt(ForStmt* F) {
- CFGBlock* LoopSuccessor = NULL;
-
- // "for" is a control-flow statement. Thus we stop processing the current
- // block.
- if (Block) {
- if (!FinishBlock(Block))
- return 0;
- LoopSuccessor = Block;
- } else
- LoopSuccessor = Succ;
-
- // Save the current value for the break targets.
- // All breaks should go to the code following the loop.
- SaveAndRestore<CFGBlock*> save_break(BreakTargetBlock);
- BreakTargetBlock = LoopSuccessor;
-
- // Because of short-circuit evaluation, the condition of the loop can span
- // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that
- // evaluate the condition.
- CFGBlock* ExitConditionBlock = createBlock(false);
- CFGBlock* EntryConditionBlock = ExitConditionBlock;
-
- // Set the terminator for the "exit" condition block.
- ExitConditionBlock->setTerminator(F);
-
- // Now add the actual condition to the condition block. Because the condition
- // itself may contain control-flow, new blocks may be created.
- if (Stmt* C = F->getCond()) {
- Block = ExitConditionBlock;
- EntryConditionBlock = addStmt(C);
- assert(Block == EntryConditionBlock);
-
- // If this block contains a condition variable, add both the condition
- // variable and initializer to the CFG.
- if (VarDecl *VD = F->getConditionVariable()) {
- if (Expr *Init = VD->getInit()) {
- autoCreateBlock();
- AppendStmt(Block, F, AddStmtChoice::AlwaysAdd);
- EntryConditionBlock = addStmt(Init);
- assert(Block == EntryConditionBlock);
- }
- }
-
- if (Block) {
- if (!FinishBlock(EntryConditionBlock))
- return 0;
- }
- }
-
- // The condition block is the implicit successor for the loop body as well as
- // any code above the loop.
- Succ = EntryConditionBlock;
-
- // See if this is a known constant.
- TryResult KnownVal(true);
-
- if (F->getCond())
- KnownVal = TryEvaluateBool(F->getCond());
-
- // Now create the loop body.
- {
- assert(F->getBody());
-
- // Save the current values for Block, Succ, and continue targets.
- SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ),
- save_continue(ContinueTargetBlock);
-
- // Create a new block to contain the (bottom) of the loop body.
- Block = NULL;
-
- if (Stmt* I = F->getInc()) {
- // Generate increment code in its own basic block. This is the target of
- // continue statements.
- Succ = addStmt(I);
- } else {
- // No increment code. Create a special, empty, block that is used as the
- // target block for "looping back" to the start of the loop.
- assert(Succ == EntryConditionBlock);
- Succ = createBlock();
- }
-
- // Finish up the increment (or empty) block if it hasn't been already.
- if (Block) {
- assert(Block == Succ);
- if (!FinishBlock(Block))
- return 0;
- Block = 0;
- }
-
- ContinueTargetBlock = Succ;
-
- // The starting block for the loop increment is the block that should
- // represent the 'loop target' for looping back to the start of the loop.
- ContinueTargetBlock->setLoopTarget(F);
-
- // Now populate the body block, and in the process create new blocks as we
- // walk the body of the loop.
- CFGBlock* BodyBlock = addStmt(F->getBody());
-
- if (!BodyBlock)
- BodyBlock = ContinueTargetBlock; // can happen for "for (...;...;...) ;"
- else if (Block && !FinishBlock(BodyBlock))
- return 0;
-
- // This new body block is a successor to our "exit" condition block.
- AddSuccessor(ExitConditionBlock, KnownVal.isFalse() ? NULL : BodyBlock);
- }
-
- // Link up the condition block with the code that follows the loop. (the
- // false branch).
- AddSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor);
-
- // If the loop contains initialization, create a new block for those
- // statements. This block can also contain statements that precede the loop.
- if (Stmt* I = F->getInit()) {
- Block = createBlock();
- return addStmt(I);
- } else {
- // There is no loop initialization. We are thus basically a while loop.
- // NULL out Block to force lazy block construction.
- Block = NULL;
- Succ = EntryConditionBlock;
- return EntryConditionBlock;
- }
-}
-
-CFGBlock *CFGBuilder::VisitMemberExpr(MemberExpr *M, AddStmtChoice asc) {
- if (asc.alwaysAdd()) {
- autoCreateBlock();
- AppendStmt(Block, M, asc);
- }
- return Visit(M->getBase(),
- M->isArrow() ? AddStmtChoice::NotAlwaysAdd
- : AddStmtChoice::AsLValueNotAlwaysAdd);
-}
-
-CFGBlock* CFGBuilder::VisitObjCForCollectionStmt(ObjCForCollectionStmt* S) {
- // Objective-C fast enumeration 'for' statements:
- // http://developer.apple.com/documentation/Cocoa/Conceptual/ObjectiveC
- //
- // for ( Type newVariable in collection_expression ) { statements }
- //
- // becomes:
- //
- // prologue:
- // 1. collection_expression
- // T. jump to loop_entry
- // loop_entry:
- // 1. side-effects of element expression
- // 1. ObjCForCollectionStmt [performs binding to newVariable]
- // T. ObjCForCollectionStmt TB, FB [jumps to TB if newVariable != nil]
- // TB:
- // statements
- // T. jump to loop_entry
- // FB:
- // what comes after
- //
- // and
- //
- // Type existingItem;
- // for ( existingItem in expression ) { statements }
- //
- // becomes:
- //
- // the same with newVariable replaced with existingItem; the binding works
- // the same except that for one ObjCForCollectionStmt::getElement() returns
- // a DeclStmt and the other returns a DeclRefExpr.
- //
-
- CFGBlock* LoopSuccessor = 0;
-
- if (Block) {
- if (!FinishBlock(Block))
- return 0;
- LoopSuccessor = Block;
- Block = 0;
- } else
- LoopSuccessor = Succ;
-
- // Build the condition blocks.
- CFGBlock* ExitConditionBlock = createBlock(false);
- CFGBlock* EntryConditionBlock = ExitConditionBlock;
-
- // Set the terminator for the "exit" condition block.
- ExitConditionBlock->setTerminator(S);
-
- // The last statement in the block should be the ObjCForCollectionStmt, which
- // performs the actual binding to 'element' and determines if there are any
- // more items in the collection.
- AppendStmt(ExitConditionBlock, S);
- Block = ExitConditionBlock;
-
- // Walk the 'element' expression to see if there are any side-effects. We
- // generate new blocks as necesary. We DON'T add the statement by default to
- // the CFG unless it contains control-flow.
- EntryConditionBlock = Visit(S->getElement(), AddStmtChoice::NotAlwaysAdd);
- if (Block) {
- if (!FinishBlock(EntryConditionBlock))
- return 0;
- Block = 0;
- }
-
- // The condition block is the implicit successor for the loop body as well as
- // any code above the loop.
- Succ = EntryConditionBlock;
-
- // Now create the true branch.
- {
- // Save the current values for Succ, continue and break targets.
- SaveAndRestore<CFGBlock*> save_Succ(Succ),
- save_continue(ContinueTargetBlock), save_break(BreakTargetBlock);
-
- BreakTargetBlock = LoopSuccessor;
- ContinueTargetBlock = EntryConditionBlock;
-
- CFGBlock* BodyBlock = addStmt(S->getBody());
-
- if (!BodyBlock)
- BodyBlock = EntryConditionBlock; // can happen for "for (X in Y) ;"
- else if (Block) {
- if (!FinishBlock(BodyBlock))
- return 0;
- }
-
- // This new body block is a successor to our "exit" condition block.
- AddSuccessor(ExitConditionBlock, BodyBlock);
- }
-
- // Link up the condition block with the code that follows the loop.
- // (the false branch).
- AddSuccessor(ExitConditionBlock, LoopSuccessor);
-
- // Now create a prologue block to contain the collection expression.
- Block = createBlock();
- return addStmt(S->getCollection());
-}
-
-CFGBlock* CFGBuilder::VisitObjCAtSynchronizedStmt(ObjCAtSynchronizedStmt* S) {
- // FIXME: Add locking 'primitives' to CFG for @synchronized.
-
- // Inline the body.
- CFGBlock *SyncBlock = addStmt(S->getSynchBody());
-
- // The sync body starts its own basic block. This makes it a little easier
- // for diagnostic clients.
- if (SyncBlock) {
- if (!FinishBlock(SyncBlock))
- return 0;
-
- Block = 0;
- Succ = SyncBlock;
- }
-
- // Inline the sync expression.
- return addStmt(S->getSynchExpr());
-}
-
-CFGBlock* CFGBuilder::VisitObjCAtTryStmt(ObjCAtTryStmt* S) {
- // FIXME
- return NYS();
-}
-
-CFGBlock* CFGBuilder::VisitWhileStmt(WhileStmt* W) {
- CFGBlock* LoopSuccessor = NULL;
-
- // "while" is a control-flow statement. Thus we stop processing the current
- // block.
- if (Block) {
- if (!FinishBlock(Block))
- return 0;
- LoopSuccessor = Block;
- } else
- LoopSuccessor = Succ;
-
- // Because of short-circuit evaluation, the condition of the loop can span
- // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that
- // evaluate the condition.
- CFGBlock* ExitConditionBlock = createBlock(false);
- CFGBlock* EntryConditionBlock = ExitConditionBlock;
-
- // Set the terminator for the "exit" condition block.
- ExitConditionBlock->setTerminator(W);
-
- // Now add the actual condition to the condition block. Because the condition
- // itself may contain control-flow, new blocks may be created. Thus we update
- // "Succ" after adding the condition.
- if (Stmt* C = W->getCond()) {
- Block = ExitConditionBlock;
- EntryConditionBlock = addStmt(C);
- assert(Block == EntryConditionBlock);
-
- // If this block contains a condition variable, add both the condition
- // variable and initializer to the CFG.
- if (VarDecl *VD = W->getConditionVariable()) {
- if (Expr *Init = VD->getInit()) {
- autoCreateBlock();
- AppendStmt(Block, W, AddStmtChoice::AlwaysAdd);
- EntryConditionBlock = addStmt(Init);
- assert(Block == EntryConditionBlock);
- }
- }
-
- if (Block) {
- if (!FinishBlock(EntryConditionBlock))
- return 0;
- }
- }
-
- // The condition block is the implicit successor for the loop body as well as
- // any code above the loop.
- Succ = EntryConditionBlock;
-
- // See if this is a known constant.
- const TryResult& KnownVal = TryEvaluateBool(W->getCond());
-
- // Process the loop body.
- {
- assert(W->getBody());
-
- // Save the current values for Block, Succ, and continue and break targets
- SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ),
- save_continue(ContinueTargetBlock),
- save_break(BreakTargetBlock);
-
- // Create an empty block to represent the transition block for looping back
- // to the head of the loop.
- Block = 0;
- assert(Succ == EntryConditionBlock);
- Succ = createBlock();
- Succ->setLoopTarget(W);
- ContinueTargetBlock = Succ;
-
- // All breaks should go to the code following the loop.
- BreakTargetBlock = LoopSuccessor;
-
- // NULL out Block to force lazy instantiation of blocks for the body.
- Block = NULL;
-
- // Create the body. The returned block is the entry to the loop body.
- CFGBlock* BodyBlock = addStmt(W->getBody());
-
- if (!BodyBlock)
- BodyBlock = ContinueTargetBlock; // can happen for "while(...) ;"
- else if (Block) {
- if (!FinishBlock(BodyBlock))
- return 0;
- }
-
- // Add the loop body entry as a successor to the condition.
- AddSuccessor(ExitConditionBlock, KnownVal.isFalse() ? NULL : BodyBlock);
- }
-
- // Link up the condition block with the code that follows the loop. (the
- // false branch).
- AddSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor);
-
- // There can be no more statements in the condition block since we loop back
- // to this block. NULL out Block to force lazy creation of another block.
- Block = NULL;
-
- // Return the condition block, which is the dominating block for the loop.
- Succ = EntryConditionBlock;
- return EntryConditionBlock;
-}
-
-
-CFGBlock *CFGBuilder::VisitObjCAtCatchStmt(ObjCAtCatchStmt* S) {
- // FIXME: For now we pretend that @catch and the code it contains does not
- // exit.
- return Block;
-}
-
-CFGBlock* CFGBuilder::VisitObjCAtThrowStmt(ObjCAtThrowStmt* S) {
- // FIXME: This isn't complete. We basically treat @throw like a return
- // statement.
-
- // If we were in the middle of a block we stop processing that block.
- if (Block && !FinishBlock(Block))
- return 0;
-
- // Create the new block.
- Block = createBlock(false);
-
- // The Exit block is the only successor.
- AddSuccessor(Block, &cfg->getExit());
-
- // Add the statement to the block. This may create new blocks if S contains
- // control-flow (short-circuit operations).
- return VisitStmt(S, AddStmtChoice::AlwaysAdd);
-}
-
-CFGBlock* CFGBuilder::VisitCXXThrowExpr(CXXThrowExpr* T) {
- // If we were in the middle of a block we stop processing that block.
- if (Block && !FinishBlock(Block))
- return 0;
-
- // Create the new block.
- Block = createBlock(false);
-
- if (TryTerminatedBlock)
- // The current try statement is the only successor.
- AddSuccessor(Block, TryTerminatedBlock);
- else
- // otherwise the Exit block is the only successor.
- AddSuccessor(Block, &cfg->getExit());
-
- // Add the statement to the block. This may create new blocks if S contains
- // control-flow (short-circuit operations).
- return VisitStmt(T, AddStmtChoice::AlwaysAdd);
-}
-
-CFGBlock *CFGBuilder::VisitDoStmt(DoStmt* D) {
- CFGBlock* LoopSuccessor = NULL;
-
- // "do...while" is a control-flow statement. Thus we stop processing the
- // current block.
- if (Block) {
- if (!FinishBlock(Block))
- return 0;
- LoopSuccessor = Block;
- } else
- LoopSuccessor = Succ;
-
- // Because of short-circuit evaluation, the condition of the loop can span
- // multiple basic blocks. Thus we need the "Entry" and "Exit" blocks that
- // evaluate the condition.
- CFGBlock* ExitConditionBlock = createBlock(false);
- CFGBlock* EntryConditionBlock = ExitConditionBlock;
-
- // Set the terminator for the "exit" condition block.
- ExitConditionBlock->setTerminator(D);
-
- // Now add the actual condition to the condition block. Because the condition
- // itself may contain control-flow, new blocks may be created.
- if (Stmt* C = D->getCond()) {
- Block = ExitConditionBlock;
- EntryConditionBlock = addStmt(C);
- if (Block) {
- if (!FinishBlock(EntryConditionBlock))
- return 0;
- }
- }
-
- // The condition block is the implicit successor for the loop body.
- Succ = EntryConditionBlock;
-
- // See if this is a known constant.
- const TryResult &KnownVal = TryEvaluateBool(D->getCond());
-
- // Process the loop body.
- CFGBlock* BodyBlock = NULL;
- {
- assert(D->getBody());
-
- // Save the current values for Block, Succ, and continue and break targets
- SaveAndRestore<CFGBlock*> save_Block(Block), save_Succ(Succ),
- save_continue(ContinueTargetBlock),
- save_break(BreakTargetBlock);
-
- // All continues within this loop should go to the condition block
- ContinueTargetBlock = EntryConditionBlock;
-
- // All breaks should go to the code following the loop.
- BreakTargetBlock = LoopSuccessor;
-
- // NULL out Block to force lazy instantiation of blocks for the body.
- Block = NULL;
-
- // Create the body. The returned block is the entry to the loop body.
- BodyBlock = addStmt(D->getBody());
-
- if (!BodyBlock)
- BodyBlock = EntryConditionBlock; // can happen for "do ; while(...)"
- else if (Block) {
- if (!FinishBlock(BodyBlock))
- return 0;
- }
-
- // Add an intermediate block between the BodyBlock and the
- // ExitConditionBlock to represent the "loop back" transition. Create an
- // empty block to represent the transition block for looping back to the
- // head of the loop.
- // FIXME: Can we do this more efficiently without adding another block?
- Block = NULL;
- Succ = BodyBlock;
- CFGBlock *LoopBackBlock = createBlock();
- LoopBackBlock->setLoopTarget(D);
-
- // Add the loop body entry as a successor to the condition.
- AddSuccessor(ExitConditionBlock, KnownVal.isFalse() ? NULL : LoopBackBlock);
- }
-
- // Link up the condition block with the code that follows the loop.
- // (the false branch).
- AddSuccessor(ExitConditionBlock, KnownVal.isTrue() ? NULL : LoopSuccessor);
-
- // There can be no more statements in the body block(s) since we loop back to
- // the body. NULL out Block to force lazy creation of another block.
- Block = NULL;
-
- // Return the loop body, which is the dominating block for the loop.
- Succ = BodyBlock;
- return BodyBlock;
-}
-
-CFGBlock* CFGBuilder::VisitContinueStmt(ContinueStmt* C) {
- // "continue" is a control-flow statement. Thus we stop processing the
- // current block.
- if (Block && !FinishBlock(Block))
- return 0;
-
- // Now create a new block that ends with the continue statement.
- Block = createBlock(false);
- Block->setTerminator(C);
-
- // If there is no target for the continue, then we are looking at an
- // incomplete AST. This means the CFG cannot be constructed.
- if (ContinueTargetBlock)
- AddSuccessor(Block, ContinueTargetBlock);
- else
- badCFG = true;
-
- return Block;
-}
-
-CFGBlock *CFGBuilder::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E,
- AddStmtChoice asc) {
-
- if (asc.alwaysAdd()) {
- autoCreateBlock();
- AppendStmt(Block, E);
- }
-
- // VLA types have expressions that must be evaluated.
- if (E->isArgumentType()) {
- for (VariableArrayType* VA = FindVA(E->getArgumentType().getTypePtr());
- VA != 0; VA = FindVA(VA->getElementType().getTypePtr()))
- addStmt(VA->getSizeExpr());
- }
-
- return Block;
-}
-
-/// VisitStmtExpr - Utility method to handle (nested) statement
-/// expressions (a GCC extension).
-CFGBlock* CFGBuilder::VisitStmtExpr(StmtExpr *SE, AddStmtChoice asc) {
- if (asc.alwaysAdd()) {
- autoCreateBlock();
- AppendStmt(Block, SE);
- }
- return VisitCompoundStmt(SE->getSubStmt());
-}
-
-CFGBlock* CFGBuilder::VisitSwitchStmt(SwitchStmt* Terminator) {
- // "switch" is a control-flow statement. Thus we stop processing the current
- // block.
- CFGBlock* SwitchSuccessor = NULL;
-
- if (Block) {
- if (!FinishBlock(Block))
- return 0;
- SwitchSuccessor = Block;
- } else SwitchSuccessor = Succ;
-
- // Save the current "switch" context.
- SaveAndRestore<CFGBlock*> save_switch(SwitchTerminatedBlock),
- save_break(BreakTargetBlock),
- save_default(DefaultCaseBlock);
-
- // Set the "default" case to be the block after the switch statement. If the
- // switch statement contains a "default:", this value will be overwritten with
- // the block for that code.
- DefaultCaseBlock = SwitchSuccessor;
-
- // Create a new block that will contain the switch statement.
- SwitchTerminatedBlock = createBlock(false);
-
- // Now process the switch body. The code after the switch is the implicit
- // successor.
- Succ = SwitchSuccessor;
- BreakTargetBlock = SwitchSuccessor;
-
- // When visiting the body, the case statements should automatically get linked
- // up to the switch. We also don't keep a pointer to the body, since all
- // control-flow from the switch goes to case/default statements.
- assert(Terminator->getBody() && "switch must contain a non-NULL body");
- Block = NULL;
- CFGBlock *BodyBlock = addStmt(Terminator->getBody());
- if (Block) {
- if (!FinishBlock(BodyBlock))
- return 0;
- }
-
- // If we have no "default:" case, the default transition is to the code
- // following the switch body.
- AddSuccessor(SwitchTerminatedBlock, DefaultCaseBlock);
-
- // Add the terminator and condition in the switch block.
- SwitchTerminatedBlock->setTerminator(Terminator);
- assert(Terminator->getCond() && "switch condition must be non-NULL");
- Block = SwitchTerminatedBlock;
- Block = addStmt(Terminator->getCond());
-
- // Finally, if the SwitchStmt contains a condition variable, add both the
- // SwitchStmt and the condition variable initialization to the CFG.
- if (VarDecl *VD = Terminator->getConditionVariable()) {
- if (Expr *Init = VD->getInit()) {
- autoCreateBlock();
- AppendStmt(Block, Terminator, AddStmtChoice::AlwaysAdd);
- addStmt(Init);
- }
- }
-
- return Block;
-}
-
-CFGBlock* CFGBuilder::VisitCaseStmt(CaseStmt* CS) {
- // CaseStmts are essentially labels, so they are the first statement in a
- // block.
-
- if (CS->getSubStmt())
- addStmt(CS->getSubStmt());
-
- CFGBlock* CaseBlock = Block;
- if (!CaseBlock)
- CaseBlock = createBlock();
-
- // Cases statements partition blocks, so this is the top of the basic block we
- // were processing (the "case XXX:" is the label).
- CaseBlock->setLabel(CS);
-
- if (!FinishBlock(CaseBlock))
- return 0;
-
- // Add this block to the list of successors for the block with the switch
- // statement.
- assert(SwitchTerminatedBlock);
- AddSuccessor(SwitchTerminatedBlock, CaseBlock);
-
- // We set Block to NULL to allow lazy creation of a new block (if necessary)
- Block = NULL;
-
- // This block is now the implicit successor of other blocks.
- Succ = CaseBlock;
-
- return CaseBlock;
-}
-
-CFGBlock* CFGBuilder::VisitDefaultStmt(DefaultStmt* Terminator) {
- if (Terminator->getSubStmt())
- addStmt(Terminator->getSubStmt());
-
- DefaultCaseBlock = Block;
-
- if (!DefaultCaseBlock)
- DefaultCaseBlock = createBlock();
-
- // Default statements partition blocks, so this is the top of the basic block
- // we were processing (the "default:" is the label).
- DefaultCaseBlock->setLabel(Terminator);
-
- if (!FinishBlock(DefaultCaseBlock))
- return 0;
-
- // Unlike case statements, we don't add the default block to the successors
- // for the switch statement immediately. This is done when we finish
- // processing the switch statement. This allows for the default case
- // (including a fall-through to the code after the switch statement) to always
- // be the last successor of a switch-terminated block.
-
- // We set Block to NULL to allow lazy creation of a new block (if necessary)
- Block = NULL;
-
- // This block is now the implicit successor of other blocks.
- Succ = DefaultCaseBlock;
-
- return DefaultCaseBlock;
-}
-
-CFGBlock *CFGBuilder::VisitCXXTryStmt(CXXTryStmt *Terminator) {
- // "try"/"catch" is a control-flow statement. Thus we stop processing the
- // current block.
- CFGBlock* TrySuccessor = NULL;
-
- if (Block) {
- if (!FinishBlock(Block))
- return 0;
- TrySuccessor = Block;
- } else TrySuccessor = Succ;
-
- CFGBlock *PrevTryTerminatedBlock = TryTerminatedBlock;
-
- // Create a new block that will contain the try statement.
- CFGBlock *NewTryTerminatedBlock = createBlock(false);
- // Add the terminator in the try block.
- NewTryTerminatedBlock->setTerminator(Terminator);
-
- bool HasCatchAll = false;
- for (unsigned h = 0; h <Terminator->getNumHandlers(); ++h) {
- // The code after the try is the implicit successor.
- Succ = TrySuccessor;
- CXXCatchStmt *CS = Terminator->getHandler(h);
- if (CS->getExceptionDecl() == 0) {
- HasCatchAll = true;
- }
- Block = NULL;
- CFGBlock *CatchBlock = VisitCXXCatchStmt(CS);
- if (CatchBlock == 0)
- return 0;
- // Add this block to the list of successors for the block with the try
- // statement.
- AddSuccessor(NewTryTerminatedBlock, CatchBlock);
- }
- if (!HasCatchAll) {
- if (PrevTryTerminatedBlock)
- AddSuccessor(NewTryTerminatedBlock, PrevTryTerminatedBlock);
- else
- AddSuccessor(NewTryTerminatedBlock, &cfg->getExit());
- }
-
- // The code after the try is the implicit successor.
- Succ = TrySuccessor;
-
- // Save the current "try" context.
- SaveAndRestore<CFGBlock*> save_try(TryTerminatedBlock);
- TryTerminatedBlock = NewTryTerminatedBlock;
-
- assert(Terminator->getTryBlock() && "try must contain a non-NULL body");
- Block = NULL;
- Block = addStmt(Terminator->getTryBlock());
- return Block;
-}
-
-CFGBlock* CFGBuilder::VisitCXXCatchStmt(CXXCatchStmt* CS) {
- // CXXCatchStmt are treated like labels, so they are the first statement in a
- // block.
-
- if (CS->getHandlerBlock())
- addStmt(CS->getHandlerBlock());
-
- CFGBlock* CatchBlock = Block;
- if (!CatchBlock)
- CatchBlock = createBlock();
-
- CatchBlock->setLabel(CS);
-
- if (!FinishBlock(CatchBlock))
- return 0;
-
- // We set Block to NULL to allow lazy creation of a new block (if necessary)
- Block = NULL;
-
- return CatchBlock;
-}
-
-CFGBlock *CFGBuilder::VisitCXXMemberCallExpr(CXXMemberCallExpr *C,
- AddStmtChoice asc) {
- AddStmtChoice::Kind K = asc.asLValue() ? AddStmtChoice::AlwaysAddAsLValue
- : AddStmtChoice::AlwaysAdd;
- autoCreateBlock();
- AppendStmt(Block, C, AddStmtChoice(K));
- return VisitChildren(C);
-}
-
-CFGBlock* CFGBuilder::VisitIndirectGotoStmt(IndirectGotoStmt* I) {
- // Lazily create the indirect-goto dispatch block if there isn't one already.
- CFGBlock* IBlock = cfg->getIndirectGotoBlock();
-
- if (!IBlock) {
- IBlock = createBlock(false);
- cfg->setIndirectGotoBlock(IBlock);
- }
-
- // IndirectGoto is a control-flow statement. Thus we stop processing the
- // current block and create a new one.
- if (Block && !FinishBlock(Block))
- return 0;
-
- Block = createBlock(false);
- Block->setTerminator(I);
- AddSuccessor(Block, IBlock);
- return addStmt(I->getTarget());
-}
-
-} // end anonymous namespace
-
-/// createBlock - Constructs and adds a new CFGBlock to the CFG. The block has
-/// no successors or predecessors. If this is the first block created in the
-/// CFG, it is automatically set to be the Entry and Exit of the CFG.
-CFGBlock* CFG::createBlock() {
- bool first_block = begin() == end();
-
- // Create the block.
- CFGBlock *Mem = getAllocator().Allocate<CFGBlock>();
- new (Mem) CFGBlock(NumBlockIDs++, BlkBVC);
- Blocks.push_back(Mem, BlkBVC);
-
- // If this is the first block, set it as the Entry and Exit.
- if (first_block)
- Entry = Exit = &back();
-
- // Return the block.
- return &back();
-}
-
-/// buildCFG - Constructs a CFG from an AST. Ownership of the returned
-/// CFG is returned to the caller.
-CFG* CFG::buildCFG(const Decl *D, Stmt* Statement, ASTContext *C,
- bool AddEHEdges, bool AddScopes) {
- CFGBuilder Builder;
- return Builder.buildCFG(D, Statement, C, AddEHEdges, AddScopes);
-}
-
-//===----------------------------------------------------------------------===//
-// CFG: Queries for BlkExprs.
-//===----------------------------------------------------------------------===//
-
-namespace {
- typedef llvm::DenseMap<const Stmt*,unsigned> BlkExprMapTy;
-}
-
-static void FindSubExprAssignments(Stmt *S,
- llvm::SmallPtrSet<Expr*,50>& Set) {
- if (!S)
- return;
-
- for (Stmt::child_iterator I=S->child_begin(), E=S->child_end(); I!=E; ++I) {
- Stmt *child = *I;
- if (!child)
- continue;
-
- if (BinaryOperator* B = dyn_cast<BinaryOperator>(child))
- if (B->isAssignmentOp()) Set.insert(B);
-
- FindSubExprAssignments(child, Set);
- }
-}
-
-static BlkExprMapTy* PopulateBlkExprMap(CFG& cfg) {
- BlkExprMapTy* M = new BlkExprMapTy();
-
- // Look for assignments that are used as subexpressions. These are the only
- // assignments that we want to *possibly* register as a block-level
- // expression. Basically, if an assignment occurs both in a subexpression and
- // at the block-level, it is a block-level expression.
- llvm::SmallPtrSet<Expr*,50> SubExprAssignments;
-
- for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I)
- for (CFGBlock::iterator BI=(*I)->begin(), EI=(*I)->end(); BI != EI; ++BI)
- FindSubExprAssignments(*BI, SubExprAssignments);
-
- for (CFG::iterator I=cfg.begin(), E=cfg.end(); I != E; ++I) {
-
- // Iterate over the statements again on identify the Expr* and Stmt* at the
- // block-level that are block-level expressions.
-
- for (CFGBlock::iterator BI=(*I)->begin(), EI=(*I)->end(); BI != EI; ++BI)
- if (Expr* Exp = dyn_cast<Expr>(*BI)) {
-
- if (BinaryOperator* B = dyn_cast<BinaryOperator>(Exp)) {
- // Assignment expressions that are not nested within another
- // expression are really "statements" whose value is never used by
- // another expression.
- if (B->isAssignmentOp() && !SubExprAssignments.count(Exp))
- continue;
- } else if (const StmtExpr* Terminator = dyn_cast<StmtExpr>(Exp)) {
- // Special handling for statement expressions. The last statement in
- // the statement expression is also a block-level expr.
- const CompoundStmt* C = Terminator->getSubStmt();
- if (!C->body_empty()) {
- unsigned x = M->size();
- (*M)[C->body_back()] = x;
- }
- }
-
- unsigned x = M->size();
- (*M)[Exp] = x;
- }
-
- // Look at terminators. The condition is a block-level expression.
-
- Stmt* S = (*I)->getTerminatorCondition();
-
- if (S && M->find(S) == M->end()) {
- unsigned x = M->size();
- (*M)[S] = x;
- }
- }
-
- return M;
-}
-
-CFG::BlkExprNumTy CFG::getBlkExprNum(const Stmt* S) {
- assert(S != NULL);
- if (!BlkExprMap) { BlkExprMap = (void*) PopulateBlkExprMap(*this); }
-
- BlkExprMapTy* M = reinterpret_cast<BlkExprMapTy*>(BlkExprMap);
- BlkExprMapTy::iterator I = M->find(S);
- return (I == M->end()) ? CFG::BlkExprNumTy() : CFG::BlkExprNumTy(I->second);
-}
-
-unsigned CFG::getNumBlkExprs() {
- if (const BlkExprMapTy* M = reinterpret_cast<const BlkExprMapTy*>(BlkExprMap))
- return M->size();
- else {
- // We assume callers interested in the number of BlkExprs will want
- // the map constructed if it doesn't already exist.
- BlkExprMap = (void*) PopulateBlkExprMap(*this);
- return reinterpret_cast<BlkExprMapTy*>(BlkExprMap)->size();
- }
-}
-
-//===----------------------------------------------------------------------===//
-// Cleanup: CFG dstor.
-//===----------------------------------------------------------------------===//
-
-CFG::~CFG() {
- delete reinterpret_cast<const BlkExprMapTy*>(BlkExprMap);
-}
-
-//===----------------------------------------------------------------------===//
-// CFG pretty printing
-//===----------------------------------------------------------------------===//
-
-namespace {
-
-class StmtPrinterHelper : public PrinterHelper {
- typedef llvm::DenseMap<Stmt*,std::pair<unsigned,unsigned> > StmtMapTy;
- StmtMapTy StmtMap;
- signed CurrentBlock;
- unsigned CurrentStmt;
- const LangOptions &LangOpts;
-public:
-
- StmtPrinterHelper(const CFG* cfg, const LangOptions &LO)
- : CurrentBlock(0), CurrentStmt(0), LangOpts(LO) {
- for (CFG::const_iterator I = cfg->begin(), E = cfg->end(); I != E; ++I ) {
- unsigned j = 1;
- for (CFGBlock::const_iterator BI = (*I)->begin(), BEnd = (*I)->end() ;
- BI != BEnd; ++BI, ++j )
- StmtMap[*BI] = std::make_pair((*I)->getBlockID(),j);
- }
- }
-
- virtual ~StmtPrinterHelper() {}
-
- const LangOptions &getLangOpts() const { return LangOpts; }
- void setBlockID(signed i) { CurrentBlock = i; }
- void setStmtID(unsigned i) { CurrentStmt = i; }
-
- virtual bool handledStmt(Stmt* Terminator, llvm::raw_ostream& OS) {
-
- StmtMapTy::iterator I = StmtMap.find(Terminator);
-
- if (I == StmtMap.end())
- return false;
-
- if (CurrentBlock >= 0 && I->second.first == (unsigned) CurrentBlock
- && I->second.second == CurrentStmt) {
- return false;
- }
-
- OS << "[B" << I->second.first << "." << I->second.second << "]";
- return true;
- }
-};
-} // end anonymous namespace
-
-
-namespace {
-class CFGBlockTerminatorPrint
- : public StmtVisitor<CFGBlockTerminatorPrint,void> {
-
- llvm::raw_ostream& OS;
- StmtPrinterHelper* Helper;
- PrintingPolicy Policy;
-public:
- CFGBlockTerminatorPrint(llvm::raw_ostream& os, StmtPrinterHelper* helper,
- const PrintingPolicy &Policy)
- : OS(os), Helper(helper), Policy(Policy) {}
-
- void VisitIfStmt(IfStmt* I) {
- OS << "if ";
- I->getCond()->printPretty(OS,Helper,Policy);
- }
-
- // Default case.
- void VisitStmt(Stmt* Terminator) {
- Terminator->printPretty(OS, Helper, Policy);
- }
-
- void VisitForStmt(ForStmt* F) {
- OS << "for (" ;
- if (F->getInit())
- OS << "...";
- OS << "; ";
- if (Stmt* C = F->getCond())
- C->printPretty(OS, Helper, Policy);
- OS << "; ";
- if (F->getInc())
- OS << "...";
- OS << ")";
- }
-
- void VisitWhileStmt(WhileStmt* W) {
- OS << "while " ;
- if (Stmt* C = W->getCond())
- C->printPretty(OS, Helper, Policy);
- }
-
- void VisitDoStmt(DoStmt* D) {
- OS << "do ... while ";
- if (Stmt* C = D->getCond())
- C->printPretty(OS, Helper, Policy);
- }
-
- void VisitSwitchStmt(SwitchStmt* Terminator) {
- OS << "switch ";
- Terminator->getCond()->printPretty(OS, Helper, Policy);
- }
-
- void VisitCXXTryStmt(CXXTryStmt* CS) {
- OS << "try ...";
- }
-
- void VisitConditionalOperator(ConditionalOperator* C) {
- C->getCond()->printPretty(OS, Helper, Policy);
- OS << " ? ... : ...";
- }
-
- void VisitChooseExpr(ChooseExpr* C) {
- OS << "__builtin_choose_expr( ";
- C->getCond()->printPretty(OS, Helper, Policy);
- OS << " )";
- }
-
- void VisitIndirectGotoStmt(IndirectGotoStmt* I) {
- OS << "goto *";
- I->getTarget()->printPretty(OS, Helper, Policy);
- }
-
- void VisitBinaryOperator(BinaryOperator* B) {
- if (!B->isLogicalOp()) {
- VisitExpr(B);
- return;
- }
-
- B->getLHS()->printPretty(OS, Helper, Policy);
-
- switch (B->getOpcode()) {
- case BinaryOperator::LOr:
- OS << " || ...";
- return;
- case BinaryOperator::LAnd:
- OS << " && ...";
- return;
- default:
- assert(false && "Invalid logical operator.");
- }
- }
-
- void VisitExpr(Expr* E) {
- E->printPretty(OS, Helper, Policy);
- }
-};
-} // end anonymous namespace
-
-
-static void print_stmt(llvm::raw_ostream &OS, StmtPrinterHelper* Helper,
- const CFGElement &E) {
- Stmt *Terminator = E;
-
- if (E.asStartScope()) {
- OS << "start scope\n";
- return;
- }
- if (E.asEndScope()) {
- OS << "end scope\n";
- return;
- }
-
- if (Helper) {
- // special printing for statement-expressions.
- if (StmtExpr* SE = dyn_cast<StmtExpr>(Terminator)) {
- CompoundStmt* Sub = SE->getSubStmt();
-
- if (Sub->child_begin() != Sub->child_end()) {
- OS << "({ ... ; ";
- Helper->handledStmt(*SE->getSubStmt()->body_rbegin(),OS);
- OS << " })\n";
- return;
- }
- }
-
- // special printing for comma expressions.
- if (BinaryOperator* B = dyn_cast<BinaryOperator>(Terminator)) {
- if (B->getOpcode() == BinaryOperator::Comma) {
- OS << "... , ";
- Helper->handledStmt(B->getRHS(),OS);
- OS << '\n';
- return;
- }
- }
- }
-
- Terminator->printPretty(OS, Helper, PrintingPolicy(Helper->getLangOpts()));
-
- // Expressions need a newline.
- if (isa<Expr>(Terminator)) OS << '\n';
-}
-
-static void print_block(llvm::raw_ostream& OS, const CFG* cfg,
- const CFGBlock& B,
- StmtPrinterHelper* Helper, bool print_edges) {
-
- if (Helper) Helper->setBlockID(B.getBlockID());
-
- // Print the header.
- OS << "\n [ B" << B.getBlockID();
-
- if (&B == &cfg->getEntry())
- OS << " (ENTRY) ]\n";
- else if (&B == &cfg->getExit())
- OS << " (EXIT) ]\n";
- else if (&B == cfg->getIndirectGotoBlock())
- OS << " (INDIRECT GOTO DISPATCH) ]\n";
- else
- OS << " ]\n";
-
- // Print the label of this block.
- if (Stmt* Label = const_cast<Stmt*>(B.getLabel())) {
-
- if (print_edges)
- OS << " ";
-
- if (LabelStmt* L = dyn_cast<LabelStmt>(Label))
- OS << L->getName();
- else if (CaseStmt* C = dyn_cast<CaseStmt>(Label)) {
- OS << "case ";
- C->getLHS()->printPretty(OS, Helper,
- PrintingPolicy(Helper->getLangOpts()));
- if (C->getRHS()) {
- OS << " ... ";
- C->getRHS()->printPretty(OS, Helper,
- PrintingPolicy(Helper->getLangOpts()));
- }
- } else if (isa<DefaultStmt>(Label))
- OS << "default";
- else if (CXXCatchStmt *CS = dyn_cast<CXXCatchStmt>(Label)) {
- OS << "catch (";
- if (CS->getExceptionDecl())
- CS->getExceptionDecl()->print(OS, PrintingPolicy(Helper->getLangOpts()),
- 0);
- else
- OS << "...";
- OS << ")";
-
- } else
- assert(false && "Invalid label statement in CFGBlock.");
-
- OS << ":\n";
- }
-
- // Iterate through the statements in the block and print them.
- unsigned j = 1;
-
- for (CFGBlock::const_iterator I = B.begin(), E = B.end() ;
- I != E ; ++I, ++j ) {
-
- // Print the statement # in the basic block and the statement itself.
- if (print_edges)
- OS << " ";
-
- OS << llvm::format("%3d", j) << ": ";
-
- if (Helper)
- Helper->setStmtID(j);
-
- print_stmt(OS,Helper,*I);
- }
-
- // Print the terminator of this block.
- if (B.getTerminator()) {
- if (print_edges)
- OS << " ";
-
- OS << " T: ";
-
- if (Helper) Helper->setBlockID(-1);
-
- CFGBlockTerminatorPrint TPrinter(OS, Helper,
- PrintingPolicy(Helper->getLangOpts()));
- TPrinter.Visit(const_cast<Stmt*>(B.getTerminator()));
- OS << '\n';
- }
-
- if (print_edges) {
- // Print the predecessors of this block.
- OS << " Predecessors (" << B.pred_size() << "):";
- unsigned i = 0;
-
- for (CFGBlock::const_pred_iterator I = B.pred_begin(), E = B.pred_end();
- I != E; ++I, ++i) {
-
- if (i == 8 || (i-8) == 0)
- OS << "\n ";
-
- OS << " B" << (*I)->getBlockID();
- }
-
- OS << '\n';
-
- // Print the successors of this block.
- OS << " Successors (" << B.succ_size() << "):";
- i = 0;
-
- for (CFGBlock::const_succ_iterator I = B.succ_begin(), E = B.succ_end();
- I != E; ++I, ++i) {
-
- if (i == 8 || (i-8) % 10 == 0)
- OS << "\n ";
-
- if (*I)
- OS << " B" << (*I)->getBlockID();
- else
- OS << " NULL";
- }
-
- OS << '\n';
- }
-}
-
-
-/// dump - A simple pretty printer of a CFG that outputs to stderr.
-void CFG::dump(const LangOptions &LO) const { print(llvm::errs(), LO); }
-
-/// print - A simple pretty printer of a CFG that outputs to an ostream.
-void CFG::print(llvm::raw_ostream &OS, const LangOptions &LO) const {
- StmtPrinterHelper Helper(this, LO);
-
- // Print the entry block.
- print_block(OS, this, getEntry(), &Helper, true);
-
- // Iterate through the CFGBlocks and print them one by one.
- for (const_iterator I = Blocks.begin(), E = Blocks.end() ; I != E ; ++I) {
- // Skip the entry block, because we already printed it.
- if (&(**I) == &getEntry() || &(**I) == &getExit())
- continue;
-
- print_block(OS, this, **I, &Helper, true);
- }
-
- // Print the exit block.
- print_block(OS, this, getExit(), &Helper, true);
- OS.flush();
-}
-
-/// dump - A simply pretty printer of a CFGBlock that outputs to stderr.
-void CFGBlock::dump(const CFG* cfg, const LangOptions &LO) const {
- print(llvm::errs(), cfg, LO);
-}
-
-/// print - A simple pretty printer of a CFGBlock that outputs to an ostream.
-/// Generally this will only be called from CFG::print.
-void CFGBlock::print(llvm::raw_ostream& OS, const CFG* cfg,
- const LangOptions &LO) const {
- StmtPrinterHelper Helper(cfg, LO);
- print_block(OS, cfg, *this, &Helper, true);
-}
-
-/// printTerminator - A simple pretty printer of the terminator of a CFGBlock.
-void CFGBlock::printTerminator(llvm::raw_ostream &OS,
- const LangOptions &LO) const {
- CFGBlockTerminatorPrint TPrinter(OS, NULL, PrintingPolicy(LO));
- TPrinter.Visit(const_cast<Stmt*>(getTerminator()));
-}
-
-Stmt* CFGBlock::getTerminatorCondition() {
-
- if (!Terminator)
- return NULL;
-
- Expr* E = NULL;
-
- switch (Terminator->getStmtClass()) {
- default:
- break;
-
- case Stmt::ForStmtClass:
- E = cast<ForStmt>(Terminator)->getCond();
- break;
-
- case Stmt::WhileStmtClass:
- E = cast<WhileStmt>(Terminator)->getCond();
- break;
-
- case Stmt::DoStmtClass:
- E = cast<DoStmt>(Terminator)->getCond();
- break;
-
- case Stmt::IfStmtClass:
- E = cast<IfStmt>(Terminator)->getCond();
- break;
-
- case Stmt::ChooseExprClass:
- E = cast<ChooseExpr>(Terminator)->getCond();
- break;
-
- case Stmt::IndirectGotoStmtClass:
- E = cast<IndirectGotoStmt>(Terminator)->getTarget();
- break;
-
- case Stmt::SwitchStmtClass:
- E = cast<SwitchStmt>(Terminator)->getCond();
- break;
-
- case Stmt::ConditionalOperatorClass:
- E = cast<ConditionalOperator>(Terminator)->getCond();
- break;
-
- case Stmt::BinaryOperatorClass: // '&&' and '||'
- E = cast<BinaryOperator>(Terminator)->getLHS();
- break;
-
- case Stmt::ObjCForCollectionStmtClass:
- return Terminator;
- }
-
- return E ? E->IgnoreParens() : NULL;
-}
-
-bool CFGBlock::hasBinaryBranchTerminator() const {
-
- if (!Terminator)
- return false;
-
- Expr* E = NULL;
-
- switch (Terminator->getStmtClass()) {
- default:
- return false;
-
- case Stmt::ForStmtClass:
- case Stmt::WhileStmtClass:
- case Stmt::DoStmtClass:
- case Stmt::IfStmtClass:
- case Stmt::ChooseExprClass:
- case Stmt::ConditionalOperatorClass:
- case Stmt::BinaryOperatorClass:
- return true;
- }
-
- return E ? E->IgnoreParens() : NULL;
-}
-
-
-//===----------------------------------------------------------------------===//
-// CFG Graphviz Visualization
-//===----------------------------------------------------------------------===//
-
-
-#ifndef NDEBUG
-static StmtPrinterHelper* GraphHelper;
-#endif
-
-void CFG::viewCFG(const LangOptions &LO) const {
-#ifndef NDEBUG
- StmtPrinterHelper H(this, LO);
- GraphHelper = &H;
- llvm::ViewGraph(this,"CFG");
- GraphHelper = NULL;
-#endif
-}
-
-namespace llvm {
-template<>
-struct DOTGraphTraits<const CFG*> : public DefaultDOTGraphTraits {
-
- DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
-
- static std::string getNodeLabel(const CFGBlock* Node, const CFG* Graph) {
-
-#ifndef NDEBUG
- std::string OutSStr;
- llvm::raw_string_ostream Out(OutSStr);
- print_block(Out,Graph, *Node, GraphHelper, false);
- std::string& OutStr = Out.str();
-
- if (OutStr[0] == '\n') OutStr.erase(OutStr.begin());
-
- // Process string output to make it nicer...
- for (unsigned i = 0; i != OutStr.length(); ++i)
- if (OutStr[i] == '\n') { // Left justify
- OutStr[i] = '\\';
- OutStr.insert(OutStr.begin()+i+1, 'l');
- }
-
- return OutStr;
-#else
- return "";
-#endif
- }
-};
-} // end namespace llvm
Removed: cfe/branches/Apple/williamson/lib/Basic/Targets.cpp.orig
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/williamson/lib/Basic/Targets.cpp.orig?rev=111417&view=auto
==============================================================================
--- cfe/branches/Apple/williamson/lib/Basic/Targets.cpp.orig (original)
+++ cfe/branches/Apple/williamson/lib/Basic/Targets.cpp.orig (removed)
@@ -1,2642 +0,0 @@
-//===--- Targets.cpp - Implement -arch option and targets -----------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements construction of a TargetInfo object from a
-// target triple.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Basic/TargetInfo.h"
-#include "clang/Basic/Builtins.h"
-#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/LangOptions.h"
-#include "clang/Basic/MacroBuilder.h"
-#include "clang/Basic/TargetBuiltins.h"
-#include "clang/Basic/TargetOptions.h"
-#include "llvm/ADT/APFloat.h"
-#include "llvm/ADT/OwningPtr.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/MC/MCSectionMachO.h"
-#include <algorithm>
-using namespace clang;
-
-//===----------------------------------------------------------------------===//
-// Common code shared among targets.
-//===----------------------------------------------------------------------===//
-
-/// DefineStd - Define a macro name and standard variants. For example if
-/// MacroName is "unix", then this will define "__unix", "__unix__", and "unix"
-/// when in GNU mode.
-static void DefineStd(MacroBuilder &Builder, llvm::StringRef MacroName,
- const LangOptions &Opts) {
- assert(MacroName[0] != '_' && "Identifier should be in the user's namespace");
-
- // If in GNU mode (e.g. -std=gnu99 but not -std=c99) define the raw identifier
- // in the user's namespace.
- if (Opts.GNUMode)
- Builder.defineMacro(MacroName);
-
- // Define __unix.
- Builder.defineMacro("__" + MacroName);
-
- // Define __unix__.
- Builder.defineMacro("__" + MacroName + "__");
-}
-
-//===----------------------------------------------------------------------===//
-// Defines specific to certain operating systems.
-//===----------------------------------------------------------------------===//
-
-namespace {
-template<typename TgtInfo>
-class OSTargetInfo : public TgtInfo {
-protected:
- virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const=0;
-public:
- OSTargetInfo(const std::string& triple) : TgtInfo(triple) {}
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- TgtInfo::getTargetDefines(Opts, Builder);
- getOSDefines(Opts, TgtInfo::getTriple(), Builder);
- }
-
-};
-} // end anonymous namespace
-
-
-static void getDarwinDefines(MacroBuilder &Builder, const LangOptions &Opts,
- const llvm::Triple &Triple) {
- Builder.defineMacro("__APPLE_CC__", "5621");
- Builder.defineMacro("__APPLE__");
- Builder.defineMacro("__MACH__");
- Builder.defineMacro("OBJC_NEW_PROPERTIES");
-
- // __weak is always defined, for use in blocks and with objc pointers.
- Builder.defineMacro("__weak", "__attribute__((objc_gc(weak)))");
-
- // Darwin defines __strong even in C mode (just to nothing).
- if (!Opts.ObjC1 || Opts.getGCMode() == LangOptions::NonGC)
- Builder.defineMacro("__strong", "");
- else
- Builder.defineMacro("__strong", "__attribute__((objc_gc(strong)))");
-
- if (Opts.Static)
- Builder.defineMacro("__STATIC__");
- else
- Builder.defineMacro("__DYNAMIC__");
-
- if (Opts.POSIXThreads)
- Builder.defineMacro("_REENTRANT");
-
- // Get the OS version number from the triple.
- unsigned Maj, Min, Rev;
-
- // If no version was given, default to to 10.4.0, for simplifying tests.
- if (Triple.getOSName() == "darwin") {
- Min = Rev = 0;
- Maj = 8;
- } else
- Triple.getDarwinNumber(Maj, Min, Rev);
-
- // Set the appropriate OS version define.
- if (Triple.getEnvironmentName() == "iphoneos") {
- assert(Maj < 10 && Min < 99 && Rev < 99 && "Invalid version!");
- char Str[6];
- Str[0] = '0' + Maj;
- Str[1] = '0' + (Min / 10);
- Str[2] = '0' + (Min % 10);
- Str[3] = '0' + (Rev / 10);
- Str[4] = '0' + (Rev % 10);
- Str[5] = '\0';
- Builder.defineMacro("__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__", Str);
- } else {
- // For historical reasons that make little sense, the version passed here is
- // the "darwin" version, which drops the 10 and offsets by 4.
- Rev = Min;
- Min = Maj - 4;
- Maj = 10;
-
- assert(Triple.getEnvironmentName().empty() && "Invalid environment!");
- assert(Maj < 99 && Min < 10 && Rev < 10 && "Invalid version!");
- char Str[5];
- Str[0] = '0' + (Maj / 10);
- Str[1] = '0' + (Maj % 10);
- Str[2] = '0' + Min;
- Str[3] = '0' + Rev;
- Str[4] = '\0';
- Builder.defineMacro("__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__", Str);
- }
-}
-
-namespace {
-template<typename Target>
-class DarwinTargetInfo : public OSTargetInfo<Target> {
-protected:
- virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const {
- getDarwinDefines(Builder, Opts, Triple);
- }
-
-public:
- DarwinTargetInfo(const std::string& triple) :
- OSTargetInfo<Target>(triple) {
- this->TLSSupported = llvm::Triple(triple).getDarwinMajorNumber() > 10;
- }
-
- virtual std::string isValidSectionSpecifier(llvm::StringRef SR) const {
- // Let MCSectionMachO validate this.
- llvm::StringRef Segment, Section;
- unsigned TAA, StubSize;
- return llvm::MCSectionMachO::ParseSectionSpecifier(SR, Segment, Section,
- TAA, StubSize);
- }
-
- virtual const char *getStaticInitSectionSpecifier() const {
- // FIXME: We should return 0 when building kexts.
- return "__TEXT,__StaticInit,regular,pure_instructions";
- }
-
-};
-
-
-// DragonFlyBSD Target
-template<typename Target>
-class DragonFlyBSDTargetInfo : public OSTargetInfo<Target> {
-protected:
- virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const {
- // DragonFly defines; list based off of gcc output
- Builder.defineMacro("__DragonFly__");
- Builder.defineMacro("__DragonFly_cc_version", "100001");
- Builder.defineMacro("__ELF__");
- Builder.defineMacro("__KPRINTF_ATTRIBUTE__");
- Builder.defineMacro("__tune_i386__");
- DefineStd(Builder, "unix", Opts);
- }
-public:
- DragonFlyBSDTargetInfo(const std::string &triple)
- : OSTargetInfo<Target>(triple) {}
-};
-
-// FreeBSD Target
-template<typename Target>
-class FreeBSDTargetInfo : public OSTargetInfo<Target> {
-protected:
- virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const {
- // FreeBSD defines; list based off of gcc output
-
- // FIXME: Move version number handling to llvm::Triple.
- llvm::StringRef Release = Triple.getOSName().substr(strlen("freebsd"), 1);
-
- Builder.defineMacro("__FreeBSD__", Release);
- Builder.defineMacro("__FreeBSD_cc_version", Release + "00001");
- Builder.defineMacro("__KPRINTF_ATTRIBUTE__");
- DefineStd(Builder, "unix", Opts);
- Builder.defineMacro("__ELF__");
- }
-public:
- FreeBSDTargetInfo(const std::string &triple)
- : OSTargetInfo<Target>(triple) {
- this->UserLabelPrefix = "";
- }
-};
-
-// Minix Target
-template<typename Target>
-class MinixTargetInfo : public OSTargetInfo<Target> {
-protected:
- virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const {
- // Minix defines
-
- Builder.defineMacro("__minix", "3");
- Builder.defineMacro("_EM_WSIZE", "4");
- Builder.defineMacro("_EM_PSIZE", "4");
- Builder.defineMacro("_EM_SSIZE", "2");
- Builder.defineMacro("_EM_LSIZE", "4");
- Builder.defineMacro("_EM_FSIZE", "4");
- Builder.defineMacro("_EM_DSIZE", "8");
- DefineStd(Builder, "unix", Opts);
- }
-public:
- MinixTargetInfo(const std::string &triple)
- : OSTargetInfo<Target>(triple) {
- this->UserLabelPrefix = "";
- }
-};
-
-// Linux target
-template<typename Target>
-class LinuxTargetInfo : public OSTargetInfo<Target> {
-protected:
- virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const {
- // Linux defines; list based off of gcc output
- DefineStd(Builder, "unix", Opts);
- DefineStd(Builder, "linux", Opts);
- Builder.defineMacro("__gnu_linux__");
- Builder.defineMacro("__ELF__");
- if (Opts.POSIXThreads)
- Builder.defineMacro("_REENTRANT");
- if (Opts.CPlusPlus)
- Builder.defineMacro("_GNU_SOURCE");
- }
-public:
- LinuxTargetInfo(const std::string& triple)
- : OSTargetInfo<Target>(triple) {
- this->UserLabelPrefix = "";
- }
-};
-
-// NetBSD Target
-template<typename Target>
-class NetBSDTargetInfo : public OSTargetInfo<Target> {
-protected:
- virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const {
- // NetBSD defines; list based off of gcc output
- Builder.defineMacro("__NetBSD__");
- Builder.defineMacro("__unix__");
- Builder.defineMacro("__ELF__");
- if (Opts.POSIXThreads)
- Builder.defineMacro("_POSIX_THREADS");
- }
-public:
- NetBSDTargetInfo(const std::string &triple)
- : OSTargetInfo<Target>(triple) {
- this->UserLabelPrefix = "";
- }
-};
-
-// OpenBSD Target
-template<typename Target>
-class OpenBSDTargetInfo : public OSTargetInfo<Target> {
-protected:
- virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const {
- // OpenBSD defines; list based off of gcc output
-
- Builder.defineMacro("__OpenBSD__");
- DefineStd(Builder, "unix", Opts);
- Builder.defineMacro("__ELF__");
- if (Opts.POSIXThreads)
- Builder.defineMacro("_POSIX_THREADS");
- }
-public:
- OpenBSDTargetInfo(const std::string &triple)
- : OSTargetInfo<Target>(triple) {}
-};
-
-// PSP Target
-template<typename Target>
-class PSPTargetInfo : public OSTargetInfo<Target> {
-protected:
- virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const {
- // PSP defines; list based on the output of the pspdev gcc toolchain.
- Builder.defineMacro("PSP");
- Builder.defineMacro("_PSP");
- Builder.defineMacro("__psp__");
- Builder.defineMacro("__ELF__");
- }
-public:
- PSPTargetInfo(const std::string& triple)
- : OSTargetInfo<Target>(triple) {
- this->UserLabelPrefix = "";
- }
-};
-
-// PS3 PPU Target
-template<typename Target>
-class PS3PPUTargetInfo : public OSTargetInfo<Target> {
-protected:
- virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const {
- // PS3 PPU defines.
- Builder.defineMacro("__PPC__");
- Builder.defineMacro("__PPU__");
- Builder.defineMacro("__CELLOS_LV2__");
- Builder.defineMacro("__ELF__");
- Builder.defineMacro("__LP32__");
- Builder.defineMacro("_ARCH_PPC64");
- Builder.defineMacro("__powerpc64__");
- }
-public:
- PS3PPUTargetInfo(const std::string& triple)
- : OSTargetInfo<Target>(triple) {
- this->UserLabelPrefix = "";
- this->LongWidth = this->LongAlign = this->PointerWidth = this->PointerAlign = 32;
- this->IntMaxType = TargetInfo::SignedLongLong;
- this->UIntMaxType = TargetInfo::UnsignedLongLong;
- this->Int64Type = TargetInfo::SignedLongLong;
- this->SizeType = TargetInfo::UnsignedInt;
- this->DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
- "i64:64:64-f32:32:32-f64:64:64-v128:128:128-n32";
- }
-};
-
-// FIXME: Need a real SPU target.
-// PS3 SPU Target
-template<typename Target>
-class PS3SPUTargetInfo : public OSTargetInfo<Target> {
-protected:
- virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const {
- // PS3 PPU defines.
- Builder.defineMacro("__SPU__");
- Builder.defineMacro("__ELF__");
- }
-public:
- PS3SPUTargetInfo(const std::string& triple)
- : OSTargetInfo<Target>(triple) {
- this->UserLabelPrefix = "";
- }
-};
-
-// AuroraUX target
-template<typename Target>
-class AuroraUXTargetInfo : public OSTargetInfo<Target> {
-protected:
- virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const {
- DefineStd(Builder, "sun", Opts);
- DefineStd(Builder, "unix", Opts);
- Builder.defineMacro("__ELF__");
- Builder.defineMacro("__svr4__");
- Builder.defineMacro("__SVR4");
- }
-public:
- AuroraUXTargetInfo(const std::string& triple)
- : OSTargetInfo<Target>(triple) {
- this->UserLabelPrefix = "";
- this->WCharType = this->SignedLong;
- // FIXME: WIntType should be SignedLong
- }
-};
-
-// Solaris target
-template<typename Target>
-class SolarisTargetInfo : public OSTargetInfo<Target> {
-protected:
- virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const {
- DefineStd(Builder, "sun", Opts);
- DefineStd(Builder, "unix", Opts);
- Builder.defineMacro("__ELF__");
- Builder.defineMacro("__svr4__");
- Builder.defineMacro("__SVR4");
- }
-public:
- SolarisTargetInfo(const std::string& triple)
- : OSTargetInfo<Target>(triple) {
- this->UserLabelPrefix = "";
- this->WCharType = this->SignedLong;
- // FIXME: WIntType should be SignedLong
- }
-};
-} // end anonymous namespace.
-
-//===----------------------------------------------------------------------===//
-// Specific target implementations.
-//===----------------------------------------------------------------------===//
-
-namespace {
-// PPC abstract base class
-class PPCTargetInfo : public TargetInfo {
- static const Builtin::Info BuiltinInfo[];
- static const char * const GCCRegNames[];
- static const TargetInfo::GCCRegAlias GCCRegAliases[];
-
-public:
- PPCTargetInfo(const std::string& triple) : TargetInfo(triple) {}
-
- virtual void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const {
- Records = BuiltinInfo;
- NumRecords = clang::PPC::LastTSBuiltin-Builtin::FirstTSBuiltin;
- }
-
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const;
-
- virtual const char *getVAListDeclaration() const {
- return "typedef char* __builtin_va_list;";
- // This is the right definition for ABI/V4: System V.4/eabi.
- /*return "typedef struct __va_list_tag {"
- " unsigned char gpr;"
- " unsigned char fpr;"
- " unsigned short reserved;"
- " void* overflow_arg_area;"
- " void* reg_save_area;"
- "} __builtin_va_list[1];";*/
- }
- virtual void getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const;
- virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const;
- virtual bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &Info) const {
- switch (*Name) {
- default: return false;
- case 'O': // Zero
- break;
- case 'b': // Base register
- case 'f': // Floating point register
- Info.setAllowsRegister();
- break;
- // FIXME: The following are added to allow parsing.
- // I just took a guess at what the actions should be.
- // Also, is more specific checking needed? I.e. specific registers?
- case 'd': // Floating point register (containing 64-bit value)
- case 'v': // Altivec vector register
- Info.setAllowsRegister();
- break;
- case 'w':
- switch (Name[1]) {
- case 'd':// VSX vector register to hold vector double data
- case 'f':// VSX vector register to hold vector float data
- case 's':// VSX vector register to hold scalar float data
- case 'a':// Any VSX register
- break;
- default:
- return false;
- }
- Info.setAllowsRegister();
- Name++; // Skip over 'w'.
- break;
- case 'h': // `MQ', `CTR', or `LINK' register
- case 'q': // `MQ' register
- case 'c': // `CTR' register
- case 'l': // `LINK' register
- case 'x': // `CR' register (condition register) number 0
- case 'y': // `CR' register (condition register)
- case 'z': // `XER[CA]' carry bit (part of the XER register)
- Info.setAllowsRegister();
- break;
- case 'I': // Signed 16-bit constant
- case 'J': // Unsigned 16-bit constant shifted left 16 bits
- // (use `L' instead for SImode constants)
- case 'K': // Unsigned 16-bit constant
- case 'L': // Signed 16-bit constant shifted left 16 bits
- case 'M': // Constant larger than 31
- case 'N': // Exact power of 2
- case 'P': // Constant whose negation is a signed 16-bit constant
- case 'G': // Floating point constant that can be loaded into a
- // register with one instruction per word
- case 'H': // Integer/Floating point constant that can be loaded
- // into a register using three instructions
- break;
- case 'm': // Memory operand. Note that on PowerPC targets, m can
- // include addresses that update the base register. It
- // is therefore only safe to use `m' in an asm statement
- // if that asm statement accesses the operand exactly once.
- // The asm statement must also use `%U<opno>' as a
- // placeholder for the update flag in the corresponding
- // load or store instruction. For example:
- // asm ("st%U0 %1,%0" : "=m" (mem) : "r" (val));
- // is correct but:
- // asm ("st %1,%0" : "=m" (mem) : "r" (val));
- // is not. Use es rather than m if you don't want the base
- // register to be updated.
- case 'e':
- if (Name[1] != 's')
- return false;
- // es: A stable memory operand; that is, one which does not
- // include any automodification of the base register. Unlike
- // `m', this constraint can be used in asm statements that
- // might access the operand several times, or that might not
- // access it at all.
- Info.setAllowsMemory();
- Name++; // Skip over 'e'.
- break;
- case 'Q': // Memory operand that is an offset from a register (it is
- // usually better to use `m' or `es' in asm statements)
- case 'Z': // Memory operand that is an indexed or indirect from a
- // register (it is usually better to use `m' or `es' in
- // asm statements)
- Info.setAllowsMemory();
- Info.setAllowsRegister();
- break;
- case 'R': // AIX TOC entry
- case 'a': // Address operand that is an indexed or indirect from a
- // register (`p' is preferable for asm statements)
- case 'S': // Constant suitable as a 64-bit mask operand
- case 'T': // Constant suitable as a 32-bit mask operand
- case 'U': // System V Release 4 small data area reference
- case 't': // AND masks that can be performed by two rldic{l, r}
- // instructions
- case 'W': // Vector constant that does not require memory
- case 'j': // Vector constant that is all zeros.
- break;
- // End FIXME.
- }
- return true;
- }
- virtual const char *getClobbers() const {
- return "";
- }
-};
-
-const Builtin::Info PPCTargetInfo::BuiltinInfo[] = {
-#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, false },
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER, false },
-#include "clang/Basic/BuiltinsPPC.def"
-};
-
-
-/// PPCTargetInfo::getTargetDefines - Return a set of the PowerPC-specific
-/// #defines that are not tied to a specific subtarget.
-void PPCTargetInfo::getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- // Target identification.
- Builder.defineMacro("__ppc__");
- Builder.defineMacro("_ARCH_PPC");
- Builder.defineMacro("__powerpc__");
- Builder.defineMacro("__POWERPC__");
- if (PointerWidth == 64) {
- Builder.defineMacro("_ARCH_PPC64");
- Builder.defineMacro("_LP64");
- Builder.defineMacro("__LP64__");
- Builder.defineMacro("__powerpc64__");
- Builder.defineMacro("__ppc64__");
- } else {
- Builder.defineMacro("__ppc__");
- }
-
- // Target properties.
- Builder.defineMacro("_BIG_ENDIAN");
- Builder.defineMacro("__BIG_ENDIAN__");
-
- // Subtarget options.
- Builder.defineMacro("__NATURAL_ALIGNMENT__");
- Builder.defineMacro("__REGISTER_PREFIX__", "");
-
- // FIXME: Should be controlled by command line option.
- Builder.defineMacro("__LONG_DOUBLE_128__");
-
- if (Opts.AltiVec) {
- Builder.defineMacro("__VEC__", "10206");
- Builder.defineMacro("__ALTIVEC__");
- }
-}
-
-
-const char * const PPCTargetInfo::GCCRegNames[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
- "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
- "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
- "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7",
- "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15",
- "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23",
- "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31",
- "mq", "lr", "ctr", "ap",
- "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7",
- "xer",
- "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
- "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
- "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
- "v24", "v25", "v26", "v27", "v28", "v29", "v30", "v31",
- "vrsave", "vscr",
- "spe_acc", "spefscr",
- "sfp"
-};
-
-void PPCTargetInfo::getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const {
- Names = GCCRegNames;
- NumNames = llvm::array_lengthof(GCCRegNames);
-}
-
-const TargetInfo::GCCRegAlias PPCTargetInfo::GCCRegAliases[] = {
- // While some of these aliases do map to different registers
- // they still share the same register name.
- { { "0" }, "r0" },
- { { "1"}, "r1" },
- { { "2" }, "r2" },
- { { "3" }, "r3" },
- { { "4" }, "r4" },
- { { "5" }, "r5" },
- { { "6" }, "r6" },
- { { "7" }, "r7" },
- { { "8" }, "r8" },
- { { "9" }, "r9" },
- { { "10" }, "r10" },
- { { "11" }, "r11" },
- { { "12" }, "r12" },
- { { "13" }, "r13" },
- { { "14" }, "r14" },
- { { "15" }, "r15" },
- { { "16" }, "r16" },
- { { "17" }, "r17" },
- { { "18" }, "r18" },
- { { "19" }, "r19" },
- { { "20" }, "r20" },
- { { "21" }, "r21" },
- { { "22" }, "r22" },
- { { "23" }, "r23" },
- { { "24" }, "r24" },
- { { "25" }, "r25" },
- { { "26" }, "r26" },
- { { "27" }, "r27" },
- { { "28" }, "r28" },
- { { "29" }, "r29" },
- { { "30" }, "r30" },
- { { "31" }, "r31" },
- { { "fr0" }, "f0" },
- { { "fr1" }, "f1" },
- { { "fr2" }, "f2" },
- { { "fr3" }, "f3" },
- { { "fr4" }, "f4" },
- { { "fr5" }, "f5" },
- { { "fr6" }, "f6" },
- { { "fr7" }, "f7" },
- { { "fr8" }, "f8" },
- { { "fr9" }, "f9" },
- { { "fr10" }, "f10" },
- { { "fr11" }, "f11" },
- { { "fr12" }, "f12" },
- { { "fr13" }, "f13" },
- { { "fr14" }, "f14" },
- { { "fr15" }, "f15" },
- { { "fr16" }, "f16" },
- { { "fr17" }, "f17" },
- { { "fr18" }, "f18" },
- { { "fr19" }, "f19" },
- { { "fr20" }, "f20" },
- { { "fr21" }, "f21" },
- { { "fr22" }, "f22" },
- { { "fr23" }, "f23" },
- { { "fr24" }, "f24" },
- { { "fr25" }, "f25" },
- { { "fr26" }, "f26" },
- { { "fr27" }, "f27" },
- { { "fr28" }, "f28" },
- { { "fr29" }, "f29" },
- { { "fr30" }, "f30" },
- { { "fr31" }, "f31" },
- { { "cc" }, "cr0" },
-};
-
-void PPCTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const {
- Aliases = GCCRegAliases;
- NumAliases = llvm::array_lengthof(GCCRegAliases);
-}
-} // end anonymous namespace.
-
-namespace {
-class PPC32TargetInfo : public PPCTargetInfo {
-public:
- PPC32TargetInfo(const std::string &triple) : PPCTargetInfo(triple) {
- DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
- "i64:64:64-f32:32:32-f64:64:64-v128:128:128-n32";
-
- if (getTriple().getOS() == llvm::Triple::FreeBSD)
- this->SizeType = TargetInfo::UnsignedInt;
- }
-};
-} // end anonymous namespace.
-
-namespace {
-class PPC64TargetInfo : public PPCTargetInfo {
-public:
- PPC64TargetInfo(const std::string& triple) : PPCTargetInfo(triple) {
- LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
- IntMaxType = SignedLong;
- UIntMaxType = UnsignedLong;
- Int64Type = SignedLong;
- DescriptionString = "E-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
- "i64:64:64-f32:32:32-f64:64:64-v128:128:128-n32:64";
- }
-};
-} // end anonymous namespace.
-
-
-namespace {
-class DarwinPPCTargetInfo :
- public DarwinTargetInfo<PPCTargetInfo> {
-public:
- DarwinPPCTargetInfo(const std::string& triple)
- : DarwinTargetInfo<PPCTargetInfo>(triple) {
- HasAlignMac68kSupport = true;
- }
-};
-
-class DarwinPPC64TargetInfo :
- public DarwinTargetInfo<PPC64TargetInfo> {
-public:
- DarwinPPC64TargetInfo(const std::string& triple)
- : DarwinTargetInfo<PPC64TargetInfo>(triple) {
- HasAlignMac68kSupport = true;
- }
-};
-} // end anonymous namespace.
-
-namespace {
-// MBlaze abstract base class
-class MBlazeTargetInfo : public TargetInfo {
- static const char * const GCCRegNames[];
- static const TargetInfo::GCCRegAlias GCCRegAliases[];
-
-public:
- MBlazeTargetInfo(const std::string& triple) : TargetInfo(triple) {
- DescriptionString = "E-p:32:32-i8:8:8-i16:16:16-i64:32:32-f64:32:32-"
- "v64:32:32-v128:32:32-n32";
- }
-
- virtual void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const {
- // FIXME: Implement.
- Records = 0;
- NumRecords = 0;
- }
-
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const;
-
- virtual const char *getVAListDeclaration() const {
- return "typedef char* __builtin_va_list;";
- }
- virtual const char *getTargetPrefix() const {
- return "mblaze";
- }
- virtual void getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const;
- virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const;
- virtual bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &Info) const {
- switch (*Name) {
- default: return false;
- case 'O': // Zero
- return true;
- case 'b': // Base register
- case 'f': // Floating point register
- Info.setAllowsRegister();
- return true;
- }
- }
- virtual const char *getClobbers() const {
- return "";
- }
-};
-
-/// MBlazeTargetInfo::getTargetDefines - Return a set of the MBlaze-specific
-/// #defines that are not tied to a specific subtarget.
-void MBlazeTargetInfo::getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- // Target identification.
- Builder.defineMacro("__microblaze__");
- Builder.defineMacro("_ARCH_MICROBLAZE");
- Builder.defineMacro("__MICROBLAZE__");
-
- // Target properties.
- Builder.defineMacro("_BIG_ENDIAN");
- Builder.defineMacro("__BIG_ENDIAN__");
-
- // Subtarget options.
- Builder.defineMacro("__REGISTER_PREFIX__", "");
-}
-
-
-const char * const MBlazeTargetInfo::GCCRegNames[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
- "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
- "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
- "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
- "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
- "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
- "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31",
- "hi", "lo", "accum","rmsr", "$fcc1","$fcc2","$fcc3","$fcc4",
- "$fcc5","$fcc6","$fcc7","$ap", "$rap", "$frp"
-};
-
-void MBlazeTargetInfo::getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const {
- Names = GCCRegNames;
- NumNames = llvm::array_lengthof(GCCRegNames);
-}
-
-const TargetInfo::GCCRegAlias MBlazeTargetInfo::GCCRegAliases[] = {
- { {"f0"}, "r0" },
- { {"f1"}, "r1" },
- { {"f2"}, "r2" },
- { {"f3"}, "r3" },
- { {"f4"}, "r4" },
- { {"f5"}, "r5" },
- { {"f6"}, "r6" },
- { {"f7"}, "r7" },
- { {"f8"}, "r8" },
- { {"f9"}, "r9" },
- { {"f10"}, "r10" },
- { {"f11"}, "r11" },
- { {"f12"}, "r12" },
- { {"f13"}, "r13" },
- { {"f14"}, "r14" },
- { {"f15"}, "r15" },
- { {"f16"}, "r16" },
- { {"f17"}, "r17" },
- { {"f18"}, "r18" },
- { {"f19"}, "r19" },
- { {"f20"}, "r20" },
- { {"f21"}, "r21" },
- { {"f22"}, "r22" },
- { {"f23"}, "r23" },
- { {"f24"}, "r24" },
- { {"f25"}, "r25" },
- { {"f26"}, "r26" },
- { {"f27"}, "r27" },
- { {"f28"}, "r28" },
- { {"f29"}, "r29" },
- { {"f30"}, "r30" },
- { {"f31"}, "r31" },
-};
-
-void MBlazeTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const {
- Aliases = GCCRegAliases;
- NumAliases = llvm::array_lengthof(GCCRegAliases);
-}
-} // end anonymous namespace.
-
-namespace {
-// Namespace for x86 abstract base class
-const Builtin::Info BuiltinInfo[] = {
-#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, false },
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER, false },
-#include "clang/Basic/BuiltinsX86.def"
-};
-
-static const char* const GCCRegNames[] = {
- "ax", "dx", "cx", "bx", "si", "di", "bp", "sp",
- "st", "st(1)", "st(2)", "st(3)", "st(4)", "st(5)", "st(6)", "st(7)",
- "argp", "flags", "fspr", "dirflag", "frame",
- "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7",
- "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
- "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15"
-};
-
-const TargetInfo::GCCRegAlias GCCRegAliases[] = {
- { { "al", "ah", "eax", "rax" }, "ax" },
- { { "bl", "bh", "ebx", "rbx" }, "bx" },
- { { "cl", "ch", "ecx", "rcx" }, "cx" },
- { { "dl", "dh", "edx", "rdx" }, "dx" },
- { { "esi", "rsi" }, "si" },
- { { "edi", "rdi" }, "di" },
- { { "esp", "rsp" }, "sp" },
- { { "ebp", "rbp" }, "bp" },
-};
-
-// X86 target abstract base class; x86-32 and x86-64 are very close, so
-// most of the implementation can be shared.
-class X86TargetInfo : public TargetInfo {
- enum X86SSEEnum {
- NoMMXSSE, MMX, SSE1, SSE2, SSE3, SSSE3, SSE41, SSE42
- } SSELevel;
- enum AMD3DNowEnum {
- NoAMD3DNow, AMD3DNow, AMD3DNowAthlon
- } AMD3DNowLevel;
-
- bool HasAES;
-
-public:
- X86TargetInfo(const std::string& triple)
- : TargetInfo(triple), SSELevel(NoMMXSSE), AMD3DNowLevel(NoAMD3DNow),
- HasAES(false) {
- LongDoubleFormat = &llvm::APFloat::x87DoubleExtended;
- }
- virtual void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const {
- Records = BuiltinInfo;
- NumRecords = clang::X86::LastTSBuiltin-Builtin::FirstTSBuiltin;
- }
- virtual void getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const {
- Names = GCCRegNames;
- NumNames = llvm::array_lengthof(GCCRegNames);
- }
- virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const {
- Aliases = GCCRegAliases;
- NumAliases = llvm::array_lengthof(GCCRegAliases);
- }
- virtual bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &info) const;
- virtual std::string convertConstraint(const char Constraint) const;
- virtual const char *getClobbers() const {
- return "~{dirflag},~{fpsr},~{flags}";
- }
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const;
- virtual bool setFeatureEnabled(llvm::StringMap<bool> &Features,
- const std::string &Name,
- bool Enabled) const;
- virtual void getDefaultFeatures(const std::string &CPU,
- llvm::StringMap<bool> &Features) const;
- virtual void HandleTargetFeatures(std::vector<std::string> &Features);
-};
-
-void X86TargetInfo::getDefaultFeatures(const std::string &CPU,
- llvm::StringMap<bool> &Features) const {
- // FIXME: This should not be here.
- Features["3dnow"] = false;
- Features["3dnowa"] = false;
- Features["mmx"] = false;
- Features["sse"] = false;
- Features["sse2"] = false;
- Features["sse3"] = false;
- Features["ssse3"] = false;
- Features["sse41"] = false;
- Features["sse42"] = false;
- Features["aes"] = false;
-
- // LLVM does not currently recognize this.
- // Features["sse4a"] = false;
-
- // FIXME: This *really* should not be here.
-
- // X86_64 always has SSE2.
- if (PointerWidth == 64)
- Features["sse2"] = Features["sse"] = Features["mmx"] = true;
-
- if (CPU == "generic" || CPU == "i386" || CPU == "i486" || CPU == "i586" ||
- CPU == "pentium" || CPU == "i686" || CPU == "pentiumpro")
- ;
- else if (CPU == "pentium-mmx" || CPU == "pentium2")
- setFeatureEnabled(Features, "mmx", true);
- else if (CPU == "pentium3")
- setFeatureEnabled(Features, "sse", true);
- else if (CPU == "pentium-m" || CPU == "pentium4" || CPU == "x86-64")
- setFeatureEnabled(Features, "sse2", true);
- else if (CPU == "yonah" || CPU == "prescott" || CPU == "nocona")
- setFeatureEnabled(Features, "sse3", true);
- else if (CPU == "core2")
- setFeatureEnabled(Features, "ssse3", true);
- else if (CPU == "penryn") {
- setFeatureEnabled(Features, "sse4", true);
- Features["sse42"] = false;
- } else if (CPU == "atom")
- setFeatureEnabled(Features, "sse3", true);
- else if (CPU == "corei7") {
- setFeatureEnabled(Features, "sse4", true);
- setFeatureEnabled(Features, "aes", true);
- }
- else if (CPU == "k6" || CPU == "winchip-c6")
- setFeatureEnabled(Features, "mmx", true);
- else if (CPU == "k6-2" || CPU == "k6-3" || CPU == "athlon" ||
- CPU == "athlon-tbird" || CPU == "winchip2" || CPU == "c3") {
- setFeatureEnabled(Features, "mmx", true);
- setFeatureEnabled(Features, "3dnow", true);
- } else if (CPU == "athlon-4" || CPU == "athlon-xp" || CPU == "athlon-mp") {
- setFeatureEnabled(Features, "sse", true);
- setFeatureEnabled(Features, "3dnowa", true);
- } else if (CPU == "k8" || CPU == "opteron" || CPU == "athlon64" ||
- CPU == "athlon-fx") {
- setFeatureEnabled(Features, "sse2", true);
- setFeatureEnabled(Features, "3dnowa", true);
- } else if (CPU == "c3-2")
- setFeatureEnabled(Features, "sse", true);
-}
-
-bool X86TargetInfo::setFeatureEnabled(llvm::StringMap<bool> &Features,
- const std::string &Name,
- bool Enabled) const {
- // FIXME: This *really* should not be here. We need some way of translating
- // options into llvm subtarget features.
- if (!Features.count(Name) &&
- (Name != "sse4" && Name != "sse4.2" && Name != "sse4.1"))
- return false;
-
- if (Enabled) {
- if (Name == "mmx")
- Features["mmx"] = true;
- else if (Name == "sse")
- Features["mmx"] = Features["sse"] = true;
- else if (Name == "sse2")
- Features["mmx"] = Features["sse"] = Features["sse2"] = true;
- else if (Name == "sse3")
- Features["mmx"] = Features["sse"] = Features["sse2"] =
- Features["sse3"] = true;
- else if (Name == "ssse3")
- Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] =
- Features["ssse3"] = true;
- else if (Name == "sse4" || Name == "sse4.2")
- Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] =
- Features["ssse3"] = Features["sse41"] = Features["sse42"] = true;
- else if (Name == "sse4.1")
- Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] =
- Features["ssse3"] = Features["sse41"] = true;
- else if (Name == "3dnow")
- Features["3dnowa"] = true;
- else if (Name == "3dnowa")
- Features["3dnow"] = Features["3dnowa"] = true;
- else if (Name == "aes")
- Features["aes"] = true;
- } else {
- if (Name == "mmx")
- Features["mmx"] = Features["sse"] = Features["sse2"] = Features["sse3"] =
- Features["ssse3"] = Features["sse41"] = Features["sse42"] = false;
- else if (Name == "sse")
- Features["sse"] = Features["sse2"] = Features["sse3"] =
- Features["ssse3"] = Features["sse41"] = Features["sse42"] = false;
- else if (Name == "sse2")
- Features["sse2"] = Features["sse3"] = Features["ssse3"] =
- Features["sse41"] = Features["sse42"] = false;
- else if (Name == "sse3")
- Features["sse3"] = Features["ssse3"] = Features["sse41"] =
- Features["sse42"] = false;
- else if (Name == "ssse3")
- Features["ssse3"] = Features["sse41"] = Features["sse42"] = false;
- else if (Name == "sse4")
- Features["sse41"] = Features["sse42"] = false;
- else if (Name == "sse4.2")
- Features["sse42"] = false;
- else if (Name == "sse4.1")
- Features["sse41"] = Features["sse42"] = false;
- else if (Name == "3dnow")
- Features["3dnow"] = Features["3dnowa"] = false;
- else if (Name == "3dnowa")
- Features["3dnowa"] = false;
- else if (Name == "aes")
- Features["aes"] = false;
- }
-
- return true;
-}
-
-/// HandleTargetOptions - Perform initialization based on the user
-/// configured set of features.
-void X86TargetInfo::HandleTargetFeatures(std::vector<std::string> &Features) {
- // Remember the maximum enabled sselevel.
- for (unsigned i = 0, e = Features.size(); i !=e; ++i) {
- // Ignore disabled features.
- if (Features[i][0] == '-')
- continue;
-
- if (Features[i].substr(1) == "aes") {
- HasAES = true;
- continue;
- }
-
- assert(Features[i][0] == '+' && "Invalid target feature!");
- X86SSEEnum Level = llvm::StringSwitch<X86SSEEnum>(Features[i].substr(1))
- .Case("sse42", SSE42)
- .Case("sse41", SSE41)
- .Case("ssse3", SSSE3)
- .Case("sse3", SSE3)
- .Case("sse2", SSE2)
- .Case("sse", SSE1)
- .Case("mmx", MMX)
- .Default(NoMMXSSE);
- SSELevel = std::max(SSELevel, Level);
-
- AMD3DNowEnum ThreeDNowLevel =
- llvm::StringSwitch<AMD3DNowEnum>(Features[i].substr(1))
- .Case("3dnowa", AMD3DNowAthlon)
- .Case("3dnow", AMD3DNow)
- .Default(NoAMD3DNow);
-
- AMD3DNowLevel = std::max(AMD3DNowLevel, ThreeDNowLevel);
- }
-}
-
-/// X86TargetInfo::getTargetDefines - Return a set of the X86-specific #defines
-/// that are not tied to a specific subtarget.
-void X86TargetInfo::getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- // Target identification.
- if (PointerWidth == 64) {
- Builder.defineMacro("_LP64");
- Builder.defineMacro("__LP64__");
- Builder.defineMacro("__amd64__");
- Builder.defineMacro("__amd64");
- Builder.defineMacro("__x86_64");
- Builder.defineMacro("__x86_64__");
- } else {
- DefineStd(Builder, "i386", Opts);
- }
-
- if (HasAES)
- Builder.defineMacro("__AES__");
-
- // Target properties.
- Builder.defineMacro("__LITTLE_ENDIAN__");
-
- // Subtarget options.
- Builder.defineMacro("__nocona");
- Builder.defineMacro("__nocona__");
- Builder.defineMacro("__tune_nocona__");
- Builder.defineMacro("__REGISTER_PREFIX__", "");
-
- // Define __NO_MATH_INLINES on linux/x86 so that we don't get inline
- // functions in glibc header files that use FP Stack inline asm which the
- // backend can't deal with (PR879).
- Builder.defineMacro("__NO_MATH_INLINES");
-
- // Each case falls through to the previous one here.
- switch (SSELevel) {
- case SSE42:
- Builder.defineMacro("__SSE4_2__");
- case SSE41:
- Builder.defineMacro("__SSE4_1__");
- case SSSE3:
- Builder.defineMacro("__SSSE3__");
- case SSE3:
- Builder.defineMacro("__SSE3__");
- case SSE2:
- Builder.defineMacro("__SSE2__");
- Builder.defineMacro("__SSE2_MATH__"); // -mfp-math=sse always implied.
- case SSE1:
- Builder.defineMacro("__SSE__");
- Builder.defineMacro("__SSE_MATH__"); // -mfp-math=sse always implied.
- case MMX:
- Builder.defineMacro("__MMX__");
- case NoMMXSSE:
- break;
- }
-
- // Each case falls through to the previous one here.
- switch (AMD3DNowLevel) {
- case AMD3DNowAthlon:
- Builder.defineMacro("__3dNOW_A__");
- case AMD3DNow:
- Builder.defineMacro("__3dNOW__");
- case NoAMD3DNow:
- break;
- }
-}
-
-
-bool
-X86TargetInfo::validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &Info) const {
- switch (*Name) {
- default: return false;
- case 'a': // eax.
- case 'b': // ebx.
- case 'c': // ecx.
- case 'd': // edx.
- case 'S': // esi.
- case 'D': // edi.
- case 'A': // edx:eax.
- case 't': // top of floating point stack.
- case 'u': // second from top of floating point stack.
- case 'q': // Any register accessible as [r]l: a, b, c, and d.
- case 'y': // Any MMX register.
- case 'x': // Any SSE register.
- case 'Q': // Any register accessible as [r]h: a, b, c, and d.
- case 'e': // 32-bit signed integer constant for use with zero-extending
- // x86_64 instructions.
- case 'Z': // 32-bit unsigned integer constant for use with zero-extending
- // x86_64 instructions.
- case 'N': // unsigned 8-bit integer constant for use with in and out
- // instructions.
- case 'R': // "legacy" registers: ax, bx, cx, dx, di, si, sp, bp.
- Info.setAllowsRegister();
- return true;
- }
-}
-
-std::string
-X86TargetInfo::convertConstraint(const char Constraint) const {
- switch (Constraint) {
- case 'a': return std::string("{ax}");
- case 'b': return std::string("{bx}");
- case 'c': return std::string("{cx}");
- case 'd': return std::string("{dx}");
- case 'S': return std::string("{si}");
- case 'D': return std::string("{di}");
- case 't': // top of floating point stack.
- return std::string("{st}");
- case 'u': // second from top of floating point stack.
- return std::string("{st(1)}"); // second from top of floating point stack.
- default:
- return std::string(1, Constraint);
- }
-}
-} // end anonymous namespace
-
-namespace {
-// X86-32 generic target
-class X86_32TargetInfo : public X86TargetInfo {
-public:
- X86_32TargetInfo(const std::string& triple) : X86TargetInfo(triple) {
- DoubleAlign = LongLongAlign = 32;
- LongDoubleWidth = 96;
- LongDoubleAlign = 32;
- DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
- "i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-"
- "a0:0:64-f80:32:32-n8:16:32";
- SizeType = UnsignedInt;
- PtrDiffType = SignedInt;
- IntPtrType = SignedInt;
- RegParmMax = 3;
-
- // Use fpret for all types.
- RealTypeUsesObjCFPRet = ((1 << TargetInfo::Float) |
- (1 << TargetInfo::Double) |
- (1 << TargetInfo::LongDouble));
- }
- virtual const char *getVAListDeclaration() const {
- return "typedef char* __builtin_va_list;";
- }
-
- int getEHDataRegisterNumber(unsigned RegNo) const {
- if (RegNo == 0) return 0;
- if (RegNo == 1) return 2;
- return -1;
- }
-};
-} // end anonymous namespace
-
-namespace {
-class OpenBSDI386TargetInfo : public OpenBSDTargetInfo<X86_32TargetInfo> {
-public:
- OpenBSDI386TargetInfo(const std::string& triple) :
- OpenBSDTargetInfo<X86_32TargetInfo>(triple) {
- SizeType = UnsignedLong;
- IntPtrType = SignedLong;
- PtrDiffType = SignedLong;
- }
-};
-} // end anonymous namespace
-
-namespace {
-class DarwinI386TargetInfo : public DarwinTargetInfo<X86_32TargetInfo> {
-public:
- DarwinI386TargetInfo(const std::string& triple) :
- DarwinTargetInfo<X86_32TargetInfo>(triple) {
- LongDoubleWidth = 128;
- LongDoubleAlign = 128;
- SizeType = UnsignedLong;
- IntPtrType = SignedLong;
- DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
- "i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-"
- "a0:0:64-f80:128:128-n8:16:32";
- HasAlignMac68kSupport = true;
- }
-
-};
-} // end anonymous namespace
-
-namespace {
-// x86-32 Windows target
-class WindowsX86_32TargetInfo : public X86_32TargetInfo {
-public:
- WindowsX86_32TargetInfo(const std::string& triple)
- : X86_32TargetInfo(triple) {
- TLSSupported = false;
- WCharType = UnsignedShort;
- DoubleAlign = LongLongAlign = 64;
- DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
- "i64:64:64-f32:32:32-f64:64:64-f80:128:128-v64:64:64-"
- "v128:128:128-a0:0:64-f80:32:32-n8:16:32";
- }
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- X86_32TargetInfo::getTargetDefines(Opts, Builder);
- // This list is based off of the the list of things MingW defines
- Builder.defineMacro("_WIN32");
- DefineStd(Builder, "WIN32", Opts);
- DefineStd(Builder, "WINNT", Opts);
- Builder.defineMacro("_X86_");
- }
-};
-} // end anonymous namespace
-
-namespace {
-
-// x86-32 Windows Visual Studio target
-class VisualStudioWindowsX86_32TargetInfo : public WindowsX86_32TargetInfo {
-public:
- VisualStudioWindowsX86_32TargetInfo(const std::string& triple)
- : WindowsX86_32TargetInfo(triple) {
- }
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- WindowsX86_32TargetInfo::getTargetDefines(Opts, Builder);
- // The value of the following reflects processor type.
- // 300=386, 400=486, 500=Pentium, 600=Blend (default)
- // We lost the original triple, so we use the default.
- Builder.defineMacro("_M_IX86", "600");
- }
-};
-} // end anonymous namespace
-
-namespace {
-// x86-32 MinGW target
-class MinGWX86_32TargetInfo : public WindowsX86_32TargetInfo {
-public:
- MinGWX86_32TargetInfo(const std::string& triple)
- : WindowsX86_32TargetInfo(triple) {
- }
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- WindowsX86_32TargetInfo::getTargetDefines(Opts, Builder);
- Builder.defineMacro("__MSVCRT__");
- Builder.defineMacro("__MINGW32__");
- Builder.defineMacro("__declspec", "__declspec");
- }
-};
-} // end anonymous namespace
-
-namespace {
-// x86-32 Cygwin target
-class CygwinX86_32TargetInfo : public X86_32TargetInfo {
-public:
- CygwinX86_32TargetInfo(const std::string& triple)
- : X86_32TargetInfo(triple) {
- TLSSupported = false;
- WCharType = UnsignedShort;
- DoubleAlign = LongLongAlign = 64;
- DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
- "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-"
- "a0:0:64-f80:32:32-n8:16:32";
- }
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- X86_32TargetInfo::getTargetDefines(Opts, Builder);
- Builder.defineMacro("__CYGWIN__");
- Builder.defineMacro("__CYGWIN32__");
- DefineStd(Builder, "unix", Opts);
- if (Opts.CPlusPlus)
- Builder.defineMacro("_GNU_SOURCE");
- }
-};
-} // end anonymous namespace
-
-namespace {
-// x86-32 Haiku target
-class HaikuX86_32TargetInfo : public X86_32TargetInfo {
-public:
- HaikuX86_32TargetInfo(const std::string& triple)
- : X86_32TargetInfo(triple) {
- SizeType = UnsignedLong;
- IntPtrType = SignedLong;
- PtrDiffType = SignedLong;
- }
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- X86_32TargetInfo::getTargetDefines(Opts, Builder);
- Builder.defineMacro("__INTEL__");
- Builder.defineMacro("__HAIKU__");
- }
-};
-} // end anonymous namespace
-
-namespace {
-// x86-64 generic target
-class X86_64TargetInfo : public X86TargetInfo {
-public:
- X86_64TargetInfo(const std::string &triple) : X86TargetInfo(triple) {
- LongWidth = LongAlign = PointerWidth = PointerAlign = 64;
- LongDoubleWidth = 128;
- LongDoubleAlign = 128;
- LargeArrayMinWidth = 128;
- LargeArrayAlign = 128;
- IntMaxType = SignedLong;
- UIntMaxType = UnsignedLong;
- Int64Type = SignedLong;
- RegParmMax = 6;
-
- DescriptionString = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
- "i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-"
- "a0:0:64-s0:64:64-f80:128:128-n8:16:32:64";
-
- // Use fpret only for long double.
- RealTypeUsesObjCFPRet = (1 << TargetInfo::LongDouble);
- }
- virtual const char *getVAListDeclaration() const {
- return "typedef struct __va_list_tag {"
- " unsigned gp_offset;"
- " unsigned fp_offset;"
- " void* overflow_arg_area;"
- " void* reg_save_area;"
- "} __va_list_tag;"
- "typedef __va_list_tag __builtin_va_list[1];";
- }
-
- int getEHDataRegisterNumber(unsigned RegNo) const {
- if (RegNo == 0) return 0;
- if (RegNo == 1) return 1;
- return -1;
- }
-};
-} // end anonymous namespace
-
-namespace {
-// x86-64 Windows target
-class WindowsX86_64TargetInfo : public X86_64TargetInfo {
-public:
- WindowsX86_64TargetInfo(const std::string& triple)
- : X86_64TargetInfo(triple) {
- TLSSupported = false;
- WCharType = UnsignedShort;
- LongWidth = LongAlign = 32;
- DoubleAlign = LongLongAlign = 64;
- IntMaxType = SignedLongLong;
- UIntMaxType = UnsignedLongLong;
- Int64Type = SignedLongLong;
- }
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- X86_64TargetInfo::getTargetDefines(Opts, Builder);
- Builder.defineMacro("_WIN64");
- DefineStd(Builder, "WIN64", Opts);
- }
-};
-} // end anonymous namespace
-
-namespace {
-// x86-64 Windows Visual Studio target
-class VisualStudioWindowsX86_64TargetInfo : public WindowsX86_64TargetInfo {
-public:
- VisualStudioWindowsX86_64TargetInfo(const std::string& triple)
- : WindowsX86_64TargetInfo(triple) {
- }
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- WindowsX86_64TargetInfo::getTargetDefines(Opts, Builder);
- Builder.defineMacro("_M_X64");
- }
- virtual const char *getVAListDeclaration() const {
- return "typedef char* va_list;";
- }
-};
-} // end anonymous namespace
-
-namespace {
-// x86-64 MinGW target
-class MinGWX86_64TargetInfo : public WindowsX86_64TargetInfo {
-public:
- MinGWX86_64TargetInfo(const std::string& triple)
- : WindowsX86_64TargetInfo(triple) {
- }
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- WindowsX86_64TargetInfo::getTargetDefines(Opts, Builder);
- Builder.defineMacro("__MSVCRT__");
- Builder.defineMacro("__MINGW64__");
- Builder.defineMacro("__declspec");
- }
-};
-} // end anonymous namespace
-
-namespace {
-class DarwinX86_64TargetInfo : public DarwinTargetInfo<X86_64TargetInfo> {
-public:
- DarwinX86_64TargetInfo(const std::string& triple)
- : DarwinTargetInfo<X86_64TargetInfo>(triple) {
- Int64Type = SignedLongLong;
- }
-};
-} // end anonymous namespace
-
-namespace {
-class OpenBSDX86_64TargetInfo : public OpenBSDTargetInfo<X86_64TargetInfo> {
-public:
- OpenBSDX86_64TargetInfo(const std::string& triple)
- : OpenBSDTargetInfo<X86_64TargetInfo>(triple) {
- IntMaxType = SignedLongLong;
- UIntMaxType = UnsignedLongLong;
- Int64Type = SignedLongLong;
- }
-};
-} // end anonymous namespace
-
-namespace {
-class ARMTargetInfo : public TargetInfo {
- // Possible FPU choices.
- enum FPUMode {
- NoFPU,
- VFP2FPU,
- VFP3FPU,
- NeonFPU
- };
-
- static bool FPUModeIsVFP(FPUMode Mode) {
- return Mode >= VFP2FPU && Mode <= NeonFPU;
- }
-
- static const TargetInfo::GCCRegAlias GCCRegAliases[];
- static const char * const GCCRegNames[];
-
- std::string ABI, CPU;
-
- unsigned FPU : 3;
-
- unsigned IsThumb : 1;
-
- // Initialized via features.
- unsigned SoftFloat : 1;
- unsigned SoftFloatABI : 1;
-
- static const Builtin::Info BuiltinInfo[];
-
-public:
- ARMTargetInfo(const std::string &TripleStr)
- : TargetInfo(TripleStr), ABI("aapcs-linux"), CPU("arm1136j-s")
- {
- SizeType = UnsignedInt;
- PtrDiffType = SignedInt;
-
- // {} in inline assembly are neon specifiers, not assembly variant
- // specifiers.
- NoAsmVariants = true;
-
- // FIXME: Should we just treat this as a feature?
- IsThumb = getTriple().getArchName().startswith("thumb");
- if (IsThumb) {
- DescriptionString = ("e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-"
- "i64:64:64-f32:32:32-f64:64:64-"
- "v64:64:64-v128:128:128-a0:0:32-n32");
- } else {
- DescriptionString = ("e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
- "i64:64:64-f32:32:32-f64:64:64-"
- "v64:64:64-v128:128:128-a0:0:64-n32");
- }
- }
- virtual const char *getABI() const { return ABI.c_str(); }
- virtual bool setABI(const std::string &Name) {
- ABI = Name;
-
- // The defaults (above) are for AAPCS, check if we need to change them.
- //
- // FIXME: We need support for -meabi... we could just mangle it into the
- // name.
- if (Name == "apcs-gnu") {
- DoubleAlign = LongLongAlign = LongDoubleAlign = 32;
- SizeType = UnsignedLong;
-
- // Do not respect the alignment of bit-field types when laying out
- // structures. This corresponds to PCC_BITFIELD_TYPE_MATTERS in gcc.
- UseBitFieldTypeAlignment = false;
-
- if (IsThumb) {
- DescriptionString = ("e-p:32:32:32-i1:8:32-i8:8:32-i16:16:32-i32:32:32-"
- "i64:32:32-f32:32:32-f64:32:32-"
- "v64:64:64-v128:128:128-a0:0:32-n32");
- } else {
- DescriptionString = ("e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
- "i64:32:32-f32:32:32-f64:32:32-"
- "v64:64:64-v128:128:128-a0:0:64-n32");
- }
-
- // FIXME: Override "preferred align" for double and long long.
- } else if (Name == "aapcs") {
- // FIXME: Enumerated types are variable width in straight AAPCS.
- } else if (Name == "aapcs-linux") {
- ;
- } else
- return false;
-
- return true;
- }
-
- void getDefaultFeatures(const std::string &CPU,
- llvm::StringMap<bool> &Features) const {
- // FIXME: This should not be here.
- Features["vfp2"] = false;
- Features["vfp3"] = false;
- Features["neon"] = false;
-
- if (CPU == "arm1136jf-s" || CPU == "arm1176jzf-s" || CPU == "mpcore")
- Features["vfp2"] = true;
- else if (CPU == "cortex-a8" || CPU == "cortex-a9")
- Features["neon"] = true;
- }
-
- virtual bool setFeatureEnabled(llvm::StringMap<bool> &Features,
- const std::string &Name,
- bool Enabled) const {
- if (Name == "soft-float" || Name == "soft-float-abi") {
- Features[Name] = Enabled;
- } else if (Name == "vfp2" || Name == "vfp3" || Name == "neon") {
- // These effectively are a single option, reset them when any is enabled.
- if (Enabled)
- Features["vfp2"] = Features["vfp3"] = Features["neon"] = false;
- Features[Name] = Enabled;
- } else
- return false;
-
- return true;
- }
-
- virtual void HandleTargetFeatures(std::vector<std::string> &Features) {
- FPU = NoFPU;
- SoftFloat = SoftFloatABI = false;
- for (unsigned i = 0, e = Features.size(); i != e; ++i) {
- if (Features[i] == "+soft-float")
- SoftFloat = true;
- else if (Features[i] == "+soft-float-abi")
- SoftFloatABI = true;
- else if (Features[i] == "+vfp2")
- FPU = VFP2FPU;
- else if (Features[i] == "+vfp3")
- FPU = VFP3FPU;
- else if (Features[i] == "+neon")
- FPU = NeonFPU;
- }
-
- // Remove front-end specific options which the backend handles differently.
- std::vector<std::string>::iterator it;
- it = std::find(Features.begin(), Features.end(), "+soft-float");
- if (it != Features.end())
- Features.erase(it);
- it = std::find(Features.begin(), Features.end(), "+soft-float-abi");
- if (it != Features.end())
- Features.erase(it);
- }
-
- static const char *getCPUDefineSuffix(llvm::StringRef Name) {
- return llvm::StringSwitch<const char*>(Name)
- .Cases("arm8", "arm810", "4")
- .Cases("strongarm", "strongarm110", "strongarm1100", "strongarm1110", "4")
- .Cases("arm7tdmi", "arm7tdmi-s", "arm710t", "arm720t", "arm9", "4T")
- .Cases("arm9tdmi", "arm920", "arm920t", "arm922t", "arm940t", "4T")
- .Case("ep9312", "4T")
- .Cases("arm10tdmi", "arm1020t", "5T")
- .Cases("arm9e", "arm946e-s", "arm966e-s", "arm968e-s", "5TE")
- .Case("arm926ej-s", "5TEJ")
- .Cases("arm10e", "arm1020e", "arm1022e", "5TE")
- .Cases("xscale", "iwmmxt", "5TE")
- .Case("arm1136j-s", "6J")
- .Cases("arm1176jz-s", "arm1176jzf-s", "6ZK")
- .Cases("arm1136jf-s", "mpcorenovfp", "mpcore", "6K")
- .Cases("arm1156t2-s", "arm1156t2f-s", "6T2")
- .Cases("cortex-a8", "cortex-a9", "7A")
- .Default(0);
- }
- virtual bool setCPU(const std::string &Name) {
- if (!getCPUDefineSuffix(Name))
- return false;
-
- CPU = Name;
- return true;
- }
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- // Target identification.
- Builder.defineMacro("__arm");
- Builder.defineMacro("__arm__");
-
- // Target properties.
- Builder.defineMacro("__ARMEL__");
- Builder.defineMacro("__LITTLE_ENDIAN__");
- Builder.defineMacro("__REGISTER_PREFIX__", "");
-
- llvm::StringRef CPUArch = getCPUDefineSuffix(CPU);
- Builder.defineMacro("__ARM_ARCH_" + CPUArch + "__");
-
- // Subtarget options.
-
- // FIXME: It's more complicated than this and we don't really support
- // interworking.
- if ('5' <= CPUArch[0] && CPUArch[0] <= '7')
- Builder.defineMacro("__THUMB_INTERWORK__");
-
- if (ABI == "aapcs" || ABI == "aapcs-linux")
- Builder.defineMacro("__ARM_EABI__");
-
- if (SoftFloat)
- Builder.defineMacro("__SOFTFP__");
-
- if (CPU == "xscale")
- Builder.defineMacro("__XSCALE__");
-
- bool IsThumb2 = IsThumb && (CPUArch == "6T2" || CPUArch.startswith("7"));
- if (IsThumb) {
- Builder.defineMacro("__THUMBEL__");
- Builder.defineMacro("__thumb__");
- if (IsThumb2)
- Builder.defineMacro("__thumb2__");
- }
-
- // Note, this is always on in gcc, even though it doesn't make sense.
- Builder.defineMacro("__APCS_32__");
-
- if (FPUModeIsVFP((FPUMode) FPU))
- Builder.defineMacro("__VFP_FP__");
-
- // This only gets set when Neon instructions are actually available, unlike
- // the VFP define, hence the soft float and arch check. This is subtly
- // different from gcc, we follow the intent which was that it should be set
- // when Neon instructions are actually available.
- if (FPU == NeonFPU && !SoftFloat && IsThumb2)
- Builder.defineMacro("__ARM_NEON__");
- }
- virtual void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const {
- Records = BuiltinInfo;
- NumRecords = clang::ARM::LastTSBuiltin-Builtin::FirstTSBuiltin;
- }
- virtual const char *getVAListDeclaration() const {
- return "typedef char* __builtin_va_list;";
- }
- virtual void getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const;
- virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const;
- virtual bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &Info) const {
- // FIXME: Check if this is complete
- switch (*Name) {
- default:
- case 'l': // r0-r7
- case 'h': // r8-r15
- case 'w': // VFP Floating point register single precision
- case 'P': // VFP Floating point register double precision
- Info.setAllowsRegister();
- return true;
- }
- return false;
- }
- virtual const char *getClobbers() const {
- // FIXME: Is this really right?
- return "";
- }
-};
-
-const char * const ARMTargetInfo::GCCRegNames[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc"
-};
-
-void ARMTargetInfo::getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const {
- Names = GCCRegNames;
- NumNames = llvm::array_lengthof(GCCRegNames);
-}
-
-const TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = {
- { { "a1" }, "r0" },
- { { "a2" }, "r1" },
- { { "a3" }, "r2" },
- { { "a4" }, "r3" },
- { { "v1" }, "r4" },
- { { "v2" }, "r5" },
- { { "v3" }, "r6" },
- { { "v4" }, "r7" },
- { { "v5" }, "r8" },
- { { "v6", "rfp" }, "r9" },
- { { "sl" }, "r10" },
- { { "fp" }, "r11" },
- { { "ip" }, "r12" },
- { { "r13" }, "sp" },
- { { "r14" }, "lr" },
- { { "r15" }, "pc" },
-};
-
-void ARMTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const {
- Aliases = GCCRegAliases;
- NumAliases = llvm::array_lengthof(GCCRegAliases);
-}
-
-const Builtin::Info ARMTargetInfo::BuiltinInfo[] = {
-#define BUILTIN(ID, TYPE, ATTRS) { #ID, TYPE, ATTRS, 0, false },
-#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) { #ID, TYPE, ATTRS, HEADER, false },
-#include "clang/Basic/BuiltinsARM.def"
-};
-} // end anonymous namespace.
-
-
-namespace {
-class DarwinARMTargetInfo :
- public DarwinTargetInfo<ARMTargetInfo> {
-protected:
- virtual void getOSDefines(const LangOptions &Opts, const llvm::Triple &Triple,
- MacroBuilder &Builder) const {
- getDarwinDefines(Builder, Opts, Triple);
- }
-
-public:
- DarwinARMTargetInfo(const std::string& triple)
- : DarwinTargetInfo<ARMTargetInfo>(triple) {
- HasAlignMac68kSupport = true;
- }
-};
-} // end anonymous namespace.
-
-namespace {
-class SparcV8TargetInfo : public TargetInfo {
- static const TargetInfo::GCCRegAlias GCCRegAliases[];
- static const char * const GCCRegNames[];
-public:
- SparcV8TargetInfo(const std::string& triple) : TargetInfo(triple) {
- // FIXME: Support Sparc quad-precision long double?
- DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-"
- "i64:64:64-f32:32:32-f64:64:64-v64:64:64-n32";
- }
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- DefineStd(Builder, "sparc", Opts);
- Builder.defineMacro("__sparcv8");
- Builder.defineMacro("__REGISTER_PREFIX__", "");
- }
- virtual void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const {
- // FIXME: Implement!
- }
- virtual const char *getVAListDeclaration() const {
- return "typedef void* __builtin_va_list;";
- }
- virtual void getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const;
- virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const;
- virtual bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &info) const {
- // FIXME: Implement!
- return false;
- }
- virtual const char *getClobbers() const {
- // FIXME: Implement!
- return "";
- }
-};
-
-const char * const SparcV8TargetInfo::GCCRegNames[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
- "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
- "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"
-};
-
-void SparcV8TargetInfo::getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const {
- Names = GCCRegNames;
- NumNames = llvm::array_lengthof(GCCRegNames);
-}
-
-const TargetInfo::GCCRegAlias SparcV8TargetInfo::GCCRegAliases[] = {
- { { "g0" }, "r0" },
- { { "g1" }, "r1" },
- { { "g2" }, "r2" },
- { { "g3" }, "r3" },
- { { "g4" }, "r4" },
- { { "g5" }, "r5" },
- { { "g6" }, "r6" },
- { { "g7" }, "r7" },
- { { "o0" }, "r8" },
- { { "o1" }, "r9" },
- { { "o2" }, "r10" },
- { { "o3" }, "r11" },
- { { "o4" }, "r12" },
- { { "o5" }, "r13" },
- { { "o6", "sp" }, "r14" },
- { { "o7" }, "r15" },
- { { "l0" }, "r16" },
- { { "l1" }, "r17" },
- { { "l2" }, "r18" },
- { { "l3" }, "r19" },
- { { "l4" }, "r20" },
- { { "l5" }, "r21" },
- { { "l6" }, "r22" },
- { { "l7" }, "r23" },
- { { "i0" }, "r24" },
- { { "i1" }, "r25" },
- { { "i2" }, "r26" },
- { { "i3" }, "r27" },
- { { "i4" }, "r28" },
- { { "i5" }, "r29" },
- { { "i6", "fp" }, "r30" },
- { { "i7" }, "r31" },
-};
-
-void SparcV8TargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const {
- Aliases = GCCRegAliases;
- NumAliases = llvm::array_lengthof(GCCRegAliases);
-}
-} // end anonymous namespace.
-
-namespace {
-class AuroraUXSparcV8TargetInfo : public AuroraUXTargetInfo<SparcV8TargetInfo> {
-public:
- AuroraUXSparcV8TargetInfo(const std::string& triple) :
- AuroraUXTargetInfo<SparcV8TargetInfo>(triple) {
- SizeType = UnsignedInt;
- PtrDiffType = SignedInt;
- }
-};
-class SolarisSparcV8TargetInfo : public SolarisTargetInfo<SparcV8TargetInfo> {
-public:
- SolarisSparcV8TargetInfo(const std::string& triple) :
- SolarisTargetInfo<SparcV8TargetInfo>(triple) {
- SizeType = UnsignedInt;
- PtrDiffType = SignedInt;
- }
-};
-} // end anonymous namespace.
-
-namespace {
- class PIC16TargetInfo : public TargetInfo{
- public:
- PIC16TargetInfo(const std::string& triple) : TargetInfo(triple) {
- TLSSupported = false;
- IntWidth = 16;
- LongWidth = LongLongWidth = 32;
- PointerWidth = 16;
- IntAlign = 8;
- LongAlign = LongLongAlign = 8;
- PointerAlign = 8;
- SizeType = UnsignedInt;
- IntMaxType = SignedLong;
- UIntMaxType = UnsignedLong;
- IntPtrType = SignedShort;
- PtrDiffType = SignedInt;
- SigAtomicType = SignedLong;
- FloatWidth = 32;
- FloatAlign = 32;
- DoubleWidth = 32;
- DoubleAlign = 32;
- LongDoubleWidth = 32;
- LongDoubleAlign = 32;
- FloatFormat = &llvm::APFloat::IEEEsingle;
- DoubleFormat = &llvm::APFloat::IEEEsingle;
- LongDoubleFormat = &llvm::APFloat::IEEEsingle;
- DescriptionString = "e-p:16:8:8-i8:8:8-i16:8:8-i32:8:8-f32:32:32-n8";
-
- }
- virtual uint64_t getPointerWidthV(unsigned AddrSpace) const { return 16; }
- virtual uint64_t getPointerAlignV(unsigned AddrSpace) const { return 8; }
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- Builder.defineMacro("__pic16");
- Builder.defineMacro("__PIC16");
- Builder.defineMacro("rom", "__attribute__((address_space(1)))");
- Builder.defineMacro("ram", "__attribute__((address_space(0)))");
- Builder.defineMacro("__section(SectName)",
- "__attribute__((section(SectName)))");
- Builder.defineMacro("near",
- "__attribute__((section(\"Address=NEAR\")))");
- Builder.defineMacro("__address(Addr)",
- "__attribute__((section(\"Address=\"#Addr)))");
- Builder.defineMacro("__config(conf)", "asm(\"CONFIG \"#conf)");
- Builder.defineMacro("__idlocs(value)", "asm(\"__IDLOCS \"#value)");
- Builder.defineMacro("interrupt",
- "__attribute__((section(\"interrupt=0x4\"))) \
- __attribute__((used))");
- }
- virtual void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const {}
- virtual const char *getVAListDeclaration() const {
- return "typedef char* __builtin_va_list;";
- }
- virtual const char *getClobbers() const {
- return "";
- }
- virtual void getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const {}
- virtual bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &info) const {
- return true;
- }
- virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const {}
- virtual bool useGlobalsForAutomaticVariables() const {return true;}
- };
-}
-
-namespace {
- class MSP430TargetInfo : public TargetInfo {
- static const char * const GCCRegNames[];
- public:
- MSP430TargetInfo(const std::string& triple) : TargetInfo(triple) {
- TLSSupported = false;
- IntWidth = 16; IntAlign = 16;
- LongWidth = 32; LongLongWidth = 64;
- LongAlign = LongLongAlign = 16;
- PointerWidth = 16; PointerAlign = 16;
- SizeType = UnsignedInt;
- IntMaxType = SignedLong;
- UIntMaxType = UnsignedLong;
- IntPtrType = SignedShort;
- PtrDiffType = SignedInt;
- SigAtomicType = SignedLong;
- DescriptionString = "e-p:16:16:16-i8:8:8-i16:16:16-i32:16:32-n8:16";
- }
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- Builder.defineMacro("MSP430");
- Builder.defineMacro("__MSP430__");
- // FIXME: defines for different 'flavours' of MCU
- }
- virtual void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const {
- // FIXME: Implement.
- Records = 0;
- NumRecords = 0;
- }
- virtual void getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const;
- virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const {
- // No aliases.
- Aliases = 0;
- NumAliases = 0;
- }
- virtual bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &info) const {
- // No target constraints for now.
- return false;
- }
- virtual const char *getClobbers() const {
- // FIXME: Is this really right?
- return "";
- }
- virtual const char *getVAListDeclaration() const {
- // FIXME: implement
- return "typedef char* __builtin_va_list;";
- }
- };
-
- const char * const MSP430TargetInfo::GCCRegNames[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
- };
-
- void MSP430TargetInfo::getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const {
- Names = GCCRegNames;
- NumNames = llvm::array_lengthof(GCCRegNames);
- }
-}
-
-
-namespace {
- class SystemZTargetInfo : public TargetInfo {
- static const char * const GCCRegNames[];
- public:
- SystemZTargetInfo(const std::string& triple) : TargetInfo(triple) {
- TLSSupported = false;
- IntWidth = IntAlign = 32;
- LongWidth = LongLongWidth = LongAlign = LongLongAlign = 64;
- PointerWidth = PointerAlign = 64;
- DescriptionString = "E-p:64:64:64-i8:8:16-i16:16:16-i32:32:32-"
- "i64:64:64-f32:32:32-f64:64:64-f128:128:128-a0:16:16-n32:64";
- }
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- Builder.defineMacro("__s390__");
- Builder.defineMacro("__s390x__");
- }
- virtual void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const {
- // FIXME: Implement.
- Records = 0;
- NumRecords = 0;
- }
-
- virtual void getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const;
- virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const {
- // No aliases.
- Aliases = 0;
- NumAliases = 0;
- }
- virtual bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &info) const {
- // FIXME: implement
- return true;
- }
- virtual const char *getClobbers() const {
- // FIXME: Is this really right?
- return "";
- }
- virtual const char *getVAListDeclaration() const {
- // FIXME: implement
- return "typedef char* __builtin_va_list;";
- }
- };
-
- const char * const SystemZTargetInfo::GCCRegNames[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
- };
-
- void SystemZTargetInfo::getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const {
- Names = GCCRegNames;
- NumNames = llvm::array_lengthof(GCCRegNames);
- }
-}
-
-namespace {
- class BlackfinTargetInfo : public TargetInfo {
- static const char * const GCCRegNames[];
- public:
- BlackfinTargetInfo(const std::string& triple) : TargetInfo(triple) {
- TLSSupported = false;
- DoubleAlign = 32;
- LongLongAlign = 32;
- LongDoubleAlign = 32;
- DescriptionString = "e-p:32:32-i64:32-f64:32-n32";
- }
-
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- DefineStd(Builder, "bfin", Opts);
- DefineStd(Builder, "BFIN", Opts);
- Builder.defineMacro("__ADSPBLACKFIN__");
- // FIXME: This one is really dependent on -mcpu
- Builder.defineMacro("__ADSPLPBLACKFIN__");
- // FIXME: Add cpu-dependent defines and __SILICON_REVISION__
- }
-
- virtual void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const {
- // FIXME: Implement.
- Records = 0;
- NumRecords = 0;
- }
-
- virtual void getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const;
-
- virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const {
- // No aliases.
- Aliases = 0;
- NumAliases = 0;
- }
-
- virtual bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &Info) const {
- if (strchr("adzDWeABbvfcCtukxywZY", Name[0])) {
- Info.setAllowsRegister();
- return true;
- }
- return false;
- }
-
- virtual const char *getClobbers() const {
- return "";
- }
-
- virtual const char *getVAListDeclaration() const {
- return "typedef char* __builtin_va_list;";
- }
- };
-
- const char * const BlackfinTargetInfo::GCCRegNames[] = {
- "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
- "p0", "p1", "p2", "p3", "p4", "p5", "sp", "fp",
- "i0", "i1", "i2", "i3", "b0", "b1", "b2", "b3",
- "l0", "l1", "l2", "l3", "m0", "m1", "m2", "m3",
- "a0", "a1", "cc",
- "rets", "reti", "retx", "retn", "rete", "astat", "seqstat", "usp",
- "argp", "lt0", "lt1", "lc0", "lc1", "lb0", "lb1"
- };
-
- void BlackfinTargetInfo::getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const {
- Names = GCCRegNames;
- NumNames = llvm::array_lengthof(GCCRegNames);
- }
-}
-
-namespace {
-
- // LLVM and Clang cannot be used directly to output native binaries for
- // target, but is used to compile C code to llvm bitcode with correct
- // type and alignment information.
- //
- // TCE uses the llvm bitcode as input and uses it for generating customized
- // target processor and program binary. TCE co-design environment is
- // publicly available in http://tce.cs.tut.fi
-
- class TCETargetInfo : public TargetInfo{
- public:
- TCETargetInfo(const std::string& triple) : TargetInfo(triple) {
- TLSSupported = false;
- IntWidth = 32;
- LongWidth = LongLongWidth = 32;
- PointerWidth = 32;
- IntAlign = 32;
- LongAlign = LongLongAlign = 32;
- PointerAlign = 32;
- SizeType = UnsignedInt;
- IntMaxType = SignedLong;
- UIntMaxType = UnsignedLong;
- IntPtrType = SignedInt;
- PtrDiffType = SignedInt;
- FloatWidth = 32;
- FloatAlign = 32;
- DoubleWidth = 32;
- DoubleAlign = 32;
- LongDoubleWidth = 32;
- LongDoubleAlign = 32;
- FloatFormat = &llvm::APFloat::IEEEsingle;
- DoubleFormat = &llvm::APFloat::IEEEsingle;
- LongDoubleFormat = &llvm::APFloat::IEEEsingle;
- DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:32-"
- "i16:16:32-i32:32:32-i64:32:32-"
- "f32:32:32-f64:64:64-v64:64:64-"
- "v128:128:128-a0:0:64-n32";
- }
-
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- DefineStd(Builder, "tce", Opts);
- Builder.defineMacro("__TCE__");
- Builder.defineMacro("__TCE_V1__");
- }
- virtual void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const {}
- virtual const char *getClobbers() const {
- return "";
- }
- virtual const char *getVAListDeclaration() const {
- return "typedef void* __builtin_va_list;";
- }
- virtual void getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const {}
- virtual bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &info) const {
- return true;
- }
- virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const {}
- };
-}
-
-namespace {
-class MipsTargetInfo : public TargetInfo {
- std::string ABI, CPU;
- static const TargetInfo::GCCRegAlias GCCRegAliases[];
- static const char * const GCCRegNames[];
-public:
- MipsTargetInfo(const std::string& triple) : TargetInfo(triple), ABI("o32") {
- DescriptionString = "E-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-"
- "i64:32:64-f32:32:32-f64:64:64-v64:64:64-n32";
- }
- virtual const char *getABI() const { return ABI.c_str(); }
- virtual bool setABI(const std::string &Name) {
-
- if ((Name == "o32") || (Name == "eabi")) {
- ABI = Name;
- return true;
- } else
- return false;
- }
- virtual bool setCPU(const std::string &Name) {
- CPU = Name;
- return true;
- }
- void getDefaultFeatures(const std::string &CPU,
- llvm::StringMap<bool> &Features) const {
- Features[ABI] = true;
- Features[CPU] = true;
- }
- virtual void getArchDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- if (ABI == "o32")
- Builder.defineMacro("__mips_o32");
- else if (ABI == "eabi")
- Builder.defineMacro("__mips_eabi");
- }
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- DefineStd(Builder, "mips", Opts);
- Builder.defineMacro("_mips");
- DefineStd(Builder, "MIPSEB", Opts);
- Builder.defineMacro("_MIPSEB");
- Builder.defineMacro("__REGISTER_PREFIX__", "");
- getArchDefines(Opts, Builder);
- }
- virtual void getTargetBuiltins(const Builtin::Info *&Records,
- unsigned &NumRecords) const {
- // FIXME: Implement!
- }
- virtual const char *getVAListDeclaration() const {
- return "typedef void* __builtin_va_list;";
- }
- virtual void getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const;
- virtual void getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const;
- virtual bool validateAsmConstraint(const char *&Name,
- TargetInfo::ConstraintInfo &Info) const {
- switch (*Name) {
- default:
- case 'r': // CPU registers.
- case 'd': // Equivalent to "r" unless generating MIPS16 code.
- case 'y': // Equivalent to "r", backwards compatibility only.
- case 'f': // floating-point registers.
- Info.setAllowsRegister();
- return true;
- }
- return false;
- }
-
- virtual const char *getClobbers() const {
- // FIXME: Implement!
- return "";
- }
-};
-
-const char * const MipsTargetInfo::GCCRegNames[] = {
- "$0", "$1", "$2", "$3", "$4", "$5", "$6", "$7",
- "$8", "$9", "$10", "$11", "$12", "$13", "$14", "$15",
- "$16", "$17", "$18", "$19", "$20", "$21", "$22", "$23",
- "$24", "$25", "$26", "$27", "$28", "$sp", "$fp", "$31",
- "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7",
- "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15",
- "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23",
- "$f24", "$f25", "$f26", "$f27", "$f28", "$f29", "$f30", "$f31",
- "hi", "lo", "", "$fcc0","$fcc1","$fcc2","$fcc3","$fcc4",
- "$fcc5","$fcc6","$fcc7"
-};
-
-void MipsTargetInfo::getGCCRegNames(const char * const *&Names,
- unsigned &NumNames) const {
- Names = GCCRegNames;
- NumNames = llvm::array_lengthof(GCCRegNames);
-}
-
-const TargetInfo::GCCRegAlias MipsTargetInfo::GCCRegAliases[] = {
- { { "at" }, "$1" },
- { { "v0" }, "$2" },
- { { "v1" }, "$3" },
- { { "a0" }, "$4" },
- { { "a1" }, "$5" },
- { { "a2" }, "$6" },
- { { "a3" }, "$7" },
- { { "t0" }, "$8" },
- { { "t1" }, "$9" },
- { { "t2" }, "$10" },
- { { "t3" }, "$11" },
- { { "t4" }, "$12" },
- { { "t5" }, "$13" },
- { { "t6" }, "$14" },
- { { "t7" }, "$15" },
- { { "s0" }, "$16" },
- { { "s1" }, "$17" },
- { { "s2" }, "$18" },
- { { "s3" }, "$19" },
- { { "s4" }, "$20" },
- { { "s5" }, "$21" },
- { { "s6" }, "$22" },
- { { "s7" }, "$23" },
- { { "t8" }, "$24" },
- { { "t9" }, "$25" },
- { { "k0" }, "$26" },
- { { "k1" }, "$27" },
- { { "gp" }, "$28" },
- { { "sp" }, "$29" },
- { { "fp" }, "$30" },
- { { "ra" }, "$31" }
-};
-
-void MipsTargetInfo::getGCCRegAliases(const GCCRegAlias *&Aliases,
- unsigned &NumAliases) const {
- Aliases = GCCRegAliases;
- NumAliases = llvm::array_lengthof(GCCRegAliases);
-}
-} // end anonymous namespace.
-
-namespace {
-class MipselTargetInfo : public MipsTargetInfo {
-public:
- MipselTargetInfo(const std::string& triple) : MipsTargetInfo(triple) {
- DescriptionString = "e-p:32:32:32-i1:8:8-i8:8:32-i16:16:32-i32:32:32-"
- "i64:32:64-f32:32:32-f64:64:64-v64:64:64-n32";
- }
-
- virtual void getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const;
-};
-
-void MipselTargetInfo::getTargetDefines(const LangOptions &Opts,
- MacroBuilder &Builder) const {
- DefineStd(Builder, "mips", Opts);
- Builder.defineMacro("_mips");
- DefineStd(Builder, "MIPSEL", Opts);
- Builder.defineMacro("_MIPSEL");
- Builder.defineMacro("__REGISTER_PREFIX__", "");
- getArchDefines(Opts, Builder);
-}
-} // end anonymous namespace.
-
-//===----------------------------------------------------------------------===//
-// Driver code
-//===----------------------------------------------------------------------===//
-
-static TargetInfo *AllocateTarget(const std::string &T) {
- llvm::Triple Triple(T);
- llvm::Triple::OSType os = Triple.getOS();
-
- switch (Triple.getArch()) {
- default:
- return NULL;
-
- case llvm::Triple::arm:
- case llvm::Triple::thumb:
- switch (os) {
- case llvm::Triple::Linux:
- return new LinuxTargetInfo<ARMTargetInfo>(T);
- case llvm::Triple::Darwin:
- return new DarwinARMTargetInfo(T);
- case llvm::Triple::FreeBSD:
- return new FreeBSDTargetInfo<ARMTargetInfo>(T);
- default:
- return new ARMTargetInfo(T);
- }
-
- case llvm::Triple::bfin:
- return new BlackfinTargetInfo(T);
-
- case llvm::Triple::msp430:
- return new MSP430TargetInfo(T);
-
- case llvm::Triple::mips:
- if (os == llvm::Triple::Psp)
- return new PSPTargetInfo<MipsTargetInfo>(T);
- if (os == llvm::Triple::Linux)
- return new LinuxTargetInfo<MipsTargetInfo>(T);
- return new MipsTargetInfo(T);
-
- case llvm::Triple::mipsel:
- if (os == llvm::Triple::Psp)
- return new PSPTargetInfo<MipselTargetInfo>(T);
- if (os == llvm::Triple::Linux)
- return new LinuxTargetInfo<MipselTargetInfo>(T);
- return new MipselTargetInfo(T);
-
- case llvm::Triple::pic16:
- return new PIC16TargetInfo(T);
-
- case llvm::Triple::ppc:
- if (os == llvm::Triple::Darwin)
- return new DarwinPPCTargetInfo(T);
- else if (os == llvm::Triple::FreeBSD)
- return new FreeBSDTargetInfo<PPC32TargetInfo>(T);
- return new PPC32TargetInfo(T);
-
- case llvm::Triple::ppc64:
- if (os == llvm::Triple::Darwin)
- return new DarwinPPC64TargetInfo(T);
- else if (os == llvm::Triple::Lv2)
- return new PS3PPUTargetInfo<PPC64TargetInfo>(T);
- else if (os == llvm::Triple::FreeBSD)
- return new FreeBSDTargetInfo<PPC64TargetInfo>(T);
- return new PPC64TargetInfo(T);
-
- case llvm::Triple::mblaze:
- return new MBlazeTargetInfo(T);
-
- case llvm::Triple::sparc:
- if (os == llvm::Triple::AuroraUX)
- return new AuroraUXSparcV8TargetInfo(T);
- if (os == llvm::Triple::Solaris)
- return new SolarisSparcV8TargetInfo(T);
- return new SparcV8TargetInfo(T);
-
- // FIXME: Need a real SPU target.
- case llvm::Triple::cellspu:
- return new PS3SPUTargetInfo<PPC64TargetInfo>(T);
-
- case llvm::Triple::systemz:
- return new SystemZTargetInfo(T);
-
- case llvm::Triple::tce:
- return new TCETargetInfo(T);
-
- case llvm::Triple::x86:
- switch (os) {
- case llvm::Triple::AuroraUX:
- return new AuroraUXTargetInfo<X86_32TargetInfo>(T);
- case llvm::Triple::Darwin:
- return new DarwinI386TargetInfo(T);
- case llvm::Triple::Linux:
- return new LinuxTargetInfo<X86_32TargetInfo>(T);
- case llvm::Triple::DragonFly:
- return new DragonFlyBSDTargetInfo<X86_32TargetInfo>(T);
- case llvm::Triple::NetBSD:
- return new NetBSDTargetInfo<X86_32TargetInfo>(T);
- case llvm::Triple::OpenBSD:
- return new OpenBSDI386TargetInfo(T);
- case llvm::Triple::FreeBSD:
- return new FreeBSDTargetInfo<X86_32TargetInfo>(T);
- case llvm::Triple::Minix:
- return new MinixTargetInfo<X86_32TargetInfo>(T);
- case llvm::Triple::Solaris:
- return new SolarisTargetInfo<X86_32TargetInfo>(T);
- case llvm::Triple::Cygwin:
- return new CygwinX86_32TargetInfo(T);
- case llvm::Triple::MinGW32:
- return new MinGWX86_32TargetInfo(T);
- case llvm::Triple::Win32:
- return new VisualStudioWindowsX86_32TargetInfo(T);
- case llvm::Triple::Haiku:
- return new HaikuX86_32TargetInfo(T);
- default:
- return new X86_32TargetInfo(T);
- }
-
- case llvm::Triple::x86_64:
- switch (os) {
- case llvm::Triple::AuroraUX:
- return new AuroraUXTargetInfo<X86_64TargetInfo>(T);
- case llvm::Triple::Darwin:
- return new DarwinX86_64TargetInfo(T);
- case llvm::Triple::Linux:
- return new LinuxTargetInfo<X86_64TargetInfo>(T);
- case llvm::Triple::DragonFly:
- return new DragonFlyBSDTargetInfo<X86_64TargetInfo>(T);
- case llvm::Triple::NetBSD:
- return new NetBSDTargetInfo<X86_64TargetInfo>(T);
- case llvm::Triple::OpenBSD:
- return new OpenBSDX86_64TargetInfo(T);
- case llvm::Triple::FreeBSD:
- return new FreeBSDTargetInfo<X86_64TargetInfo>(T);
- case llvm::Triple::Solaris:
- return new SolarisTargetInfo<X86_64TargetInfo>(T);
- case llvm::Triple::MinGW64:
- return new MinGWX86_64TargetInfo(T);
- case llvm::Triple::Win32: // This is what Triple.h supports now.
- return new VisualStudioWindowsX86_64TargetInfo(T);
- default:
- return new X86_64TargetInfo(T);
- }
- }
-}
-
-/// CreateTargetInfo - Return the target info object for the specified target
-/// triple.
-TargetInfo *TargetInfo::CreateTargetInfo(Diagnostic &Diags,
- TargetOptions &Opts) {
- llvm::Triple Triple(Opts.Triple);
-
- // Construct the target
- llvm::OwningPtr<TargetInfo> Target(AllocateTarget(Triple.str()));
- if (!Target) {
- Diags.Report(diag::err_target_unknown_triple) << Triple.str();
- return 0;
- }
-
- // Set the target CPU if specified.
- if (!Opts.CPU.empty() && !Target->setCPU(Opts.CPU)) {
- Diags.Report(diag::err_target_unknown_cpu) << Opts.CPU;
- return 0;
- }
-
- // Set the target ABI if specified.
- if (!Opts.ABI.empty() && !Target->setABI(Opts.ABI)) {
- Diags.Report(diag::err_target_unknown_abi) << Opts.ABI;
- return 0;
- }
-
- // Set the target C++ ABI.
- if (!Target->setCXXABI(Opts.CXXABI)) {
- Diags.Report(diag::err_target_unknown_cxxabi) << Opts.CXXABI;
- return 0;
- }
-
- // Compute the default target features, we need the target to handle this
- // because features may have dependencies on one another.
- llvm::StringMap<bool> Features;
- Target->getDefaultFeatures(Opts.CPU, Features);
-
- // Apply the user specified deltas.
- for (std::vector<std::string>::const_iterator it = Opts.Features.begin(),
- ie = Opts.Features.end(); it != ie; ++it) {
- const char *Name = it->c_str();
-
- // Apply the feature via the target.
- if ((Name[0] != '-' && Name[0] != '+') ||
- !Target->setFeatureEnabled(Features, Name + 1, (Name[0] == '+'))) {
- Diags.Report(diag::err_target_invalid_feature) << Name;
- return 0;
- }
- }
-
- // Add the features to the compile options.
- //
- // FIXME: If we are completely confident that we have the right set, we only
- // need to pass the minuses.
- Opts.Features.clear();
- for (llvm::StringMap<bool>::const_iterator it = Features.begin(),
- ie = Features.end(); it != ie; ++it)
- Opts.Features.push_back(std::string(it->second ? "+" : "-") + it->first());
- Target->HandleTargetFeatures(Opts.Features);
-
- return Target.take();
-}
Removed: cfe/branches/Apple/williamson/lib/Checker/AnalysisConsumer.cpp.orig
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/williamson/lib/Checker/AnalysisConsumer.cpp.orig?rev=111417&view=auto
==============================================================================
--- cfe/branches/Apple/williamson/lib/Checker/AnalysisConsumer.cpp.orig (original)
+++ cfe/branches/Apple/williamson/lib/Checker/AnalysisConsumer.cpp.orig (removed)
@@ -1,590 +0,0 @@
-//===--- AnalysisConsumer.cpp - ASTConsumer for running Analyses ----------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// "Meta" ASTConsumer for running different source analyses.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Checker/AnalysisConsumer.h"
-#include "clang/AST/ASTConsumer.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/AST/ParentMap.h"
-#include "clang/Analysis/Analyses/LiveVariables.h"
-#include "clang/Analysis/Analyses/UninitializedValues.h"
-#include "clang/Analysis/CFG.h"
-#include "clang/Checker/Checkers/LocalCheckers.h"
-#include "clang/Checker/ManagerRegistry.h"
-#include "clang/Checker/BugReporter/PathDiagnostic.h"
-#include "clang/Checker/PathSensitive/AnalysisManager.h"
-#include "clang/Checker/BugReporter/BugReporter.h"
-#include "clang/Checker/PathSensitive/GRExprEngine.h"
-#include "clang/Checker/PathSensitive/GRTransferFuncs.h"
-#include "clang/Checker/PathDiagnosticClients.h"
-#include "GRExprEngineExperimentalChecks.h"
-#include "clang/Basic/FileManager.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Frontend/AnalyzerOptions.h"
-#include "clang/Lex/Preprocessor.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/System/Path.h"
-#include "llvm/System/Program.h"
-#include "llvm/ADT/OwningPtr.h"
-
-using namespace clang;
-
-static ExplodedNode::Auditor* CreateUbiViz();
-
-//===----------------------------------------------------------------------===//
-// Special PathDiagnosticClients.
-//===----------------------------------------------------------------------===//
-
-static PathDiagnosticClient*
-CreatePlistHTMLDiagnosticClient(const std::string& prefix,
- const Preprocessor &PP) {
- llvm::sys::Path F(prefix);
- PathDiagnosticClient *PD = CreateHTMLDiagnosticClient(F.getDirname(), PP);
- return CreatePlistDiagnosticClient(prefix, PP, PD);
-}
-
-//===----------------------------------------------------------------------===//
-// AnalysisConsumer declaration.
-//===----------------------------------------------------------------------===//
-
-namespace {
-
-class AnalysisConsumer : public ASTConsumer {
-public:
- typedef void (*CodeAction)(AnalysisConsumer &C, AnalysisManager &M, Decl *D);
- typedef void (*TUAction)(AnalysisConsumer &C, AnalysisManager &M,
- TranslationUnitDecl &TU);
-
-private:
- typedef std::vector<CodeAction> Actions;
- typedef std::vector<TUAction> TUActions;
-
- Actions FunctionActions;
- Actions ObjCMethodActions;
- Actions ObjCImplementationActions;
- Actions CXXMethodActions;
- TUActions TranslationUnitActions; // Remove this.
-
-public:
- ASTContext* Ctx;
- const Preprocessor &PP;
- const std::string OutDir;
- AnalyzerOptions Opts;
-
- // PD is owned by AnalysisManager.
- PathDiagnosticClient *PD;
-
- StoreManagerCreator CreateStoreMgr;
- ConstraintManagerCreator CreateConstraintMgr;
-
- llvm::OwningPtr<AnalysisManager> Mgr;
-
- AnalysisConsumer(const Preprocessor& pp,
- const std::string& outdir,
- const AnalyzerOptions& opts)
- : Ctx(0), PP(pp), OutDir(outdir),
- Opts(opts), PD(0) {
- DigestAnalyzerOptions();
- }
-
- void DigestAnalyzerOptions() {
- // Create the PathDiagnosticClient.
- if (!OutDir.empty()) {
- switch (Opts.AnalysisDiagOpt) {
- default:
-#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATEFN, AUTOCREATE) \
- case PD_##NAME: PD = CREATEFN(OutDir, PP); break;
-#include "clang/Frontend/Analyses.def"
- }
- }
-
- // Create the analyzer component creators.
- if (ManagerRegistry::StoreMgrCreator != 0) {
- CreateStoreMgr = ManagerRegistry::StoreMgrCreator;
- }
- else {
- switch (Opts.AnalysisStoreOpt) {
- default:
- assert(0 && "Unknown store manager.");
-#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATEFN) \
- case NAME##Model: CreateStoreMgr = CREATEFN; break;
-#include "clang/Frontend/Analyses.def"
- }
- }
-
- if (ManagerRegistry::ConstraintMgrCreator != 0)
- CreateConstraintMgr = ManagerRegistry::ConstraintMgrCreator;
- else {
- switch (Opts.AnalysisConstraintsOpt) {
- default:
- assert(0 && "Unknown store manager.");
-#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATEFN) \
- case NAME##Model: CreateConstraintMgr = CREATEFN; break;
-#include "clang/Frontend/Analyses.def"
- }
- }
- }
-
- void DisplayFunction(const Decl *D) {
- if (!Opts.AnalyzerDisplayProgress)
- return;
-
- SourceManager &SM = Mgr->getASTContext().getSourceManager();
- PresumedLoc Loc = SM.getPresumedLoc(D->getLocation());
- llvm::errs() << "ANALYZE: " << Loc.getFilename();
-
- if (isa<FunctionDecl>(D) || isa<ObjCMethodDecl>(D)) {
- const NamedDecl *ND = cast<NamedDecl>(D);
- llvm::errs() << ' ' << ND << '\n';
- }
- else if (isa<BlockDecl>(D)) {
- llvm::errs() << ' ' << "block(line:" << Loc.getLine() << ",col:"
- << Loc.getColumn() << '\n';
- }
- }
-
- void addCodeAction(CodeAction action) {
- FunctionActions.push_back(action);
- ObjCMethodActions.push_back(action);
- CXXMethodActions.push_back(action);
- }
-
- void addTranslationUnitAction(TUAction action) {
- TranslationUnitActions.push_back(action);
- }
-
- void addObjCImplementationAction(CodeAction action) {
- ObjCImplementationActions.push_back(action);
- }
-
- virtual void Initialize(ASTContext &Context) {
- Ctx = &Context;
- Mgr.reset(new AnalysisManager(*Ctx, PP.getDiagnostics(),
- PP.getLangOptions(), PD,
- CreateStoreMgr, CreateConstraintMgr,
- /* Indexer */ 0,
- Opts.MaxNodes, Opts.MaxLoop,
- Opts.VisualizeEGDot, Opts.VisualizeEGUbi,
- Opts.PurgeDead, Opts.EagerlyAssume,
- Opts.TrimGraph, Opts.InlineCall));
- }
-
- virtual void HandleTranslationUnit(ASTContext &C);
- void HandleCode(Decl *D, Actions& actions);
-};
-} // end anonymous namespace
-
-//===----------------------------------------------------------------------===//
-// AnalysisConsumer implementation.
-//===----------------------------------------------------------------------===//
-
-void AnalysisConsumer::HandleTranslationUnit(ASTContext &C) {
-
- TranslationUnitDecl *TU = C.getTranslationUnitDecl();
-
- for (DeclContext::decl_iterator I = TU->decls_begin(), E = TU->decls_end();
- I != E; ++I) {
- Decl *D = *I;
-
- switch (D->getKind()) {
- case Decl::CXXConstructor:
- case Decl::CXXDestructor:
- case Decl::CXXConversion:
- case Decl::CXXMethod:
- case Decl::Function: {
- FunctionDecl* FD = cast<FunctionDecl>(D);
-
- if (FD->isThisDeclarationADefinition()) {
- if (!Opts.AnalyzeSpecificFunction.empty() &&
- FD->getDeclName().getAsString() != Opts.AnalyzeSpecificFunction)
- break;
- DisplayFunction(FD);
- HandleCode(FD, FunctionActions);
- }
- break;
- }
-
- case Decl::ObjCMethod: {
- ObjCMethodDecl* MD = cast<ObjCMethodDecl>(D);
-
- if (MD->isThisDeclarationADefinition()) {
- if (!Opts.AnalyzeSpecificFunction.empty() &&
- Opts.AnalyzeSpecificFunction != MD->getSelector().getAsString())
- break;
- DisplayFunction(MD);
- HandleCode(MD, ObjCMethodActions);
- }
- break;
- }
-
- case Decl::ObjCImplementation: {
- ObjCImplementationDecl* ID = cast<ObjCImplementationDecl>(*I);
- HandleCode(ID, ObjCImplementationActions);
-
- for (ObjCImplementationDecl::method_iterator MI = ID->meth_begin(),
- ME = ID->meth_end(); MI != ME; ++MI) {
- if ((*MI)->isThisDeclarationADefinition()) {
- if (!Opts.AnalyzeSpecificFunction.empty() &&
- Opts.AnalyzeSpecificFunction != (*MI)->getSelector().getAsString())
- break;
- HandleCode(*MI, ObjCMethodActions);
- }
- }
- break;
- }
-
- default:
- break;
- }
- }
-
- for (TUActions::iterator I = TranslationUnitActions.begin(),
- E = TranslationUnitActions.end(); I != E; ++I) {
- (*I)(*this, *Mgr, *TU);
- }
-
- // Explicitly destroy the PathDiagnosticClient. This will flush its output.
- // FIXME: This should be replaced with something that doesn't rely on
- // side-effects in PathDiagnosticClient's destructor. This is required when
- // used with option -disable-free.
- Mgr.reset(NULL);
-}
-
-static void FindBlocks(DeclContext *D, llvm::SmallVectorImpl<Decl*> &WL) {
- if (BlockDecl *BD = dyn_cast<BlockDecl>(D))
- WL.push_back(BD);
-
- for (DeclContext::decl_iterator I = D->decls_begin(), E = D->decls_end();
- I!=E; ++I)
- if (DeclContext *DC = dyn_cast<DeclContext>(*I))
- FindBlocks(DC, WL);
-}
-
-void AnalysisConsumer::HandleCode(Decl *D, Actions& actions) {
-
- // Don't run the actions if an error has occured with parsing the file.
- Diagnostic &Diags = PP.getDiagnostics();
- if (Diags.hasErrorOccurred() || Diags.hasFatalErrorOccurred())
- return;
-
- // Don't run the actions on declarations in header files unless
- // otherwise specified.
- SourceManager &SM = Ctx->getSourceManager();
- SourceLocation SL = SM.getInstantiationLoc(D->getLocation());
- if (!Opts.AnalyzeAll && !SM.isFromMainFile(SL))
- return;
-
- // Clear the AnalysisManager of old AnalysisContexts.
- Mgr->ClearContexts();
-
- // Dispatch on the actions.
- llvm::SmallVector<Decl*, 10> WL;
- WL.push_back(D);
-
- if (D->hasBody() && Opts.AnalyzeNestedBlocks)
- FindBlocks(cast<DeclContext>(D), WL);
-
- for (Actions::iterator I = actions.begin(), E = actions.end(); I != E; ++I)
- for (llvm::SmallVectorImpl<Decl*>::iterator WI=WL.begin(), WE=WL.end();
- WI != WE; ++WI)
- (*I)(*this, *Mgr, *WI);
-}
-
-//===----------------------------------------------------------------------===//
-// Analyses
-//===----------------------------------------------------------------------===//
-
-static void ActionWarnDeadStores(AnalysisConsumer &C, AnalysisManager& mgr,
- Decl *D) {
- if (LiveVariables *L = mgr.getLiveVariables(D)) {
- BugReporter BR(mgr);
- CheckDeadStores(*mgr.getCFG(D), *L, mgr.getParentMap(D), BR);
- }
-}
-
-static void ActionWarnUninitVals(AnalysisConsumer &C, AnalysisManager& mgr,
- Decl *D) {
- if (CFG* c = mgr.getCFG(D)) {
- CheckUninitializedValues(*c, mgr.getASTContext(), mgr.getDiagnostic());
- }
-}
-
-
-static void ActionGRExprEngine(AnalysisConsumer &C, AnalysisManager& mgr,
- Decl *D,
- GRTransferFuncs* tf) {
-
- llvm::OwningPtr<GRTransferFuncs> TF(tf);
-
- // Construct the analysis engine. We first query for the LiveVariables
- // information to see if the CFG is valid.
- // FIXME: Inter-procedural analysis will need to handle invalid CFGs.
- if (!mgr.getLiveVariables(D))
- return;
- GRExprEngine Eng(mgr, TF.take());
-
- if (C.Opts.EnableExperimentalInternalChecks)
- RegisterExperimentalInternalChecks(Eng);
-
- RegisterAppleChecks(Eng, *D);
-
- if (C.Opts.EnableExperimentalChecks)
- RegisterExperimentalChecks(Eng);
-
- // Set the graph auditor.
- llvm::OwningPtr<ExplodedNode::Auditor> Auditor;
- if (mgr.shouldVisualizeUbigraph()) {
- Auditor.reset(CreateUbiViz());
- ExplodedNode::SetAuditor(Auditor.get());
- }
-
- // Execute the worklist algorithm.
- Eng.ExecuteWorkList(mgr.getStackFrame(D, 0), mgr.getMaxNodes());
-
- // Release the auditor (if any) so that it doesn't monitor the graph
- // created BugReporter.
- ExplodedNode::SetAuditor(0);
-
- // Visualize the exploded graph.
- if (mgr.shouldVisualizeGraphviz())
- Eng.ViewGraph(mgr.shouldTrimGraph());
-
- // Display warnings.
- Eng.getBugReporter().FlushReports();
-}
-
-static void ActionObjCMemCheckerAux(AnalysisConsumer &C, AnalysisManager& mgr,
- Decl *D, bool GCEnabled) {
-
- GRTransferFuncs* TF = MakeCFRefCountTF(mgr.getASTContext(),
- GCEnabled,
- mgr.getLangOptions());
-
- ActionGRExprEngine(C, mgr, D, TF);
-}
-
-static void ActionObjCMemChecker(AnalysisConsumer &C, AnalysisManager& mgr,
- Decl *D) {
-
- switch (mgr.getLangOptions().getGCMode()) {
- default:
- assert (false && "Invalid GC mode.");
- case LangOptions::NonGC:
- ActionObjCMemCheckerAux(C, mgr, D, false);
- break;
-
- case LangOptions::GCOnly:
- ActionObjCMemCheckerAux(C, mgr, D, true);
- break;
-
- case LangOptions::HybridGC:
- ActionObjCMemCheckerAux(C, mgr, D, false);
- ActionObjCMemCheckerAux(C, mgr, D, true);
- break;
- }
-}
-
-static void ActionDisplayLiveVariables(AnalysisConsumer &C,
- AnalysisManager& mgr, Decl *D) {
- if (LiveVariables* L = mgr.getLiveVariables(D)) {
- L->dumpBlockLiveness(mgr.getSourceManager());
- }
-}
-
-static void ActionCFGDump(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) {
- if (CFG *cfg = mgr.getCFG(D)) {
- cfg->dump(mgr.getLangOptions());
- }
-}
-
-static void ActionCFGView(AnalysisConsumer &C, AnalysisManager& mgr, Decl *D) {
- if (CFG *cfg = mgr.getCFG(D)) {
- cfg->viewCFG(mgr.getLangOptions());
- }
-}
-
-static void ActionSecuritySyntacticChecks(AnalysisConsumer &C,
- AnalysisManager &mgr, Decl *D) {
- BugReporter BR(mgr);
- CheckSecuritySyntaxOnly(D, BR);
-}
-
-static void ActionLLVMConventionChecker(AnalysisConsumer &C,
- AnalysisManager &mgr,
- TranslationUnitDecl &TU) {
- BugReporter BR(mgr);
- CheckLLVMConventions(TU, BR);
-}
-
-static void ActionWarnObjCDealloc(AnalysisConsumer &C, AnalysisManager& mgr,
- Decl *D) {
- if (mgr.getLangOptions().getGCMode() == LangOptions::GCOnly)
- return;
- BugReporter BR(mgr);
- CheckObjCDealloc(cast<ObjCImplementationDecl>(D), mgr.getLangOptions(), BR);
-}
-
-static void ActionWarnObjCUnusedIvars(AnalysisConsumer &C, AnalysisManager& mgr,
- Decl *D) {
- BugReporter BR(mgr);
- CheckObjCUnusedIvar(cast<ObjCImplementationDecl>(D), BR);
-}
-
-static void ActionWarnObjCMethSigs(AnalysisConsumer &C, AnalysisManager& mgr,
- Decl *D) {
- BugReporter BR(mgr);
- CheckObjCInstMethSignature(cast<ObjCImplementationDecl>(D), BR);
-}
-
-static void ActionWarnSizeofPointer(AnalysisConsumer &C, AnalysisManager &mgr,
- Decl *D) {
- BugReporter BR(mgr);
- CheckSizeofPointer(D, BR);
-}
-
-//===----------------------------------------------------------------------===//
-// AnalysisConsumer creation.
-//===----------------------------------------------------------------------===//
-
-ASTConsumer* clang::CreateAnalysisConsumer(const Preprocessor& pp,
- const std::string& OutDir,
- const AnalyzerOptions& Opts) {
- llvm::OwningPtr<AnalysisConsumer> C(new AnalysisConsumer(pp, OutDir, Opts));
-
- for (unsigned i = 0; i < Opts.AnalysisList.size(); ++i)
- switch (Opts.AnalysisList[i]) {
-#define ANALYSIS(NAME, CMD, DESC, SCOPE)\
- case NAME:\
- C->add ## SCOPE ## Action(&Action ## NAME);\
- break;
-#include "clang/Frontend/Analyses.def"
- default: break;
- }
-
- // Last, disable the effects of '-Werror' when using the AnalysisConsumer.
- pp.getDiagnostics().setWarningsAsErrors(false);
-
- return C.take();
-}
-
-//===----------------------------------------------------------------------===//
-// Ubigraph Visualization. FIXME: Move to separate file.
-//===----------------------------------------------------------------------===//
-
-namespace {
-
-class UbigraphViz : public ExplodedNode::Auditor {
- llvm::OwningPtr<llvm::raw_ostream> Out;
- llvm::sys::Path Dir, Filename;
- unsigned Cntr;
-
- typedef llvm::DenseMap<void*,unsigned> VMap;
- VMap M;
-
-public:
- UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
- llvm::sys::Path& filename);
-
- ~UbigraphViz();
-
- virtual void AddEdge(ExplodedNode* Src, ExplodedNode* Dst);
-};
-
-} // end anonymous namespace
-
-static ExplodedNode::Auditor* CreateUbiViz() {
- std::string ErrMsg;
-
- llvm::sys::Path Dir = llvm::sys::Path::GetTemporaryDirectory(&ErrMsg);
- if (!ErrMsg.empty())
- return 0;
-
- llvm::sys::Path Filename = Dir;
- Filename.appendComponent("llvm_ubi");
- Filename.makeUnique(true,&ErrMsg);
-
- if (!ErrMsg.empty())
- return 0;
-
- llvm::errs() << "Writing '" << Filename.str() << "'.\n";
-
- llvm::OwningPtr<llvm::raw_fd_ostream> Stream;
- Stream.reset(new llvm::raw_fd_ostream(Filename.c_str(), ErrMsg));
-
- if (!ErrMsg.empty())
- return 0;
-
- return new UbigraphViz(Stream.take(), Dir, Filename);
-}
-
-void UbigraphViz::AddEdge(ExplodedNode* Src, ExplodedNode* Dst) {
-
- assert (Src != Dst && "Self-edges are not allowed.");
-
- // Lookup the Src. If it is a new node, it's a root.
- VMap::iterator SrcI= M.find(Src);
- unsigned SrcID;
-
- if (SrcI == M.end()) {
- M[Src] = SrcID = Cntr++;
- *Out << "('vertex', " << SrcID << ", ('color','#00ff00'))\n";
- }
- else
- SrcID = SrcI->second;
-
- // Lookup the Dst.
- VMap::iterator DstI= M.find(Dst);
- unsigned DstID;
-
- if (DstI == M.end()) {
- M[Dst] = DstID = Cntr++;
- *Out << "('vertex', " << DstID << ")\n";
- }
- else {
- // We have hit DstID before. Change its style to reflect a cache hit.
- DstID = DstI->second;
- *Out << "('change_vertex_style', " << DstID << ", 1)\n";
- }
-
- // Add the edge.
- *Out << "('edge', " << SrcID << ", " << DstID
- << ", ('arrow','true'), ('oriented', 'true'))\n";
-}
-
-UbigraphViz::UbigraphViz(llvm::raw_ostream* out, llvm::sys::Path& dir,
- llvm::sys::Path& filename)
- : Out(out), Dir(dir), Filename(filename), Cntr(0) {
-
- *Out << "('vertex_style_attribute', 0, ('shape', 'icosahedron'))\n";
- *Out << "('vertex_style', 1, 0, ('shape', 'sphere'), ('color', '#ffcc66'),"
- " ('size', '1.5'))\n";
-}
-
-UbigraphViz::~UbigraphViz() {
- Out.reset(0);
- llvm::errs() << "Running 'ubiviz' program... ";
- std::string ErrMsg;
- llvm::sys::Path Ubiviz = llvm::sys::Program::FindProgramByName("ubiviz");
- std::vector<const char*> args;
- args.push_back(Ubiviz.c_str());
- args.push_back(Filename.c_str());
- args.push_back(0);
-
- if (llvm::sys::Program::ExecuteAndWait(Ubiviz, &args[0],0,0,0,0,&ErrMsg)) {
- llvm::errs() << "Error viewing graph: " << ErrMsg << "\n";
- }
-
- // Delete the directory.
- Dir.eraseFromDisk(true);
-}
Removed: cfe/branches/Apple/williamson/lib/Checker/GRExprEngine.cpp.orig
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/williamson/lib/Checker/GRExprEngine.cpp.orig?rev=111417&view=auto
==============================================================================
--- cfe/branches/Apple/williamson/lib/Checker/GRExprEngine.cpp.orig (original)
+++ cfe/branches/Apple/williamson/lib/Checker/GRExprEngine.cpp.orig (removed)
@@ -1,3619 +0,0 @@
-//=-- GRExprEngine.cpp - Path-Sensitive Expression-Level Dataflow ---*- C++ -*-=
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines a meta-engine for path-sensitive dataflow analysis that
-// is built on GREngine, but provides the boilerplate to execute transfer
-// functions and build the ExplodedGraph at the expression level.
-//
-//===----------------------------------------------------------------------===//
-#include "GRExprEngineInternalChecks.h"
-#include "clang/Checker/BugReporter/BugType.h"
-#include "clang/Checker/PathSensitive/AnalysisManager.h"
-#include "clang/Checker/PathSensitive/GRExprEngine.h"
-#include "clang/Checker/PathSensitive/GRExprEngineBuilders.h"
-#include "clang/Checker/PathSensitive/Checker.h"
-#include "clang/AST/CharUnits.h"
-#include "clang/AST/ParentMap.h"
-#include "clang/AST/StmtObjC.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/Basic/Builtins.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/SourceManager.h"
-#include "clang/Basic/PrettyStackTrace.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/ADT/ImmutableList.h"
-
-#ifndef NDEBUG
-#include "llvm/Support/GraphWriter.h"
-#endif
-
-using namespace clang;
-using llvm::dyn_cast;
-using llvm::dyn_cast_or_null;
-using llvm::cast;
-using llvm::APSInt;
-
-namespace {
- // Trait class for recording returned expression in the state.
- struct ReturnExpr {
- static int TagInt;
- typedef const Stmt *data_type;
- };
- int ReturnExpr::TagInt;
-}
-
-//===----------------------------------------------------------------------===//
-// Utility functions.
-//===----------------------------------------------------------------------===//
-
-static inline Selector GetNullarySelector(const char* name, ASTContext& Ctx) {
- IdentifierInfo* II = &Ctx.Idents.get(name);
- return Ctx.Selectors.getSelector(0, &II);
-}
-
-
-static QualType GetCalleeReturnType(const CallExpr *CE) {
- const Expr *Callee = CE->getCallee();
- QualType T = Callee->getType();
- if (const PointerType *PT = T->getAs<PointerType>()) {
- const FunctionType *FT = PT->getPointeeType()->getAs<FunctionType>();
- T = FT->getResultType();
- }
- else {
- const BlockPointerType *BT = T->getAs<BlockPointerType>();
- T = BT->getPointeeType()->getAs<FunctionType>()->getResultType();
- }
- return T;
-}
-
-static bool CalleeReturnsReference(const CallExpr *CE) {
- return (bool) GetCalleeReturnType(CE)->getAs<ReferenceType>();
-}
-
-static bool ReceiverReturnsReference(const ObjCMessageExpr *ME) {
- const ObjCMethodDecl *MD = ME->getMethodDecl();
- if (!MD)
- return false;
- return MD->getResultType()->getAs<ReferenceType>();
-}
-
-#ifndef NDEBUG
-static bool ReceiverReturnsReferenceOrRecord(const ObjCMessageExpr *ME) {
- const ObjCMethodDecl *MD = ME->getMethodDecl();
- if (!MD)
- return false;
- QualType T = MD->getResultType();
- return T->getAs<RecordType>() || T->getAs<ReferenceType>();
-}
-
-static bool CalleeReturnsReferenceOrRecord(const CallExpr *CE) {
- QualType T = GetCalleeReturnType(CE);
- return T->getAs<ReferenceType>() || T->getAs<RecordType>();
-}
-#endif
-
-//===----------------------------------------------------------------------===//
-// Batch auditor. DEPRECATED.
-//===----------------------------------------------------------------------===//
-
-namespace {
-
-class MappedBatchAuditor : public GRSimpleAPICheck {
- typedef llvm::ImmutableList<GRSimpleAPICheck*> Checks;
- typedef llvm::DenseMap<void*,Checks> MapTy;
-
- MapTy M;
- Checks::Factory F;
- Checks AllStmts;
-
-public:
- MappedBatchAuditor(llvm::BumpPtrAllocator& Alloc) :
- F(Alloc), AllStmts(F.GetEmptyList()) {}
-
- virtual ~MappedBatchAuditor() {
- llvm::DenseSet<GRSimpleAPICheck*> AlreadyVisited;
-
- for (MapTy::iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI)
- for (Checks::iterator I=MI->second.begin(), E=MI->second.end(); I!=E;++I){
-
- GRSimpleAPICheck* check = *I;
-
- if (AlreadyVisited.count(check))
- continue;
-
- AlreadyVisited.insert(check);
- delete check;
- }
- }
-
- void AddCheck(GRSimpleAPICheck *A, Stmt::StmtClass C) {
- assert (A && "Check cannot be null.");
- void* key = reinterpret_cast<void*>((uintptr_t) C);
- MapTy::iterator I = M.find(key);
- M[key] = F.Concat(A, I == M.end() ? F.GetEmptyList() : I->second);
- }
-
- void AddCheck(GRSimpleAPICheck *A) {
- assert (A && "Check cannot be null.");
- AllStmts = F.Concat(A, AllStmts);
- }
-
- virtual bool Audit(ExplodedNode* N, GRStateManager& VMgr) {
- // First handle the auditors that accept all statements.
- bool isSink = false;
- for (Checks::iterator I = AllStmts.begin(), E = AllStmts.end(); I!=E; ++I)
- isSink |= (*I)->Audit(N, VMgr);
-
- // Next handle the auditors that accept only specific statements.
- const Stmt* S = cast<PostStmt>(N->getLocation()).getStmt();
- void* key = reinterpret_cast<void*>((uintptr_t) S->getStmtClass());
- MapTy::iterator MI = M.find(key);
- if (MI != M.end()) {
- for (Checks::iterator I=MI->second.begin(), E=MI->second.end(); I!=E; ++I)
- isSink |= (*I)->Audit(N, VMgr);
- }
-
- return isSink;
- }
-};
-
-} // end anonymous namespace
-
-//===----------------------------------------------------------------------===//
-// Checker worklist routines.
-//===----------------------------------------------------------------------===//
-
-void GRExprEngine::CheckerVisit(const Stmt *S, ExplodedNodeSet &Dst,
- ExplodedNodeSet &Src, bool isPrevisit) {
-
- // Determine if we already have a cached 'CheckersOrdered' vector
- // specifically tailored for the provided <Stmt kind, isPrevisit>. This
- // can reduce the number of checkers actually called.
- CheckersOrdered *CO = &Checkers;
- llvm::OwningPtr<CheckersOrdered> NewCO;
-
- const std::pair<unsigned, unsigned> &K =
- std::make_pair((unsigned)S->getStmtClass(), isPrevisit ? 1U : 0U);
-
- CheckersOrdered *& CO_Ref = COCache[K];
-
- if (!CO_Ref) {
- // If we have no previously cached CheckersOrdered vector for this
- // statement kind, then create one.
- NewCO.reset(new CheckersOrdered);
- }
- else {
- // Use the already cached set.
- CO = CO_Ref;
- }
-
- if (CO->empty()) {
- // If there are no checkers, return early without doing any
- // more work.
- Dst.insert(Src);
- return;
- }
-
- ExplodedNodeSet Tmp;
- ExplodedNodeSet *PrevSet = &Src;
- unsigned checkersEvaluated = 0;
-
- for (CheckersOrdered::iterator I=CO->begin(), E=CO->end(); I!=E; ++I){
- ExplodedNodeSet *CurrSet = 0;
- if (I+1 == E)
- CurrSet = &Dst;
- else {
- CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;
- CurrSet->clear();
- }
- void *tag = I->first;
- Checker *checker = I->second;
- bool respondsToCallback = true;
-
- for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
- NI != NE; ++NI) {
-
- checker->GR_Visit(*CurrSet, *Builder, *this, S, *NI, tag, isPrevisit,
- respondsToCallback);
-
- }
-
- PrevSet = CurrSet;
-
- if (NewCO.get()) {
- ++checkersEvaluated;
- if (respondsToCallback)
- NewCO->push_back(*I);
- }
- }
-
- // If we built NewCO, check if we called all the checkers. This is important
- // so that we know that we accurately determined the entire set of checkers
- // that responds to this callback.
- if (NewCO.get() && checkersEvaluated == Checkers.size())
- CO_Ref = NewCO.take();
-
- // Don't autotransition. The CheckerContext objects should do this
- // automatically.
-}
-
-void GRExprEngine::CheckerEvalNilReceiver(const ObjCMessageExpr *ME,
- ExplodedNodeSet &Dst,
- const GRState *state,
- ExplodedNode *Pred) {
- bool Evaluated = false;
- ExplodedNodeSet DstTmp;
-
- for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end();I!=E;++I) {
- void *tag = I->first;
- Checker *checker = I->second;
-
- if (checker->GR_EvalNilReceiver(DstTmp, *Builder, *this, ME, Pred, state,
- tag)) {
- Evaluated = true;
- break;
- } else
- // The checker didn't evaluate the expr. Restore the Dst.
- DstTmp.clear();
- }
-
- if (Evaluated)
- Dst.insert(DstTmp);
- else
- Dst.insert(Pred);
-}
-
-// CheckerEvalCall returns true if one of the checkers processed the node.
-// This may return void when all call evaluation logic goes to some checker
-// in the future.
-bool GRExprEngine::CheckerEvalCall(const CallExpr *CE,
- ExplodedNodeSet &Dst,
- ExplodedNode *Pred) {
- bool Evaluated = false;
- ExplodedNodeSet DstTmp;
-
- for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end();I!=E;++I) {
- void *tag = I->first;
- Checker *checker = I->second;
-
- if (checker->GR_EvalCallExpr(DstTmp, *Builder, *this, CE, Pred, tag)) {
- Evaluated = true;
- break;
- } else
- // The checker didn't evaluate the expr. Restore the DstTmp set.
- DstTmp.clear();
- }
-
- if (Evaluated)
- Dst.insert(DstTmp);
- else
- Dst.insert(Pred);
-
- return Evaluated;
-}
-
-// FIXME: This is largely copy-paste from CheckerVisit(). Need to
-// unify.
-void GRExprEngine::CheckerVisitBind(const Stmt *AssignE, const Stmt *StoreE,
- ExplodedNodeSet &Dst,
- ExplodedNodeSet &Src,
- SVal location, SVal val, bool isPrevisit) {
-
- if (Checkers.empty()) {
- Dst.insert(Src);
- return;
- }
-
- ExplodedNodeSet Tmp;
- ExplodedNodeSet *PrevSet = &Src;
-
- for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E; ++I)
- {
- ExplodedNodeSet *CurrSet = 0;
- if (I+1 == E)
- CurrSet = &Dst;
- else {
- CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;
- CurrSet->clear();
- }
-
- void *tag = I->first;
- Checker *checker = I->second;
-
- for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
- NI != NE; ++NI)
- checker->GR_VisitBind(*CurrSet, *Builder, *this, AssignE, StoreE,
- *NI, tag, location, val, isPrevisit);
-
- // Update which NodeSet is the current one.
- PrevSet = CurrSet;
- }
-
- // Don't autotransition. The CheckerContext objects should do this
- // automatically.
-}
-//===----------------------------------------------------------------------===//
-// Engine construction and deletion.
-//===----------------------------------------------------------------------===//
-
-static void RegisterInternalChecks(GRExprEngine &Eng) {
- // Register internal "built-in" BugTypes with the BugReporter. These BugTypes
- // are different than what probably many checks will do since they don't
- // create BugReports on-the-fly but instead wait until GRExprEngine finishes
- // analyzing a function. Generation of BugReport objects is done via a call
- // to 'FlushReports' from BugReporter.
- // The following checks do not need to have their associated BugTypes
- // explicitly registered with the BugReporter. If they issue any BugReports,
- // their associated BugType will get registered with the BugReporter
- // automatically. Note that the check itself is owned by the GRExprEngine
- // object.
- RegisterAdjustedReturnValueChecker(Eng);
- // CallAndMessageChecker should be registered before AttrNonNullChecker,
- // where we assume arguments are not undefined.
- RegisterCallAndMessageChecker(Eng);
- RegisterAttrNonNullChecker(Eng);
- RegisterDereferenceChecker(Eng);
- RegisterVLASizeChecker(Eng);
- RegisterDivZeroChecker(Eng);
- RegisterIdempotentOperationChecker(Eng);
- RegisterReturnUndefChecker(Eng);
- RegisterUndefinedArraySubscriptChecker(Eng);
- RegisterUndefinedAssignmentChecker(Eng);
- RegisterUndefBranchChecker(Eng);
- RegisterUndefCapturedBlockVarChecker(Eng);
- RegisterUndefResultChecker(Eng);
- RegisterStackAddrLeakChecker(Eng);
-
- // This is not a checker yet.
- RegisterNoReturnFunctionChecker(Eng);
- RegisterBuiltinFunctionChecker(Eng);
- RegisterOSAtomicChecker(Eng);
- RegisterUnixAPIChecker(Eng);
- RegisterMacOSXAPIChecker(Eng);
-}
-
-GRExprEngine::GRExprEngine(AnalysisManager &mgr, GRTransferFuncs *tf)
- : AMgr(mgr),
- CoreEngine(*this),
- G(CoreEngine.getGraph()),
- Builder(NULL),
- StateMgr(getContext(), mgr.getStoreManagerCreator(),
- mgr.getConstraintManagerCreator(), G.getAllocator(),
- *this),
- SymMgr(StateMgr.getSymbolManager()),
- ValMgr(StateMgr.getValueManager()),
- SVator(ValMgr.getSValuator()),
- CurrentStmt(NULL),
- NSExceptionII(NULL), NSExceptionInstanceRaiseSelectors(NULL),
- RaiseSel(GetNullarySelector("raise", getContext())),
- BR(mgr, *this), TF(tf) {
- // Register internal checks.
- RegisterInternalChecks(*this);
-
- // FIXME: Eventually remove the TF object entirely.
- TF->RegisterChecks(*this);
- TF->RegisterPrinters(getStateManager().Printers);
-}
-
-GRExprEngine::~GRExprEngine() {
- BR.FlushReports();
- delete [] NSExceptionInstanceRaiseSelectors;
-
- // Delete the set of checkers.
- for (CheckersOrdered::iterator I=Checkers.begin(), E=Checkers.end(); I!=E;++I)
- delete I->second;
-
- for (CheckersOrderedCache::iterator I=COCache.begin(), E=COCache.end();
- I!=E;++I)
- delete I->second;
-}
-
-//===----------------------------------------------------------------------===//
-// Utility methods.
-//===----------------------------------------------------------------------===//
-
-void GRExprEngine::AddCheck(GRSimpleAPICheck* A, Stmt::StmtClass C) {
- if (!BatchAuditor)
- BatchAuditor.reset(new MappedBatchAuditor(getGraph().getAllocator()));
-
- ((MappedBatchAuditor*) BatchAuditor.get())->AddCheck(A, C);
-}
-
-void GRExprEngine::AddCheck(GRSimpleAPICheck *A) {
- if (!BatchAuditor)
- BatchAuditor.reset(new MappedBatchAuditor(getGraph().getAllocator()));
-
- ((MappedBatchAuditor*) BatchAuditor.get())->AddCheck(A);
-}
-
-const GRState* GRExprEngine::getInitialState(const LocationContext *InitLoc) {
- const GRState *state = StateMgr.getInitialState(InitLoc);
-
- // Preconditions.
-
- // FIXME: It would be nice if we had a more general mechanism to add
- // such preconditions. Some day.
- do {
- const Decl *D = InitLoc->getDecl();
- if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
- // Precondition: the first argument of 'main' is an integer guaranteed
- // to be > 0.
- const IdentifierInfo *II = FD->getIdentifier();
- if (!II || !(II->getName() == "main" && FD->getNumParams() > 0))
- break;
-
- const ParmVarDecl *PD = FD->getParamDecl(0);
- QualType T = PD->getType();
- if (!T->isIntegerType())
- break;
-
- const MemRegion *R = state->getRegion(PD, InitLoc);
- if (!R)
- break;
-
- SVal V = state->getSVal(loc::MemRegionVal(R));
- SVal Constraint_untested = EvalBinOp(state, BinaryOperator::GT, V,
- ValMgr.makeZeroVal(T),
- getContext().IntTy);
-
- DefinedOrUnknownSVal *Constraint =
- dyn_cast<DefinedOrUnknownSVal>(&Constraint_untested);
-
- if (!Constraint)
- break;
-
- if (const GRState *newState = state->Assume(*Constraint, true))
- state = newState;
-
- break;
- }
-
- if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
- // Precondition: 'self' is always non-null upon entry to an Objective-C
- // method.
- const ImplicitParamDecl *SelfD = MD->getSelfDecl();
- const MemRegion *R = state->getRegion(SelfD, InitLoc);
- SVal V = state->getSVal(loc::MemRegionVal(R));
-
- if (const Loc *LV = dyn_cast<Loc>(&V)) {
- // Assume that the pointer value in 'self' is non-null.
- state = state->Assume(*LV, true);
- assert(state && "'self' cannot be null");
- }
- }
- } while (0);
-
- return state;
-}
-
-//===----------------------------------------------------------------------===//
-// Top-level transfer function logic (Dispatcher).
-//===----------------------------------------------------------------------===//
-
-/// EvalAssume - Called by ConstraintManager. Used to call checker-specific
-/// logic for handling assumptions on symbolic values.
-const GRState *GRExprEngine::ProcessAssume(const GRState *state, SVal cond,
- bool assumption) {
- for (CheckersOrdered::iterator I = Checkers.begin(), E = Checkers.end();
- I != E; ++I) {
-
- if (!state)
- return NULL;
-
- state = I->second->EvalAssume(state, cond, assumption);
- }
-
- if (!state)
- return NULL;
-
- return TF->EvalAssume(state, cond, assumption);
-}
-
-void GRExprEngine::ProcessEndWorklist(bool hasWorkRemaining) {
- for (CheckersOrdered::iterator I = Checkers.begin(), E = Checkers.end();
- I != E; ++I) {
- I->second->VisitEndAnalysis(G, BR, hasWorkRemaining);
- }
-}
-
-void GRExprEngine::ProcessStmt(const CFGElement CE,GRStmtNodeBuilder& builder) {
- CurrentStmt = CE.getStmt();
- PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
- CurrentStmt->getLocStart(),
- "Error evaluating statement");
-
- Builder = &builder;
- EntryNode = builder.getBasePredecessor();
-
- // Set up our simple checks.
- if (BatchAuditor)
- Builder->setAuditor(BatchAuditor.get());
-
- // Create the cleaned state.
- const ExplodedNode *BasePred = Builder->getBasePredecessor();
-
- SymbolReaper SymReaper(BasePred->getLocationContext(), CurrentStmt, SymMgr);
-
- CleanedState = AMgr.shouldPurgeDead()
- ? StateMgr.RemoveDeadBindings(EntryNode->getState(),
- BasePred->getLocationContext()->getCurrentStackFrame(),
- SymReaper)
- : EntryNode->getState();
-
- // Process any special transfer function for dead symbols.
- ExplodedNodeSet Tmp;
-
- if (!SymReaper.hasDeadSymbols())
- Tmp.Add(EntryNode);
- else {
- SaveAndRestore<bool> OldSink(Builder->BuildSinks);
- SaveOr OldHasGen(Builder->HasGeneratedNode);
-
- SaveAndRestore<bool> OldPurgeDeadSymbols(Builder->PurgingDeadSymbols);
- Builder->PurgingDeadSymbols = true;
-
- // FIXME: This should soon be removed.
- ExplodedNodeSet Tmp2;
- getTF().EvalDeadSymbols(Tmp2, *this, *Builder, EntryNode,
- CleanedState, SymReaper);
-
- if (Checkers.empty())
- Tmp.insert(Tmp2);
- else {
- ExplodedNodeSet Tmp3;
- ExplodedNodeSet *SrcSet = &Tmp2;
- for (CheckersOrdered::iterator I = Checkers.begin(), E = Checkers.end();
- I != E; ++I) {
- ExplodedNodeSet *DstSet = 0;
- if (I+1 == E)
- DstSet = &Tmp;
- else {
- DstSet = (SrcSet == &Tmp2) ? &Tmp3 : &Tmp2;
- DstSet->clear();
- }
-
- void *tag = I->first;
- Checker *checker = I->second;
- for (ExplodedNodeSet::iterator NI = SrcSet->begin(), NE = SrcSet->end();
- NI != NE; ++NI)
- checker->GR_EvalDeadSymbols(*DstSet, *Builder, *this, CurrentStmt,
- *NI, SymReaper, tag);
- SrcSet = DstSet;
- }
- }
-
- if (!Builder->BuildSinks && !Builder->HasGeneratedNode)
- Tmp.Add(EntryNode);
- }
-
- bool HasAutoGenerated = false;
-
- for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
-
- ExplodedNodeSet Dst;
-
- // Set the cleaned state.
- Builder->SetCleanedState(*I == EntryNode ? CleanedState : GetState(*I));
-
- // Visit the statement.
- if (CE.asLValue())
- VisitLValue(cast<Expr>(CurrentStmt), *I, Dst);
- else
- Visit(CurrentStmt, *I, Dst);
-
- // Do we need to auto-generate a node? We only need to do this to generate
- // a node with a "cleaned" state; GRCoreEngine will actually handle
- // auto-transitions for other cases.
- if (Dst.size() == 1 && *Dst.begin() == EntryNode
- && !Builder->HasGeneratedNode && !HasAutoGenerated) {
- HasAutoGenerated = true;
- builder.generateNode(CurrentStmt, GetState(EntryNode), *I);
- }
- }
-
- // NULL out these variables to cleanup.
- CleanedState = NULL;
- EntryNode = NULL;
-
- CurrentStmt = 0;
-
- Builder = NULL;
-}
-
-void GRExprEngine::Visit(const Stmt* S, ExplodedNode* Pred,
- ExplodedNodeSet& Dst) {
- PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
- S->getLocStart(),
- "Error evaluating statement");
-
- // FIXME: add metadata to the CFG so that we can disable
- // this check when we KNOW that there is no block-level subexpression.
- // The motivation is that this check requires a hashtable lookup.
-
- if (S != CurrentStmt && Pred->getLocationContext()->getCFG()->isBlkExpr(S)) {
- Dst.Add(Pred);
- return;
- }
-
- switch (S->getStmtClass()) {
- // C++ stuff we don't support yet.
- case Stmt::CXXBindReferenceExprClass:
- case Stmt::CXXBindTemporaryExprClass:
- case Stmt::CXXCatchStmtClass:
- case Stmt::CXXConstructExprClass:
- case Stmt::CXXDefaultArgExprClass:
- case Stmt::CXXDependentScopeMemberExprClass:
- case Stmt::CXXExprWithTemporariesClass:
- case Stmt::CXXNullPtrLiteralExprClass:
- case Stmt::CXXPseudoDestructorExprClass:
- case Stmt::CXXTemporaryObjectExprClass:
- case Stmt::CXXThrowExprClass:
- case Stmt::CXXTryStmtClass:
- case Stmt::CXXTypeidExprClass:
- case Stmt::CXXUnresolvedConstructExprClass:
- case Stmt::CXXScalarValueInitExprClass:
- case Stmt::DependentScopeDeclRefExprClass:
- case Stmt::UnaryTypeTraitExprClass:
- case Stmt::UnresolvedLookupExprClass:
- case Stmt::UnresolvedMemberExprClass:
- {
- SaveAndRestore<bool> OldSink(Builder->BuildSinks);
- Builder->BuildSinks = true;
- MakeNode(Dst, S, Pred, GetState(Pred));
- break;
- }
-
- // Cases that should never be evaluated simply because they shouldn't
- // appear in the CFG.
- case Stmt::BreakStmtClass:
- case Stmt::CaseStmtClass:
- case Stmt::CompoundStmtClass:
- case Stmt::ContinueStmtClass:
- case Stmt::DefaultStmtClass:
- case Stmt::DoStmtClass:
- case Stmt::GotoStmtClass:
- case Stmt::IndirectGotoStmtClass:
- case Stmt::LabelStmtClass:
- case Stmt::NoStmtClass:
- case Stmt::NullStmtClass:
- case Stmt::SwitchCaseClass:
- llvm_unreachable("Stmt should not be in analyzer evaluation loop");
- break;
-
- case Stmt::GNUNullExprClass: {
- MakeNode(Dst, S, Pred, GetState(Pred)->BindExpr(S, ValMgr.makeNull()));
- break;
- }
-
- // Cases not handled yet; but will handle some day.
- case Stmt::DesignatedInitExprClass:
- case Stmt::ExtVectorElementExprClass:
- case Stmt::ImaginaryLiteralClass:
- case Stmt::ImplicitValueInitExprClass:
- case Stmt::ObjCAtCatchStmtClass:
- case Stmt::ObjCAtFinallyStmtClass:
- case Stmt::ObjCAtSynchronizedStmtClass:
- case Stmt::ObjCAtTryStmtClass:
- case Stmt::ObjCEncodeExprClass:
- case Stmt::ObjCImplicitSetterGetterRefExprClass:
- case Stmt::ObjCIsaExprClass:
- case Stmt::ObjCPropertyRefExprClass:
- case Stmt::ObjCProtocolExprClass:
- case Stmt::ObjCSelectorExprClass:
- case Stmt::ObjCStringLiteralClass:
- case Stmt::ObjCSuperExprClass:
- case Stmt::ParenListExprClass:
- case Stmt::PredefinedExprClass:
- case Stmt::ShuffleVectorExprClass:
- case Stmt::TypesCompatibleExprClass:
- case Stmt::VAArgExprClass:
- // Fall through.
-
- // Cases we intentionally don't evaluate, since they don't need
- // to be explicitly evaluated.
- case Stmt::AddrLabelExprClass:
- case Stmt::IntegerLiteralClass:
- case Stmt::CharacterLiteralClass:
- case Stmt::CXXBoolLiteralExprClass:
- case Stmt::FloatingLiteralClass:
- Dst.Add(Pred); // No-op. Simply propagate the current state unchanged.
- break;
-
- case Stmt::ArraySubscriptExprClass:
- VisitArraySubscriptExpr(cast<ArraySubscriptExpr>(S), Pred, Dst, false);
- break;
-
- case Stmt::AsmStmtClass:
- VisitAsmStmt(cast<AsmStmt>(S), Pred, Dst);
- break;
-
- case Stmt::BlockDeclRefExprClass:
- VisitBlockDeclRefExpr(cast<BlockDeclRefExpr>(S), Pred, Dst, false);
- break;
-
- case Stmt::BlockExprClass:
- VisitBlockExpr(cast<BlockExpr>(S), Pred, Dst);
- break;
-
- case Stmt::BinaryOperatorClass: {
- const BinaryOperator* B = cast<BinaryOperator>(S);
-
- if (B->isLogicalOp()) {
- VisitLogicalExpr(B, Pred, Dst);
- break;
- }
- else if (B->getOpcode() == BinaryOperator::Comma) {
- const GRState* state = GetState(Pred);
- MakeNode(Dst, B, Pred, state->BindExpr(B, state->getSVal(B->getRHS())));
- break;
- }
-
- if (AMgr.shouldEagerlyAssume() &&
- (B->isRelationalOp() || B->isEqualityOp())) {
- ExplodedNodeSet Tmp;
- VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Tmp, false);
- EvalEagerlyAssume(Dst, Tmp, cast<Expr>(S));
- }
- else
- VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst, false);
-
- break;
- }
-
- case Stmt::CallExprClass:
- case Stmt::CXXOperatorCallExprClass: {
- const CallExpr* C = cast<CallExpr>(S);
- VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst, false);
- break;
- }
-
- case Stmt::CXXMemberCallExprClass: {
- const CXXMemberCallExpr *MCE = cast<CXXMemberCallExpr>(S);
- VisitCXXMemberCallExpr(MCE, Pred, Dst);
- break;
- }
-
- case Stmt::CXXNewExprClass: {
- const CXXNewExpr *NE = cast<CXXNewExpr>(S);
- VisitCXXNewExpr(NE, Pred, Dst);
- break;
- }
-
- case Stmt::CXXDeleteExprClass: {
- const CXXDeleteExpr *CDE = cast<CXXDeleteExpr>(S);
- VisitCXXDeleteExpr(CDE, Pred, Dst);
- break;
- }
- // FIXME: ChooseExpr is really a constant. We need to fix
- // the CFG do not model them as explicit control-flow.
-
- case Stmt::ChooseExprClass: { // __builtin_choose_expr
- const ChooseExpr* C = cast<ChooseExpr>(S);
- VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
- break;
- }
-
- case Stmt::CompoundAssignOperatorClass:
- VisitBinaryOperator(cast<BinaryOperator>(S), Pred, Dst, false);
- break;
-
- case Stmt::CompoundLiteralExprClass:
- VisitCompoundLiteralExpr(cast<CompoundLiteralExpr>(S), Pred, Dst, false);
- break;
-
- case Stmt::ConditionalOperatorClass: { // '?' operator
- const ConditionalOperator* C = cast<ConditionalOperator>(S);
- VisitGuardedExpr(C, C->getLHS(), C->getRHS(), Pred, Dst);
- break;
- }
-
- case Stmt::CXXThisExprClass:
- VisitCXXThisExpr(cast<CXXThisExpr>(S), Pred, Dst);
- break;
-
- case Stmt::DeclRefExprClass:
- VisitDeclRefExpr(cast<DeclRefExpr>(S), Pred, Dst, false);
- break;
-
- case Stmt::DeclStmtClass:
- VisitDeclStmt(cast<DeclStmt>(S), Pred, Dst);
- break;
-
- case Stmt::ForStmtClass:
- // This case isn't for branch processing, but for handling the
- // initialization of a condition variable.
- VisitCondInit(cast<ForStmt>(S)->getConditionVariable(), S, Pred, Dst);
- break;
-
- case Stmt::ImplicitCastExprClass:
- case Stmt::CStyleCastExprClass:
- case Stmt::CXXStaticCastExprClass:
- case Stmt::CXXDynamicCastExprClass:
- case Stmt::CXXReinterpretCastExprClass:
- case Stmt::CXXConstCastExprClass:
- case Stmt::CXXFunctionalCastExprClass: {
- const CastExpr* C = cast<CastExpr>(S);
- VisitCast(C, C->getSubExpr(), Pred, Dst, false);
- break;
- }
-
- case Stmt::IfStmtClass:
- // This case isn't for branch processing, but for handling the
- // initialization of a condition variable.
- VisitCondInit(cast<IfStmt>(S)->getConditionVariable(), S, Pred, Dst);
- break;
-
- case Stmt::InitListExprClass:
- VisitInitListExpr(cast<InitListExpr>(S), Pred, Dst);
- break;
-
- case Stmt::MemberExprClass:
- VisitMemberExpr(cast<MemberExpr>(S), Pred, Dst, false);
- break;
-
- case Stmt::ObjCIvarRefExprClass:
- VisitObjCIvarRefExpr(cast<ObjCIvarRefExpr>(S), Pred, Dst, false);
- break;
-
- case Stmt::ObjCForCollectionStmtClass:
- VisitObjCForCollectionStmt(cast<ObjCForCollectionStmt>(S), Pred, Dst);
- break;
-
- case Stmt::ObjCMessageExprClass:
- VisitObjCMessageExpr(cast<ObjCMessageExpr>(S), Pred, Dst, false);
- break;
-
- case Stmt::ObjCAtThrowStmtClass: {
- // FIXME: This is not complete. We basically treat @throw as
- // an abort.
- SaveAndRestore<bool> OldSink(Builder->BuildSinks);
- Builder->BuildSinks = true;
- MakeNode(Dst, S, Pred, GetState(Pred));
- break;
- }
-
- case Stmt::ParenExprClass:
- Visit(cast<ParenExpr>(S)->getSubExpr()->IgnoreParens(), Pred, Dst);
- break;
-
- case Stmt::ReturnStmtClass:
- VisitReturnStmt(cast<ReturnStmt>(S), Pred, Dst);
- break;
-
- case Stmt::OffsetOfExprClass:
- VisitOffsetOfExpr(cast<OffsetOfExpr>(S), Pred, Dst);
- break;
-
- case Stmt::SizeOfAlignOfExprClass:
- VisitSizeOfAlignOfExpr(cast<SizeOfAlignOfExpr>(S), Pred, Dst);
- break;
-
- case Stmt::StmtExprClass: {
- const StmtExpr* SE = cast<StmtExpr>(S);
-
- if (SE->getSubStmt()->body_empty()) {
- // Empty statement expression.
- assert(SE->getType() == getContext().VoidTy
- && "Empty statement expression must have void type.");
- Dst.Add(Pred);
- break;
- }
-
- if (Expr* LastExpr = dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) {
- const GRState* state = GetState(Pred);
- MakeNode(Dst, SE, Pred, state->BindExpr(SE, state->getSVal(LastExpr)));
- }
- else
- Dst.Add(Pred);
-
- break;
- }
-
- case Stmt::StringLiteralClass:
- VisitLValue(cast<StringLiteral>(S), Pred, Dst);
- break;
-
- case Stmt::SwitchStmtClass:
- // This case isn't for branch processing, but for handling the
- // initialization of a condition variable.
- VisitCondInit(cast<SwitchStmt>(S)->getConditionVariable(), S, Pred, Dst);
- break;
-
- case Stmt::UnaryOperatorClass: {
- const UnaryOperator *U = cast<UnaryOperator>(S);
- if (AMgr.shouldEagerlyAssume()&&(U->getOpcode() == UnaryOperator::LNot)) {
- ExplodedNodeSet Tmp;
- VisitUnaryOperator(U, Pred, Tmp, false);
- EvalEagerlyAssume(Dst, Tmp, U);
- }
- else
- VisitUnaryOperator(U, Pred, Dst, false);
- break;
- }
-
- case Stmt::WhileStmtClass:
- // This case isn't for branch processing, but for handling the
- // initialization of a condition variable.
- VisitCondInit(cast<WhileStmt>(S)->getConditionVariable(), S, Pred, Dst);
- break;
- }
-}
-
-void GRExprEngine::VisitLValue(const Expr* Ex, ExplodedNode* Pred,
- ExplodedNodeSet& Dst) {
-
- PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
- Ex->getLocStart(),
- "Error evaluating statement");
-
-
- Ex = Ex->IgnoreParens();
-
- if (Ex != CurrentStmt && Pred->getLocationContext()->getCFG()->isBlkExpr(Ex)){
- Dst.Add(Pred);
- return;
- }
-
- switch (Ex->getStmtClass()) {
- // C++ stuff we don't support yet.
- case Stmt::CXXExprWithTemporariesClass:
- case Stmt::CXXMemberCallExprClass:
- case Stmt::CXXScalarValueInitExprClass: {
- SaveAndRestore<bool> OldSink(Builder->BuildSinks);
- Builder->BuildSinks = true;
- MakeNode(Dst, Ex, Pred, GetState(Pred));
- break;
- }
-
- case Stmt::ArraySubscriptExprClass:
- VisitArraySubscriptExpr(cast<ArraySubscriptExpr>(Ex), Pred, Dst, true);
- return;
-
- case Stmt::BinaryOperatorClass:
- case Stmt::CompoundAssignOperatorClass:
- VisitBinaryOperator(cast<BinaryOperator>(Ex), Pred, Dst, true);
- return;
-
- case Stmt::BlockDeclRefExprClass:
- VisitBlockDeclRefExpr(cast<BlockDeclRefExpr>(Ex), Pred, Dst, true);
- return;
-
- case Stmt::CallExprClass:
- case Stmt::CXXOperatorCallExprClass: {
- const CallExpr *C = cast<CallExpr>(Ex);
- assert(CalleeReturnsReferenceOrRecord(C));
- VisitCall(C, Pred, C->arg_begin(), C->arg_end(), Dst, true);
- break;
- }
-
- case Stmt::CompoundLiteralExprClass:
- VisitCompoundLiteralExpr(cast<CompoundLiteralExpr>(Ex), Pred, Dst, true);
- return;
-
- case Stmt::DeclRefExprClass:
- VisitDeclRefExpr(cast<DeclRefExpr>(Ex), Pred, Dst, true);
- return;
-
- case Stmt::ImplicitCastExprClass:
- case Stmt::CStyleCastExprClass: {
- const CastExpr *C = cast<CastExpr>(Ex);
- QualType T = Ex->getType();
- VisitCast(C, C->getSubExpr(), Pred, Dst, true);
- break;
- }
-
- case Stmt::MemberExprClass:
- VisitMemberExpr(cast<MemberExpr>(Ex), Pred, Dst, true);
- return;
-
- case Stmt::ObjCIvarRefExprClass:
- VisitObjCIvarRefExpr(cast<ObjCIvarRefExpr>(Ex), Pred, Dst, true);
- return;
-
- case Stmt::ObjCMessageExprClass: {
- const ObjCMessageExpr *ME = cast<ObjCMessageExpr>(Ex);
- assert(ReceiverReturnsReferenceOrRecord(ME));
- VisitObjCMessageExpr(ME, Pred, Dst, true);
- return;
- }
-
- case Stmt::ObjCIsaExprClass:
- // FIXME: Do something more intelligent with 'x->isa = ...'.
- // For now, just ignore the assignment.
- return;
-
- case Stmt::ObjCPropertyRefExprClass:
- case Stmt::ObjCImplicitSetterGetterRefExprClass:
- // FIXME: Property assignments are lvalues, but not really "locations".
- // e.g.: self.x = something;
- // Here the "self.x" really can translate to a method call (setter) when
- // the assignment is made. Moreover, the entire assignment expression
- // evaluate to whatever "something" is, not calling the "getter" for
- // the property (which would make sense since it can have side effects).
- // We'll probably treat this as a location, but not one that we can
- // take the address of. Perhaps we need a new SVal class for cases
- // like thsis?
- // Note that we have a similar problem for bitfields, since they don't
- // have "locations" in the sense that we can take their address.
- Dst.Add(Pred);
- return;
-
- case Stmt::StringLiteralClass: {
- const GRState* state = GetState(Pred);
- SVal V = state->getLValue(cast<StringLiteral>(Ex));
- MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, V));
- return;
- }
-
- case Stmt::UnaryOperatorClass:
- VisitUnaryOperator(cast<UnaryOperator>(Ex), Pred, Dst, true);
- return;
-
- // In C++, binding an rvalue to a reference requires to create an object.
- case Stmt::CXXBoolLiteralExprClass:
- case Stmt::IntegerLiteralClass:
- case Stmt::CharacterLiteralClass:
- case Stmt::FloatingLiteralClass:
- case Stmt::ImaginaryLiteralClass:
- CreateCXXTemporaryObject(Ex, Pred, Dst);
- return;
-
- default: {
- // Arbitrary subexpressions can return aggregate temporaries that
- // can be used in a lvalue context. We need to enhance our support
- // of such temporaries in both the environment and the store, so right
- // now we just do a regular visit.
-
- // NOTE: Do not use 'isAggregateType()' here as CXXRecordDecls that
- // are non-pod are not aggregates.
- assert ((isa<RecordType>(Ex->getType().getDesugaredType()) ||
- isa<ArrayType>(Ex->getType().getDesugaredType())) &&
- "Other kinds of expressions with non-aggregate/union/class types"
- " do not have lvalues.");
-
- Visit(Ex, Pred, Dst);
- }
- }
-}
-
-//===----------------------------------------------------------------------===//
-// Block entrance. (Update counters).
-//===----------------------------------------------------------------------===//
-
-bool GRExprEngine::ProcessBlockEntrance(const CFGBlock* B,
- const ExplodedNode *Pred,
- GRBlockCounter BC) {
- return BC.getNumVisited(Pred->getLocationContext()->getCurrentStackFrame(),
- B->getBlockID()) < AMgr.getMaxLoop();
-}
-
-//===----------------------------------------------------------------------===//
-// Generic node creation.
-//===----------------------------------------------------------------------===//
-
-ExplodedNode* GRExprEngine::MakeNode(ExplodedNodeSet& Dst, const Stmt* S,
- ExplodedNode* Pred, const GRState* St,
- ProgramPoint::Kind K, const void *tag) {
- assert (Builder && "GRStmtNodeBuilder not present.");
- SaveAndRestore<const void*> OldTag(Builder->Tag);
- Builder->Tag = tag;
- return Builder->MakeNode(Dst, S, Pred, St, K);
-}
-
-//===----------------------------------------------------------------------===//
-// Branch processing.
-//===----------------------------------------------------------------------===//
-
-const GRState* GRExprEngine::MarkBranch(const GRState* state,
- const Stmt* Terminator,
- bool branchTaken) {
-
- switch (Terminator->getStmtClass()) {
- default:
- return state;
-
- case Stmt::BinaryOperatorClass: { // '&&' and '||'
-
- const BinaryOperator* B = cast<BinaryOperator>(Terminator);
- BinaryOperator::Opcode Op = B->getOpcode();
-
- assert (Op == BinaryOperator::LAnd || Op == BinaryOperator::LOr);
-
- // For &&, if we take the true branch, then the value of the whole
- // expression is that of the RHS expression.
- //
- // For ||, if we take the false branch, then the value of the whole
- // expression is that of the RHS expression.
-
- const Expr* Ex = (Op == BinaryOperator::LAnd && branchTaken) ||
- (Op == BinaryOperator::LOr && !branchTaken)
- ? B->getRHS() : B->getLHS();
-
- return state->BindExpr(B, UndefinedVal(Ex));
- }
-
- case Stmt::ConditionalOperatorClass: { // ?:
-
- const ConditionalOperator* C = cast<ConditionalOperator>(Terminator);
-
- // For ?, if branchTaken == true then the value is either the LHS or
- // the condition itself. (GNU extension).
-
- const Expr* Ex;
-
- if (branchTaken)
- Ex = C->getLHS() ? C->getLHS() : C->getCond();
- else
- Ex = C->getRHS();
-
- return state->BindExpr(C, UndefinedVal(Ex));
- }
-
- case Stmt::ChooseExprClass: { // ?:
-
- const ChooseExpr* C = cast<ChooseExpr>(Terminator);
-
- const Expr* Ex = branchTaken ? C->getLHS() : C->getRHS();
- return state->BindExpr(C, UndefinedVal(Ex));
- }
- }
-}
-
-/// RecoverCastedSymbol - A helper function for ProcessBranch that is used
-/// to try to recover some path-sensitivity for casts of symbolic
-/// integers that promote their values (which are currently not tracked well).
-/// This function returns the SVal bound to Condition->IgnoreCasts if all the
-// cast(s) did was sign-extend the original value.
-static SVal RecoverCastedSymbol(GRStateManager& StateMgr, const GRState* state,
- const Stmt* Condition, ASTContext& Ctx) {
-
- const Expr *Ex = dyn_cast<Expr>(Condition);
- if (!Ex)
- return UnknownVal();
-
- uint64_t bits = 0;
- bool bitsInit = false;
-
- while (const CastExpr *CE = dyn_cast<CastExpr>(Ex)) {
- QualType T = CE->getType();
-
- if (!T->isIntegerType())
- return UnknownVal();
-
- uint64_t newBits = Ctx.getTypeSize(T);
- if (!bitsInit || newBits < bits) {
- bitsInit = true;
- bits = newBits;
- }
-
- Ex = CE->getSubExpr();
- }
-
- // We reached a non-cast. Is it a symbolic value?
- QualType T = Ex->getType();
-
- if (!bitsInit || !T->isIntegerType() || Ctx.getTypeSize(T) > bits)
- return UnknownVal();
-
- return state->getSVal(Ex);
-}
-
-void GRExprEngine::ProcessBranch(const Stmt* Condition, const Stmt* Term,
- GRBranchNodeBuilder& builder) {
-
- // Check for NULL conditions; e.g. "for(;;)"
- if (!Condition) {
- builder.markInfeasible(false);
- return;
- }
-
- PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
- Condition->getLocStart(),
- "Error evaluating branch");
-
- for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end();I!=E;++I) {
- void *tag = I->first;
- Checker *checker = I->second;
- checker->VisitBranchCondition(builder, *this, Condition, tag);
- }
-
- // If the branch condition is undefined, return;
- if (!builder.isFeasible(true) && !builder.isFeasible(false))
- return;
-
- const GRState* PrevState = builder.getState();
- SVal X = PrevState->getSVal(Condition);
-
- if (X.isUnknown()) {
- // Give it a chance to recover from unknown.
- if (const Expr *Ex = dyn_cast<Expr>(Condition)) {
- if (Ex->getType()->isIntegerType()) {
- // Try to recover some path-sensitivity. Right now casts of symbolic
- // integers that promote their values are currently not tracked well.
- // If 'Condition' is such an expression, try and recover the
- // underlying value and use that instead.
- SVal recovered = RecoverCastedSymbol(getStateManager(),
- builder.getState(), Condition,
- getContext());
-
- if (!recovered.isUnknown()) {
- X = recovered;
- }
- }
- }
- // If the condition is still unknown, give up.
- if (X.isUnknown()) {
- builder.generateNode(MarkBranch(PrevState, Term, true), true);
- builder.generateNode(MarkBranch(PrevState, Term, false), false);
- return;
- }
- }
-
- DefinedSVal V = cast<DefinedSVal>(X);
-
- // Process the true branch.
- if (builder.isFeasible(true)) {
- if (const GRState *state = PrevState->Assume(V, true))
- builder.generateNode(MarkBranch(state, Term, true), true);
- else
- builder.markInfeasible(true);
- }
-
- // Process the false branch.
- if (builder.isFeasible(false)) {
- if (const GRState *state = PrevState->Assume(V, false))
- builder.generateNode(MarkBranch(state, Term, false), false);
- else
- builder.markInfeasible(false);
- }
-}
-
-/// ProcessIndirectGoto - Called by GRCoreEngine. Used to generate successor
-/// nodes by processing the 'effects' of a computed goto jump.
-void GRExprEngine::ProcessIndirectGoto(GRIndirectGotoNodeBuilder& builder) {
-
- const GRState *state = builder.getState();
- SVal V = state->getSVal(builder.getTarget());
-
- // Three possibilities:
- //
- // (1) We know the computed label.
- // (2) The label is NULL (or some other constant), or Undefined.
- // (3) We have no clue about the label. Dispatch to all targets.
- //
-
- typedef GRIndirectGotoNodeBuilder::iterator iterator;
-
- if (isa<loc::GotoLabel>(V)) {
- const LabelStmt* L = cast<loc::GotoLabel>(V).getLabel();
-
- for (iterator I=builder.begin(), E=builder.end(); I != E; ++I) {
- if (I.getLabel() == L) {
- builder.generateNode(I, state);
- return;
- }
- }
-
- assert (false && "No block with label.");
- return;
- }
-
- if (isa<loc::ConcreteInt>(V) || isa<UndefinedVal>(V)) {
- // Dispatch to the first target and mark it as a sink.
- //ExplodedNode* N = builder.generateNode(builder.begin(), state, true);
- // FIXME: add checker visit.
- // UndefBranches.insert(N);
- return;
- }
-
- // This is really a catch-all. We don't support symbolics yet.
- // FIXME: Implement dispatch for symbolic pointers.
-
- for (iterator I=builder.begin(), E=builder.end(); I != E; ++I)
- builder.generateNode(I, state);
-}
-
-
-void GRExprEngine::VisitGuardedExpr(const Expr* Ex, const Expr* L,
- const Expr* R,
- ExplodedNode* Pred, ExplodedNodeSet& Dst) {
-
- assert(Ex == CurrentStmt &&
- Pred->getLocationContext()->getCFG()->isBlkExpr(Ex));
-
- const GRState* state = GetState(Pred);
- SVal X = state->getSVal(Ex);
-
- assert (X.isUndef());
-
- const Expr *SE = (Expr*) cast<UndefinedVal>(X).getData();
- assert(SE);
- X = state->getSVal(SE);
-
- // Make sure that we invalidate the previous binding.
- MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, X, true));
-}
-
-/// ProcessEndPath - Called by GRCoreEngine. Used to generate end-of-path
-/// nodes when the control reaches the end of a function.
-void GRExprEngine::ProcessEndPath(GREndPathNodeBuilder& builder) {
- getTF().EvalEndPath(*this, builder);
- StateMgr.EndPath(builder.getState());
- for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E;++I){
- void *tag = I->first;
- Checker *checker = I->second;
- checker->EvalEndPath(builder, tag, *this);
- }
-}
-
-/// ProcessSwitch - Called by GRCoreEngine. Used to generate successor
-/// nodes by processing the 'effects' of a switch statement.
-void GRExprEngine::ProcessSwitch(GRSwitchNodeBuilder& builder) {
- typedef GRSwitchNodeBuilder::iterator iterator;
- const GRState* state = builder.getState();
- const Expr* CondE = builder.getCondition();
- SVal CondV_untested = state->getSVal(CondE);
-
- if (CondV_untested.isUndef()) {
- //ExplodedNode* N = builder.generateDefaultCaseNode(state, true);
- // FIXME: add checker
- //UndefBranches.insert(N);
-
- return;
- }
- DefinedOrUnknownSVal CondV = cast<DefinedOrUnknownSVal>(CondV_untested);
-
- const GRState *DefaultSt = state;
- bool defaultIsFeasible = false;
-
- for (iterator I = builder.begin(), EI = builder.end(); I != EI; ++I) {
- const CaseStmt* Case = cast<CaseStmt>(I.getCase());
-
- // Evaluate the LHS of the case value.
- Expr::EvalResult V1;
- bool b = Case->getLHS()->Evaluate(V1, getContext());
-
- // Sanity checks. These go away in Release builds.
- assert(b && V1.Val.isInt() && !V1.HasSideEffects
- && "Case condition must evaluate to an integer constant.");
- b = b; // silence unused variable warning
- assert(V1.Val.getInt().getBitWidth() ==
- getContext().getTypeSize(CondE->getType()));
-
- // Get the RHS of the case, if it exists.
- Expr::EvalResult V2;
-
- if (const Expr* E = Case->getRHS()) {
- b = E->Evaluate(V2, getContext());
- assert(b && V2.Val.isInt() && !V2.HasSideEffects
- && "Case condition must evaluate to an integer constant.");
- b = b; // silence unused variable warning
- }
- else
- V2 = V1;
-
- // FIXME: Eventually we should replace the logic below with a range
- // comparison, rather than concretize the values within the range.
- // This should be easy once we have "ranges" for NonLVals.
-
- do {
- nonloc::ConcreteInt CaseVal(getBasicVals().getValue(V1.Val.getInt()));
- DefinedOrUnknownSVal Res = SVator.EvalEQ(DefaultSt ? DefaultSt : state,
- CondV, CaseVal);
-
- // Now "assume" that the case matches.
- if (const GRState* stateNew = state->Assume(Res, true)) {
- builder.generateCaseStmtNode(I, stateNew);
-
- // If CondV evaluates to a constant, then we know that this
- // is the *only* case that we can take, so stop evaluating the
- // others.
- if (isa<nonloc::ConcreteInt>(CondV))
- return;
- }
-
- // Now "assume" that the case doesn't match. Add this state
- // to the default state (if it is feasible).
- if (DefaultSt) {
- if (const GRState *stateNew = DefaultSt->Assume(Res, false)) {
- defaultIsFeasible = true;
- DefaultSt = stateNew;
- }
- else {
- defaultIsFeasible = false;
- DefaultSt = NULL;
- }
- }
-
- // Concretize the next value in the range.
- if (V1.Val.getInt() == V2.Val.getInt())
- break;
-
- ++V1.Val.getInt();
- assert (V1.Val.getInt() <= V2.Val.getInt());
-
- } while (true);
- }
-
- // If we reach here, than we know that the default branch is
- // possible.
- if (defaultIsFeasible) builder.generateDefaultCaseNode(DefaultSt);
-}
-
-void GRExprEngine::ProcessCallEnter(GRCallEnterNodeBuilder &B) {
- const StackFrameContext *LocCtx
- = AMgr.getStackFrame(B.getCalleeContext(),
- B.getLocationContext(),
- B.getCallExpr(),
- B.getBlock(),
- B.getIndex());
-
- const GRState *state = B.getState();
- state = getStoreManager().EnterStackFrame(state, LocCtx);
-
- B.GenerateNode(state, LocCtx);
-}
-
-void GRExprEngine::ProcessCallExit(GRCallExitNodeBuilder &B) {
- const GRState *state = B.getState();
- const ExplodedNode *Pred = B.getPredecessor();
- const StackFrameContext *LocCtx =
- cast<StackFrameContext>(Pred->getLocationContext());
- const Stmt *CE = LocCtx->getCallSite();
-
- // If the callee returns an expression, bind its value to CallExpr.
- const Stmt *ReturnedExpr = state->get<ReturnExpr>();
- if (ReturnedExpr) {
- SVal RetVal = state->getSVal(ReturnedExpr);
- state = state->BindExpr(CE, RetVal);
- // Clear the return expr GDM.
- state = state->remove<ReturnExpr>();
- }
-
- // Bind the constructed object value to CXXConstructExpr.
- if (const CXXConstructExpr *CCE = dyn_cast<CXXConstructExpr>(CE)) {
- const CXXThisRegion *ThisR = getCXXThisRegion(CCE->getConstructor(),LocCtx);
- // We might not have 'this' region in the binding if we didn't inline
- // the ctor call.
- SVal ThisV = state->getSVal(ThisR);
- loc::MemRegionVal *V = dyn_cast<loc::MemRegionVal>(&ThisV);
- if (V) {
- SVal ObjVal = state->getSVal(V->getRegion());
- assert(isa<nonloc::LazyCompoundVal>(ObjVal));
- state = state->BindExpr(CCE, ObjVal);
- }
- }
-
- B.GenerateNode(state);
-}
-
-//===----------------------------------------------------------------------===//
-// Transfer functions: logical operations ('&&', '||').
-//===----------------------------------------------------------------------===//
-
-void GRExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode* Pred,
- ExplodedNodeSet& Dst) {
-
- assert(B->getOpcode() == BinaryOperator::LAnd ||
- B->getOpcode() == BinaryOperator::LOr);
-
- assert(B==CurrentStmt && Pred->getLocationContext()->getCFG()->isBlkExpr(B));
-
- const GRState* state = GetState(Pred);
- SVal X = state->getSVal(B);
- assert(X.isUndef());
-
- const Expr *Ex = (const Expr*) cast<UndefinedVal>(X).getData();
- assert(Ex);
-
- if (Ex == B->getRHS()) {
- X = state->getSVal(Ex);
-
- // Handle undefined values.
- if (X.isUndef()) {
- MakeNode(Dst, B, Pred, state->BindExpr(B, X));
- return;
- }
-
- DefinedOrUnknownSVal XD = cast<DefinedOrUnknownSVal>(X);
-
- // We took the RHS. Because the value of the '&&' or '||' expression must
- // evaluate to 0 or 1, we must assume the value of the RHS evaluates to 0
- // or 1. Alternatively, we could take a lazy approach, and calculate this
- // value later when necessary. We don't have the machinery in place for
- // this right now, and since most logical expressions are used for branches,
- // the payoff is not likely to be large. Instead, we do eager evaluation.
- if (const GRState *newState = state->Assume(XD, true))
- MakeNode(Dst, B, Pred,
- newState->BindExpr(B, ValMgr.makeIntVal(1U, B->getType())));
-
- if (const GRState *newState = state->Assume(XD, false))
- MakeNode(Dst, B, Pred,
- newState->BindExpr(B, ValMgr.makeIntVal(0U, B->getType())));
- }
- else {
- // We took the LHS expression. Depending on whether we are '&&' or
- // '||' we know what the value of the expression is via properties of
- // the short-circuiting.
- X = ValMgr.makeIntVal(B->getOpcode() == BinaryOperator::LAnd ? 0U : 1U,
- B->getType());
- MakeNode(Dst, B, Pred, state->BindExpr(B, X));
- }
-}
-
-//===----------------------------------------------------------------------===//
-// Transfer functions: Loads and stores.
-//===----------------------------------------------------------------------===//
-
-void GRExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred,
- ExplodedNodeSet &Dst) {
-
- ExplodedNodeSet Tmp;
-
- CanQualType T = getContext().getCanonicalType(BE->getType());
- SVal V = ValMgr.getBlockPointer(BE->getBlockDecl(), T,
- Pred->getLocationContext());
-
- MakeNode(Tmp, BE, Pred, GetState(Pred)->BindExpr(BE, V),
- ProgramPoint::PostLValueKind);
-
- // Post-visit the BlockExpr.
- CheckerVisit(BE, Dst, Tmp, false);
-}
-
-void GRExprEngine::VisitDeclRefExpr(const DeclRefExpr *Ex, ExplodedNode *Pred,
- ExplodedNodeSet &Dst, bool asLValue) {
- VisitCommonDeclRefExpr(Ex, Ex->getDecl(), Pred, Dst, asLValue);
-}
-
-void GRExprEngine::VisitBlockDeclRefExpr(const BlockDeclRefExpr *Ex,
- ExplodedNode *Pred,
- ExplodedNodeSet &Dst, bool asLValue) {
- VisitCommonDeclRefExpr(Ex, Ex->getDecl(), Pred, Dst, asLValue);
-}
-
-void GRExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D,
- ExplodedNode *Pred,
- ExplodedNodeSet &Dst, bool asLValue) {
-
- const GRState *state = GetState(Pred);
-
- if (const VarDecl* VD = dyn_cast<VarDecl>(D)) {
-
- SVal V = state->getLValue(VD, Pred->getLocationContext());
-
- if (asLValue) {
- // For references, the 'lvalue' is the pointer address stored in the
- // reference region.
- if (VD->getType()->isReferenceType()) {
- if (const MemRegion *R = V.getAsRegion())
- V = state->getSVal(R);
- else
- V = UnknownVal();
- }
-
- MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, V),
- ProgramPoint::PostLValueKind);
- }
- else
- EvalLoad(Dst, Ex, Pred, state, V);
-
- return;
- } else if (const EnumConstantDecl* ED = dyn_cast<EnumConstantDecl>(D)) {
- assert(!asLValue && "EnumConstantDecl does not have lvalue.");
-
- SVal V = ValMgr.makeIntVal(ED->getInitVal());
- MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, V));
- return;
-
- } else if (const FunctionDecl* FD = dyn_cast<FunctionDecl>(D)) {
- // This code is valid regardless of the value of 'isLValue'.
- SVal V = ValMgr.getFunctionPointer(FD);
- MakeNode(Dst, Ex, Pred, state->BindExpr(Ex, V),
- ProgramPoint::PostLValueKind);
- return;
- }
-
- assert (false &&
- "ValueDecl support for this ValueDecl not implemented.");
-}
-
-/// VisitArraySubscriptExpr - Transfer function for array accesses
-void GRExprEngine::VisitArraySubscriptExpr(const ArraySubscriptExpr* A,
- ExplodedNode* Pred,
- ExplodedNodeSet& Dst, bool asLValue){
-
- const Expr* Base = A->getBase()->IgnoreParens();
- const Expr* Idx = A->getIdx()->IgnoreParens();
- ExplodedNodeSet Tmp;
-
- if (Base->getType()->isVectorType()) {
- // For vector types get its lvalue.
- // FIXME: This may not be correct. Is the rvalue of a vector its location?
- // In fact, I think this is just a hack. We need to get the right
- // semantics.
- VisitLValue(Base, Pred, Tmp);
- }
- else
- Visit(Base, Pred, Tmp); // Get Base's rvalue, which should be an LocVal.
-
- for (ExplodedNodeSet::iterator I1=Tmp.begin(), E1=Tmp.end(); I1!=E1; ++I1) {
- ExplodedNodeSet Tmp2;
- Visit(Idx, *I1, Tmp2); // Evaluate the index.
-
- ExplodedNodeSet Tmp3;
- CheckerVisit(A, Tmp3, Tmp2, true);
-
- for (ExplodedNodeSet::iterator I2=Tmp3.begin(),E2=Tmp3.end();I2!=E2; ++I2) {
- const GRState* state = GetState(*I2);
- SVal V = state->getLValue(A->getType(), state->getSVal(Idx),
- state->getSVal(Base));
-
- if (asLValue)
- MakeNode(Dst, A, *I2, state->BindExpr(A, V),
- ProgramPoint::PostLValueKind);
- else
- EvalLoad(Dst, A, *I2, state, V);
- }
- }
-}
-
-/// VisitMemberExpr - Transfer function for member expressions.
-void GRExprEngine::VisitMemberExpr(const MemberExpr* M, ExplodedNode* Pred,
- ExplodedNodeSet& Dst, bool asLValue) {
-
- Expr* Base = M->getBase()->IgnoreParens();
- ExplodedNodeSet Tmp;
-
- if (M->isArrow())
- Visit(Base, Pred, Tmp); // p->f = ... or ... = p->f
- else
- VisitLValue(Base, Pred, Tmp); // x.f = ... or ... = x.f
-
- FieldDecl *Field = dyn_cast<FieldDecl>(M->getMemberDecl());
- if (!Field) // FIXME: skipping member expressions for non-fields
- return;
-
- for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I != E; ++I) {
- const GRState* state = GetState(*I);
- // FIXME: Should we insert some assumption logic in here to determine
- // if "Base" is a valid piece of memory? Before we put this assumption
- // later when using FieldOffset lvals (which we no longer have).
- SVal L = state->getLValue(Field, state->getSVal(Base));
-
- if (asLValue)
- MakeNode(Dst, M, *I, state->BindExpr(M, L), ProgramPoint::PostLValueKind);
- else
- EvalLoad(Dst, M, *I, state, L);
- }
-}
-
-/// EvalBind - Handle the semantics of binding a value to a specific location.
-/// This method is used by EvalStore and (soon) VisitDeclStmt, and others.
-void GRExprEngine::EvalBind(ExplodedNodeSet& Dst, const Stmt *AssignE,
- const Stmt* StoreE, ExplodedNode* Pred,
- const GRState* state, SVal location, SVal Val,
- bool atDeclInit) {
-
-
- // Do a previsit of the bind.
- ExplodedNodeSet CheckedSet, Src;
- Src.Add(Pred);
- CheckerVisitBind(AssignE, StoreE, CheckedSet, Src, location, Val, true);
-
- for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
- I!=E; ++I) {
-
- if (Pred != *I)
- state = GetState(*I);
-
- const GRState* newState = 0;
-
- if (atDeclInit) {
- const VarRegion *VR =
- cast<VarRegion>(cast<loc::MemRegionVal>(location).getRegion());
-
- newState = state->bindDecl(VR, Val);
- }
- else {
- if (location.isUnknown()) {
- // We know that the new state will be the same as the old state since
- // the location of the binding is "unknown". Consequently, there
- // is no reason to just create a new node.
- newState = state;
- }
- else {
- // We are binding to a value other than 'unknown'. Perform the binding
- // using the StoreManager.
- newState = state->bindLoc(cast<Loc>(location), Val);
- }
- }
-
- // The next thing to do is check if the GRTransferFuncs object wants to
- // update the state based on the new binding. If the GRTransferFunc object
- // doesn't do anything, just auto-propagate the current state.
- GRStmtNodeBuilderRef BuilderRef(Dst, *Builder, *this, *I, newState, StoreE,
- newState != state);
-
- getTF().EvalBind(BuilderRef, location, Val);
- }
-}
-
-/// EvalStore - Handle the semantics of a store via an assignment.
-/// @param Dst The node set to store generated state nodes
-/// @param Ex The expression representing the location of the store
-/// @param state The current simulation state
-/// @param location The location to store the value
-/// @param Val The value to be stored
-void GRExprEngine::EvalStore(ExplodedNodeSet& Dst, const Expr *AssignE,
- const Expr* StoreE,
- ExplodedNode* Pred,
- const GRState* state, SVal location, SVal Val,
- const void *tag) {
-
- assert(Builder && "GRStmtNodeBuilder must be defined.");
-
- // Evaluate the location (checks for bad dereferences).
- ExplodedNodeSet Tmp;
- EvalLocation(Tmp, StoreE, Pred, state, location, tag, false);
-
- if (Tmp.empty())
- return;
-
- assert(!location.isUndef());
-
- SaveAndRestore<ProgramPoint::Kind> OldSPointKind(Builder->PointKind,
- ProgramPoint::PostStoreKind);
- SaveAndRestore<const void*> OldTag(Builder->Tag, tag);
-
- // Proceed with the store.
- for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI)
- EvalBind(Dst, AssignE, StoreE, *NI, GetState(*NI), location, Val);
-}
-
-void GRExprEngine::EvalLoad(ExplodedNodeSet& Dst, const Expr *Ex,
- ExplodedNode* Pred,
- const GRState* state, SVal location,
- const void *tag, QualType LoadTy) {
-
- // Are we loading from a region? This actually results in two loads; one
- // to fetch the address of the referenced value and one to fetch the
- // referenced value.
- if (const TypedRegion *TR =
- dyn_cast_or_null<TypedRegion>(location.getAsRegion())) {
-
- QualType ValTy = TR->getValueType(getContext());
- if (const ReferenceType *RT = ValTy->getAs<ReferenceType>()) {
- static int loadReferenceTag = 0;
- ExplodedNodeSet Tmp;
- EvalLoadCommon(Tmp, Ex, Pred, state, location, &loadReferenceTag,
- getContext().getPointerType(RT->getPointeeType()));
-
- // Perform the load from the referenced value.
- for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end() ; I!=E; ++I) {
- state = GetState(*I);
- location = state->getSVal(Ex);
- EvalLoadCommon(Dst, Ex, *I, state, location, tag, LoadTy);
- }
- return;
- }
- }
-
- EvalLoadCommon(Dst, Ex, Pred, state, location, tag, LoadTy);
-}
-
-void GRExprEngine::EvalLoadCommon(ExplodedNodeSet& Dst, const Expr *Ex,
- ExplodedNode* Pred,
- const GRState* state, SVal location,
- const void *tag, QualType LoadTy) {
-
- // Evaluate the location (checks for bad dereferences).
- ExplodedNodeSet Tmp;
- EvalLocation(Tmp, Ex, Pred, state, location, tag, true);
-
- if (Tmp.empty())
- return;
-
- assert(!location.isUndef());
-
- SaveAndRestore<ProgramPoint::Kind> OldSPointKind(Builder->PointKind);
- SaveAndRestore<const void*> OldTag(Builder->Tag);
-
- // Proceed with the load.
- for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI) {
- state = GetState(*NI);
- if (location.isUnknown()) {
- // This is important. We must nuke the old binding.
- MakeNode(Dst, Ex, *NI, state->BindExpr(Ex, UnknownVal()),
- ProgramPoint::PostLoadKind, tag);
- }
- else {
- SVal V = state->getSVal(cast<Loc>(location), LoadTy.isNull() ?
- Ex->getType() : LoadTy);
- MakeNode(Dst, Ex, *NI, state->BindExpr(Ex, V), ProgramPoint::PostLoadKind,
- tag);
- }
- }
-}
-
-void GRExprEngine::EvalLocation(ExplodedNodeSet &Dst, const Stmt *S,
- ExplodedNode* Pred,
- const GRState* state, SVal location,
- const void *tag, bool isLoad) {
- // Early checks for performance reason.
- if (location.isUnknown() || Checkers.empty()) {
- Dst.Add(Pred);
- return;
- }
-
- ExplodedNodeSet Src, Tmp;
- Src.Add(Pred);
- ExplodedNodeSet *PrevSet = &Src;
-
- for (CheckersOrdered::iterator I=Checkers.begin(),E=Checkers.end(); I!=E; ++I)
- {
- ExplodedNodeSet *CurrSet = 0;
- if (I+1 == E)
- CurrSet = &Dst;
- else {
- CurrSet = (PrevSet == &Tmp) ? &Src : &Tmp;
- CurrSet->clear();
- }
-
- void *tag = I->first;
- Checker *checker = I->second;
-
- for (ExplodedNodeSet::iterator NI = PrevSet->begin(), NE = PrevSet->end();
- NI != NE; ++NI) {
- // Use the 'state' argument only when the predecessor node is the
- // same as Pred. This allows us to catch updates to the state.
- checker->GR_VisitLocation(*CurrSet, *Builder, *this, S, *NI,
- *NI == Pred ? state : GetState(*NI),
- location, tag, isLoad);
- }
-
- // Update which NodeSet is the current one.
- PrevSet = CurrSet;
- }
-}
-
-bool GRExprEngine::InlineCall(ExplodedNodeSet &Dst, const CallExpr *CE,
- ExplodedNode *Pred) {
- const GRState *state = GetState(Pred);
- const Expr *Callee = CE->getCallee();
- SVal L = state->getSVal(Callee);
-
- const FunctionDecl *FD = L.getAsFunctionDecl();
- if (!FD)
- return false;
-
- // Check if the function definition is in the same translation unit.
- if (FD->hasBody(FD)) {
- // Now we have the definition of the callee, create a CallEnter node.
- CallEnter Loc(CE, AMgr.getAnalysisContext(FD), Pred->getLocationContext());
-
- ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
- Dst.Add(N);
- return true;
- }
-
- // Check if we can find the function definition in other translation units.
- if (AMgr.hasIndexer()) {
- const AnalysisContext *C = AMgr.getAnalysisContextInAnotherTU(FD);
- if (C == 0)
- return false;
-
- CallEnter Loc(CE, C, Pred->getLocationContext());
- ExplodedNode *N = Builder->generateNode(Loc, state, Pred);
- Dst.Add(N);
- return true;
- }
-
- return false;
-}
-
-void GRExprEngine::VisitCall(const CallExpr* CE, ExplodedNode* Pred,
- CallExpr::const_arg_iterator AI,
- CallExpr::const_arg_iterator AE,
- ExplodedNodeSet& Dst, bool asLValue) {
-
- // Determine the type of function we're calling (if available).
- const FunctionProtoType *Proto = NULL;
- QualType FnType = CE->getCallee()->IgnoreParens()->getType();
- if (const PointerType *FnTypePtr = FnType->getAs<PointerType>())
- Proto = FnTypePtr->getPointeeType()->getAs<FunctionProtoType>();
-
- // Create a worklist to process the arguments.
- llvm::SmallVector<CallExprWLItem, 20> WorkList;
- WorkList.reserve(AE - AI);
- WorkList.push_back(CallExprWLItem(AI, Pred));
-
- ExplodedNodeSet ArgsEvaluated;
-
- while (!WorkList.empty()) {
- CallExprWLItem Item = WorkList.back();
- WorkList.pop_back();
-
- if (Item.I == AE) {
- ArgsEvaluated.insert(Item.N);
- continue;
- }
-
- // Evaluate the argument.
- ExplodedNodeSet Tmp;
- const unsigned ParamIdx = Item.I - AI;
-
- bool VisitAsLvalue = false;
- if (Proto && ParamIdx < Proto->getNumArgs())
- VisitAsLvalue = Proto->getArgType(ParamIdx)->isReferenceType();
-
- if (VisitAsLvalue)
- VisitLValue(*Item.I, Item.N, Tmp);
- else
- Visit(*Item.I, Item.N, Tmp);
-
- // Enqueue evaluating the next argument on the worklist.
- ++(Item.I);
-
- for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI)
- WorkList.push_back(CallExprWLItem(Item.I, *NI));
- }
-
- // Now process the call itself.
- ExplodedNodeSet DstTmp;
- const Expr* Callee = CE->getCallee()->IgnoreParens();
-
- for (ExplodedNodeSet::iterator NI=ArgsEvaluated.begin(),
- NE=ArgsEvaluated.end(); NI != NE; ++NI) {
- // Evaluate the callee.
- ExplodedNodeSet DstTmp2;
- Visit(Callee, *NI, DstTmp2);
- // Perform the previsit of the CallExpr, storing the results in DstTmp.
- CheckerVisit(CE, DstTmp, DstTmp2, true);
- }
-
- // Finally, evaluate the function call. We try each of the checkers
- // to see if the can evaluate the function call.
- ExplodedNodeSet DstTmp3;
-
-
- for (ExplodedNodeSet::iterator DI = DstTmp.begin(), DE = DstTmp.end();
- DI != DE; ++DI) {
-
- const GRState* state = GetState(*DI);
- SVal L = state->getSVal(Callee);
-
- // FIXME: Add support for symbolic function calls (calls involving
- // function pointer values that are symbolic).
- SaveAndRestore<bool> OldSink(Builder->BuildSinks);
- ExplodedNodeSet DstChecker;
-
- // If the callee is processed by a checker, skip the rest logic.
- if (CheckerEvalCall(CE, DstChecker, *DI))
- DstTmp3.insert(DstChecker);
- else if (AMgr.shouldInlineCall() && InlineCall(Dst, CE, *DI)) {
- // Callee is inlined. We shouldn't do post call checking.
- return;
- }
- else {
- for (ExplodedNodeSet::iterator DI_Checker = DstChecker.begin(),
- DE_Checker = DstChecker.end();
- DI_Checker != DE_Checker; ++DI_Checker) {
-
- // Dispatch to the plug-in transfer function.
- unsigned OldSize = DstTmp3.size();
- SaveOr OldHasGen(Builder->HasGeneratedNode);
- Pred = *DI_Checker;
-
- // Dispatch to transfer function logic to handle the call itself.
- // FIXME: Allow us to chain together transfer functions.
- assert(Builder && "GRStmtNodeBuilder must be defined.");
- getTF().EvalCall(DstTmp3, *this, *Builder, CE, L, Pred);
-
- // Handle the case where no nodes where generated. Auto-generate that
- // contains the updated state if we aren't generating sinks.
- if (!Builder->BuildSinks && DstTmp3.size() == OldSize &&
- !Builder->HasGeneratedNode)
- MakeNode(DstTmp3, CE, Pred, state);
- }
- }
- }
-
- // Finally, perform the post-condition check of the CallExpr and store
- // the created nodes in 'Dst'.
- // If the callee returns a reference and we want an rvalue, skip this check
- // and do the load.
- if (!(!asLValue && CalleeReturnsReference(CE))) {
- CheckerVisit(CE, Dst, DstTmp3, false);
- return;
- }
-
- // Handle the case where the called function returns a reference but
- // we expect an rvalue. For such cases, convert the reference to
- // an rvalue.
- // FIXME: This conversion doesn't actually happen unless the result
- // of CallExpr is consumed by another expression.
- ExplodedNodeSet DstTmp4;
- CheckerVisit(CE, DstTmp4, DstTmp3, false);
- QualType LoadTy = CE->getType();
-
- static int *ConvertToRvalueTag = 0;
- for (ExplodedNodeSet::iterator NI = DstTmp4.begin(), NE = DstTmp4.end();
- NI!=NE; ++NI) {
- const GRState *state = GetState(*NI);
- EvalLoad(Dst, CE, *NI, state, state->getSVal(CE),
- &ConvertToRvalueTag, LoadTy);
- }
-}
-
-//===----------------------------------------------------------------------===//
-// Transfer function: Objective-C ivar references.
-//===----------------------------------------------------------------------===//
-
-static std::pair<const void*,const void*> EagerlyAssumeTag
- = std::pair<const void*,const void*>(&EagerlyAssumeTag,static_cast<void*>(0));
-
-void GRExprEngine::EvalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src,
- const Expr *Ex) {
- for (ExplodedNodeSet::iterator I=Src.begin(), E=Src.end(); I!=E; ++I) {
- ExplodedNode *Pred = *I;
-
- // Test if the previous node was as the same expression. This can happen
- // when the expression fails to evaluate to anything meaningful and
- // (as an optimization) we don't generate a node.
- ProgramPoint P = Pred->getLocation();
- if (!isa<PostStmt>(P) || cast<PostStmt>(P).getStmt() != Ex) {
- Dst.Add(Pred);
- continue;
- }
-
- const GRState* state = GetState(Pred);
- SVal V = state->getSVal(Ex);
- if (nonloc::SymExprVal *SEV = dyn_cast<nonloc::SymExprVal>(&V)) {
- // First assume that the condition is true.
- if (const GRState *stateTrue = state->Assume(*SEV, true)) {
- stateTrue = stateTrue->BindExpr(Ex,
- ValMgr.makeIntVal(1U, Ex->getType()));
- Dst.Add(Builder->generateNode(PostStmtCustom(Ex,
- &EagerlyAssumeTag, Pred->getLocationContext()),
- stateTrue, Pred));
- }
-
- // Next, assume that the condition is false.
- if (const GRState *stateFalse = state->Assume(*SEV, false)) {
- stateFalse = stateFalse->BindExpr(Ex,
- ValMgr.makeIntVal(0U, Ex->getType()));
- Dst.Add(Builder->generateNode(PostStmtCustom(Ex, &EagerlyAssumeTag,
- Pred->getLocationContext()),
- stateFalse, Pred));
- }
- }
- else
- Dst.Add(Pred);
- }
-}
-
-//===----------------------------------------------------------------------===//
-// Transfer function: Objective-C ivar references.
-//===----------------------------------------------------------------------===//
-
-void GRExprEngine::VisitObjCIvarRefExpr(const ObjCIvarRefExpr* Ex,
- ExplodedNode* Pred,
- ExplodedNodeSet& Dst, bool asLValue) {
-
- const Expr* Base = cast<Expr>(Ex->getBase());
- ExplodedNodeSet Tmp;
- Visit(Base, Pred, Tmp);
-
- for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
- const GRState* state = GetState(*I);
- SVal BaseVal = state->getSVal(Base);
- SVal location = state->getLValue(Ex->getDecl(), BaseVal);
-
- if (asLValue)
- MakeNode(Dst, Ex, *I, state->BindExpr(Ex, location));
- else
- EvalLoad(Dst, Ex, *I, state, location);
- }
-}
-
-//===----------------------------------------------------------------------===//
-// Transfer function: Objective-C fast enumeration 'for' statements.
-//===----------------------------------------------------------------------===//
-
-void GRExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt* S,
- ExplodedNode* Pred, ExplodedNodeSet& Dst) {
-
- // ObjCForCollectionStmts are processed in two places. This method
- // handles the case where an ObjCForCollectionStmt* occurs as one of the
- // statements within a basic block. This transfer function does two things:
- //
- // (1) binds the next container value to 'element'. This creates a new
- // node in the ExplodedGraph.
- //
- // (2) binds the value 0/1 to the ObjCForCollectionStmt* itself, indicating
- // whether or not the container has any more elements. This value
- // will be tested in ProcessBranch. We need to explicitly bind
- // this value because a container can contain nil elements.
- //
- // FIXME: Eventually this logic should actually do dispatches to
- // 'countByEnumeratingWithState:objects:count:' (NSFastEnumeration).
- // This will require simulating a temporary NSFastEnumerationState, either
- // through an SVal or through the use of MemRegions. This value can
- // be affixed to the ObjCForCollectionStmt* instead of 0/1; when the loop
- // terminates we reclaim the temporary (it goes out of scope) and we
- // we can test if the SVal is 0 or if the MemRegion is null (depending
- // on what approach we take).
- //
- // For now: simulate (1) by assigning either a symbol or nil if the
- // container is empty. Thus this transfer function will by default
- // result in state splitting.
-
- const Stmt* elem = S->getElement();
- SVal ElementV;
-
- if (const DeclStmt* DS = dyn_cast<DeclStmt>(elem)) {
- const VarDecl* ElemD = cast<VarDecl>(DS->getSingleDecl());
- assert (ElemD->getInit() == 0);
- ElementV = GetState(Pred)->getLValue(ElemD, Pred->getLocationContext());
- VisitObjCForCollectionStmtAux(S, Pred, Dst, ElementV);
- return;
- }
-
- ExplodedNodeSet Tmp;
- VisitLValue(cast<Expr>(elem), Pred, Tmp);
-
- for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I) {
- const GRState* state = GetState(*I);
- VisitObjCForCollectionStmtAux(S, *I, Dst, state->getSVal(elem));
- }
-}
-
-void GRExprEngine::VisitObjCForCollectionStmtAux(const ObjCForCollectionStmt* S,
- ExplodedNode* Pred, ExplodedNodeSet& Dst,
- SVal ElementV) {
-
- // Check if the location we are writing back to is a null pointer.
- const Stmt* elem = S->getElement();
- ExplodedNodeSet Tmp;
- EvalLocation(Tmp, elem, Pred, GetState(Pred), ElementV, NULL, false);
-
- if (Tmp.empty())
- return;
-
- for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI) {
- Pred = *NI;
- const GRState *state = GetState(Pred);
-
- // Handle the case where the container still has elements.
- SVal TrueV = ValMgr.makeTruthVal(1);
- const GRState *hasElems = state->BindExpr(S, TrueV);
-
- // Handle the case where the container has no elements.
- SVal FalseV = ValMgr.makeTruthVal(0);
- const GRState *noElems = state->BindExpr(S, FalseV);
-
- if (loc::MemRegionVal* MV = dyn_cast<loc::MemRegionVal>(&ElementV))
- if (const TypedRegion* R = dyn_cast<TypedRegion>(MV->getRegion())) {
- // FIXME: The proper thing to do is to really iterate over the
- // container. We will do this with dispatch logic to the store.
- // For now, just 'conjure' up a symbolic value.
- QualType T = R->getValueType(getContext());
- assert(Loc::IsLocType(T));
- unsigned Count = Builder->getCurrentBlockCount();
- SymbolRef Sym = SymMgr.getConjuredSymbol(elem, T, Count);
- SVal V = ValMgr.makeLoc(Sym);
- hasElems = hasElems->bindLoc(ElementV, V);
-
- // Bind the location to 'nil' on the false branch.
- SVal nilV = ValMgr.makeIntVal(0, T);
- noElems = noElems->bindLoc(ElementV, nilV);
- }
-
- // Create the new nodes.
- MakeNode(Dst, S, Pred, hasElems);
- MakeNode(Dst, S, Pred, noElems);
- }
-}
-
-//===----------------------------------------------------------------------===//
-// Transfer function: Objective-C message expressions.
-//===----------------------------------------------------------------------===//
-
-namespace {
-class ObjCMsgWLItem {
-public:
- ObjCMessageExpr::const_arg_iterator I;
- ExplodedNode *N;
-
- ObjCMsgWLItem(const ObjCMessageExpr::const_arg_iterator &i, ExplodedNode *n)
- : I(i), N(n) {}
-};
-} // end anonymous namespace
-
-void GRExprEngine::VisitObjCMessageExpr(const ObjCMessageExpr* ME,
- ExplodedNode* Pred,
- ExplodedNodeSet& Dst, bool asLValue){
-
- // Create a worklist to process both the arguments.
- llvm::SmallVector<ObjCMsgWLItem, 20> WL;
-
- // But first evaluate the receiver (if any).
- ObjCMessageExpr::const_arg_iterator AI = ME->arg_begin(), AE = ME->arg_end();
- if (const Expr *Receiver = ME->getInstanceReceiver()) {
- ExplodedNodeSet Tmp;
- Visit(Receiver, Pred, Tmp);
-
- if (Tmp.empty())
- return;
-
- for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I)
- WL.push_back(ObjCMsgWLItem(AI, *I));
- }
- else
- WL.push_back(ObjCMsgWLItem(AI, Pred));
-
- // Evaluate the arguments.
- ExplodedNodeSet ArgsEvaluated;
- while (!WL.empty()) {
- ObjCMsgWLItem Item = WL.back();
- WL.pop_back();
-
- if (Item.I == AE) {
- ArgsEvaluated.insert(Item.N);
- continue;
- }
-
- // Evaluate the subexpression.
- ExplodedNodeSet Tmp;
-
- // FIXME: [Objective-C++] handle arguments that are references
- Visit(*Item.I, Item.N, Tmp);
-
- // Enqueue evaluating the next argument on the worklist.
- ++(Item.I);
- for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI)
- WL.push_back(ObjCMsgWLItem(Item.I, *NI));
- }
-
- // Now that the arguments are processed, handle the previsits checks.
- ExplodedNodeSet DstPrevisit;
- CheckerVisit(ME, DstPrevisit, ArgsEvaluated, true);
-
- // Proceed with evaluate the message expression.
- ExplodedNodeSet DstEval;
-
- for (ExplodedNodeSet::iterator DI = DstPrevisit.begin(),
- DE = DstPrevisit.end(); DI != DE; ++DI) {
-
- Pred = *DI;
- bool RaisesException = false;
- unsigned OldSize = DstEval.size();
- SaveAndRestore<bool> OldSink(Builder->BuildSinks);
- SaveOr OldHasGen(Builder->HasGeneratedNode);
-
- if (const Expr *Receiver = ME->getInstanceReceiver()) {
- const GRState *state = GetState(Pred);
-
- // Bifurcate the state into nil and non-nil ones.
- DefinedOrUnknownSVal receiverVal =
- cast<DefinedOrUnknownSVal>(state->getSVal(Receiver));
-
- const GRState *notNilState, *nilState;
- llvm::tie(notNilState, nilState) = state->Assume(receiverVal);
-
- // There are three cases: can be nil or non-nil, must be nil, must be
- // non-nil. We handle must be nil, and merge the rest two into non-nil.
- if (nilState && !notNilState) {
- CheckerEvalNilReceiver(ME, DstEval, nilState, Pred);
- continue;
- }
-
- // Check if the "raise" message was sent.
- assert(notNilState);
- if (ME->getSelector() == RaiseSel)
- RaisesException = true;
-
- // Check if we raise an exception. For now treat these as sinks.
- // Eventually we will want to handle exceptions properly.
- if (RaisesException)
- Builder->BuildSinks = true;
-
- // Dispatch to plug-in transfer function.
- EvalObjCMessageExpr(DstEval, ME, Pred, notNilState);
- }
- else if (ObjCInterfaceDecl *Iface = ME->getReceiverInterface()) {
- IdentifierInfo* ClsName = Iface->getIdentifier();
- Selector S = ME->getSelector();
-
- // Check for special instance methods.
- if (!NSExceptionII) {
- ASTContext& Ctx = getContext();
- NSExceptionII = &Ctx.Idents.get("NSException");
- }
-
- if (ClsName == NSExceptionII) {
- enum { NUM_RAISE_SELECTORS = 2 };
-
- // Lazily create a cache of the selectors.
- if (!NSExceptionInstanceRaiseSelectors) {
- ASTContext& Ctx = getContext();
- NSExceptionInstanceRaiseSelectors =
- new Selector[NUM_RAISE_SELECTORS];
- llvm::SmallVector<IdentifierInfo*, NUM_RAISE_SELECTORS> II;
- unsigned idx = 0;
-
- // raise:format:
- II.push_back(&Ctx.Idents.get("raise"));
- II.push_back(&Ctx.Idents.get("format"));
- NSExceptionInstanceRaiseSelectors[idx++] =
- Ctx.Selectors.getSelector(II.size(), &II[0]);
-
- // raise:format::arguments:
- II.push_back(&Ctx.Idents.get("arguments"));
- NSExceptionInstanceRaiseSelectors[idx++] =
- Ctx.Selectors.getSelector(II.size(), &II[0]);
- }
-
- for (unsigned i = 0; i < NUM_RAISE_SELECTORS; ++i)
- if (S == NSExceptionInstanceRaiseSelectors[i]) {
- RaisesException = true;
- break;
- }
- }
-
- // Check if we raise an exception. For now treat these as sinks.
- // Eventually we will want to handle exceptions properly.
- if (RaisesException)
- Builder->BuildSinks = true;
-
- // Dispatch to plug-in transfer function.
- EvalObjCMessageExpr(DstEval, ME, Pred, Builder->GetState(Pred));
- }
-
- // Handle the case where no nodes where generated. Auto-generate that
- // contains the updated state if we aren't generating sinks.
- if (!Builder->BuildSinks && DstEval.size() == OldSize &&
- !Builder->HasGeneratedNode)
- MakeNode(DstEval, ME, Pred, GetState(Pred));
- }
-
- // Finally, perform the post-condition check of the ObjCMessageExpr and store
- // the created nodes in 'Dst'.
- if (!(!asLValue && ReceiverReturnsReference(ME))) {
- CheckerVisit(ME, Dst, DstEval, false);
- return;
- }
-
- // Handle the case where the message expression returns a reference but
- // we expect an rvalue. For such cases, convert the reference to
- // an rvalue.
- // FIXME: This conversion doesn't actually happen unless the result
- // of ObjCMessageExpr is consumed by another expression.
- ExplodedNodeSet DstRValueConvert;
- CheckerVisit(ME, DstRValueConvert, DstEval, false);
- QualType LoadTy = ME->getType();
-
- static int *ConvertToRvalueTag = 0;
- for (ExplodedNodeSet::iterator NI = DstRValueConvert.begin(),
- NE = DstRValueConvert.end(); NI != NE; ++NI) {
- const GRState *state = GetState(*NI);
- EvalLoad(Dst, ME, *NI, state, state->getSVal(ME),
- &ConvertToRvalueTag, LoadTy);
- }
-}
-
-//===----------------------------------------------------------------------===//
-// Transfer functions: Miscellaneous statements.
-//===----------------------------------------------------------------------===//
-
-void GRExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex,
- ExplodedNode *Pred, ExplodedNodeSet &Dst,
- bool asLValue) {
- ExplodedNodeSet S1;
- QualType T = CastE->getType();
- QualType ExTy = Ex->getType();
-
- if (const ExplicitCastExpr *ExCast=dyn_cast_or_null<ExplicitCastExpr>(CastE))
- T = ExCast->getTypeAsWritten();
-
- if (ExTy->isArrayType() || ExTy->isFunctionType() || T->isReferenceType() ||
- asLValue)
- VisitLValue(Ex, Pred, S1);
- else
- Visit(Ex, Pred, S1);
-
- ExplodedNodeSet S2;
- CheckerVisit(CastE, S2, S1, true);
-
- // If we are evaluating the cast in an lvalue context, we implicitly want
- // the cast to evaluate to a location.
- if (asLValue) {
- ASTContext &Ctx = getContext();
- T = Ctx.getPointerType(Ctx.getCanonicalType(T));
- ExTy = Ctx.getPointerType(Ctx.getCanonicalType(ExTy));
- }
-
- switch (CastE->getCastKind()) {
- case CastExpr::CK_ToVoid:
- assert(!asLValue);
- for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I)
- Dst.Add(*I);
- return;
-
- case CastExpr::CK_NoOp:
- case CastExpr::CK_FunctionToPointerDecay:
- for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {
- // Copy the SVal of Ex to CastE.
- ExplodedNode *N = *I;
- const GRState *state = GetState(N);
- SVal V = state->getSVal(Ex);
- state = state->BindExpr(CastE, V);
- MakeNode(Dst, CastE, N, state);
- }
- return;
-
- case CastExpr::CK_Unknown:
- case CastExpr::CK_ArrayToPointerDecay:
- case CastExpr::CK_BitCast:
- case CastExpr::CK_LValueBitCast:
- case CastExpr::CK_IntegralCast:
- case CastExpr::CK_IntegralToPointer:
- case CastExpr::CK_PointerToIntegral:
- case CastExpr::CK_IntegralToFloating:
- case CastExpr::CK_FloatingToIntegral:
- case CastExpr::CK_FloatingCast:
- case CastExpr::CK_AnyPointerToObjCPointerCast:
- case CastExpr::CK_AnyPointerToBlockPointerCast:
- case CastExpr::CK_DerivedToBase:
- case CastExpr::CK_UncheckedDerivedToBase: {
- // Delegate to SValuator to process.
- for (ExplodedNodeSet::iterator I = S2.begin(), E = S2.end(); I != E; ++I) {
- ExplodedNode* N = *I;
- const GRState* state = GetState(N);
- SVal V = state->getSVal(Ex);
- V = SVator.EvalCast(V, T, ExTy);
- state = state->BindExpr(CastE, V);
- MakeNode(Dst, CastE, N, state);
- }
- return;
- }
-
- // Various C++ casts that are not handled yet.
- case CastExpr::CK_Dynamic:
- case CastExpr::CK_ToUnion:
- case CastExpr::CK_BaseToDerived:
- case CastExpr::CK_NullToMemberPointer:
- case CastExpr::CK_BaseToDerivedMemberPointer:
- case CastExpr::CK_DerivedToBaseMemberPointer:
- case CastExpr::CK_UserDefinedConversion:
- case CastExpr::CK_ConstructorConversion:
- case CastExpr::CK_VectorSplat:
- case CastExpr::CK_MemberPointerToBoolean: {
- SaveAndRestore<bool> OldSink(Builder->BuildSinks);
- Builder->BuildSinks = true;
- MakeNode(Dst, CastE, Pred, GetState(Pred));
- return;
- }
- }
-}
-
-void GRExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr* CL,
- ExplodedNode* Pred,
- ExplodedNodeSet& Dst,
- bool asLValue) {
- const InitListExpr* ILE
- = cast<InitListExpr>(CL->getInitializer()->IgnoreParens());
- ExplodedNodeSet Tmp;
- Visit(ILE, Pred, Tmp);
-
- for (ExplodedNodeSet::iterator I = Tmp.begin(), EI = Tmp.end(); I!=EI; ++I) {
- const GRState* state = GetState(*I);
- SVal ILV = state->getSVal(ILE);
- const LocationContext *LC = (*I)->getLocationContext();
- state = state->bindCompoundLiteral(CL, LC, ILV);
-
- if (asLValue) {
- MakeNode(Dst, CL, *I, state->BindExpr(CL, state->getLValue(CL, LC)));
- }
- else
- MakeNode(Dst, CL, *I, state->BindExpr(CL, ILV));
- }
-}
-
-void GRExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred,
- ExplodedNodeSet& Dst) {
-
- // The CFG has one DeclStmt per Decl.
- const Decl* D = *DS->decl_begin();
-
- if (!D || !isa<VarDecl>(D))
- return;
-
- const VarDecl* VD = dyn_cast<VarDecl>(D);
- const Expr* InitEx = VD->getInit();
-
- // FIXME: static variables may have an initializer, but the second
- // time a function is called those values may not be current.
- ExplodedNodeSet Tmp;
-
- if (InitEx) {
- QualType InitTy = InitEx->getType();
- if (getContext().getLangOptions().CPlusPlus && InitTy->isRecordType()) {
- // Delegate expressions of C++ record type evaluation to AggExprVisitor.
- VisitAggExpr(InitEx, GetState(Pred)->getLValue(VD,
- Pred->getLocationContext()), Pred, Dst);
- return;
- } else if (VD->getType()->isReferenceType())
- VisitLValue(InitEx, Pred, Tmp);
- else
- Visit(InitEx, Pred, Tmp);
- }
- else
- Tmp.Add(Pred);
-
- ExplodedNodeSet Tmp2;
- CheckerVisit(DS, Tmp2, Tmp, true);
-
- for (ExplodedNodeSet::iterator I=Tmp2.begin(), E=Tmp2.end(); I!=E; ++I) {
- ExplodedNode *N = *I;
- const GRState *state = GetState(N);
-
- // Decls without InitExpr are not initialized explicitly.
- const LocationContext *LC = N->getLocationContext();
-
- if (InitEx) {
- SVal InitVal = state->getSVal(InitEx);
-
- // Recover some path-sensitivity if a scalar value evaluated to
- // UnknownVal.
- if ((InitVal.isUnknown() ||
- !getConstraintManager().canReasonAbout(InitVal)) &&
- !VD->getType()->isReferenceType()) {
- InitVal = ValMgr.getConjuredSymbolVal(NULL, InitEx,
- Builder->getCurrentBlockCount());
- }
-
- EvalBind(Dst, DS, DS, *I, state,
- loc::MemRegionVal(state->getRegion(VD, LC)), InitVal, true);
- }
- else {
- state = state->bindDeclWithNoInit(state->getRegion(VD, LC));
- MakeNode(Dst, DS, *I, state);
- }
- }
-}
-
-void GRExprEngine::VisitCondInit(const VarDecl *VD, const Stmt *S,
- ExplodedNode *Pred, ExplodedNodeSet& Dst) {
-
- const Expr* InitEx = VD->getInit();
- ExplodedNodeSet Tmp;
- Visit(InitEx, Pred, Tmp);
-
- for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
- ExplodedNode *N = *I;
- const GRState *state = GetState(N);
-
- const LocationContext *LC = N->getLocationContext();
- SVal InitVal = state->getSVal(InitEx);
-
- // Recover some path-sensitivity if a scalar value evaluated to
- // UnknownVal.
- if (InitVal.isUnknown() ||
- !getConstraintManager().canReasonAbout(InitVal)) {
- InitVal = ValMgr.getConjuredSymbolVal(NULL, InitEx,
- Builder->getCurrentBlockCount());
- }
-
- EvalBind(Dst, S, S, N, state,
- loc::MemRegionVal(state->getRegion(VD, LC)), InitVal, true);
- }
-}
-
-namespace {
- // This class is used by VisitInitListExpr as an item in a worklist
- // for processing the values contained in an InitListExpr.
-class InitListWLItem {
-public:
- llvm::ImmutableList<SVal> Vals;
- ExplodedNode* N;
- InitListExpr::const_reverse_iterator Itr;
-
- InitListWLItem(ExplodedNode* n, llvm::ImmutableList<SVal> vals,
- InitListExpr::const_reverse_iterator itr)
- : Vals(vals), N(n), Itr(itr) {}
-};
-}
-
-
-void GRExprEngine::VisitInitListExpr(const InitListExpr* E, ExplodedNode* Pred,
- ExplodedNodeSet& Dst) {
-
- const GRState* state = GetState(Pred);
- QualType T = getContext().getCanonicalType(E->getType());
- unsigned NumInitElements = E->getNumInits();
-
- if (T->isArrayType() || T->isRecordType() || T->isVectorType()) {
- llvm::ImmutableList<SVal> StartVals = getBasicVals().getEmptySValList();
-
- // Handle base case where the initializer has no elements.
- // e.g: static int* myArray[] = {};
- if (NumInitElements == 0) {
- SVal V = ValMgr.makeCompoundVal(T, StartVals);
- MakeNode(Dst, E, Pred, state->BindExpr(E, V));
- return;
- }
-
- // Create a worklist to process the initializers.
- llvm::SmallVector<InitListWLItem, 10> WorkList;
- WorkList.reserve(NumInitElements);
- WorkList.push_back(InitListWLItem(Pred, StartVals, E->rbegin()));
- InitListExpr::const_reverse_iterator ItrEnd = E->rend();
- assert(!(E->rbegin() == E->rend()));
-
- // Process the worklist until it is empty.
- while (!WorkList.empty()) {
- InitListWLItem X = WorkList.back();
- WorkList.pop_back();
-
- ExplodedNodeSet Tmp;
- Visit(*X.Itr, X.N, Tmp);
-
- InitListExpr::const_reverse_iterator NewItr = X.Itr + 1;
-
- for (ExplodedNodeSet::iterator NI=Tmp.begin(),NE=Tmp.end();NI!=NE;++NI) {
- // Get the last initializer value.
- state = GetState(*NI);
- SVal InitV = state->getSVal(cast<Expr>(*X.Itr));
-
- // Construct the new list of values by prepending the new value to
- // the already constructed list.
- llvm::ImmutableList<SVal> NewVals =
- getBasicVals().consVals(InitV, X.Vals);
-
- if (NewItr == ItrEnd) {
- // Now we have a list holding all init values. Make CompoundValData.
- SVal V = ValMgr.makeCompoundVal(T, NewVals);
-
- // Make final state and node.
- MakeNode(Dst, E, *NI, state->BindExpr(E, V));
- }
- else {
- // Still some initializer values to go. Push them onto the worklist.
- WorkList.push_back(InitListWLItem(*NI, NewVals, NewItr));
- }
- }
- }
-
- return;
- }
-
- if (Loc::IsLocType(T) || T->isIntegerType()) {
- assert (E->getNumInits() == 1);
- ExplodedNodeSet Tmp;
- const Expr* Init = E->getInit(0);
- Visit(Init, Pred, Tmp);
- for (ExplodedNodeSet::iterator I=Tmp.begin(), EI=Tmp.end(); I != EI; ++I) {
- state = GetState(*I);
- MakeNode(Dst, E, *I, state->BindExpr(E, state->getSVal(Init)));
- }
- return;
- }
-
- assert(0 && "unprocessed InitListExpr type");
-}
-
-/// VisitSizeOfAlignOfExpr - Transfer function for sizeof(type).
-void GRExprEngine::VisitSizeOfAlignOfExpr(const SizeOfAlignOfExpr* Ex,
- ExplodedNode* Pred,
- ExplodedNodeSet& Dst) {
- QualType T = Ex->getTypeOfArgument();
- CharUnits amt;
-
- if (Ex->isSizeOf()) {
- if (T == getContext().VoidTy) {
- // sizeof(void) == 1 byte.
- amt = CharUnits::One();
- }
- else if (!T->isConstantSizeType()) {
- assert(T->isVariableArrayType() && "Unknown non-constant-sized type.");
-
- // FIXME: Add support for VLA type arguments, not just VLA expressions.
- // When that happens, we should probably refactor VLASizeChecker's code.
- if (Ex->isArgumentType()) {
- Dst.Add(Pred);
- return;
- }
-
- // Get the size by getting the extent of the sub-expression.
- // First, visit the sub-expression to find its region.
- const Expr *Arg = Ex->getArgumentExpr();
- ExplodedNodeSet Tmp;
- VisitLValue(Arg, Pred, Tmp);
-
- for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
- const GRState* state = GetState(*I);
- const MemRegion *MR = state->getSVal(Arg).getAsRegion();
-
- // If the subexpression can't be resolved to a region, we don't know
- // anything about its size. Just leave the state as is and continue.
- if (!MR) {
- Dst.Add(*I);
- continue;
- }
-
- // The result is the extent of the VLA.
- SVal Extent = cast<SubRegion>(MR)->getExtent(ValMgr);
- MakeNode(Dst, Ex, *I, state->BindExpr(Ex, Extent));
- }
-
- return;
- }
- else if (T->getAs<ObjCObjectType>()) {
- // Some code tries to take the sizeof an ObjCObjectType, relying that
- // the compiler has laid out its representation. Just report Unknown
- // for these.
- Dst.Add(Pred);
- return;
- }
- else {
- // All other cases.
- amt = getContext().getTypeSizeInChars(T);
- }
- }
- else // Get alignment of the type.
- amt = getContext().getTypeAlignInChars(T);
-
- MakeNode(Dst, Ex, Pred,
- GetState(Pred)->BindExpr(Ex,
- ValMgr.makeIntVal(amt.getQuantity(), Ex->getType())));
-}
-
-void GRExprEngine::VisitOffsetOfExpr(const OffsetOfExpr* OOE,
- ExplodedNode* Pred, ExplodedNodeSet& Dst) {
- Expr::EvalResult Res;
- if (OOE->Evaluate(Res, getContext()) && Res.Val.isInt()) {
- const APSInt &IV = Res.Val.getInt();
- assert(IV.getBitWidth() == getContext().getTypeSize(OOE->getType()));
- assert(OOE->getType()->isIntegerType());
- assert(IV.isSigned() == OOE->getType()->isSignedIntegerType());
- SVal X = ValMgr.makeIntVal(IV);
- MakeNode(Dst, OOE, Pred, GetState(Pred)->BindExpr(OOE, X));
- return;
- }
- // FIXME: Handle the case where __builtin_offsetof is not a constant.
- Dst.Add(Pred);
-}
-
-void GRExprEngine::VisitUnaryOperator(const UnaryOperator* U,
- ExplodedNode* Pred,
- ExplodedNodeSet& Dst, bool asLValue) {
-
- switch (U->getOpcode()) {
-
- default:
- break;
-
- case UnaryOperator::Deref: {
-
- const Expr* Ex = U->getSubExpr()->IgnoreParens();
- ExplodedNodeSet Tmp;
- Visit(Ex, Pred, Tmp);
-
- for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
-
- const GRState* state = GetState(*I);
- SVal location = state->getSVal(Ex);
-
- if (asLValue)
- MakeNode(Dst, U, *I, state->BindExpr(U, location),
- ProgramPoint::PostLValueKind);
- else
- EvalLoad(Dst, U, *I, state, location);
- }
-
- return;
- }
-
- case UnaryOperator::Real: {
-
- const Expr* Ex = U->getSubExpr()->IgnoreParens();
- ExplodedNodeSet Tmp;
- Visit(Ex, Pred, Tmp);
-
- for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
-
- // FIXME: We don't have complex SValues yet.
- if (Ex->getType()->isAnyComplexType()) {
- // Just report "Unknown."
- Dst.Add(*I);
- continue;
- }
-
- // For all other types, UnaryOperator::Real is an identity operation.
- assert (U->getType() == Ex->getType());
- const GRState* state = GetState(*I);
- MakeNode(Dst, U, *I, state->BindExpr(U, state->getSVal(Ex)));
- }
-
- return;
- }
-
- case UnaryOperator::Imag: {
-
- const Expr* Ex = U->getSubExpr()->IgnoreParens();
- ExplodedNodeSet Tmp;
- Visit(Ex, Pred, Tmp);
-
- for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
- // FIXME: We don't have complex SValues yet.
- if (Ex->getType()->isAnyComplexType()) {
- // Just report "Unknown."
- Dst.Add(*I);
- continue;
- }
-
- // For all other types, UnaryOperator::Imag returns 0.
- const GRState* state = GetState(*I);
- SVal X = ValMgr.makeZeroVal(Ex->getType());
- MakeNode(Dst, U, *I, state->BindExpr(U, X));
- }
-
- return;
- }
-
- case UnaryOperator::OffsetOf: {
- Expr::EvalResult Res;
- if (U->Evaluate(Res, getContext()) && Res.Val.isInt()) {
- const APSInt &IV = Res.Val.getInt();
- assert(IV.getBitWidth() == getContext().getTypeSize(U->getType()));
- assert(U->getType()->isIntegerType());
- assert(IV.isSigned() == U->getType()->isSignedIntegerType());
- SVal X = ValMgr.makeIntVal(IV);
- MakeNode(Dst, U, Pred, GetState(Pred)->BindExpr(U, X));
- return;
- }
- // FIXME: Handle the case where __builtin_offsetof is not a constant.
- Dst.Add(Pred);
- return;
- }
-
- case UnaryOperator::Plus: assert(!asLValue); // FALL-THROUGH.
- case UnaryOperator::Extension: {
-
- // Unary "+" is a no-op, similar to a parentheses. We still have places
- // where it may be a block-level expression, so we need to
- // generate an extra node that just propagates the value of the
- // subexpression.
-
- const Expr* Ex = U->getSubExpr()->IgnoreParens();
- ExplodedNodeSet Tmp;
-
- if (asLValue)
- VisitLValue(Ex, Pred, Tmp);
- else
- Visit(Ex, Pred, Tmp);
-
- for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
- const GRState* state = GetState(*I);
- MakeNode(Dst, U, *I, state->BindExpr(U, state->getSVal(Ex)));
- }
-
- return;
- }
-
- case UnaryOperator::AddrOf: {
-
- assert(!asLValue);
- const Expr* Ex = U->getSubExpr()->IgnoreParens();
- ExplodedNodeSet Tmp;
- VisitLValue(Ex, Pred, Tmp);
-
- for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
- const GRState* state = GetState(*I);
- SVal V = state->getSVal(Ex);
- state = state->BindExpr(U, V);
- MakeNode(Dst, U, *I, state);
- }
-
- return;
- }
-
- case UnaryOperator::LNot:
- case UnaryOperator::Minus:
- case UnaryOperator::Not: {
-
- assert (!asLValue);
- const Expr* Ex = U->getSubExpr()->IgnoreParens();
- ExplodedNodeSet Tmp;
- Visit(Ex, Pred, Tmp);
-
- for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) {
- const GRState* state = GetState(*I);
-
- // Get the value of the subexpression.
- SVal V = state->getSVal(Ex);
-
- if (V.isUnknownOrUndef()) {
- MakeNode(Dst, U, *I, state->BindExpr(U, V));
- continue;
- }
-
-// QualType DstT = getContext().getCanonicalType(U->getType());
-// QualType SrcT = getContext().getCanonicalType(Ex->getType());
-//
-// if (DstT != SrcT) // Perform promotions.
-// V = EvalCast(V, DstT);
-//
-// if (V.isUnknownOrUndef()) {
-// MakeNode(Dst, U, *I, BindExpr(St, U, V));
-// continue;
-// }
-
- switch (U->getOpcode()) {
- default:
- assert(false && "Invalid Opcode.");
- break;
-
- case UnaryOperator::Not:
- // FIXME: Do we need to handle promotions?
- state = state->BindExpr(U, EvalComplement(cast<NonLoc>(V)));
- break;
-
- case UnaryOperator::Minus:
- // FIXME: Do we need to handle promotions?
- state = state->BindExpr(U, EvalMinus(cast<NonLoc>(V)));
- break;
-
- case UnaryOperator::LNot:
-
- // C99 6.5.3.3: "The expression !E is equivalent to (0==E)."
- //
- // Note: technically we do "E == 0", but this is the same in the
- // transfer functions as "0 == E".
- SVal Result;
-
- if (isa<Loc>(V)) {
- Loc X = ValMgr.makeNull();
- Result = EvalBinOp(state, BinaryOperator::EQ, cast<Loc>(V), X,
- U->getType());
- }
- else {
- nonloc::ConcreteInt X(getBasicVals().getValue(0, Ex->getType()));
- Result = EvalBinOp(state, BinaryOperator::EQ, cast<NonLoc>(V), X,
- U->getType());
- }
-
- state = state->BindExpr(U, Result);
-
- break;
- }
-
- MakeNode(Dst, U, *I, state);
- }
-
- return;
- }
- }
-
- // Handle ++ and -- (both pre- and post-increment).
-
- assert (U->isIncrementDecrementOp());
- ExplodedNodeSet Tmp;
- const Expr* Ex = U->getSubExpr()->IgnoreParens();
- VisitLValue(Ex, Pred, Tmp);
-
- for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I) {
-
- const GRState* state = GetState(*I);
- SVal V1 = state->getSVal(Ex);
-
- // Perform a load.
- ExplodedNodeSet Tmp2;
- EvalLoad(Tmp2, Ex, *I, state, V1);
-
- for (ExplodedNodeSet::iterator I2=Tmp2.begin(), E2=Tmp2.end();I2!=E2;++I2) {
-
- state = GetState(*I2);
- SVal V2_untested = state->getSVal(Ex);
-
- // Propagate unknown and undefined values.
- if (V2_untested.isUnknownOrUndef()) {
- MakeNode(Dst, U, *I2, state->BindExpr(U, V2_untested));
- continue;
- }
- DefinedSVal V2 = cast<DefinedSVal>(V2_untested);
-
- // Handle all other values.
- BinaryOperator::Opcode Op = U->isIncrementOp() ? BinaryOperator::Add
- : BinaryOperator::Sub;
-
- // If the UnaryOperator has non-location type, use its type to create the
- // constant value. If the UnaryOperator has location type, create the
- // constant with int type and pointer width.
- SVal RHS;
-
- if (U->getType()->isAnyPointerType())
- RHS = ValMgr.makeIntValWithPtrWidth(1, false);
- else
- RHS = ValMgr.makeIntVal(1, U->getType());
-
- SVal Result = EvalBinOp(state, Op, V2, RHS, U->getType());
-
- // Conjure a new symbol if necessary to recover precision.
- if (Result.isUnknown() || !getConstraintManager().canReasonAbout(Result)){
- DefinedOrUnknownSVal SymVal =
- ValMgr.getConjuredSymbolVal(NULL, Ex,
- Builder->getCurrentBlockCount());
- Result = SymVal;
-
- // If the value is a location, ++/-- should always preserve
- // non-nullness. Check if the original value was non-null, and if so
- // propagate that constraint.
- if (Loc::IsLocType(U->getType())) {
- DefinedOrUnknownSVal Constraint =
- SVator.EvalEQ(state, V2, ValMgr.makeZeroVal(U->getType()));
-
- if (!state->Assume(Constraint, true)) {
- // It isn't feasible for the original value to be null.
- // Propagate this constraint.
- Constraint = SVator.EvalEQ(state, SymVal,
- ValMgr.makeZeroVal(U->getType()));
-
-
- state = state->Assume(Constraint, false);
- assert(state);
- }
- }
- }
-
- state = state->BindExpr(U, U->isPostfix() ? V2 : Result);
-
- // Perform the store.
- EvalStore(Dst, NULL, U, *I2, state, V1, Result);
- }
- }
-}
-
-void GRExprEngine::VisitAsmStmt(const AsmStmt* A, ExplodedNode* Pred,
- ExplodedNodeSet& Dst) {
- VisitAsmStmtHelperOutputs(A, A->begin_outputs(), A->end_outputs(), Pred, Dst);
-}
-
-void GRExprEngine::VisitAsmStmtHelperOutputs(const AsmStmt* A,
- AsmStmt::const_outputs_iterator I,
- AsmStmt::const_outputs_iterator E,
- ExplodedNode* Pred, ExplodedNodeSet& Dst) {
- if (I == E) {
- VisitAsmStmtHelperInputs(A, A->begin_inputs(), A->end_inputs(), Pred, Dst);
- return;
- }
-
- ExplodedNodeSet Tmp;
- VisitLValue(*I, Pred, Tmp);
-
- ++I;
-
- for (ExplodedNodeSet::iterator NI = Tmp.begin(), NE = Tmp.end();NI != NE;++NI)
- VisitAsmStmtHelperOutputs(A, I, E, *NI, Dst);
-}
-
-void GRExprEngine::VisitAsmStmtHelperInputs(const AsmStmt* A,
- AsmStmt::const_inputs_iterator I,
- AsmStmt::const_inputs_iterator E,
- ExplodedNode* Pred,
- ExplodedNodeSet& Dst) {
- if (I == E) {
-
- // We have processed both the inputs and the outputs. All of the outputs
- // should evaluate to Locs. Nuke all of their values.
-
- // FIXME: Some day in the future it would be nice to allow a "plug-in"
- // which interprets the inline asm and stores proper results in the
- // outputs.
-
- const GRState* state = GetState(Pred);
-
- for (AsmStmt::const_outputs_iterator OI = A->begin_outputs(),
- OE = A->end_outputs(); OI != OE; ++OI) {
-
- SVal X = state->getSVal(*OI);
- assert (!isa<NonLoc>(X)); // Should be an Lval, or unknown, undef.
-
- if (isa<Loc>(X))
- state = state->bindLoc(cast<Loc>(X), UnknownVal());
- }
-
- MakeNode(Dst, A, Pred, state);
- return;
- }
-
- ExplodedNodeSet Tmp;
- Visit(*I, Pred, Tmp);
-
- ++I;
-
- for (ExplodedNodeSet::iterator NI = Tmp.begin(), NE = Tmp.end(); NI!=NE; ++NI)
- VisitAsmStmtHelperInputs(A, I, E, *NI, Dst);
-}
-
-void GRExprEngine::VisitReturnStmt(const ReturnStmt *RS, ExplodedNode *Pred,
- ExplodedNodeSet &Dst) {
- ExplodedNodeSet Src;
- if (const Expr *RetE = RS->getRetValue()) {
- // Record the returned expression in the state. It will be used in
- // ProcessCallExit to bind the return value to the call expr.
- {
- static int Tag = 0;
- SaveAndRestore<const void *> OldTag(Builder->Tag, &Tag);
- const GRState *state = GetState(Pred);
- state = state->set<ReturnExpr>(RetE);
- Pred = Builder->generateNode(RetE, state, Pred);
- }
- // We may get a NULL Pred because we generated a cached node.
- if (Pred)
- Visit(RetE, Pred, Src);
- }
- else {
- Src.Add(Pred);
- }
-
- ExplodedNodeSet CheckedSet;
- CheckerVisit(RS, CheckedSet, Src, true);
-
- for (ExplodedNodeSet::iterator I = CheckedSet.begin(), E = CheckedSet.end();
- I != E; ++I) {
-
- assert(Builder && "GRStmtNodeBuilder must be defined.");
-
- Pred = *I;
- unsigned size = Dst.size();
-
- SaveAndRestore<bool> OldSink(Builder->BuildSinks);
- SaveOr OldHasGen(Builder->HasGeneratedNode);
-
- getTF().EvalReturn(Dst, *this, *Builder, RS, Pred);
-
- // Handle the case where no nodes where generated.
- if (!Builder->BuildSinks && Dst.size() == size &&
- !Builder->HasGeneratedNode)
- MakeNode(Dst, RS, Pred, GetState(Pred));
- }
-}
-
-//===----------------------------------------------------------------------===//
-// Transfer functions: Binary operators.
-//===----------------------------------------------------------------------===//
-
-void GRExprEngine::VisitBinaryOperator(const BinaryOperator* B,
- ExplodedNode* Pred,
- ExplodedNodeSet& Dst, bool asLValue) {
-
- ExplodedNodeSet Tmp1;
- Expr* LHS = B->getLHS()->IgnoreParens();
- Expr* RHS = B->getRHS()->IgnoreParens();
-
- // FIXME: Add proper support for ObjCImplicitSetterGetterRefExpr.
- if (isa<ObjCImplicitSetterGetterRefExpr>(LHS)) {
- Visit(RHS, Pred, Dst);
- return;
- }
-
- if (B->isAssignmentOp())
- VisitLValue(LHS, Pred, Tmp1);
- else
- Visit(LHS, Pred, Tmp1);
-
- ExplodedNodeSet Tmp3;
-
- for (ExplodedNodeSet::iterator I1=Tmp1.begin(), E1=Tmp1.end(); I1!=E1; ++I1) {
- SVal LeftV = GetState(*I1)->getSVal(LHS);
- ExplodedNodeSet Tmp2;
- Visit(RHS, *I1, Tmp2);
-
- ExplodedNodeSet CheckedSet;
- CheckerVisit(B, CheckedSet, Tmp2, true);
-
- // With both the LHS and RHS evaluated, process the operation itself.
-
- for (ExplodedNodeSet::iterator I2=CheckedSet.begin(), E2=CheckedSet.end();
- I2 != E2; ++I2) {
-
- const GRState *state = GetState(*I2);
- const GRState *OldSt = state;
- SVal RightV = state->getSVal(RHS);
-
- BinaryOperator::Opcode Op = B->getOpcode();
-
- if (Op == BinaryOperator::Assign) {
- // EXPERIMENTAL: "Conjured" symbols.
- // FIXME: Handle structs.
- QualType T = RHS->getType();
-
- if (RightV.isUnknown() ||!getConstraintManager().canReasonAbout(RightV))
- {
- unsigned Count = Builder->getCurrentBlockCount();
- RightV = ValMgr.getConjuredSymbolVal(NULL, B->getRHS(), Count);
- }
-
- SVal ExprVal = asLValue ? LeftV : RightV;
-
- // Simulate the effects of a "store": bind the value of the RHS
- // to the L-Value represented by the LHS.
- EvalStore(Tmp3, B, LHS, *I2, state->BindExpr(B, ExprVal), LeftV,RightV);
- continue;
- }
-
- if (!B->isAssignmentOp()) {
- // Process non-assignments except commas or short-circuited
- // logical expressions (LAnd and LOr).
- SVal Result = EvalBinOp(state, Op, LeftV, RightV, B->getType());
-
- if (Result.isUnknown()) {
- if (OldSt != state) {
- // Generate a new node if we have already created a new state.
- MakeNode(Tmp3, B, *I2, state);
- }
- else
- Tmp3.Add(*I2);
-
- continue;
- }
-
- state = state->BindExpr(B, Result);
-
- MakeNode(Tmp3, B, *I2, state);
- continue;
- }
-
- assert (B->isCompoundAssignmentOp());
-
- switch (Op) {
- default:
- assert(0 && "Invalid opcode for compound assignment.");
- case BinaryOperator::MulAssign: Op = BinaryOperator::Mul; break;
- case BinaryOperator::DivAssign: Op = BinaryOperator::Div; break;
- case BinaryOperator::RemAssign: Op = BinaryOperator::Rem; break;
- case BinaryOperator::AddAssign: Op = BinaryOperator::Add; break;
- case BinaryOperator::SubAssign: Op = BinaryOperator::Sub; break;
- case BinaryOperator::ShlAssign: Op = BinaryOperator::Shl; break;
- case BinaryOperator::ShrAssign: Op = BinaryOperator::Shr; break;
- case BinaryOperator::AndAssign: Op = BinaryOperator::And; break;
- case BinaryOperator::XorAssign: Op = BinaryOperator::Xor; break;
- case BinaryOperator::OrAssign: Op = BinaryOperator::Or; break;
- }
-
- // Perform a load (the LHS). This performs the checks for
- // null dereferences, and so on.
- ExplodedNodeSet Tmp4;
- SVal location = state->getSVal(LHS);
- EvalLoad(Tmp4, LHS, *I2, state, location);
-
- for (ExplodedNodeSet::iterator I4=Tmp4.begin(), E4=Tmp4.end(); I4!=E4;
- ++I4) {
- state = GetState(*I4);
- SVal V = state->getSVal(LHS);
-
- // Get the computation type.
- QualType CTy =
- cast<CompoundAssignOperator>(B)->getComputationResultType();
- CTy = getContext().getCanonicalType(CTy);
-
- QualType CLHSTy =
- cast<CompoundAssignOperator>(B)->getComputationLHSType();
- CLHSTy = getContext().getCanonicalType(CLHSTy);
-
- QualType LTy = getContext().getCanonicalType(LHS->getType());
- QualType RTy = getContext().getCanonicalType(RHS->getType());
-
- // Promote LHS.
- V = SVator.EvalCast(V, CLHSTy, LTy);
-
- // Compute the result of the operation.
- SVal Result = SVator.EvalCast(EvalBinOp(state, Op, V, RightV, CTy),
- B->getType(), CTy);
-
- // EXPERIMENTAL: "Conjured" symbols.
- // FIXME: Handle structs.
-
- SVal LHSVal;
-
- if (Result.isUnknown() ||
- !getConstraintManager().canReasonAbout(Result)) {
-
- unsigned Count = Builder->getCurrentBlockCount();
-
- // The symbolic value is actually for the type of the left-hand side
- // expression, not the computation type, as this is the value the
- // LValue on the LHS will bind to.
- LHSVal = ValMgr.getConjuredSymbolVal(NULL, B->getRHS(), LTy, Count);
-
- // However, we need to convert the symbol to the computation type.
- Result = SVator.EvalCast(LHSVal, CTy, LTy);
- }
- else {
- // The left-hand side may bind to a different value then the
- // computation type.
- LHSVal = SVator.EvalCast(Result, LTy, CTy);
- }
-
- EvalStore(Tmp3, B, LHS, *I4, state->BindExpr(B, Result),
- location, LHSVal);
- }
- }
- }
-
- CheckerVisit(B, Dst, Tmp3, false);
-}
-
-//===----------------------------------------------------------------------===//
-// Checker registration/lookup.
-//===----------------------------------------------------------------------===//
-
-Checker *GRExprEngine::lookupChecker(void *tag) const {
- CheckerMap::const_iterator I = CheckerM.find(tag);
- return (I == CheckerM.end()) ? NULL : Checkers[I->second].second;
-}
-
-//===----------------------------------------------------------------------===//
-// Visualization.
-//===----------------------------------------------------------------------===//
-
-#ifndef NDEBUG
-static GRExprEngine* GraphPrintCheckerState;
-static SourceManager* GraphPrintSourceManager;
-
-namespace llvm {
-template<>
-struct DOTGraphTraits<ExplodedNode*> :
- public DefaultDOTGraphTraits {
-
- DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {}
-
- // FIXME: Since we do not cache error nodes in GRExprEngine now, this does not
- // work.
- static std::string getNodeAttributes(const ExplodedNode* N, void*) {
-
-#if 0
- // FIXME: Replace with a general scheme to tell if the node is
- // an error node.
- if (GraphPrintCheckerState->isImplicitNullDeref(N) ||
- GraphPrintCheckerState->isExplicitNullDeref(N) ||
- GraphPrintCheckerState->isUndefDeref(N) ||
- GraphPrintCheckerState->isUndefStore(N) ||
- GraphPrintCheckerState->isUndefControlFlow(N) ||
- GraphPrintCheckerState->isUndefResult(N) ||
- GraphPrintCheckerState->isBadCall(N) ||
- GraphPrintCheckerState->isUndefArg(N))
- return "color=\"red\",style=\"filled\"";
-
- if (GraphPrintCheckerState->isNoReturnCall(N))
- return "color=\"blue\",style=\"filled\"";
-#endif
- return "";
- }
-
- static std::string getNodeLabel(const ExplodedNode* N, void*){
-
- std::string sbuf;
- llvm::raw_string_ostream Out(sbuf);
-
- // Program Location.
- ProgramPoint Loc = N->getLocation();
-
- switch (Loc.getKind()) {
- case ProgramPoint::BlockEntranceKind:
- Out << "Block Entrance: B"
- << cast<BlockEntrance>(Loc).getBlock()->getBlockID();
- break;
-
- case ProgramPoint::BlockExitKind:
- assert (false);
- break;
-
- case ProgramPoint::CallEnterKind:
- Out << "CallEnter";
- break;
-
- case ProgramPoint::CallExitKind:
- Out << "CallExit";
- break;
-
- default: {
- if (StmtPoint *L = dyn_cast<StmtPoint>(&Loc)) {
- const Stmt* S = L->getStmt();
- SourceLocation SLoc = S->getLocStart();
-
- Out << S->getStmtClassName() << ' ' << (void*) S << ' ';
- LangOptions LO; // FIXME.
- S->printPretty(Out, 0, PrintingPolicy(LO));
-
- if (SLoc.isFileID()) {
- Out << "\\lline="
- << GraphPrintSourceManager->getInstantiationLineNumber(SLoc)
- << " col="
- << GraphPrintSourceManager->getInstantiationColumnNumber(SLoc)
- << "\\l";
- }
-
- if (isa<PreStmt>(Loc))
- Out << "\\lPreStmt\\l;";
- else if (isa<PostLoad>(Loc))
- Out << "\\lPostLoad\\l;";
- else if (isa<PostStore>(Loc))
- Out << "\\lPostStore\\l";
- else if (isa<PostLValue>(Loc))
- Out << "\\lPostLValue\\l";
-
-#if 0
- // FIXME: Replace with a general scheme to determine
- // the name of the check.
- if (GraphPrintCheckerState->isImplicitNullDeref(N))
- Out << "\\|Implicit-Null Dereference.\\l";
- else if (GraphPrintCheckerState->isExplicitNullDeref(N))
- Out << "\\|Explicit-Null Dereference.\\l";
- else if (GraphPrintCheckerState->isUndefDeref(N))
- Out << "\\|Dereference of undefialied value.\\l";
- else if (GraphPrintCheckerState->isUndefStore(N))
- Out << "\\|Store to Undefined Loc.";
- else if (GraphPrintCheckerState->isUndefResult(N))
- Out << "\\|Result of operation is undefined.";
- else if (GraphPrintCheckerState->isNoReturnCall(N))
- Out << "\\|Call to function marked \"noreturn\".";
- else if (GraphPrintCheckerState->isBadCall(N))
- Out << "\\|Call to NULL/Undefined.";
- else if (GraphPrintCheckerState->isUndefArg(N))
- Out << "\\|Argument in call is undefined";
-#endif
-
- break;
- }
-
- const BlockEdge& E = cast<BlockEdge>(Loc);
- Out << "Edge: (B" << E.getSrc()->getBlockID() << ", B"
- << E.getDst()->getBlockID() << ')';
-
- if (const Stmt* T = E.getSrc()->getTerminator()) {
-
- SourceLocation SLoc = T->getLocStart();
-
- Out << "\\|Terminator: ";
- LangOptions LO; // FIXME.
- E.getSrc()->printTerminator(Out, LO);
-
- if (SLoc.isFileID()) {
- Out << "\\lline="
- << GraphPrintSourceManager->getInstantiationLineNumber(SLoc)
- << " col="
- << GraphPrintSourceManager->getInstantiationColumnNumber(SLoc);
- }
-
- if (isa<SwitchStmt>(T)) {
- const Stmt* Label = E.getDst()->getLabel();
-
- if (Label) {
- if (const CaseStmt* C = dyn_cast<CaseStmt>(Label)) {
- Out << "\\lcase ";
- LangOptions LO; // FIXME.
- C->getLHS()->printPretty(Out, 0, PrintingPolicy(LO));
-
- if (const Stmt* RHS = C->getRHS()) {
- Out << " .. ";
- RHS->printPretty(Out, 0, PrintingPolicy(LO));
- }
-
- Out << ":";
- }
- else {
- assert (isa<DefaultStmt>(Label));
- Out << "\\ldefault:";
- }
- }
- else
- Out << "\\l(implicit) default:";
- }
- else if (isa<IndirectGotoStmt>(T)) {
- // FIXME
- }
- else {
- Out << "\\lCondition: ";
- if (*E.getSrc()->succ_begin() == E.getDst())
- Out << "true";
- else
- Out << "false";
- }
-
- Out << "\\l";
- }
-
-#if 0
- // FIXME: Replace with a general scheme to determine
- // the name of the check.
- if (GraphPrintCheckerState->isUndefControlFlow(N)) {
- Out << "\\|Control-flow based on\\lUndefined value.\\l";
- }
-#endif
- }
- }
-
- Out << "\\|StateID: " << (void*) N->getState() << "\\|";
-
- const GRState *state = N->getState();
- state->printDOT(Out, *N->getLocationContext()->getCFG());
-
- Out << "\\l";
- return Out.str();
- }
-};
-} // end llvm namespace
-#endif
-
-#ifndef NDEBUG
-template <typename ITERATOR>
-ExplodedNode* GetGraphNode(ITERATOR I) { return *I; }
-
-template <> ExplodedNode*
-GetGraphNode<llvm::DenseMap<ExplodedNode*, Expr*>::iterator>
- (llvm::DenseMap<ExplodedNode*, Expr*>::iterator I) {
- return I->first;
-}
-#endif
-
-void GRExprEngine::ViewGraph(bool trim) {
-#ifndef NDEBUG
- if (trim) {
- std::vector<ExplodedNode*> Src;
-
- // Flush any outstanding reports to make sure we cover all the nodes.
- // This does not cause them to get displayed.
- for (BugReporter::iterator I=BR.begin(), E=BR.end(); I!=E; ++I)
- const_cast<BugType*>(*I)->FlushReports(BR);
-
- // Iterate through the reports and get their nodes.
- for (BugReporter::iterator I=BR.begin(), E=BR.end(); I!=E; ++I) {
- for (BugType::const_iterator I2=(*I)->begin(), E2=(*I)->end();
- I2!=E2; ++I2) {
- const BugReportEquivClass& EQ = *I2;
- const BugReport &R = **EQ.begin();
- ExplodedNode *N = const_cast<ExplodedNode*>(R.getEndNode());
- if (N) Src.push_back(N);
- }
- }
-
- ViewGraph(&Src[0], &Src[0]+Src.size());
- }
- else {
- GraphPrintCheckerState = this;
- GraphPrintSourceManager = &getContext().getSourceManager();
-
- llvm::ViewGraph(*G.roots_begin(), "GRExprEngine");
-
- GraphPrintCheckerState = NULL;
- GraphPrintSourceManager = NULL;
- }
-#endif
-}
-
-void GRExprEngine::ViewGraph(ExplodedNode** Beg, ExplodedNode** End) {
-#ifndef NDEBUG
- GraphPrintCheckerState = this;
- GraphPrintSourceManager = &getContext().getSourceManager();
-
- std::auto_ptr<ExplodedGraph> TrimmedG(G.Trim(Beg, End).first);
-
- if (!TrimmedG.get())
- llvm::errs() << "warning: Trimmed ExplodedGraph is empty.\n";
- else
- llvm::ViewGraph(*TrimmedG->roots_begin(), "TrimmedGRExprEngine");
-
- GraphPrintCheckerState = NULL;
- GraphPrintSourceManager = NULL;
-#endif
-}
Removed: cfe/branches/Apple/williamson/lib/CodeGen/CGObjCMac.cpp.orig
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/williamson/lib/CodeGen/CGObjCMac.cpp.orig?rev=111417&view=auto
==============================================================================
--- cfe/branches/Apple/williamson/lib/CodeGen/CGObjCMac.cpp.orig (original)
+++ cfe/branches/Apple/williamson/lib/CodeGen/CGObjCMac.cpp.orig (removed)
@@ -1,6193 +0,0 @@
-//===------- CGObjCMac.cpp - Interface to Apple Objective-C Runtime -------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This provides Objective-C code generation targetting the Apple runtime.
-//
-//===----------------------------------------------------------------------===//
-
-#include "CGObjCRuntime.h"
-
-#include "CGRecordLayout.h"
-#include "CodeGenModule.h"
-#include "CodeGenFunction.h"
-#include "CGException.h"
-#include "clang/AST/ASTContext.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclObjC.h"
-#include "clang/AST/RecordLayout.h"
-#include "clang/AST/StmtObjC.h"
-#include "clang/Basic/LangOptions.h"
-#include "clang/Frontend/CodeGenOptions.h"
-
-#include "llvm/InlineAsm.h"
-#include "llvm/IntrinsicInst.h"
-#include "llvm/LLVMContext.h"
-#include "llvm/Module.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/SetVector.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/Support/CallSite.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Target/TargetData.h"
-#include <cstdio>
-
-using namespace clang;
-using namespace CodeGen;
-
-// Common CGObjCRuntime functions, these don't belong here, but they
-// don't belong in CGObjCRuntime either so we will live with it for
-// now.
-
-static uint64_t LookupFieldBitOffset(CodeGen::CodeGenModule &CGM,
- const ObjCInterfaceDecl *OID,
- const ObjCImplementationDecl *ID,
- const ObjCIvarDecl *Ivar) {
- const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
-
- // FIXME: We should eliminate the need to have ObjCImplementationDecl passed
- // in here; it should never be necessary because that should be the lexical
- // decl context for the ivar.
-
- // If we know have an implementation (and the ivar is in it) then
- // look up in the implementation layout.
- const ASTRecordLayout *RL;
- if (ID && ID->getClassInterface() == Container)
- RL = &CGM.getContext().getASTObjCImplementationLayout(ID);
- else
- RL = &CGM.getContext().getASTObjCInterfaceLayout(Container);
-
- // Compute field index.
- //
- // FIXME: The index here is closely tied to how ASTContext::getObjCLayout is
- // implemented. This should be fixed to get the information from the layout
- // directly.
- unsigned Index = 0;
- llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
- CGM.getContext().ShallowCollectObjCIvars(Container, Ivars);
- for (unsigned k = 0, e = Ivars.size(); k != e; ++k) {
- if (Ivar == Ivars[k])
- break;
- ++Index;
- }
- assert(Index != Ivars.size() && "Ivar is not inside container!");
-
- return RL->getFieldOffset(Index);
-}
-
-uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
- const ObjCInterfaceDecl *OID,
- const ObjCIvarDecl *Ivar) {
- return LookupFieldBitOffset(CGM, OID, 0, Ivar) / 8;
-}
-
-uint64_t CGObjCRuntime::ComputeIvarBaseOffset(CodeGen::CodeGenModule &CGM,
- const ObjCImplementationDecl *OID,
- const ObjCIvarDecl *Ivar) {
- return LookupFieldBitOffset(CGM, OID->getClassInterface(), OID, Ivar) / 8;
-}
-
-LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
- const ObjCInterfaceDecl *OID,
- llvm::Value *BaseValue,
- const ObjCIvarDecl *Ivar,
- unsigned CVRQualifiers,
- llvm::Value *Offset) {
- // Compute (type*) ( (char *) BaseValue + Offset)
- const llvm::Type *I8Ptr = llvm::Type::getInt8PtrTy(CGF.getLLVMContext());
- QualType IvarTy = Ivar->getType();
- const llvm::Type *LTy = CGF.CGM.getTypes().ConvertTypeForMem(IvarTy);
- llvm::Value *V = CGF.Builder.CreateBitCast(BaseValue, I8Ptr);
- V = CGF.Builder.CreateGEP(V, Offset, "add.ptr");
- V = CGF.Builder.CreateBitCast(V, llvm::PointerType::getUnqual(LTy));
-
- Qualifiers Quals = CGF.MakeQualifiers(IvarTy);
- Quals.addCVRQualifiers(CVRQualifiers);
-
- if (!Ivar->isBitField())
- return LValue::MakeAddr(V, Quals);
-
- // We need to compute the bit offset for the bit-field, the offset is to the
- // byte. Note, there is a subtle invariant here: we can only call this routine
- // on non-synthesized ivars but we may be called for synthesized ivars.
- // However, a synthesized ivar can never be a bit-field, so this is safe.
- uint64_t BitOffset = LookupFieldBitOffset(CGF.CGM, OID, 0, Ivar) % 8;
- uint64_t BitFieldSize =
- Ivar->getBitWidth()->EvaluateAsInt(CGF.getContext()).getZExtValue();
-
- // Allocate a new CGBitFieldInfo object to describe this access.
- //
- // FIXME: This is incredibly wasteful, these should be uniqued or part of some
- // layout object. However, this is blocked on other cleanups to the
- // Objective-C code, so for now we just live with allocating a bunch of these
- // objects.
-
- // We always construct a single, possibly unaligned, access for this case.
- CGBitFieldInfo::AccessInfo AI;
- AI.FieldIndex = 0;
- AI.FieldByteOffset = 0;
- AI.FieldBitStart = BitOffset;
- AI.AccessWidth = CGF.CGM.getContext().getTypeSize(IvarTy);
- AI.AccessAlignment = 0;
- AI.TargetBitOffset = 0;
- AI.TargetBitWidth = BitFieldSize;
-
- CGBitFieldInfo *Info =
- new (CGF.CGM.getContext()) CGBitFieldInfo(BitFieldSize, 1, &AI,
- IvarTy->isSignedIntegerType());
-
- // FIXME: We need to set a very conservative alignment on this, or make sure
- // that the runtime is doing the right thing.
- return LValue::MakeBitfield(V, *Info, Quals.getCVRQualifiers());
-}
-
-///
-
-namespace {
-
-typedef std::vector<llvm::Constant*> ConstantVector;
-
-// FIXME: We should find a nicer way to make the labels for metadata, string
-// concatenation is lame.
-
-class ObjCCommonTypesHelper {
-protected:
- llvm::LLVMContext &VMContext;
-
-private:
- llvm::Constant *getMessageSendFn() const {
- // id objc_msgSend (id, SEL, ...)
- std::vector<const llvm::Type*> Params;
- Params.push_back(ObjectPtrTy);
- Params.push_back(SelectorPtrTy);
- return
- CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
- Params, true),
- "objc_msgSend");
- }
-
- llvm::Constant *getMessageSendStretFn() const {
- // id objc_msgSend_stret (id, SEL, ...)
- std::vector<const llvm::Type*> Params;
- Params.push_back(ObjectPtrTy);
- Params.push_back(SelectorPtrTy);
- return
- CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
- Params, true),
- "objc_msgSend_stret");
-
- }
-
- llvm::Constant *getMessageSendFpretFn() const {
- // FIXME: This should be long double on x86_64?
- // [double | long double] objc_msgSend_fpret(id self, SEL op, ...)
- std::vector<const llvm::Type*> Params;
- Params.push_back(ObjectPtrTy);
- Params.push_back(SelectorPtrTy);
- return
- CGM.CreateRuntimeFunction(llvm::FunctionType::get(
- llvm::Type::getDoubleTy(VMContext),
- Params,
- true),
- "objc_msgSend_fpret");
-
- }
-
- llvm::Constant *getMessageSendSuperFn() const {
- // id objc_msgSendSuper(struct objc_super *super, SEL op, ...)
- const char *SuperName = "objc_msgSendSuper";
- std::vector<const llvm::Type*> Params;
- Params.push_back(SuperPtrTy);
- Params.push_back(SelectorPtrTy);
- return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
- Params, true),
- SuperName);
- }
-
- llvm::Constant *getMessageSendSuperFn2() const {
- // id objc_msgSendSuper2(struct objc_super *super, SEL op, ...)
- const char *SuperName = "objc_msgSendSuper2";
- std::vector<const llvm::Type*> Params;
- Params.push_back(SuperPtrTy);
- Params.push_back(SelectorPtrTy);
- return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
- Params, true),
- SuperName);
- }
-
- llvm::Constant *getMessageSendSuperStretFn() const {
- // void objc_msgSendSuper_stret(void * stretAddr, struct objc_super *super,
- // SEL op, ...)
- std::vector<const llvm::Type*> Params;
- Params.push_back(Int8PtrTy);
- Params.push_back(SuperPtrTy);
- Params.push_back(SelectorPtrTy);
- return CGM.CreateRuntimeFunction(
- llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
- Params, true),
- "objc_msgSendSuper_stret");
- }
-
- llvm::Constant *getMessageSendSuperStretFn2() const {
- // void objc_msgSendSuper2_stret(void * stretAddr, struct objc_super *super,
- // SEL op, ...)
- std::vector<const llvm::Type*> Params;
- Params.push_back(Int8PtrTy);
- Params.push_back(SuperPtrTy);
- Params.push_back(SelectorPtrTy);
- return CGM.CreateRuntimeFunction(
- llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
- Params, true),
- "objc_msgSendSuper2_stret");
- }
-
- llvm::Constant *getMessageSendSuperFpretFn() const {
- // There is no objc_msgSendSuper_fpret? How can that work?
- return getMessageSendSuperFn();
- }
-
- llvm::Constant *getMessageSendSuperFpretFn2() const {
- // There is no objc_msgSendSuper_fpret? How can that work?
- return getMessageSendSuperFn2();
- }
-
-protected:
- CodeGen::CodeGenModule &CGM;
-
-public:
- const llvm::Type *ShortTy, *IntTy, *LongTy, *LongLongTy;
- const llvm::Type *Int8PtrTy;
-
- /// ObjectPtrTy - LLVM type for object handles (typeof(id))
- const llvm::Type *ObjectPtrTy;
-
- /// PtrObjectPtrTy - LLVM type for id *
- const llvm::Type *PtrObjectPtrTy;
-
- /// SelectorPtrTy - LLVM type for selector handles (typeof(SEL))
- const llvm::Type *SelectorPtrTy;
- /// ProtocolPtrTy - LLVM type for external protocol handles
- /// (typeof(Protocol))
- const llvm::Type *ExternalProtocolPtrTy;
-
- // SuperCTy - clang type for struct objc_super.
- QualType SuperCTy;
- // SuperPtrCTy - clang type for struct objc_super *.
- QualType SuperPtrCTy;
-
- /// SuperTy - LLVM type for struct objc_super.
- const llvm::StructType *SuperTy;
- /// SuperPtrTy - LLVM type for struct objc_super *.
- const llvm::Type *SuperPtrTy;
-
- /// PropertyTy - LLVM type for struct objc_property (struct _prop_t
- /// in GCC parlance).
- const llvm::StructType *PropertyTy;
-
- /// PropertyListTy - LLVM type for struct objc_property_list
- /// (_prop_list_t in GCC parlance).
- const llvm::StructType *PropertyListTy;
- /// PropertyListPtrTy - LLVM type for struct objc_property_list*.
- const llvm::Type *PropertyListPtrTy;
-
- // MethodTy - LLVM type for struct objc_method.
- const llvm::StructType *MethodTy;
-
- /// CacheTy - LLVM type for struct objc_cache.
- const llvm::Type *CacheTy;
- /// CachePtrTy - LLVM type for struct objc_cache *.
- const llvm::Type *CachePtrTy;
-
- llvm::Constant *getGetPropertyFn() {
- CodeGen::CodeGenTypes &Types = CGM.getTypes();
- ASTContext &Ctx = CGM.getContext();
- // id objc_getProperty (id, SEL, ptrdiff_t, bool)
- llvm::SmallVector<CanQualType,4> Params;
- CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
- CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
- Params.push_back(IdType);
- Params.push_back(SelType);
- Params.push_back(Ctx.LongTy);
- Params.push_back(Ctx.BoolTy);
- const llvm::FunctionType *FTy =
- Types.GetFunctionType(Types.getFunctionInfo(IdType, Params,
- FunctionType::ExtInfo()),
- false);
- return CGM.CreateRuntimeFunction(FTy, "objc_getProperty");
- }
-
- llvm::Constant *getSetPropertyFn() {
- CodeGen::CodeGenTypes &Types = CGM.getTypes();
- ASTContext &Ctx = CGM.getContext();
- // void objc_setProperty (id, SEL, ptrdiff_t, id, bool, bool)
- llvm::SmallVector<CanQualType,6> Params;
- CanQualType IdType = Ctx.getCanonicalParamType(Ctx.getObjCIdType());
- CanQualType SelType = Ctx.getCanonicalParamType(Ctx.getObjCSelType());
- Params.push_back(IdType);
- Params.push_back(SelType);
- Params.push_back(Ctx.LongTy);
- Params.push_back(IdType);
- Params.push_back(Ctx.BoolTy);
- Params.push_back(Ctx.BoolTy);
- const llvm::FunctionType *FTy =
- Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
- FunctionType::ExtInfo()),
- false);
- return CGM.CreateRuntimeFunction(FTy, "objc_setProperty");
- }
-
-
- llvm::Constant *getCopyStructFn() {
- CodeGen::CodeGenTypes &Types = CGM.getTypes();
- ASTContext &Ctx = CGM.getContext();
- // void objc_copyStruct (void *, const void *, size_t, bool, bool)
- llvm::SmallVector<CanQualType,5> Params;
- Params.push_back(Ctx.VoidPtrTy);
- Params.push_back(Ctx.VoidPtrTy);
- Params.push_back(Ctx.LongTy);
- Params.push_back(Ctx.BoolTy);
- Params.push_back(Ctx.BoolTy);
- const llvm::FunctionType *FTy =
- Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
- FunctionType::ExtInfo()),
- false);
- return CGM.CreateRuntimeFunction(FTy, "objc_copyStruct");
- }
-
- llvm::Constant *getEnumerationMutationFn() {
- CodeGen::CodeGenTypes &Types = CGM.getTypes();
- ASTContext &Ctx = CGM.getContext();
- // void objc_enumerationMutation (id)
- llvm::SmallVector<CanQualType,1> Params;
- Params.push_back(Ctx.getCanonicalParamType(Ctx.getObjCIdType()));
- const llvm::FunctionType *FTy =
- Types.GetFunctionType(Types.getFunctionInfo(Ctx.VoidTy, Params,
- FunctionType::ExtInfo()),
- false);
- return CGM.CreateRuntimeFunction(FTy, "objc_enumerationMutation");
- }
-
- /// GcReadWeakFn -- LLVM objc_read_weak (id *src) function.
- llvm::Constant *getGcReadWeakFn() {
- // id objc_read_weak (id *)
- std::vector<const llvm::Type*> Args;
- Args.push_back(ObjectPtrTy->getPointerTo());
- llvm::FunctionType *FTy =
- llvm::FunctionType::get(ObjectPtrTy, Args, false);
- return CGM.CreateRuntimeFunction(FTy, "objc_read_weak");
- }
-
- /// GcAssignWeakFn -- LLVM objc_assign_weak function.
- llvm::Constant *getGcAssignWeakFn() {
- // id objc_assign_weak (id, id *)
- std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
- Args.push_back(ObjectPtrTy->getPointerTo());
- llvm::FunctionType *FTy =
- llvm::FunctionType::get(ObjectPtrTy, Args, false);
- return CGM.CreateRuntimeFunction(FTy, "objc_assign_weak");
- }
-
- /// GcAssignGlobalFn -- LLVM objc_assign_global function.
- llvm::Constant *getGcAssignGlobalFn() {
- // id objc_assign_global(id, id *)
- std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
- Args.push_back(ObjectPtrTy->getPointerTo());
- llvm::FunctionType *FTy =
- llvm::FunctionType::get(ObjectPtrTy, Args, false);
- return CGM.CreateRuntimeFunction(FTy, "objc_assign_global");
- }
-
- /// GcAssignThreadLocalFn -- LLVM objc_assign_threadlocal function.
- llvm::Constant *getGcAssignThreadLocalFn() {
- // id objc_assign_threadlocal(id src, id * dest)
- std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
- Args.push_back(ObjectPtrTy->getPointerTo());
- llvm::FunctionType *FTy =
- llvm::FunctionType::get(ObjectPtrTy, Args, false);
- return CGM.CreateRuntimeFunction(FTy, "objc_assign_threadlocal");
- }
-
- /// GcAssignIvarFn -- LLVM objc_assign_ivar function.
- llvm::Constant *getGcAssignIvarFn() {
- // id objc_assign_ivar(id, id *, ptrdiff_t)
- std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
- Args.push_back(ObjectPtrTy->getPointerTo());
- Args.push_back(LongTy);
- llvm::FunctionType *FTy =
- llvm::FunctionType::get(ObjectPtrTy, Args, false);
- return CGM.CreateRuntimeFunction(FTy, "objc_assign_ivar");
- }
-
- /// GcMemmoveCollectableFn -- LLVM objc_memmove_collectable function.
- llvm::Constant *GcMemmoveCollectableFn() {
- // void *objc_memmove_collectable(void *dst, const void *src, size_t size)
- std::vector<const llvm::Type*> Args(1, Int8PtrTy);
- Args.push_back(Int8PtrTy);
- Args.push_back(LongTy);
- llvm::FunctionType *FTy = llvm::FunctionType::get(Int8PtrTy, Args, false);
- return CGM.CreateRuntimeFunction(FTy, "objc_memmove_collectable");
- }
-
- /// GcAssignStrongCastFn -- LLVM objc_assign_strongCast function.
- llvm::Constant *getGcAssignStrongCastFn() {
- // id objc_assign_strongCast(id, id *)
- std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
- Args.push_back(ObjectPtrTy->getPointerTo());
- llvm::FunctionType *FTy =
- llvm::FunctionType::get(ObjectPtrTy, Args, false);
- return CGM.CreateRuntimeFunction(FTy, "objc_assign_strongCast");
- }
-
- /// ExceptionThrowFn - LLVM objc_exception_throw function.
- llvm::Constant *getExceptionThrowFn() {
- // void objc_exception_throw(id)
- std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
- llvm::FunctionType *FTy =
- llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
- return CGM.CreateRuntimeFunction(FTy, "objc_exception_throw");
- }
-
- /// ExceptionRethrowFn - LLVM objc_exception_rethrow function.
- llvm::Constant *getExceptionRethrowFn() {
- // void objc_exception_rethrow(void)
- std::vector<const llvm::Type*> Args;
- llvm::FunctionType *FTy =
- llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, true);
- return CGM.CreateRuntimeFunction(FTy, "objc_exception_rethrow");
- }
-
- /// SyncEnterFn - LLVM object_sync_enter function.
- llvm::Constant *getSyncEnterFn() {
- // void objc_sync_enter (id)
- std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
- llvm::FunctionType *FTy =
- llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
- return CGM.CreateRuntimeFunction(FTy, "objc_sync_enter");
- }
-
- /// SyncExitFn - LLVM object_sync_exit function.
- llvm::Constant *getSyncExitFn() {
- // void objc_sync_exit (id)
- std::vector<const llvm::Type*> Args(1, ObjectPtrTy);
- llvm::FunctionType *FTy =
- llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext), Args, false);
- return CGM.CreateRuntimeFunction(FTy, "objc_sync_exit");
- }
-
- llvm::Constant *getSendFn(bool IsSuper) const {
- return IsSuper ? getMessageSendSuperFn() : getMessageSendFn();
- }
-
- llvm::Constant *getSendFn2(bool IsSuper) const {
- return IsSuper ? getMessageSendSuperFn2() : getMessageSendFn();
- }
-
- llvm::Constant *getSendStretFn(bool IsSuper) const {
- return IsSuper ? getMessageSendSuperStretFn() : getMessageSendStretFn();
- }
-
- llvm::Constant *getSendStretFn2(bool IsSuper) const {
- return IsSuper ? getMessageSendSuperStretFn2() : getMessageSendStretFn();
- }
-
- llvm::Constant *getSendFpretFn(bool IsSuper) const {
- return IsSuper ? getMessageSendSuperFpretFn() : getMessageSendFpretFn();
- }
-
- llvm::Constant *getSendFpretFn2(bool IsSuper) const {
- return IsSuper ? getMessageSendSuperFpretFn2() : getMessageSendFpretFn();
- }
-
- ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm);
- ~ObjCCommonTypesHelper(){}
-};
-
-/// ObjCTypesHelper - Helper class that encapsulates lazy
-/// construction of varies types used during ObjC generation.
-class ObjCTypesHelper : public ObjCCommonTypesHelper {
-public:
- /// SymtabTy - LLVM type for struct objc_symtab.
- const llvm::StructType *SymtabTy;
- /// SymtabPtrTy - LLVM type for struct objc_symtab *.
- const llvm::Type *SymtabPtrTy;
- /// ModuleTy - LLVM type for struct objc_module.
- const llvm::StructType *ModuleTy;
-
- /// ProtocolTy - LLVM type for struct objc_protocol.
- const llvm::StructType *ProtocolTy;
- /// ProtocolPtrTy - LLVM type for struct objc_protocol *.
- const llvm::Type *ProtocolPtrTy;
- /// ProtocolExtensionTy - LLVM type for struct
- /// objc_protocol_extension.
- const llvm::StructType *ProtocolExtensionTy;
- /// ProtocolExtensionTy - LLVM type for struct
- /// objc_protocol_extension *.
- const llvm::Type *ProtocolExtensionPtrTy;
- /// MethodDescriptionTy - LLVM type for struct
- /// objc_method_description.
- const llvm::StructType *MethodDescriptionTy;
- /// MethodDescriptionListTy - LLVM type for struct
- /// objc_method_description_list.
- const llvm::StructType *MethodDescriptionListTy;
- /// MethodDescriptionListPtrTy - LLVM type for struct
- /// objc_method_description_list *.
- const llvm::Type *MethodDescriptionListPtrTy;
- /// ProtocolListTy - LLVM type for struct objc_property_list.
- const llvm::Type *ProtocolListTy;
- /// ProtocolListPtrTy - LLVM type for struct objc_property_list*.
- const llvm::Type *ProtocolListPtrTy;
- /// CategoryTy - LLVM type for struct objc_category.
- const llvm::StructType *CategoryTy;
- /// ClassTy - LLVM type for struct objc_class.
- const llvm::StructType *ClassTy;
- /// ClassPtrTy - LLVM type for struct objc_class *.
- const llvm::Type *ClassPtrTy;
- /// ClassExtensionTy - LLVM type for struct objc_class_ext.
- const llvm::StructType *ClassExtensionTy;
- /// ClassExtensionPtrTy - LLVM type for struct objc_class_ext *.
- const llvm::Type *ClassExtensionPtrTy;
- // IvarTy - LLVM type for struct objc_ivar.
- const llvm::StructType *IvarTy;
- /// IvarListTy - LLVM type for struct objc_ivar_list.
- const llvm::Type *IvarListTy;
- /// IvarListPtrTy - LLVM type for struct objc_ivar_list *.
- const llvm::Type *IvarListPtrTy;
- /// MethodListTy - LLVM type for struct objc_method_list.
- const llvm::Type *MethodListTy;
- /// MethodListPtrTy - LLVM type for struct objc_method_list *.
- const llvm::Type *MethodListPtrTy;
-
- /// ExceptionDataTy - LLVM type for struct _objc_exception_data.
- const llvm::Type *ExceptionDataTy;
-
- /// ExceptionTryEnterFn - LLVM objc_exception_try_enter function.
- llvm::Constant *getExceptionTryEnterFn() {
- std::vector<const llvm::Type*> Params;
- Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
- return CGM.CreateRuntimeFunction(
- llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
- Params, false),
- "objc_exception_try_enter");
- }
-
- /// ExceptionTryExitFn - LLVM objc_exception_try_exit function.
- llvm::Constant *getExceptionTryExitFn() {
- std::vector<const llvm::Type*> Params;
- Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
- return CGM.CreateRuntimeFunction(
- llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
- Params, false),
- "objc_exception_try_exit");
- }
-
- /// ExceptionExtractFn - LLVM objc_exception_extract function.
- llvm::Constant *getExceptionExtractFn() {
- std::vector<const llvm::Type*> Params;
- Params.push_back(llvm::PointerType::getUnqual(ExceptionDataTy));
- return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
- Params, false),
- "objc_exception_extract");
-
- }
-
- /// ExceptionMatchFn - LLVM objc_exception_match function.
- llvm::Constant *getExceptionMatchFn() {
- std::vector<const llvm::Type*> Params;
- Params.push_back(ClassPtrTy);
- Params.push_back(ObjectPtrTy);
- return CGM.CreateRuntimeFunction(
- llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
- Params, false),
- "objc_exception_match");
-
- }
-
- /// SetJmpFn - LLVM _setjmp function.
- llvm::Constant *getSetJmpFn() {
- std::vector<const llvm::Type*> Params;
- Params.push_back(llvm::Type::getInt32PtrTy(VMContext));
- return
- CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
- Params, false),
- "_setjmp");
-
- }
-
-public:
- ObjCTypesHelper(CodeGen::CodeGenModule &cgm);
- ~ObjCTypesHelper() {}
-};
-
-/// ObjCNonFragileABITypesHelper - will have all types needed by objective-c's
-/// modern abi
-class ObjCNonFragileABITypesHelper : public ObjCCommonTypesHelper {
-public:
-
- // MethodListnfABITy - LLVM for struct _method_list_t
- const llvm::StructType *MethodListnfABITy;
-
- // MethodListnfABIPtrTy - LLVM for struct _method_list_t*
- const llvm::Type *MethodListnfABIPtrTy;
-
- // ProtocolnfABITy = LLVM for struct _protocol_t
- const llvm::StructType *ProtocolnfABITy;
-
- // ProtocolnfABIPtrTy = LLVM for struct _protocol_t*
- const llvm::Type *ProtocolnfABIPtrTy;
-
- // ProtocolListnfABITy - LLVM for struct _objc_protocol_list
- const llvm::StructType *ProtocolListnfABITy;
-
- // ProtocolListnfABIPtrTy - LLVM for struct _objc_protocol_list*
- const llvm::Type *ProtocolListnfABIPtrTy;
-
- // ClassnfABITy - LLVM for struct _class_t
- const llvm::StructType *ClassnfABITy;
-
- // ClassnfABIPtrTy - LLVM for struct _class_t*
- const llvm::Type *ClassnfABIPtrTy;
-
- // IvarnfABITy - LLVM for struct _ivar_t
- const llvm::StructType *IvarnfABITy;
-
- // IvarListnfABITy - LLVM for struct _ivar_list_t
- const llvm::StructType *IvarListnfABITy;
-
- // IvarListnfABIPtrTy = LLVM for struct _ivar_list_t*
- const llvm::Type *IvarListnfABIPtrTy;
-
- // ClassRonfABITy - LLVM for struct _class_ro_t
- const llvm::StructType *ClassRonfABITy;
-
- // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
- const llvm::Type *ImpnfABITy;
-
- // CategorynfABITy - LLVM for struct _category_t
- const llvm::StructType *CategorynfABITy;
-
- // New types for nonfragile abi messaging.
-
- // MessageRefTy - LLVM for:
- // struct _message_ref_t {
- // IMP messenger;
- // SEL name;
- // };
- const llvm::StructType *MessageRefTy;
- // MessageRefCTy - clang type for struct _message_ref_t
- QualType MessageRefCTy;
-
- // MessageRefPtrTy - LLVM for struct _message_ref_t*
- const llvm::Type *MessageRefPtrTy;
- // MessageRefCPtrTy - clang type for struct _message_ref_t*
- QualType MessageRefCPtrTy;
-
- // MessengerTy - Type of the messenger (shown as IMP above)
- const llvm::FunctionType *MessengerTy;
-
- // SuperMessageRefTy - LLVM for:
- // struct _super_message_ref_t {
- // SUPER_IMP messenger;
- // SEL name;
- // };
- const llvm::StructType *SuperMessageRefTy;
-
- // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
- const llvm::Type *SuperMessageRefPtrTy;
-
- llvm::Constant *getMessageSendFixupFn() {
- // id objc_msgSend_fixup(id, struct message_ref_t*, ...)
- std::vector<const llvm::Type*> Params;
- Params.push_back(ObjectPtrTy);
- Params.push_back(MessageRefPtrTy);
- return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
- Params, true),
- "objc_msgSend_fixup");
- }
-
- llvm::Constant *getMessageSendFpretFixupFn() {
- // id objc_msgSend_fpret_fixup(id, struct message_ref_t*, ...)
- std::vector<const llvm::Type*> Params;
- Params.push_back(ObjectPtrTy);
- Params.push_back(MessageRefPtrTy);
- return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
- Params, true),
- "objc_msgSend_fpret_fixup");
- }
-
- llvm::Constant *getMessageSendStretFixupFn() {
- // id objc_msgSend_stret_fixup(id, struct message_ref_t*, ...)
- std::vector<const llvm::Type*> Params;
- Params.push_back(ObjectPtrTy);
- Params.push_back(MessageRefPtrTy);
- return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
- Params, true),
- "objc_msgSend_stret_fixup");
- }
-
- llvm::Constant *getMessageSendIdFixupFn() {
- // id objc_msgSendId_fixup(id, struct message_ref_t*, ...)
- std::vector<const llvm::Type*> Params;
- Params.push_back(ObjectPtrTy);
- Params.push_back(MessageRefPtrTy);
- return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
- Params, true),
- "objc_msgSendId_fixup");
- }
-
- llvm::Constant *getMessageSendIdStretFixupFn() {
- // id objc_msgSendId_stret_fixup(id, struct message_ref_t*, ...)
- std::vector<const llvm::Type*> Params;
- Params.push_back(ObjectPtrTy);
- Params.push_back(MessageRefPtrTy);
- return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
- Params, true),
- "objc_msgSendId_stret_fixup");
- }
- llvm::Constant *getMessageSendSuper2FixupFn() {
- // id objc_msgSendSuper2_fixup (struct objc_super *,
- // struct _super_message_ref_t*, ...)
- std::vector<const llvm::Type*> Params;
- Params.push_back(SuperPtrTy);
- Params.push_back(SuperMessageRefPtrTy);
- return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
- Params, true),
- "objc_msgSendSuper2_fixup");
- }
-
- llvm::Constant *getMessageSendSuper2StretFixupFn() {
- // id objc_msgSendSuper2_stret_fixup(struct objc_super *,
- // struct _super_message_ref_t*, ...)
- std::vector<const llvm::Type*> Params;
- Params.push_back(SuperPtrTy);
- Params.push_back(SuperMessageRefPtrTy);
- return CGM.CreateRuntimeFunction(llvm::FunctionType::get(ObjectPtrTy,
- Params, true),
- "objc_msgSendSuper2_stret_fixup");
- }
-
-
-
- /// EHPersonalityPtr - LLVM value for an i8* to the Objective-C
- /// exception personality function.
- llvm::Value *getEHPersonalityPtr() {
- llvm::Constant *Personality =
- CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getInt32Ty(VMContext),
- true),
- "__objc_personality_v0");
- return llvm::ConstantExpr::getBitCast(Personality, Int8PtrTy);
- }
-
- llvm::Constant *getUnwindResumeOrRethrowFn() {
- std::vector<const llvm::Type*> Params;
- Params.push_back(Int8PtrTy);
- return CGM.CreateRuntimeFunction(
- llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
- Params, false),
- (CGM.getLangOptions().SjLjExceptions ? "_Unwind_SjLj_Resume" :
- "_Unwind_Resume_or_Rethrow"));
- }
-
- llvm::Constant *getObjCEndCatchFn() {
- return CGM.CreateRuntimeFunction(llvm::FunctionType::get(llvm::Type::getVoidTy(VMContext),
- false),
- "objc_end_catch");
-
- }
-
- llvm::Constant *getObjCBeginCatchFn() {
- std::vector<const llvm::Type*> Params;
- Params.push_back(Int8PtrTy);
- return CGM.CreateRuntimeFunction(llvm::FunctionType::get(Int8PtrTy,
- Params, false),
- "objc_begin_catch");
- }
-
- const llvm::StructType *EHTypeTy;
- const llvm::Type *EHTypePtrTy;
-
- ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm);
- ~ObjCNonFragileABITypesHelper(){}
-};
-
-class CGObjCCommonMac : public CodeGen::CGObjCRuntime {
-public:
- // FIXME - accessibility
- class GC_IVAR {
- public:
- unsigned ivar_bytepos;
- unsigned ivar_size;
- GC_IVAR(unsigned bytepos = 0, unsigned size = 0)
- : ivar_bytepos(bytepos), ivar_size(size) {}
-
- // Allow sorting based on byte pos.
- bool operator<(const GC_IVAR &b) const {
- return ivar_bytepos < b.ivar_bytepos;
- }
- };
-
- class SKIP_SCAN {
- public:
- unsigned skip;
- unsigned scan;
- SKIP_SCAN(unsigned _skip = 0, unsigned _scan = 0)
- : skip(_skip), scan(_scan) {}
- };
-
-protected:
- CodeGen::CodeGenModule &CGM;
- llvm::LLVMContext &VMContext;
- // FIXME! May not be needing this after all.
- unsigned ObjCABI;
-
- // gc ivar layout bitmap calculation helper caches.
- llvm::SmallVector<GC_IVAR, 16> SkipIvars;
- llvm::SmallVector<GC_IVAR, 16> IvarsInfo;
-
- /// LazySymbols - Symbols to generate a lazy reference for. See
- /// DefinedSymbols and FinishModule().
- llvm::SetVector<IdentifierInfo*> LazySymbols;
-
- /// DefinedSymbols - External symbols which are defined by this
- /// module. The symbols in this list and LazySymbols are used to add
- /// special linker symbols which ensure that Objective-C modules are
- /// linked properly.
- llvm::SetVector<IdentifierInfo*> DefinedSymbols;
-
- /// ClassNames - uniqued class names.
- llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassNames;
-
- /// MethodVarNames - uniqued method variable names.
- llvm::DenseMap<Selector, llvm::GlobalVariable*> MethodVarNames;
-
- /// DefinedCategoryNames - list of category names in form Class_Category.
- llvm::SetVector<std::string> DefinedCategoryNames;
-
- /// MethodVarTypes - uniqued method type signatures. We have to use
- /// a StringMap here because have no other unique reference.
- llvm::StringMap<llvm::GlobalVariable*> MethodVarTypes;
-
- /// MethodDefinitions - map of methods which have been defined in
- /// this translation unit.
- llvm::DenseMap<const ObjCMethodDecl*, llvm::Function*> MethodDefinitions;
-
- /// PropertyNames - uniqued method variable names.
- llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> PropertyNames;
-
- /// ClassReferences - uniqued class references.
- llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> ClassReferences;
-
- /// SelectorReferences - uniqued selector references.
- llvm::DenseMap<Selector, llvm::GlobalVariable*> SelectorReferences;
-
- /// Protocols - Protocols for which an objc_protocol structure has
- /// been emitted. Forward declarations are handled by creating an
- /// empty structure whose initializer is filled in when/if defined.
- llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> Protocols;
-
- /// DefinedProtocols - Protocols which have actually been
- /// defined. We should not need this, see FIXME in GenerateProtocol.
- llvm::DenseSet<IdentifierInfo*> DefinedProtocols;
-
- /// DefinedClasses - List of defined classes.
- std::vector<llvm::GlobalValue*> DefinedClasses;
-
- /// DefinedNonLazyClasses - List of defined "non-lazy" classes.
- std::vector<llvm::GlobalValue*> DefinedNonLazyClasses;
-
- /// DefinedCategories - List of defined categories.
- std::vector<llvm::GlobalValue*> DefinedCategories;
-
- /// DefinedNonLazyCategories - List of defined "non-lazy" categories.
- std::vector<llvm::GlobalValue*> DefinedNonLazyCategories;
-
- /// GetNameForMethod - Return a name for the given method.
- /// \param[out] NameOut - The return value.
- void GetNameForMethod(const ObjCMethodDecl *OMD,
- const ObjCContainerDecl *CD,
- llvm::SmallVectorImpl<char> &NameOut);
-
- /// GetMethodVarName - Return a unique constant for the given
- /// selector's name. The return value has type char *.
- llvm::Constant *GetMethodVarName(Selector Sel);
- llvm::Constant *GetMethodVarName(IdentifierInfo *Ident);
- llvm::Constant *GetMethodVarName(const std::string &Name);
-
- /// GetMethodVarType - Return a unique constant for the given
- /// selector's name. The return value has type char *.
-
- // FIXME: This is a horrible name.
- llvm::Constant *GetMethodVarType(const ObjCMethodDecl *D);
- llvm::Constant *GetMethodVarType(const FieldDecl *D);
-
- /// GetPropertyName - Return a unique constant for the given
- /// name. The return value has type char *.
- llvm::Constant *GetPropertyName(IdentifierInfo *Ident);
-
- // FIXME: This can be dropped once string functions are unified.
- llvm::Constant *GetPropertyTypeString(const ObjCPropertyDecl *PD,
- const Decl *Container);
-
- /// GetClassName - Return a unique constant for the given selector's
- /// name. The return value has type char *.
- llvm::Constant *GetClassName(IdentifierInfo *Ident);
-
- /// BuildIvarLayout - Builds ivar layout bitmap for the class
- /// implementation for the __strong or __weak case.
- ///
- llvm::Constant *BuildIvarLayout(const ObjCImplementationDecl *OI,
- bool ForStrongLayout);
-
- void BuildAggrIvarRecordLayout(const RecordType *RT,
- unsigned int BytePos, bool ForStrongLayout,
- bool &HasUnion);
- void BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
- const llvm::StructLayout *Layout,
- const RecordDecl *RD,
- const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
- unsigned int BytePos, bool ForStrongLayout,
- bool &HasUnion);
-
- /// GetIvarLayoutName - Returns a unique constant for the given
- /// ivar layout bitmap.
- llvm::Constant *GetIvarLayoutName(IdentifierInfo *Ident,
- const ObjCCommonTypesHelper &ObjCTypes);
-
- /// EmitPropertyList - Emit the given property list. The return
- /// value has type PropertyListPtrTy.
- llvm::Constant *EmitPropertyList(llvm::Twine Name,
- const Decl *Container,
- const ObjCContainerDecl *OCD,
- const ObjCCommonTypesHelper &ObjCTypes);
-
- /// PushProtocolProperties - Push protocol's property on the input stack.
- void PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
- std::vector<llvm::Constant*> &Properties,
- const Decl *Container,
- const ObjCProtocolDecl *PROTO,
- const ObjCCommonTypesHelper &ObjCTypes);
-
- /// GetProtocolRef - Return a reference to the internal protocol
- /// description, creating an empty one if it has not been
- /// defined. The return value has type ProtocolPtrTy.
- llvm::Constant *GetProtocolRef(const ObjCProtocolDecl *PD);
-
- /// CreateMetadataVar - Create a global variable with internal
- /// linkage for use by the Objective-C runtime.
- ///
- /// This is a convenience wrapper which not only creates the
- /// variable, but also sets the section and alignment and adds the
- /// global to the "llvm.used" list.
- ///
- /// \param Name - The variable name.
- /// \param Init - The variable initializer; this is also used to
- /// define the type of the variable.
- /// \param Section - The section the variable should go into, or 0.
- /// \param Align - The alignment for the variable, or 0.
- /// \param AddToUsed - Whether the variable should be added to
- /// "llvm.used".
- llvm::GlobalVariable *CreateMetadataVar(llvm::Twine Name,
- llvm::Constant *Init,
- const char *Section,
- unsigned Align,
- bool AddToUsed);
-
- CodeGen::RValue EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF,
- ReturnValueSlot Return,
- QualType ResultType,
- llvm::Value *Sel,
- llvm::Value *Arg0,
- QualType Arg0Ty,
- bool IsSuper,
- const CallArgList &CallArgs,
- const ObjCMethodDecl *OMD,
- const ObjCCommonTypesHelper &ObjCTypes);
-
- /// EmitImageInfo - Emit the image info marker used to encode some module
- /// level information.
- void EmitImageInfo();
-
-public:
- CGObjCCommonMac(CodeGen::CodeGenModule &cgm) :
- CGM(cgm), VMContext(cgm.getLLVMContext()) { }
-
- virtual llvm::Constant *GenerateConstantString(const StringLiteral *SL);
-
- virtual llvm::Function *GenerateMethod(const ObjCMethodDecl *OMD,
- const ObjCContainerDecl *CD=0);
-
- virtual void GenerateProtocol(const ObjCProtocolDecl *PD);
-
- /// GetOrEmitProtocol - Get the protocol object for the given
- /// declaration, emitting it if necessary. The return value has type
- /// ProtocolPtrTy.
- virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD)=0;
-
- /// GetOrEmitProtocolRef - Get a forward reference to the protocol
- /// object for the given declaration, emitting it if needed. These
- /// forward references will be filled in with empty bodies if no
- /// definition is seen. The return value has type ProtocolPtrTy.
- virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD)=0;
-};
-
-class CGObjCMac : public CGObjCCommonMac {
-private:
- ObjCTypesHelper ObjCTypes;
-
- /// EmitModuleInfo - Another marker encoding module level
- /// information.
- void EmitModuleInfo();
-
- /// EmitModuleSymols - Emit module symbols, the list of defined
- /// classes and categories. The result has type SymtabPtrTy.
- llvm::Constant *EmitModuleSymbols();
-
- /// FinishModule - Write out global data structures at the end of
- /// processing a translation unit.
- void FinishModule();
-
- /// EmitClassExtension - Generate the class extension structure used
- /// to store the weak ivar layout and properties. The return value
- /// has type ClassExtensionPtrTy.
- llvm::Constant *EmitClassExtension(const ObjCImplementationDecl *ID);
-
- /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
- /// for the given class.
- llvm::Value *EmitClassRef(CGBuilderTy &Builder,
- const ObjCInterfaceDecl *ID);
-
- /// EmitSuperClassRef - Emits reference to class's main metadata class.
- llvm::Value *EmitSuperClassRef(const ObjCInterfaceDecl *ID);
-
- CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
- ReturnValueSlot Return,
- QualType ResultType,
- Selector Sel,
- llvm::Value *Arg0,
- QualType Arg0Ty,
- bool IsSuper,
- const CallArgList &CallArgs);
-
- /// EmitIvarList - Emit the ivar list for the given
- /// implementation. If ForClass is true the list of class ivars
- /// (i.e. metaclass ivars) is emitted, otherwise the list of
- /// interface ivars will be emitted. The return value has type
- /// IvarListPtrTy.
- llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID,
- bool ForClass);
-
- /// EmitMetaClass - Emit a forward reference to the class structure
- /// for the metaclass of the given interface. The return value has
- /// type ClassPtrTy.
- llvm::Constant *EmitMetaClassRef(const ObjCInterfaceDecl *ID);
-
- /// EmitMetaClass - Emit a class structure for the metaclass of the
- /// given implementation. The return value has type ClassPtrTy.
- llvm::Constant *EmitMetaClass(const ObjCImplementationDecl *ID,
- llvm::Constant *Protocols,
- const ConstantVector &Methods);
-
- llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
-
- llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
-
- /// EmitMethodList - Emit the method list for the given
- /// implementation. The return value has type MethodListPtrTy.
- llvm::Constant *EmitMethodList(llvm::Twine Name,
- const char *Section,
- const ConstantVector &Methods);
-
- /// EmitMethodDescList - Emit a method description list for a list of
- /// method declarations.
- /// - TypeName: The name for the type containing the methods.
- /// - IsProtocol: True iff these methods are for a protocol.
- /// - ClassMethds: True iff these are class methods.
- /// - Required: When true, only "required" methods are
- /// listed. Similarly, when false only "optional" methods are
- /// listed. For classes this should always be true.
- /// - begin, end: The method list to output.
- ///
- /// The return value has type MethodDescriptionListPtrTy.
- llvm::Constant *EmitMethodDescList(llvm::Twine Name,
- const char *Section,
- const ConstantVector &Methods);
-
- /// GetOrEmitProtocol - Get the protocol object for the given
- /// declaration, emitting it if necessary. The return value has type
- /// ProtocolPtrTy.
- virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
-
- /// GetOrEmitProtocolRef - Get a forward reference to the protocol
- /// object for the given declaration, emitting it if needed. These
- /// forward references will be filled in with empty bodies if no
- /// definition is seen. The return value has type ProtocolPtrTy.
- virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
-
- /// EmitProtocolExtension - Generate the protocol extension
- /// structure used to store optional instance and class methods, and
- /// protocol properties. The return value has type
- /// ProtocolExtensionPtrTy.
- llvm::Constant *
- EmitProtocolExtension(const ObjCProtocolDecl *PD,
- const ConstantVector &OptInstanceMethods,
- const ConstantVector &OptClassMethods);
-
- /// EmitProtocolList - Generate the list of referenced
- /// protocols. The return value has type ProtocolListPtrTy.
- llvm::Constant *EmitProtocolList(llvm::Twine Name,
- ObjCProtocolDecl::protocol_iterator begin,
- ObjCProtocolDecl::protocol_iterator end);
-
- /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
- /// for the given selector.
- llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
- bool lval=false);
-
-public:
- CGObjCMac(CodeGen::CodeGenModule &cgm);
-
- virtual llvm::Function *ModuleInitFunction();
-
- virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
- ReturnValueSlot Return,
- QualType ResultType,
- Selector Sel,
- llvm::Value *Receiver,
- const CallArgList &CallArgs,
- const ObjCInterfaceDecl *Class,
- const ObjCMethodDecl *Method);
-
- virtual CodeGen::RValue
- GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
- ReturnValueSlot Return,
- QualType ResultType,
- Selector Sel,
- const ObjCInterfaceDecl *Class,
- bool isCategoryImpl,
- llvm::Value *Receiver,
- bool IsClassMessage,
- const CallArgList &CallArgs,
- const ObjCMethodDecl *Method);
-
- virtual llvm::Value *GetClass(CGBuilderTy &Builder,
- const ObjCInterfaceDecl *ID);
-
- virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
- bool lval = false);
-
- /// The NeXT/Apple runtimes do not support typed selectors; just emit an
- /// untyped one.
- virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
- const ObjCMethodDecl *Method);
-
- virtual llvm::Constant *GetEHType(QualType T);
-
- virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
-
- virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
-
- virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
- const ObjCProtocolDecl *PD);
-
- virtual llvm::Constant *GetPropertyGetFunction();
- virtual llvm::Constant *GetPropertySetFunction();
- virtual llvm::Constant *GetCopyStructFunction();
- virtual llvm::Constant *EnumerationMutationFunction();
-
- virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
- const ObjCAtTryStmt &S);
- virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
- const ObjCAtSynchronizedStmt &S);
- void EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF, const Stmt &S);
- virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
- const ObjCAtThrowStmt &S);
- virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
- llvm::Value *AddrWeakObj);
- virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dst);
- virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dest,
- bool threadlocal = false);
- virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dest,
- llvm::Value *ivarOffset);
- virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dest);
- virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
- llvm::Value *dest, llvm::Value *src,
- llvm::Value *size);
-
- virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
- QualType ObjectTy,
- llvm::Value *BaseValue,
- const ObjCIvarDecl *Ivar,
- unsigned CVRQualifiers);
- virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
- const ObjCInterfaceDecl *Interface,
- const ObjCIvarDecl *Ivar);
-};
-
-class CGObjCNonFragileABIMac : public CGObjCCommonMac {
-private:
- ObjCNonFragileABITypesHelper ObjCTypes;
- llvm::GlobalVariable* ObjCEmptyCacheVar;
- llvm::GlobalVariable* ObjCEmptyVtableVar;
-
- /// SuperClassReferences - uniqued super class references.
- llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> SuperClassReferences;
-
- /// MetaClassReferences - uniqued meta class references.
- llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> MetaClassReferences;
-
- /// EHTypeReferences - uniqued class ehtype references.
- llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*> EHTypeReferences;
-
- /// NonLegacyDispatchMethods - List of methods for which we do *not* generate
- /// legacy messaging dispatch.
- llvm::DenseSet<Selector> NonLegacyDispatchMethods;
-
- /// DefinedMetaClasses - List of defined meta-classes.
- std::vector<llvm::GlobalValue*> DefinedMetaClasses;
-
- /// LegacyDispatchedSelector - Returns true if SEL is not in the list of
- /// NonLegacyDispatchMethods; false otherwise.
- bool LegacyDispatchedSelector(Selector Sel);
-
- /// FinishNonFragileABIModule - Write out global data structures at the end of
- /// processing a translation unit.
- void FinishNonFragileABIModule();
-
- /// AddModuleClassList - Add the given list of class pointers to the
- /// module with the provided symbol and section names.
- void AddModuleClassList(const std::vector<llvm::GlobalValue*> &Container,
- const char *SymbolName,
- const char *SectionName);
-
- llvm::GlobalVariable * BuildClassRoTInitializer(unsigned flags,
- unsigned InstanceStart,
- unsigned InstanceSize,
- const ObjCImplementationDecl *ID);
- llvm::GlobalVariable * BuildClassMetaData(std::string &ClassName,
- llvm::Constant *IsAGV,
- llvm::Constant *SuperClassGV,
- llvm::Constant *ClassRoGV,
- bool HiddenVisibility);
-
- llvm::Constant *GetMethodConstant(const ObjCMethodDecl *MD);
-
- llvm::Constant *GetMethodDescriptionConstant(const ObjCMethodDecl *MD);
-
- /// EmitMethodList - Emit the method list for the given
- /// implementation. The return value has type MethodListnfABITy.
- llvm::Constant *EmitMethodList(llvm::Twine Name,
- const char *Section,
- const ConstantVector &Methods);
- /// EmitIvarList - Emit the ivar list for the given
- /// implementation. If ForClass is true the list of class ivars
- /// (i.e. metaclass ivars) is emitted, otherwise the list of
- /// interface ivars will be emitted. The return value has type
- /// IvarListnfABIPtrTy.
- llvm::Constant *EmitIvarList(const ObjCImplementationDecl *ID);
-
- llvm::Constant *EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
- const ObjCIvarDecl *Ivar,
- unsigned long int offset);
-
- /// GetOrEmitProtocol - Get the protocol object for the given
- /// declaration, emitting it if necessary. The return value has type
- /// ProtocolPtrTy.
- virtual llvm::Constant *GetOrEmitProtocol(const ObjCProtocolDecl *PD);
-
- /// GetOrEmitProtocolRef - Get a forward reference to the protocol
- /// object for the given declaration, emitting it if needed. These
- /// forward references will be filled in with empty bodies if no
- /// definition is seen. The return value has type ProtocolPtrTy.
- virtual llvm::Constant *GetOrEmitProtocolRef(const ObjCProtocolDecl *PD);
-
- /// EmitProtocolList - Generate the list of referenced
- /// protocols. The return value has type ProtocolListPtrTy.
- llvm::Constant *EmitProtocolList(llvm::Twine Name,
- ObjCProtocolDecl::protocol_iterator begin,
- ObjCProtocolDecl::protocol_iterator end);
-
- CodeGen::RValue EmitMessageSend(CodeGen::CodeGenFunction &CGF,
- ReturnValueSlot Return,
- QualType ResultType,
- Selector Sel,
- llvm::Value *Receiver,
- QualType Arg0Ty,
- bool IsSuper,
- const CallArgList &CallArgs);
-
- /// GetClassGlobal - Return the global variable for the Objective-C
- /// class of the given name.
- llvm::GlobalVariable *GetClassGlobal(const std::string &Name);
-
- /// EmitClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
- /// for the given class reference.
- llvm::Value *EmitClassRef(CGBuilderTy &Builder,
- const ObjCInterfaceDecl *ID);
-
- /// EmitSuperClassRef - Return a Value*, of type ObjCTypes.ClassPtrTy,
- /// for the given super class reference.
- llvm::Value *EmitSuperClassRef(CGBuilderTy &Builder,
- const ObjCInterfaceDecl *ID);
-
- /// EmitMetaClassRef - Return a Value * of the address of _class_t
- /// meta-data
- llvm::Value *EmitMetaClassRef(CGBuilderTy &Builder,
- const ObjCInterfaceDecl *ID);
-
- /// ObjCIvarOffsetVariable - Returns the ivar offset variable for
- /// the given ivar.
- ///
- llvm::GlobalVariable * ObjCIvarOffsetVariable(
- const ObjCInterfaceDecl *ID,
- const ObjCIvarDecl *Ivar);
-
- /// EmitSelector - Return a Value*, of type ObjCTypes.SelectorPtrTy,
- /// for the given selector.
- llvm::Value *EmitSelector(CGBuilderTy &Builder, Selector Sel,
- bool lval=false);
-
- /// GetInterfaceEHType - Get the cached ehtype for the given Objective-C
- /// interface. The return value has type EHTypePtrTy.
- llvm::Constant *GetInterfaceEHType(const ObjCInterfaceDecl *ID,
- bool ForDefinition);
-
- const char *getMetaclassSymbolPrefix() const {
- return "OBJC_METACLASS_$_";
- }
-
- const char *getClassSymbolPrefix() const {
- return "OBJC_CLASS_$_";
- }
-
- void GetClassSizeInfo(const ObjCImplementationDecl *OID,
- uint32_t &InstanceStart,
- uint32_t &InstanceSize);
-
- // Shamelessly stolen from Analysis/CFRefCount.cpp
- Selector GetNullarySelector(const char* name) const {
- IdentifierInfo* II = &CGM.getContext().Idents.get(name);
- return CGM.getContext().Selectors.getSelector(0, &II);
- }
-
- Selector GetUnarySelector(const char* name) const {
- IdentifierInfo* II = &CGM.getContext().Idents.get(name);
- return CGM.getContext().Selectors.getSelector(1, &II);
- }
-
- /// ImplementationIsNonLazy - Check whether the given category or
- /// class implementation is "non-lazy".
- bool ImplementationIsNonLazy(const ObjCImplDecl *OD) const;
-
-public:
- CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm);
- // FIXME. All stubs for now!
- virtual llvm::Function *ModuleInitFunction();
-
- virtual CodeGen::RValue GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
- ReturnValueSlot Return,
- QualType ResultType,
- Selector Sel,
- llvm::Value *Receiver,
- const CallArgList &CallArgs,
- const ObjCInterfaceDecl *Class,
- const ObjCMethodDecl *Method);
-
- virtual CodeGen::RValue
- GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
- ReturnValueSlot Return,
- QualType ResultType,
- Selector Sel,
- const ObjCInterfaceDecl *Class,
- bool isCategoryImpl,
- llvm::Value *Receiver,
- bool IsClassMessage,
- const CallArgList &CallArgs,
- const ObjCMethodDecl *Method);
-
- virtual llvm::Value *GetClass(CGBuilderTy &Builder,
- const ObjCInterfaceDecl *ID);
-
- virtual llvm::Value *GetSelector(CGBuilderTy &Builder, Selector Sel,
- bool lvalue = false)
- { return EmitSelector(Builder, Sel, lvalue); }
-
- /// The NeXT/Apple runtimes do not support typed selectors; just emit an
- /// untyped one.
- virtual llvm::Value *GetSelector(CGBuilderTy &Builder,
- const ObjCMethodDecl *Method)
- { return EmitSelector(Builder, Method->getSelector()); }
-
- virtual void GenerateCategory(const ObjCCategoryImplDecl *CMD);
-
- virtual void GenerateClass(const ObjCImplementationDecl *ClassDecl);
- virtual llvm::Value *GenerateProtocolRef(CGBuilderTy &Builder,
- const ObjCProtocolDecl *PD);
-
- virtual llvm::Constant *GetEHType(QualType T);
-
- virtual llvm::Constant *GetPropertyGetFunction() {
- return ObjCTypes.getGetPropertyFn();
- }
- virtual llvm::Constant *GetPropertySetFunction() {
- return ObjCTypes.getSetPropertyFn();
- }
-
- virtual llvm::Constant *GetCopyStructFunction() {
- return ObjCTypes.getCopyStructFn();
- }
-
- virtual llvm::Constant *EnumerationMutationFunction() {
- return ObjCTypes.getEnumerationMutationFn();
- }
-
- virtual void EmitTryStmt(CodeGen::CodeGenFunction &CGF,
- const ObjCAtTryStmt &S);
- virtual void EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
- const ObjCAtSynchronizedStmt &S);
- virtual void EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
- const ObjCAtThrowStmt &S);
- virtual llvm::Value * EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
- llvm::Value *AddrWeakObj);
- virtual void EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dst);
- virtual void EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dest,
- bool threadlocal = false);
- virtual void EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dest,
- llvm::Value *ivarOffset);
- virtual void EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dest);
- virtual void EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
- llvm::Value *dest, llvm::Value *src,
- llvm::Value *size);
- virtual LValue EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
- QualType ObjectTy,
- llvm::Value *BaseValue,
- const ObjCIvarDecl *Ivar,
- unsigned CVRQualifiers);
- virtual llvm::Value *EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
- const ObjCInterfaceDecl *Interface,
- const ObjCIvarDecl *Ivar);
-};
-
-} // end anonymous namespace
-
-/* *** Helper Functions *** */
-
-/// getConstantGEP() - Help routine to construct simple GEPs.
-static llvm::Constant *getConstantGEP(llvm::LLVMContext &VMContext,
- llvm::Constant *C,
- unsigned idx0,
- unsigned idx1) {
- llvm::Value *Idxs[] = {
- llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx0),
- llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), idx1)
- };
- return llvm::ConstantExpr::getGetElementPtr(C, Idxs, 2);
-}
-
-/// hasObjCExceptionAttribute - Return true if this class or any super
-/// class has the __objc_exception__ attribute.
-static bool hasObjCExceptionAttribute(ASTContext &Context,
- const ObjCInterfaceDecl *OID) {
- if (OID->hasAttr<ObjCExceptionAttr>())
- return true;
- if (const ObjCInterfaceDecl *Super = OID->getSuperClass())
- return hasObjCExceptionAttribute(Context, Super);
- return false;
-}
-
-/* *** CGObjCMac Public Interface *** */
-
-CGObjCMac::CGObjCMac(CodeGen::CodeGenModule &cgm) : CGObjCCommonMac(cgm),
- ObjCTypes(cgm) {
- ObjCABI = 1;
- EmitImageInfo();
-}
-
-/// GetClass - Return a reference to the class for the given interface
-/// decl.
-llvm::Value *CGObjCMac::GetClass(CGBuilderTy &Builder,
- const ObjCInterfaceDecl *ID) {
- return EmitClassRef(Builder, ID);
-}
-
-/// GetSelector - Return the pointer to the unique'd string for this selector.
-llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, Selector Sel,
- bool lval) {
- return EmitSelector(Builder, Sel, lval);
-}
-llvm::Value *CGObjCMac::GetSelector(CGBuilderTy &Builder, const ObjCMethodDecl
- *Method) {
- return EmitSelector(Builder, Method->getSelector());
-}
-
-llvm::Constant *CGObjCMac::GetEHType(QualType T) {
- llvm_unreachable("asking for catch type for ObjC type in fragile runtime");
- return 0;
-}
-
-/// Generate a constant CFString object.
-/*
- struct __builtin_CFString {
- const int *isa; // point to __CFConstantStringClassReference
- int flags;
- const char *str;
- long length;
- };
-*/
-
-/// or Generate a constant NSString object.
-/*
- struct __builtin_NSString {
- const int *isa; // point to __NSConstantStringClassReference
- const char *str;
- unsigned int length;
- };
-*/
-
-llvm::Constant *CGObjCCommonMac::GenerateConstantString(
- const StringLiteral *SL) {
- return (CGM.getLangOptions().NoConstantCFStrings == 0 ?
- CGM.GetAddrOfConstantCFString(SL) :
- CGM.GetAddrOfConstantNSString(SL));
-}
-
-/// Generates a message send where the super is the receiver. This is
-/// a message send to self with special delivery semantics indicating
-/// which class's method should be called.
-CodeGen::RValue
-CGObjCMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
- ReturnValueSlot Return,
- QualType ResultType,
- Selector Sel,
- const ObjCInterfaceDecl *Class,
- bool isCategoryImpl,
- llvm::Value *Receiver,
- bool IsClassMessage,
- const CodeGen::CallArgList &CallArgs,
- const ObjCMethodDecl *Method) {
- // Create and init a super structure; this is a (receiver, class)
- // pair we will pass to objc_msgSendSuper.
- llvm::Value *ObjCSuper =
- CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super");
- llvm::Value *ReceiverAsObject =
- CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
- CGF.Builder.CreateStore(ReceiverAsObject,
- CGF.Builder.CreateStructGEP(ObjCSuper, 0));
-
- // If this is a class message the metaclass is passed as the target.
- llvm::Value *Target;
- if (IsClassMessage) {
- if (isCategoryImpl) {
- // Message sent to 'super' in a class method defined in a category
- // implementation requires an odd treatment.
- // If we are in a class method, we must retrieve the
- // _metaclass_ for the current class, pointed at by
- // the class's "isa" pointer. The following assumes that
- // isa" is the first ivar in a class (which it must be).
- Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
- Target = CGF.Builder.CreateStructGEP(Target, 0);
- Target = CGF.Builder.CreateLoad(Target);
- } else {
- llvm::Value *MetaClassPtr = EmitMetaClassRef(Class);
- llvm::Value *SuperPtr = CGF.Builder.CreateStructGEP(MetaClassPtr, 1);
- llvm::Value *Super = CGF.Builder.CreateLoad(SuperPtr);
- Target = Super;
- }
- }
- else if (isCategoryImpl)
- Target = EmitClassRef(CGF.Builder, Class->getSuperClass());
- else {
- llvm::Value *ClassPtr = EmitSuperClassRef(Class);
- ClassPtr = CGF.Builder.CreateStructGEP(ClassPtr, 1);
- Target = CGF.Builder.CreateLoad(ClassPtr);
- }
- // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
- // ObjCTypes types.
- const llvm::Type *ClassTy =
- CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
- Target = CGF.Builder.CreateBitCast(Target, ClassTy);
- CGF.Builder.CreateStore(Target,
- CGF.Builder.CreateStructGEP(ObjCSuper, 1));
- return EmitLegacyMessageSend(CGF, Return, ResultType,
- EmitSelector(CGF.Builder, Sel),
- ObjCSuper, ObjCTypes.SuperPtrCTy,
- true, CallArgs, Method, ObjCTypes);
-}
-
-/// Generate code for a message send expression.
-CodeGen::RValue CGObjCMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
- ReturnValueSlot Return,
- QualType ResultType,
- Selector Sel,
- llvm::Value *Receiver,
- const CallArgList &CallArgs,
- const ObjCInterfaceDecl *Class,
- const ObjCMethodDecl *Method) {
- return EmitLegacyMessageSend(CGF, Return, ResultType,
- EmitSelector(CGF.Builder, Sel),
- Receiver, CGF.getContext().getObjCIdType(),
- false, CallArgs, Method, ObjCTypes);
-}
-
-CodeGen::RValue
-CGObjCCommonMac::EmitLegacyMessageSend(CodeGen::CodeGenFunction &CGF,
- ReturnValueSlot Return,
- QualType ResultType,
- llvm::Value *Sel,
- llvm::Value *Arg0,
- QualType Arg0Ty,
- bool IsSuper,
- const CallArgList &CallArgs,
- const ObjCMethodDecl *Method,
- const ObjCCommonTypesHelper &ObjCTypes) {
- CallArgList ActualArgs;
- if (!IsSuper)
- Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp");
- ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty));
- ActualArgs.push_back(std::make_pair(RValue::get(Sel),
- CGF.getContext().getObjCSelType()));
- ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
-
- CodeGenTypes &Types = CGM.getTypes();
- const CGFunctionInfo &FnInfo = Types.getFunctionInfo(ResultType, ActualArgs,
- FunctionType::ExtInfo());
- const llvm::FunctionType *FTy =
- Types.GetFunctionType(FnInfo, Method ? Method->isVariadic() : false);
-
- if (Method)
- assert(CGM.getContext().getCanonicalType(Method->getResultType()) ==
- CGM.getContext().getCanonicalType(ResultType) &&
- "Result type mismatch!");
-
- llvm::Constant *Fn = NULL;
- if (CGM.ReturnTypeUsesSRet(FnInfo)) {
- Fn = (ObjCABI == 2) ? ObjCTypes.getSendStretFn2(IsSuper)
- : ObjCTypes.getSendStretFn(IsSuper);
- } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {
- Fn = (ObjCABI == 2) ? ObjCTypes.getSendFpretFn2(IsSuper)
- : ObjCTypes.getSendFpretFn(IsSuper);
- } else {
- Fn = (ObjCABI == 2) ? ObjCTypes.getSendFn2(IsSuper)
- : ObjCTypes.getSendFn(IsSuper);
- }
- Fn = llvm::ConstantExpr::getBitCast(Fn, llvm::PointerType::getUnqual(FTy));
- return CGF.EmitCall(FnInfo, Fn, Return, ActualArgs);
-}
-
-llvm::Value *CGObjCMac::GenerateProtocolRef(CGBuilderTy &Builder,
- const ObjCProtocolDecl *PD) {
- // FIXME: I don't understand why gcc generates this, or where it is
- // resolved. Investigate. Its also wasteful to look this up over and over.
- LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
-
- return llvm::ConstantExpr::getBitCast(GetProtocolRef(PD),
- ObjCTypes.ExternalProtocolPtrTy);
-}
-
-void CGObjCCommonMac::GenerateProtocol(const ObjCProtocolDecl *PD) {
- // FIXME: We shouldn't need this, the protocol decl should contain enough
- // information to tell us whether this was a declaration or a definition.
- DefinedProtocols.insert(PD->getIdentifier());
-
- // If we have generated a forward reference to this protocol, emit
- // it now. Otherwise do nothing, the protocol objects are lazily
- // emitted.
- if (Protocols.count(PD->getIdentifier()))
- GetOrEmitProtocol(PD);
-}
-
-llvm::Constant *CGObjCCommonMac::GetProtocolRef(const ObjCProtocolDecl *PD) {
- if (DefinedProtocols.count(PD->getIdentifier()))
- return GetOrEmitProtocol(PD);
- return GetOrEmitProtocolRef(PD);
-}
-
-/*
-// APPLE LOCAL radar 4585769 - Objective-C 1.0 extensions
-struct _objc_protocol {
-struct _objc_protocol_extension *isa;
-char *protocol_name;
-struct _objc_protocol_list *protocol_list;
-struct _objc__method_prototype_list *instance_methods;
-struct _objc__method_prototype_list *class_methods
-};
-
-See EmitProtocolExtension().
-*/
-llvm::Constant *CGObjCMac::GetOrEmitProtocol(const ObjCProtocolDecl *PD) {
- llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
-
- // Early exit if a defining object has already been generated.
- if (Entry && Entry->hasInitializer())
- return Entry;
-
- // FIXME: I don't understand why gcc generates this, or where it is
- // resolved. Investigate. Its also wasteful to look this up over and over.
- LazySymbols.insert(&CGM.getContext().Idents.get("Protocol"));
-
- // Construct method lists.
- std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
- std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
- for (ObjCProtocolDecl::instmeth_iterator
- i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
- ObjCMethodDecl *MD = *i;
- llvm::Constant *C = GetMethodDescriptionConstant(MD);
- if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
- OptInstanceMethods.push_back(C);
- } else {
- InstanceMethods.push_back(C);
- }
- }
-
- for (ObjCProtocolDecl::classmeth_iterator
- i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
- ObjCMethodDecl *MD = *i;
- llvm::Constant *C = GetMethodDescriptionConstant(MD);
- if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
- OptClassMethods.push_back(C);
- } else {
- ClassMethods.push_back(C);
- }
- }
-
- std::vector<llvm::Constant*> Values(5);
- Values[0] = EmitProtocolExtension(PD, OptInstanceMethods, OptClassMethods);
- Values[1] = GetClassName(PD->getIdentifier());
- Values[2] =
- EmitProtocolList("\01L_OBJC_PROTOCOL_REFS_" + PD->getName(),
- PD->protocol_begin(),
- PD->protocol_end());
- Values[3] =
- EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_" + PD->getName(),
- "__OBJC,__cat_inst_meth,regular,no_dead_strip",
- InstanceMethods);
- Values[4] =
- EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_" + PD->getName(),
- "__OBJC,__cat_cls_meth,regular,no_dead_strip",
- ClassMethods);
- llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
- Values);
-
- if (Entry) {
- // Already created, fix the linkage and update the initializer.
- Entry->setLinkage(llvm::GlobalValue::InternalLinkage);
- Entry->setInitializer(Init);
- } else {
- Entry =
- new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
- llvm::GlobalValue::InternalLinkage,
- Init,
- "\01L_OBJC_PROTOCOL_" + PD->getName());
- Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
- // FIXME: Is this necessary? Why only for protocol?
- Entry->setAlignment(4);
- }
- CGM.AddUsedGlobal(Entry);
-
- return Entry;
-}
-
-llvm::Constant *CGObjCMac::GetOrEmitProtocolRef(const ObjCProtocolDecl *PD) {
- llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
-
- if (!Entry) {
- // We use the initializer as a marker of whether this is a forward
- // reference or not. At module finalization we add the empty
- // contents for protocols which were referenced but never defined.
- Entry =
- new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolTy, false,
- llvm::GlobalValue::ExternalLinkage,
- 0,
- "\01L_OBJC_PROTOCOL_" + PD->getName());
- Entry->setSection("__OBJC,__protocol,regular,no_dead_strip");
- // FIXME: Is this necessary? Why only for protocol?
- Entry->setAlignment(4);
- }
-
- return Entry;
-}
-
-/*
- struct _objc_protocol_extension {
- uint32_t size;
- struct objc_method_description_list *optional_instance_methods;
- struct objc_method_description_list *optional_class_methods;
- struct objc_property_list *instance_properties;
- };
-*/
-llvm::Constant *
-CGObjCMac::EmitProtocolExtension(const ObjCProtocolDecl *PD,
- const ConstantVector &OptInstanceMethods,
- const ConstantVector &OptClassMethods) {
- uint64_t Size =
- CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolExtensionTy);
- std::vector<llvm::Constant*> Values(4);
- Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
- Values[1] =
- EmitMethodDescList("\01L_OBJC_PROTOCOL_INSTANCE_METHODS_OPT_"
- + PD->getName(),
- "__OBJC,__cat_inst_meth,regular,no_dead_strip",
- OptInstanceMethods);
- Values[2] =
- EmitMethodDescList("\01L_OBJC_PROTOCOL_CLASS_METHODS_OPT_" + PD->getName(),
- "__OBJC,__cat_cls_meth,regular,no_dead_strip",
- OptClassMethods);
- Values[3] = EmitPropertyList("\01L_OBJC_$_PROP_PROTO_LIST_" + PD->getName(),
- 0, PD, ObjCTypes);
-
- // Return null if no extension bits are used.
- if (Values[1]->isNullValue() && Values[2]->isNullValue() &&
- Values[3]->isNullValue())
- return llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
-
- llvm::Constant *Init =
- llvm::ConstantStruct::get(ObjCTypes.ProtocolExtensionTy, Values);
-
- // No special section, but goes in llvm.used
- return CreateMetadataVar("\01L_OBJC_PROTOCOLEXT_" + PD->getName(),
- Init,
- 0, 0, true);
-}
-
-/*
- struct objc_protocol_list {
- struct objc_protocol_list *next;
- long count;
- Protocol *list[];
- };
-*/
-llvm::Constant *
-CGObjCMac::EmitProtocolList(llvm::Twine Name,
- ObjCProtocolDecl::protocol_iterator begin,
- ObjCProtocolDecl::protocol_iterator end) {
- std::vector<llvm::Constant*> ProtocolRefs;
-
- for (; begin != end; ++begin)
- ProtocolRefs.push_back(GetProtocolRef(*begin));
-
- // Just return null for empty protocol lists
- if (ProtocolRefs.empty())
- return llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
-
- // This list is null terminated.
- ProtocolRefs.push_back(llvm::Constant::getNullValue(ObjCTypes.ProtocolPtrTy));
-
- std::vector<llvm::Constant*> Values(3);
- // This field is only used by the runtime.
- Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
- Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy,
- ProtocolRefs.size() - 1);
- Values[2] =
- llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.ProtocolPtrTy,
- ProtocolRefs.size()),
- ProtocolRefs);
-
- llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
- llvm::GlobalVariable *GV =
- CreateMetadataVar(Name, Init, "__OBJC,__cat_cls_meth,regular,no_dead_strip",
- 4, false);
- return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListPtrTy);
-}
-
-void CGObjCCommonMac::PushProtocolProperties(llvm::SmallPtrSet<const IdentifierInfo*, 16> &PropertySet,
- std::vector<llvm::Constant*> &Properties,
- const Decl *Container,
- const ObjCProtocolDecl *PROTO,
- const ObjCCommonTypesHelper &ObjCTypes) {
- std::vector<llvm::Constant*> Prop(2);
- for (ObjCProtocolDecl::protocol_iterator P = PROTO->protocol_begin(),
- E = PROTO->protocol_end(); P != E; ++P)
- PushProtocolProperties(PropertySet, Properties, Container, (*P), ObjCTypes);
- for (ObjCContainerDecl::prop_iterator I = PROTO->prop_begin(),
- E = PROTO->prop_end(); I != E; ++I) {
- const ObjCPropertyDecl *PD = *I;
- if (!PropertySet.insert(PD->getIdentifier()))
- continue;
- Prop[0] = GetPropertyName(PD->getIdentifier());
- Prop[1] = GetPropertyTypeString(PD, Container);
- Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy, Prop));
- }
-}
-
-/*
- struct _objc_property {
- const char * const name;
- const char * const attributes;
- };
-
- struct _objc_property_list {
- uint32_t entsize; // sizeof (struct _objc_property)
- uint32_t prop_count;
- struct _objc_property[prop_count];
- };
-*/
-llvm::Constant *CGObjCCommonMac::EmitPropertyList(llvm::Twine Name,
- const Decl *Container,
- const ObjCContainerDecl *OCD,
- const ObjCCommonTypesHelper &ObjCTypes) {
- std::vector<llvm::Constant*> Properties, Prop(2);
- llvm::SmallPtrSet<const IdentifierInfo*, 16> PropertySet;
- for (ObjCContainerDecl::prop_iterator I = OCD->prop_begin(),
- E = OCD->prop_end(); I != E; ++I) {
- const ObjCPropertyDecl *PD = *I;
- PropertySet.insert(PD->getIdentifier());
- Prop[0] = GetPropertyName(PD->getIdentifier());
- Prop[1] = GetPropertyTypeString(PD, Container);
- Properties.push_back(llvm::ConstantStruct::get(ObjCTypes.PropertyTy,
- Prop));
- }
- if (const ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) {
- for (ObjCInterfaceDecl::protocol_iterator P = OID->protocol_begin(),
- E = OID->protocol_end(); P != E; ++P)
- PushProtocolProperties(PropertySet, Properties, Container, (*P),
- ObjCTypes);
- }
- else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(OCD)) {
- for (ObjCCategoryDecl::protocol_iterator P = CD->protocol_begin(),
- E = CD->protocol_end(); P != E; ++P)
- PushProtocolProperties(PropertySet, Properties, Container, (*P),
- ObjCTypes);
- }
-
- // Return null for empty list.
- if (Properties.empty())
- return llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
-
- unsigned PropertySize =
- CGM.getTargetData().getTypeAllocSize(ObjCTypes.PropertyTy);
- std::vector<llvm::Constant*> Values(3);
- Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, PropertySize);
- Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Properties.size());
- llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.PropertyTy,
- Properties.size());
- Values[2] = llvm::ConstantArray::get(AT, Properties);
- llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
-
- llvm::GlobalVariable *GV =
- CreateMetadataVar(Name, Init,
- (ObjCABI == 2) ? "__DATA, __objc_const" :
- "__OBJC,__property,regular,no_dead_strip",
- (ObjCABI == 2) ? 8 : 4,
- true);
- return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.PropertyListPtrTy);
-}
-
-/*
- struct objc_method_description_list {
- int count;
- struct objc_method_description list[];
- };
-*/
-llvm::Constant *
-CGObjCMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
- std::vector<llvm::Constant*> Desc(2);
- Desc[0] =
- llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
- ObjCTypes.SelectorPtrTy);
- Desc[1] = GetMethodVarType(MD);
- return llvm::ConstantStruct::get(ObjCTypes.MethodDescriptionTy,
- Desc);
-}
-
-llvm::Constant *CGObjCMac::EmitMethodDescList(llvm::Twine Name,
- const char *Section,
- const ConstantVector &Methods) {
- // Return null for empty list.
- if (Methods.empty())
- return llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
-
- std::vector<llvm::Constant*> Values(2);
- Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
- llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodDescriptionTy,
- Methods.size());
- Values[1] = llvm::ConstantArray::get(AT, Methods);
- llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
-
- llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
- return llvm::ConstantExpr::getBitCast(GV,
- ObjCTypes.MethodDescriptionListPtrTy);
-}
-
-/*
- struct _objc_category {
- char *category_name;
- char *class_name;
- struct _objc_method_list *instance_methods;
- struct _objc_method_list *class_methods;
- struct _objc_protocol_list *protocols;
- uint32_t size; // <rdar://4585769>
- struct _objc_property_list *instance_properties;
- };
-*/
-void CGObjCMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
- unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.CategoryTy);
-
- // FIXME: This is poor design, the OCD should have a pointer to the category
- // decl. Additionally, note that Category can be null for the @implementation
- // w/o an @interface case. Sema should just create one for us as it does for
- // @implementation so everyone else can live life under a clear blue sky.
- const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
- const ObjCCategoryDecl *Category =
- Interface->FindCategoryDeclaration(OCD->getIdentifier());
-
- llvm::SmallString<256> ExtName;
- llvm::raw_svector_ostream(ExtName) << Interface->getName() << '_'
- << OCD->getName();
-
- std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
- for (ObjCCategoryImplDecl::instmeth_iterator
- i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
- // Instance methods should always be defined.
- InstanceMethods.push_back(GetMethodConstant(*i));
- }
- for (ObjCCategoryImplDecl::classmeth_iterator
- i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
- // Class methods should always be defined.
- ClassMethods.push_back(GetMethodConstant(*i));
- }
-
- std::vector<llvm::Constant*> Values(7);
- Values[0] = GetClassName(OCD->getIdentifier());
- Values[1] = GetClassName(Interface->getIdentifier());
- LazySymbols.insert(Interface->getIdentifier());
- Values[2] =
- EmitMethodList("\01L_OBJC_CATEGORY_INSTANCE_METHODS_" + ExtName.str(),
- "__OBJC,__cat_inst_meth,regular,no_dead_strip",
- InstanceMethods);
- Values[3] =
- EmitMethodList("\01L_OBJC_CATEGORY_CLASS_METHODS_" + ExtName.str(),
- "__OBJC,__cat_cls_meth,regular,no_dead_strip",
- ClassMethods);
- if (Category) {
- Values[4] =
- EmitProtocolList("\01L_OBJC_CATEGORY_PROTOCOLS_" + ExtName.str(),
- Category->protocol_begin(),
- Category->protocol_end());
- } else {
- Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
- }
- Values[5] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
-
- // If there is no category @interface then there can be no properties.
- if (Category) {
- Values[6] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
- OCD, Category, ObjCTypes);
- } else {
- Values[6] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
- }
-
- llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.CategoryTy,
- Values);
-
- llvm::GlobalVariable *GV =
- CreateMetadataVar("\01L_OBJC_CATEGORY_" + ExtName.str(), Init,
- "__OBJC,__category,regular,no_dead_strip",
- 4, true);
- DefinedCategories.push_back(GV);
- DefinedCategoryNames.insert(ExtName.str());
-}
-
-// FIXME: Get from somewhere?
-enum ClassFlags {
- eClassFlags_Factory = 0x00001,
- eClassFlags_Meta = 0x00002,
- // <rdr://5142207>
- eClassFlags_HasCXXStructors = 0x02000,
- eClassFlags_Hidden = 0x20000,
- eClassFlags_ABI2_Hidden = 0x00010,
- eClassFlags_ABI2_HasCXXStructors = 0x00004 // <rdr://4923634>
-};
-
-/*
- struct _objc_class {
- Class isa;
- Class super_class;
- const char *name;
- long version;
- long info;
- long instance_size;
- struct _objc_ivar_list *ivars;
- struct _objc_method_list *methods;
- struct _objc_cache *cache;
- struct _objc_protocol_list *protocols;
- // Objective-C 1.0 extensions (<rdr://4585769>)
- const char *ivar_layout;
- struct _objc_class_ext *ext;
- };
-
- See EmitClassExtension();
-*/
-void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
- DefinedSymbols.insert(ID->getIdentifier());
-
- std::string ClassName = ID->getNameAsString();
- // FIXME: Gross
- ObjCInterfaceDecl *Interface =
- const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
- llvm::Constant *Protocols =
- EmitProtocolList("\01L_OBJC_CLASS_PROTOCOLS_" + ID->getName(),
- Interface->protocol_begin(),
- Interface->protocol_end());
- unsigned Flags = eClassFlags_Factory;
- if (ID->getNumIvarInitializers())
- Flags |= eClassFlags_HasCXXStructors;
- unsigned Size =
- CGM.getContext().getASTObjCImplementationLayout(ID).getSize() / 8;
-
- // FIXME: Set CXX-structors flag.
- if (CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden)
- Flags |= eClassFlags_Hidden;
-
- std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
- for (ObjCImplementationDecl::instmeth_iterator
- i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
- // Instance methods should always be defined.
- InstanceMethods.push_back(GetMethodConstant(*i));
- }
- for (ObjCImplementationDecl::classmeth_iterator
- i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
- // Class methods should always be defined.
- ClassMethods.push_back(GetMethodConstant(*i));
- }
-
- for (ObjCImplementationDecl::propimpl_iterator
- i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
- ObjCPropertyImplDecl *PID = *i;
-
- if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize) {
- ObjCPropertyDecl *PD = PID->getPropertyDecl();
-
- if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
- if (llvm::Constant *C = GetMethodConstant(MD))
- InstanceMethods.push_back(C);
- if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
- if (llvm::Constant *C = GetMethodConstant(MD))
- InstanceMethods.push_back(C);
- }
- }
-
- std::vector<llvm::Constant*> Values(12);
- Values[ 0] = EmitMetaClass(ID, Protocols, ClassMethods);
- if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) {
- // Record a reference to the super class.
- LazySymbols.insert(Super->getIdentifier());
-
- Values[ 1] =
- llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
- ObjCTypes.ClassPtrTy);
- } else {
- Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
- }
- Values[ 2] = GetClassName(ID->getIdentifier());
- // Version is always 0.
- Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
- Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
- Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
- Values[ 6] = EmitIvarList(ID, false);
- Values[ 7] =
- EmitMethodList("\01L_OBJC_INSTANCE_METHODS_" + ID->getName(),
- "__OBJC,__inst_meth,regular,no_dead_strip",
- InstanceMethods);
- // cache is always NULL.
- Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
- Values[ 9] = Protocols;
- Values[10] = BuildIvarLayout(ID, true);
- Values[11] = EmitClassExtension(ID);
- llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
- Values);
- std::string Name("\01L_OBJC_CLASS_");
- Name += ClassName;
- const char *Section = "__OBJC,__class,regular,no_dead_strip";
- // Check for a forward reference.
- llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
- if (GV) {
- assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
- "Forward metaclass reference has incorrect type.");
- GV->setLinkage(llvm::GlobalValue::InternalLinkage);
- GV->setInitializer(Init);
- GV->setSection(Section);
- GV->setAlignment(4);
- CGM.AddUsedGlobal(GV);
- }
- else
- GV = CreateMetadataVar(Name, Init, Section, 4, true);
- DefinedClasses.push_back(GV);
-}
-
-llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
- llvm::Constant *Protocols,
- const ConstantVector &Methods) {
- unsigned Flags = eClassFlags_Meta;
- unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassTy);
-
- if (CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden)
- Flags |= eClassFlags_Hidden;
-
- std::vector<llvm::Constant*> Values(12);
- // The isa for the metaclass is the root of the hierarchy.
- const ObjCInterfaceDecl *Root = ID->getClassInterface();
- while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
- Root = Super;
- Values[ 0] =
- llvm::ConstantExpr::getBitCast(GetClassName(Root->getIdentifier()),
- ObjCTypes.ClassPtrTy);
- // The super class for the metaclass is emitted as the name of the
- // super class. The runtime fixes this up to point to the
- // *metaclass* for the super class.
- if (ObjCInterfaceDecl *Super = ID->getClassInterface()->getSuperClass()) {
- Values[ 1] =
- llvm::ConstantExpr::getBitCast(GetClassName(Super->getIdentifier()),
- ObjCTypes.ClassPtrTy);
- } else {
- Values[ 1] = llvm::Constant::getNullValue(ObjCTypes.ClassPtrTy);
- }
- Values[ 2] = GetClassName(ID->getIdentifier());
- // Version is always 0.
- Values[ 3] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
- Values[ 4] = llvm::ConstantInt::get(ObjCTypes.LongTy, Flags);
- Values[ 5] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
- Values[ 6] = EmitIvarList(ID, true);
- Values[ 7] =
- EmitMethodList("\01L_OBJC_CLASS_METHODS_" + ID->getNameAsString(),
- "__OBJC,__cls_meth,regular,no_dead_strip",
- Methods);
- // cache is always NULL.
- Values[ 8] = llvm::Constant::getNullValue(ObjCTypes.CachePtrTy);
- Values[ 9] = Protocols;
- // ivar_layout for metaclass is always NULL.
- Values[10] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
- // The class extension is always unused for metaclasses.
- Values[11] = llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
- llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassTy,
- Values);
-
- std::string Name("\01L_OBJC_METACLASS_");
- Name += ID->getNameAsCString();
-
- // Check for a forward reference.
- llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
- if (GV) {
- assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
- "Forward metaclass reference has incorrect type.");
- GV->setLinkage(llvm::GlobalValue::InternalLinkage);
- GV->setInitializer(Init);
- } else {
- GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
- llvm::GlobalValue::InternalLinkage,
- Init, Name);
- }
- GV->setSection("__OBJC,__meta_class,regular,no_dead_strip");
- GV->setAlignment(4);
- CGM.AddUsedGlobal(GV);
-
- return GV;
-}
-
-llvm::Constant *CGObjCMac::EmitMetaClassRef(const ObjCInterfaceDecl *ID) {
- std::string Name = "\01L_OBJC_METACLASS_" + ID->getNameAsString();
-
- // FIXME: Should we look these up somewhere other than the module. Its a bit
- // silly since we only generate these while processing an implementation, so
- // exactly one pointer would work if know when we entered/exitted an
- // implementation block.
-
- // Check for an existing forward reference.
- // Previously, metaclass with internal linkage may have been defined.
- // pass 'true' as 2nd argument so it is returned.
- if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
- true)) {
- assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
- "Forward metaclass reference has incorrect type.");
- return GV;
- } else {
- // Generate as an external reference to keep a consistent
- // module. This will be patched up when we emit the metaclass.
- return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
- llvm::GlobalValue::ExternalLinkage,
- 0,
- Name);
- }
-}
-
-llvm::Value *CGObjCMac::EmitSuperClassRef(const ObjCInterfaceDecl *ID) {
- std::string Name = "\01L_OBJC_CLASS_" + ID->getNameAsString();
-
- if (llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name,
- true)) {
- assert(GV->getType()->getElementType() == ObjCTypes.ClassTy &&
- "Forward class metadata reference has incorrect type.");
- return GV;
- } else {
- return new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassTy, false,
- llvm::GlobalValue::ExternalLinkage,
- 0,
- Name);
- }
-}
-
-/*
- struct objc_class_ext {
- uint32_t size;
- const char *weak_ivar_layout;
- struct _objc_property_list *properties;
- };
-*/
-llvm::Constant *
-CGObjCMac::EmitClassExtension(const ObjCImplementationDecl *ID) {
- uint64_t Size =
- CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassExtensionTy);
-
- std::vector<llvm::Constant*> Values(3);
- Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
- Values[1] = BuildIvarLayout(ID, false);
- Values[2] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
- ID, ID->getClassInterface(), ObjCTypes);
-
- // Return null if no extension bits are used.
- if (Values[1]->isNullValue() && Values[2]->isNullValue())
- return llvm::Constant::getNullValue(ObjCTypes.ClassExtensionPtrTy);
-
- llvm::Constant *Init =
- llvm::ConstantStruct::get(ObjCTypes.ClassExtensionTy, Values);
- return CreateMetadataVar("\01L_OBJC_CLASSEXT_" + ID->getName(),
- Init, "__OBJC,__class_ext,regular,no_dead_strip",
- 4, true);
-}
-
-/*
- struct objc_ivar {
- char *ivar_name;
- char *ivar_type;
- int ivar_offset;
- };
-
- struct objc_ivar_list {
- int ivar_count;
- struct objc_ivar list[count];
- };
-*/
-llvm::Constant *CGObjCMac::EmitIvarList(const ObjCImplementationDecl *ID,
- bool ForClass) {
- std::vector<llvm::Constant*> Ivars, Ivar(3);
-
- // When emitting the root class GCC emits ivar entries for the
- // actual class structure. It is not clear if we need to follow this
- // behavior; for now lets try and get away with not doing it. If so,
- // the cleanest solution would be to make up an ObjCInterfaceDecl
- // for the class.
- if (ForClass)
- return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
-
- ObjCInterfaceDecl *OID =
- const_cast<ObjCInterfaceDecl*>(ID->getClassInterface());
-
- llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
- CGM.getContext().ShallowCollectObjCIvars(OID, OIvars);
-
- for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
- ObjCIvarDecl *IVD = OIvars[i];
- // Ignore unnamed bit-fields.
- if (!IVD->getDeclName())
- continue;
- Ivar[0] = GetMethodVarName(IVD->getIdentifier());
- Ivar[1] = GetMethodVarType(IVD);
- Ivar[2] = llvm::ConstantInt::get(ObjCTypes.IntTy,
- ComputeIvarBaseOffset(CGM, OID, IVD));
- Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarTy, Ivar));
- }
-
- // Return null for empty list.
- if (Ivars.empty())
- return llvm::Constant::getNullValue(ObjCTypes.IvarListPtrTy);
-
- std::vector<llvm::Constant*> Values(2);
- Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
- llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarTy,
- Ivars.size());
- Values[1] = llvm::ConstantArray::get(AT, Ivars);
- llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
-
- llvm::GlobalVariable *GV;
- if (ForClass)
- GV = CreateMetadataVar("\01L_OBJC_CLASS_VARIABLES_" + ID->getName(),
- Init, "__OBJC,__class_vars,regular,no_dead_strip",
- 4, true);
- else
- GV = CreateMetadataVar("\01L_OBJC_INSTANCE_VARIABLES_" + ID->getName(),
- Init, "__OBJC,__instance_vars,regular,no_dead_strip",
- 4, true);
- return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListPtrTy);
-}
-
-/*
- struct objc_method {
- SEL method_name;
- char *method_types;
- void *method;
- };
-
- struct objc_method_list {
- struct objc_method_list *obsolete;
- int count;
- struct objc_method methods_list[count];
- };
-*/
-
-/// GetMethodConstant - Return a struct objc_method constant for the
-/// given method if it has been defined. The result is null if the
-/// method has not been defined. The return value has type MethodPtrTy.
-llvm::Constant *CGObjCMac::GetMethodConstant(const ObjCMethodDecl *MD) {
- // FIXME: Use DenseMap::lookup
- llvm::Function *Fn = MethodDefinitions[MD];
- if (!Fn)
- return 0;
-
- std::vector<llvm::Constant*> Method(3);
- Method[0] =
- llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
- ObjCTypes.SelectorPtrTy);
- Method[1] = GetMethodVarType(MD);
- Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
- return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
-}
-
-llvm::Constant *CGObjCMac::EmitMethodList(llvm::Twine Name,
- const char *Section,
- const ConstantVector &Methods) {
- // Return null for empty list.
- if (Methods.empty())
- return llvm::Constant::getNullValue(ObjCTypes.MethodListPtrTy);
-
- std::vector<llvm::Constant*> Values(3);
- Values[0] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
- Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
- llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
- Methods.size());
- Values[2] = llvm::ConstantArray::get(AT, Methods);
- llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
-
- llvm::GlobalVariable *GV = CreateMetadataVar(Name, Init, Section, 4, true);
- return llvm::ConstantExpr::getBitCast(GV,
- ObjCTypes.MethodListPtrTy);
-}
-
-llvm::Function *CGObjCCommonMac::GenerateMethod(const ObjCMethodDecl *OMD,
- const ObjCContainerDecl *CD) {
- llvm::SmallString<256> Name;
- GetNameForMethod(OMD, CD, Name);
-
- CodeGenTypes &Types = CGM.getTypes();
- const llvm::FunctionType *MethodTy =
- Types.GetFunctionType(Types.getFunctionInfo(OMD), OMD->isVariadic());
- llvm::Function *Method =
- llvm::Function::Create(MethodTy,
- llvm::GlobalValue::InternalLinkage,
- Name.str(),
- &CGM.getModule());
- MethodDefinitions.insert(std::make_pair(OMD, Method));
-
- return Method;
-}
-
-llvm::GlobalVariable *
-CGObjCCommonMac::CreateMetadataVar(llvm::Twine Name,
- llvm::Constant *Init,
- const char *Section,
- unsigned Align,
- bool AddToUsed) {
- const llvm::Type *Ty = Init->getType();
- llvm::GlobalVariable *GV =
- new llvm::GlobalVariable(CGM.getModule(), Ty, false,
- llvm::GlobalValue::InternalLinkage, Init, Name);
- if (Section)
- GV->setSection(Section);
- if (Align)
- GV->setAlignment(Align);
- if (AddToUsed)
- CGM.AddUsedGlobal(GV);
- return GV;
-}
-
-llvm::Function *CGObjCMac::ModuleInitFunction() {
- // Abuse this interface function as a place to finalize.
- FinishModule();
- return NULL;
-}
-
-llvm::Constant *CGObjCMac::GetPropertyGetFunction() {
- return ObjCTypes.getGetPropertyFn();
-}
-
-llvm::Constant *CGObjCMac::GetPropertySetFunction() {
- return ObjCTypes.getSetPropertyFn();
-}
-
-llvm::Constant *CGObjCMac::GetCopyStructFunction() {
- return ObjCTypes.getCopyStructFn();
-}
-
-llvm::Constant *CGObjCMac::EnumerationMutationFunction() {
- return ObjCTypes.getEnumerationMutationFn();
-}
-
-void CGObjCMac::EmitTryStmt(CodeGenFunction &CGF, const ObjCAtTryStmt &S) {
- return EmitTryOrSynchronizedStmt(CGF, S);
-}
-
-void CGObjCMac::EmitSynchronizedStmt(CodeGenFunction &CGF,
- const ObjCAtSynchronizedStmt &S) {
- return EmitTryOrSynchronizedStmt(CGF, S);
-}
-
-namespace {
- struct PerformFragileFinally : EHScopeStack::Cleanup {
- const Stmt &S;
- llvm::Value *SyncArgSlot;
- llvm::Value *CallTryExitVar;
- llvm::Value *ExceptionData;
- ObjCTypesHelper &ObjCTypes;
- PerformFragileFinally(const Stmt *S,
- llvm::Value *SyncArgSlot,
- llvm::Value *CallTryExitVar,
- llvm::Value *ExceptionData,
- ObjCTypesHelper *ObjCTypes)
- : S(*S), SyncArgSlot(SyncArgSlot), CallTryExitVar(CallTryExitVar),
- ExceptionData(ExceptionData), ObjCTypes(*ObjCTypes) {}
-
- void Emit(CodeGenFunction &CGF, bool IsForEH) {
- // Check whether we need to call objc_exception_try_exit.
- // In optimized code, this branch will always be folded.
- llvm::BasicBlock *FinallyCallExit =
- CGF.createBasicBlock("finally.call_exit");
- llvm::BasicBlock *FinallyNoCallExit =
- CGF.createBasicBlock("finally.no_call_exit");
- CGF.Builder.CreateCondBr(CGF.Builder.CreateLoad(CallTryExitVar),
- FinallyCallExit, FinallyNoCallExit);
-
- CGF.EmitBlock(FinallyCallExit);
- CGF.Builder.CreateCall(ObjCTypes.getExceptionTryExitFn(), ExceptionData)
- ->setDoesNotThrow();
-
- CGF.EmitBlock(FinallyNoCallExit);
-
- if (isa<ObjCAtTryStmt>(S)) {
- if (const ObjCAtFinallyStmt* FinallyStmt =
- cast<ObjCAtTryStmt>(S).getFinallyStmt())
- CGF.EmitStmt(FinallyStmt->getFinallyBody());
-
- // Currently, the end of the cleanup must always exist.
- CGF.EnsureInsertPoint();
- } else {
- // Emit objc_sync_exit(expr); as finally's sole statement for
- // @synchronized.
- llvm::Value *SyncArg = CGF.Builder.CreateLoad(SyncArgSlot);
- CGF.Builder.CreateCall(ObjCTypes.getSyncExitFn(), SyncArg)
- ->setDoesNotThrow();
- }
- }
- };
-
- class FragileHazards {
- CodeGenFunction &CGF;
- llvm::SmallVector<llvm::Value*, 20> Locals;
- llvm::DenseSet<llvm::BasicBlock*> BlocksBeforeTry;
-
- llvm::InlineAsm *ReadHazard;
- llvm::InlineAsm *WriteHazard;
-
- llvm::FunctionType *GetAsmFnType();
-
- void collectLocals();
- void emitReadHazard(CGBuilderTy &Builder);
-
- public:
- FragileHazards(CodeGenFunction &CGF);
-
- void emitWriteHazard();
- void emitHazardsInNewBlocks();
- };
-}
-
-/// Create the fragile-ABI read and write hazards based on the current
-/// state of the function, which is presumed to be immediately prior
-/// to a @try block. These hazards are used to maintain correct
-/// semantics in the face of optimization and the fragile ABI's
-/// cavalier use of setjmp/longjmp.
-FragileHazards::FragileHazards(CodeGenFunction &CGF) : CGF(CGF) {
- collectLocals();
-
- if (Locals.empty()) return;
-
- // Collect all the blocks in the function.
- for (llvm::Function::iterator
- I = CGF.CurFn->begin(), E = CGF.CurFn->end(); I != E; ++I)
- BlocksBeforeTry.insert(&*I);
-
- llvm::FunctionType *AsmFnTy = GetAsmFnType();
-
- // Create a read hazard for the allocas. This inhibits dead-store
- // optimizations and forces the values to memory. This hazard is
- // inserted before any 'throwing' calls in the protected scope to
- // reflect the possibility that the variables might be read from the
- // catch block if the call throws.
- {
- std::string Constraint;
- for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
- if (I) Constraint += ',';
- Constraint += "*m";
- }
-
- ReadHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
- }
-
- // Create a write hazard for the allocas. This inhibits folding
- // loads across the hazard. This hazard is inserted at the
- // beginning of the catch path to reflect the possibility that the
- // variables might have been written within the protected scope.
- {
- std::string Constraint;
- for (unsigned I = 0, E = Locals.size(); I != E; ++I) {
- if (I) Constraint += ',';
- Constraint += "=*m";
- }
-
- WriteHazard = llvm::InlineAsm::get(AsmFnTy, "", Constraint, true, false);
- }
-}
-
-/// Emit a write hazard at the current location.
-void FragileHazards::emitWriteHazard() {
- if (Locals.empty()) return;
-
- CGF.Builder.CreateCall(WriteHazard, Locals.begin(), Locals.end())
- ->setDoesNotThrow();
-}
-
-void FragileHazards::emitReadHazard(CGBuilderTy &Builder) {
- assert(!Locals.empty());
- Builder.CreateCall(ReadHazard, Locals.begin(), Locals.end())
- ->setDoesNotThrow();
-}
-
-/// Emit read hazards in all the protected blocks, i.e. all the blocks
-/// which have been inserted since the beginning of the try.
-void FragileHazards::emitHazardsInNewBlocks() {
- if (Locals.empty()) return;
-
- CGBuilderTy Builder(CGF.getLLVMContext());
-
- // Iterate through all blocks, skipping those prior to the try.
- for (llvm::Function::iterator
- FI = CGF.CurFn->begin(), FE = CGF.CurFn->end(); FI != FE; ++FI) {
- llvm::BasicBlock &BB = *FI;
- if (BlocksBeforeTry.count(&BB)) continue;
-
- // Walk through all the calls in the block.
- for (llvm::BasicBlock::iterator
- BI = BB.begin(), BE = BB.end(); BI != BE; ++BI) {
- llvm::Instruction &I = *BI;
-
- // Ignore instructions that aren't non-intrinsic calls.
- // These are the only calls that can possibly call longjmp.
- if (!isa<llvm::CallInst>(I) && !isa<llvm::InvokeInst>(I)) continue;
- if (isa<llvm::IntrinsicInst>(I))
- continue;
-
- // Ignore call sites marked nounwind. This may be questionable,
- // since 'nounwind' doesn't necessarily mean 'does not call longjmp'.
- llvm::CallSite CS(&I);
- if (CS.doesNotThrow()) continue;
-
- // Insert a read hazard before the call. This will ensure that
- // any writes to the locals are performed before making the
- // call. If the call throws, then this is sufficient to
- // guarantee correctness as long as it doesn't also write to any
- // locals.
- Builder.SetInsertPoint(&BB, BI);
- emitReadHazard(Builder);
- }
- }
-}
-
-static void addIfPresent(llvm::DenseSet<llvm::Value*> &S, llvm::Value *V) {
- if (V) S.insert(V);
-}
-
-void FragileHazards::collectLocals() {
- // Compute a set of allocas to ignore.
- llvm::DenseSet<llvm::Value*> AllocasToIgnore;
- addIfPresent(AllocasToIgnore, CGF.ReturnValue);
- addIfPresent(AllocasToIgnore, CGF.NormalCleanupDest);
- addIfPresent(AllocasToIgnore, CGF.EHCleanupDest);
-
- // Collect all the allocas currently in the function. This is
- // probably way too aggressive.
- llvm::BasicBlock &Entry = CGF.CurFn->getEntryBlock();
- for (llvm::BasicBlock::iterator
- I = Entry.begin(), E = Entry.end(); I != E; ++I)
- if (isa<llvm::AllocaInst>(*I) && !AllocasToIgnore.count(&*I))
- Locals.push_back(&*I);
-}
-
-llvm::FunctionType *FragileHazards::GetAsmFnType() {
- std::vector<const llvm::Type *> Tys(Locals.size());
- for (unsigned I = 0, E = Locals.size(); I != E; ++I)
- Tys[I] = Locals[I]->getType();
- return llvm::FunctionType::get(CGF.Builder.getVoidTy(), Tys, false);
-}
-
-/*
-
- Objective-C setjmp-longjmp (sjlj) Exception Handling
- --
-
- A catch buffer is a setjmp buffer plus:
- - a pointer to the exception that was caught
- - a pointer to the previous exception data buffer
- - two pointers of reserved storage
- Therefore catch buffers form a stack, with a pointer to the top
- of the stack kept in thread-local storage.
-
- objc_exception_try_enter pushes a catch buffer onto the EH stack.
- objc_exception_try_exit pops the given catch buffer, which is
- required to be the top of the EH stack.
- objc_exception_throw pops the top of the EH stack, writes the
- thrown exception into the appropriate field, and longjmps
- to the setjmp buffer. It crashes the process (with a printf
- and an abort()) if there are no catch buffers on the stack.
- objc_exception_extract just reads the exception pointer out of the
- catch buffer.
-
- There's no reason an implementation couldn't use a light-weight
- setjmp here --- something like __builtin_setjmp, but API-compatible
- with the heavyweight setjmp. This will be more important if we ever
- want to implement correct ObjC/C++ exception interactions for the
- fragile ABI.
-
- Note that for this use of setjmp/longjmp to be correct, we may need
- to mark some local variables volatile: if a non-volatile local
- variable is modified between the setjmp and the longjmp, it has
- indeterminate value. For the purposes of LLVM IR, it may be
- sufficient to make loads and stores within the @try (to variables
- declared outside the @try) volatile. This is necessary for
- optimized correctness, but is not currently being done; this is
- being tracked as rdar://problem/8160285
-
- The basic framework for a @try-catch-finally is as follows:
- {
- objc_exception_data d;
- id _rethrow = null;
- bool _call_try_exit = true;
-
- objc_exception_try_enter(&d);
- if (!setjmp(d.jmp_buf)) {
- ... try body ...
- } else {
- // exception path
- id _caught = objc_exception_extract(&d);
-
- // enter new try scope for handlers
- if (!setjmp(d.jmp_buf)) {
- ... match exception and execute catch blocks ...
-
- // fell off end, rethrow.
- _rethrow = _caught;
- ... jump-through-finally to finally_rethrow ...
- } else {
- // exception in catch block
- _rethrow = objc_exception_extract(&d);
- _call_try_exit = false;
- ... jump-through-finally to finally_rethrow ...
- }
- }
- ... jump-through-finally to finally_end ...
-
- finally:
- if (_call_try_exit)
- objc_exception_try_exit(&d);
-
- ... finally block ....
- ... dispatch to finally destination ...
-
- finally_rethrow:
- objc_exception_throw(_rethrow);
-
- finally_end:
- }
-
- This framework differs slightly from the one gcc uses, in that gcc
- uses _rethrow to determine if objc_exception_try_exit should be called
- and if the object should be rethrown. This breaks in the face of
- throwing nil and introduces unnecessary branches.
-
- We specialize this framework for a few particular circumstances:
-
- - If there are no catch blocks, then we avoid emitting the second
- exception handling context.
-
- - If there is a catch-all catch block (i.e. @catch(...) or @catch(id
- e)) we avoid emitting the code to rethrow an uncaught exception.
-
- - FIXME: If there is no @finally block we can do a few more
- simplifications.
-
- Rethrows and Jumps-Through-Finally
- --
-
- '@throw;' is supported by pushing the currently-caught exception
- onto ObjCEHStack while the @catch blocks are emitted.
-
- Branches through the @finally block are handled with an ordinary
- normal cleanup. We do not register an EH cleanup; fragile-ABI ObjC
- exceptions are not compatible with C++ exceptions, and this is
- hardly the only place where this will go wrong.
-
- @synchronized(expr) { stmt; } is emitted as if it were:
- id synch_value = expr;
- objc_sync_enter(synch_value);
- @try { stmt; } @finally { objc_sync_exit(synch_value); }
-*/
-
-void CGObjCMac::EmitTryOrSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
- const Stmt &S) {
- bool isTry = isa<ObjCAtTryStmt>(S);
-
- // A destination for the fall-through edges of the catch handlers to
- // jump to.
- CodeGenFunction::JumpDest FinallyEnd =
- CGF.getJumpDestInCurrentScope("finally.end");
-
- // A destination for the rethrow edge of the catch handlers to jump
- // to.
- CodeGenFunction::JumpDest FinallyRethrow =
- CGF.getJumpDestInCurrentScope("finally.rethrow");
-
- // For @synchronized, call objc_sync_enter(sync.expr). The
- // evaluation of the expression must occur before we enter the
- // @synchronized. We can't avoid a temp here because we need the
- // value to be preserved. If the backend ever does liveness
- // correctly after setjmp, this will be unnecessary.
- llvm::Value *SyncArgSlot = 0;
- if (!isTry) {
- llvm::Value *SyncArg =
- CGF.EmitScalarExpr(cast<ObjCAtSynchronizedStmt>(S).getSynchExpr());
- SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
- CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg)
- ->setDoesNotThrow();
-
- SyncArgSlot = CGF.CreateTempAlloca(SyncArg->getType(), "sync.arg");
- CGF.Builder.CreateStore(SyncArg, SyncArgSlot);
- }
-
- // Allocate memory for the setjmp buffer. This needs to be kept
- // live throughout the try and catch blocks.
- llvm::Value *ExceptionData = CGF.CreateTempAlloca(ObjCTypes.ExceptionDataTy,
- "exceptiondata.ptr");
-
- // Create the fragile hazards. Note that this will not capture any
- // of the allocas required for exception processing, but will
- // capture the current basic block (which extends all the way to the
- // setjmp call) as "before the @try".
- FragileHazards Hazards(CGF);
-
- // Create a flag indicating whether the cleanup needs to call
- // objc_exception_try_exit. This is true except when
- // - no catches match and we're branching through the cleanup
- // just to rethrow the exception, or
- // - a catch matched and we're falling out of the catch handler.
- // The setjmp-safety rule here is that we should always store to this
- // variable in a place that dominates the branch through the cleanup
- // without passing through any setjmps.
- llvm::Value *CallTryExitVar = CGF.CreateTempAlloca(CGF.Builder.getInt1Ty(),
- "_call_try_exit");
-
- // Push a normal cleanup to leave the try scope.
- CGF.EHStack.pushCleanup<PerformFragileFinally>(NormalCleanup, &S,
- SyncArgSlot,
- CallTryExitVar,
- ExceptionData,
- &ObjCTypes);
-
- // Enter a try block:
- // - Call objc_exception_try_enter to push ExceptionData on top of
- // the EH stack.
- CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
- ->setDoesNotThrow();
-
- // - Call setjmp on the exception data buffer.
- llvm::Constant *Zero = llvm::ConstantInt::get(CGF.Builder.getInt32Ty(), 0);
- llvm::Value *GEPIndexes[] = { Zero, Zero, Zero };
- llvm::Value *SetJmpBuffer =
- CGF.Builder.CreateGEP(ExceptionData, GEPIndexes, GEPIndexes+3, "setjmp_buffer");
- llvm::CallInst *SetJmpResult =
- CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer, "setjmp_result");
- SetJmpResult->setDoesNotThrow();
-
- // If setjmp returned 0, enter the protected block; otherwise,
- // branch to the handler.
- llvm::BasicBlock *TryBlock = CGF.createBasicBlock("try");
- llvm::BasicBlock *TryHandler = CGF.createBasicBlock("try.handler");
- llvm::Value *DidCatch =
- CGF.Builder.CreateIsNull(SetJmpResult, "did_catch_exception");
- CGF.Builder.CreateCondBr(DidCatch, TryBlock, TryHandler);
-
- // Emit the protected block.
- CGF.EmitBlock(TryBlock);
- CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
- CGF.EmitStmt(isTry ? cast<ObjCAtTryStmt>(S).getTryBody()
- : cast<ObjCAtSynchronizedStmt>(S).getSynchBody());
-
- CGBuilderTy::InsertPoint TryFallthroughIP = CGF.Builder.saveAndClearIP();
-
- // Emit the exception handler block.
- CGF.EmitBlock(TryHandler);
-
- // Don't optimize loads of the in-scope locals across this point.
- Hazards.emitWriteHazard();
-
- // For a @synchronized (or a @try with no catches), just branch
- // through the cleanup to the rethrow block.
- if (!isTry || !cast<ObjCAtTryStmt>(S).getNumCatchStmts()) {
- // Tell the cleanup not to re-pop the exit.
- CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
- CGF.EmitBranchThroughCleanup(FinallyRethrow);
-
- // Otherwise, we have to match against the caught exceptions.
- } else {
- // Retrieve the exception object. We may emit multiple blocks but
- // nothing can cross this so the value is already in SSA form.
- llvm::CallInst *Caught =
- CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
- ExceptionData, "caught");
- Caught->setDoesNotThrow();
-
- // Push the exception to rethrow onto the EH value stack for the
- // benefit of any @throws in the handlers.
- CGF.ObjCEHValueStack.push_back(Caught);
-
- const ObjCAtTryStmt* AtTryStmt = cast<ObjCAtTryStmt>(&S);
-
- bool HasFinally = (AtTryStmt->getFinallyStmt() != 0);
-
- llvm::BasicBlock *CatchBlock = 0;
- llvm::BasicBlock *CatchHandler = 0;
- if (HasFinally) {
- // Enter a new exception try block (in case a @catch block
- // throws an exception).
- CGF.Builder.CreateCall(ObjCTypes.getExceptionTryEnterFn(), ExceptionData)
- ->setDoesNotThrow();
-
- llvm::CallInst *SetJmpResult =
- CGF.Builder.CreateCall(ObjCTypes.getSetJmpFn(), SetJmpBuffer,
- "setjmp.result");
- SetJmpResult->setDoesNotThrow();
-
- llvm::Value *Threw =
- CGF.Builder.CreateIsNotNull(SetJmpResult, "did_catch_exception");
-
- CatchBlock = CGF.createBasicBlock("catch");
- CatchHandler = CGF.createBasicBlock("catch_for_catch");
- CGF.Builder.CreateCondBr(Threw, CatchHandler, CatchBlock);
-
- CGF.EmitBlock(CatchBlock);
- }
-
- CGF.Builder.CreateStore(CGF.Builder.getInt1(HasFinally), CallTryExitVar);
-
- // Handle catch list. As a special case we check if everything is
- // matched and avoid generating code for falling off the end if
- // so.
- bool AllMatched = false;
- for (unsigned I = 0, N = AtTryStmt->getNumCatchStmts(); I != N; ++I) {
- const ObjCAtCatchStmt *CatchStmt = AtTryStmt->getCatchStmt(I);
-
- const VarDecl *CatchParam = CatchStmt->getCatchParamDecl();
- const ObjCObjectPointerType *OPT = 0;
-
- // catch(...) always matches.
- if (!CatchParam) {
- AllMatched = true;
- } else {
- OPT = CatchParam->getType()->getAs<ObjCObjectPointerType>();
-
- // catch(id e) always matches under this ABI, since only
- // ObjC exceptions end up here in the first place.
- // FIXME: For the time being we also match id<X>; this should
- // be rejected by Sema instead.
- if (OPT && (OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()))
- AllMatched = true;
- }
-
- // If this is a catch-all, we don't need to test anything.
- if (AllMatched) {
- CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
-
- if (CatchParam) {
- CGF.EmitLocalBlockVarDecl(*CatchParam);
- assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
-
- // These types work out because ConvertType(id) == i8*.
- CGF.Builder.CreateStore(Caught, CGF.GetAddrOfLocalVar(CatchParam));
- }
-
- CGF.EmitStmt(CatchStmt->getCatchBody());
-
- // The scope of the catch variable ends right here.
- CatchVarCleanups.ForceCleanup();
-
- CGF.EmitBranchThroughCleanup(FinallyEnd);
- break;
- }
-
- assert(OPT && "Unexpected non-object pointer type in @catch");
- const ObjCObjectType *ObjTy = OPT->getObjectType();
-
- // FIXME: @catch (Class c) ?
- ObjCInterfaceDecl *IDecl = ObjTy->getInterface();
- assert(IDecl && "Catch parameter must have Objective-C type!");
-
- // Check if the @catch block matches the exception object.
- llvm::Value *Class = EmitClassRef(CGF.Builder, IDecl);
-
- llvm::CallInst *Match =
- CGF.Builder.CreateCall2(ObjCTypes.getExceptionMatchFn(),
- Class, Caught, "match");
- Match->setDoesNotThrow();
-
- llvm::BasicBlock *MatchedBlock = CGF.createBasicBlock("match");
- llvm::BasicBlock *NextCatchBlock = CGF.createBasicBlock("catch.next");
-
- CGF.Builder.CreateCondBr(CGF.Builder.CreateIsNotNull(Match, "matched"),
- MatchedBlock, NextCatchBlock);
-
- // Emit the @catch block.
- CGF.EmitBlock(MatchedBlock);
-
- // Collect any cleanups for the catch variable. The scope lasts until
- // the end of the catch body.
- CodeGenFunction::RunCleanupsScope CatchVarCleanups(CGF);
-
- CGF.EmitLocalBlockVarDecl(*CatchParam);
- assert(CGF.HaveInsertPoint() && "DeclStmt destroyed insert point?");
-
- // Initialize the catch variable.
- llvm::Value *Tmp =
- CGF.Builder.CreateBitCast(Caught,
- CGF.ConvertType(CatchParam->getType()),
- "tmp");
- CGF.Builder.CreateStore(Tmp, CGF.GetAddrOfLocalVar(CatchParam));
-
- CGF.EmitStmt(CatchStmt->getCatchBody());
-
- // We're done with the catch variable.
- CatchVarCleanups.ForceCleanup();
-
- CGF.EmitBranchThroughCleanup(FinallyEnd);
-
- CGF.EmitBlock(NextCatchBlock);
- }
-
- CGF.ObjCEHValueStack.pop_back();
-
- // If nothing wanted anything to do with the caught exception,
- // kill the extract call.
- if (Caught->use_empty())
- Caught->eraseFromParent();
-
- if (!AllMatched)
- CGF.EmitBranchThroughCleanup(FinallyRethrow);
-
- if (HasFinally) {
- // Emit the exception handler for the @catch blocks.
- CGF.EmitBlock(CatchHandler);
-
- // In theory we might now need a write hazard, but actually it's
- // unnecessary because there's no local-accessing code between
- // the try's write hazard and here.
- //Hazards.emitWriteHazard();
-
- // Don't pop the catch handler; the throw already did.
- CGF.Builder.CreateStore(CGF.Builder.getFalse(), CallTryExitVar);
- CGF.EmitBranchThroughCleanup(FinallyRethrow);
- }
- }
-
- // Insert read hazards as required in the new blocks.
- Hazards.emitHazardsInNewBlocks();
-
- // Pop the cleanup.
- CGF.Builder.restoreIP(TryFallthroughIP);
- if (CGF.HaveInsertPoint())
- CGF.Builder.CreateStore(CGF.Builder.getTrue(), CallTryExitVar);
- CGF.PopCleanupBlock();
- CGF.EmitBlock(FinallyEnd.getBlock(), true);
-
- // Emit the rethrow block.
- CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
- CGF.EmitBlock(FinallyRethrow.getBlock(), true);
- if (CGF.HaveInsertPoint()) {
- // Just look in the buffer for the exception to throw.
- llvm::CallInst *Caught =
- CGF.Builder.CreateCall(ObjCTypes.getExceptionExtractFn(),
- ExceptionData);
- Caught->setDoesNotThrow();
-
- CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), Caught)
- ->setDoesNotThrow();
- CGF.Builder.CreateUnreachable();
- }
-
- CGF.Builder.restoreIP(SavedIP);
-}
-
-void CGObjCMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
- const ObjCAtThrowStmt &S) {
- llvm::Value *ExceptionAsObject;
-
- if (const Expr *ThrowExpr = S.getThrowExpr()) {
- llvm::Value *Exception = CGF.EmitScalarExpr(ThrowExpr);
- ExceptionAsObject =
- CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp");
- } else {
- assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
- "Unexpected rethrow outside @catch block.");
- ExceptionAsObject = CGF.ObjCEHValueStack.back();
- }
-
- CGF.Builder.CreateCall(ObjCTypes.getExceptionThrowFn(), ExceptionAsObject)
- ->setDoesNotReturn();
- CGF.Builder.CreateUnreachable();
-
- // Clear the insertion point to indicate we are in unreachable code.
- CGF.Builder.ClearInsertionPoint();
-}
-
-/// EmitObjCWeakRead - Code gen for loading value of a __weak
-/// object: objc_read_weak (id *src)
-///
-llvm::Value * CGObjCMac::EmitObjCWeakRead(CodeGen::CodeGenFunction &CGF,
- llvm::Value *AddrWeakObj) {
- const llvm::Type* DestTy =
- cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
- AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj,
- ObjCTypes.PtrObjectPtrTy);
- llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
- AddrWeakObj, "weakread");
- read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
- return read_weak;
-}
-
-/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
-/// objc_assign_weak (id src, id *dst)
-///
-void CGObjCMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dst) {
- const llvm::Type * SrcTy = src->getType();
- if (!isa<llvm::PointerType>(SrcTy)) {
- unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
- assert(Size <= 8 && "does not support size > 8");
- src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
- : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
- src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
- }
- src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
- dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
- CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
- src, dst, "weakassign");
- return;
-}
-
-/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
-/// objc_assign_global (id src, id *dst)
-///
-void CGObjCMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dst,
- bool threadlocal) {
- const llvm::Type * SrcTy = src->getType();
- if (!isa<llvm::PointerType>(SrcTy)) {
- unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
- assert(Size <= 8 && "does not support size > 8");
- src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
- : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
- src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
- }
- src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
- dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
- if (!threadlocal)
- CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
- src, dst, "globalassign");
- else
- CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
- src, dst, "threadlocalassign");
- return;
-}
-
-/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
-/// objc_assign_ivar (id src, id *dst, ptrdiff_t ivaroffset)
-///
-void CGObjCMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dst,
- llvm::Value *ivarOffset) {
- assert(ivarOffset && "EmitObjCIvarAssign - ivarOffset is NULL");
- const llvm::Type * SrcTy = src->getType();
- if (!isa<llvm::PointerType>(SrcTy)) {
- unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
- assert(Size <= 8 && "does not support size > 8");
- src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
- : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
- src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
- }
- src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
- dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
- CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
- src, dst, ivarOffset);
- return;
-}
-
-/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
-/// objc_assign_strongCast (id src, id *dst)
-///
-void CGObjCMac::EmitObjCStrongCastAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dst) {
- const llvm::Type * SrcTy = src->getType();
- if (!isa<llvm::PointerType>(SrcTy)) {
- unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
- assert(Size <= 8 && "does not support size > 8");
- src = (Size == 4) ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
- : CGF.Builder.CreateBitCast(src, ObjCTypes.LongLongTy);
- src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
- }
- src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
- dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
- CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
- src, dst, "weakassign");
- return;
-}
-
-void CGObjCMac::EmitGCMemmoveCollectable(CodeGen::CodeGenFunction &CGF,
- llvm::Value *DestPtr,
- llvm::Value *SrcPtr,
- llvm::Value *size) {
- SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
- DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
- CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
- DestPtr, SrcPtr, size);
- return;
-}
-
-/// EmitObjCValueForIvar - Code Gen for ivar reference.
-///
-LValue CGObjCMac::EmitObjCValueForIvar(CodeGen::CodeGenFunction &CGF,
- QualType ObjectTy,
- llvm::Value *BaseValue,
- const ObjCIvarDecl *Ivar,
- unsigned CVRQualifiers) {
- const ObjCInterfaceDecl *ID =
- ObjectTy->getAs<ObjCObjectType>()->getInterface();
- return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
- EmitIvarOffset(CGF, ID, Ivar));
-}
-
-llvm::Value *CGObjCMac::EmitIvarOffset(CodeGen::CodeGenFunction &CGF,
- const ObjCInterfaceDecl *Interface,
- const ObjCIvarDecl *Ivar) {
- uint64_t Offset = ComputeIvarBaseOffset(CGM, Interface, Ivar);
- return llvm::ConstantInt::get(
- CGM.getTypes().ConvertType(CGM.getContext().LongTy),
- Offset);
-}
-
-/* *** Private Interface *** */
-
-/// EmitImageInfo - Emit the image info marker used to encode some module
-/// level information.
-///
-/// See: <rdr://4810609&4810587&4810587>
-/// struct IMAGE_INFO {
-/// unsigned version;
-/// unsigned flags;
-/// };
-enum ImageInfoFlags {
- eImageInfo_FixAndContinue = (1 << 0),
- eImageInfo_GarbageCollected = (1 << 1),
- eImageInfo_GCOnly = (1 << 2),
- eImageInfo_OptimizedByDyld = (1 << 3), // FIXME: When is this set.
-
- // A flag indicating that the module has no instances of a @synthesize of a
- // superclass variable. <rdar://problem/6803242>
- eImageInfo_CorrectedSynthesize = (1 << 4)
-};
-
-void CGObjCCommonMac::EmitImageInfo() {
- unsigned version = 0; // Version is unused?
- unsigned flags = 0;
-
- // FIXME: Fix and continue?
- if (CGM.getLangOptions().getGCMode() != LangOptions::NonGC)
- flags |= eImageInfo_GarbageCollected;
- if (CGM.getLangOptions().getGCMode() == LangOptions::GCOnly)
- flags |= eImageInfo_GCOnly;
-
- // We never allow @synthesize of a superclass property.
- flags |= eImageInfo_CorrectedSynthesize;
-
- const llvm::Type *Int32Ty = llvm::Type::getInt32Ty(VMContext);
-
- // Emitted as int[2];
- llvm::Constant *values[2] = {
- llvm::ConstantInt::get(Int32Ty, version),
- llvm::ConstantInt::get(Int32Ty, flags)
- };
- llvm::ArrayType *AT = llvm::ArrayType::get(Int32Ty, 2);
-
- const char *Section;
- if (ObjCABI == 1)
- Section = "__OBJC, __image_info,regular";
- else
- Section = "__DATA, __objc_imageinfo, regular, no_dead_strip";
- llvm::GlobalVariable *GV =
- CreateMetadataVar("\01L_OBJC_IMAGE_INFO",
- llvm::ConstantArray::get(AT, values, 2),
- Section,
- 0,
- true);
- GV->setConstant(true);
-}
-
-
-// struct objc_module {
-// unsigned long version;
-// unsigned long size;
-// const char *name;
-// Symtab symtab;
-// };
-
-// FIXME: Get from somewhere
-static const int ModuleVersion = 7;
-
-void CGObjCMac::EmitModuleInfo() {
- uint64_t Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ModuleTy);
-
- std::vector<llvm::Constant*> Values(4);
- Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, ModuleVersion);
- Values[1] = llvm::ConstantInt::get(ObjCTypes.LongTy, Size);
- // This used to be the filename, now it is unused. <rdr://4327263>
- Values[2] = GetClassName(&CGM.getContext().Idents.get(""));
- Values[3] = EmitModuleSymbols();
- CreateMetadataVar("\01L_OBJC_MODULES",
- llvm::ConstantStruct::get(ObjCTypes.ModuleTy, Values),
- "__OBJC,__module_info,regular,no_dead_strip",
- 4, true);
-}
-
-llvm::Constant *CGObjCMac::EmitModuleSymbols() {
- unsigned NumClasses = DefinedClasses.size();
- unsigned NumCategories = DefinedCategories.size();
-
- // Return null if no symbols were defined.
- if (!NumClasses && !NumCategories)
- return llvm::Constant::getNullValue(ObjCTypes.SymtabPtrTy);
-
- std::vector<llvm::Constant*> Values(5);
- Values[0] = llvm::ConstantInt::get(ObjCTypes.LongTy, 0);
- Values[1] = llvm::Constant::getNullValue(ObjCTypes.SelectorPtrTy);
- Values[2] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumClasses);
- Values[3] = llvm::ConstantInt::get(ObjCTypes.ShortTy, NumCategories);
-
- // The runtime expects exactly the list of defined classes followed
- // by the list of defined categories, in a single array.
- std::vector<llvm::Constant*> Symbols(NumClasses + NumCategories);
- for (unsigned i=0; i<NumClasses; i++)
- Symbols[i] = llvm::ConstantExpr::getBitCast(DefinedClasses[i],
- ObjCTypes.Int8PtrTy);
- for (unsigned i=0; i<NumCategories; i++)
- Symbols[NumClasses + i] =
- llvm::ConstantExpr::getBitCast(DefinedCategories[i],
- ObjCTypes.Int8PtrTy);
-
- Values[4] =
- llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
- NumClasses + NumCategories),
- Symbols);
-
- llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
-
- llvm::GlobalVariable *GV =
- CreateMetadataVar("\01L_OBJC_SYMBOLS", Init,
- "__OBJC,__symbols,regular,no_dead_strip",
- 4, true);
- return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.SymtabPtrTy);
-}
-
-llvm::Value *CGObjCMac::EmitClassRef(CGBuilderTy &Builder,
- const ObjCInterfaceDecl *ID) {
- LazySymbols.insert(ID->getIdentifier());
-
- llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
-
- if (!Entry) {
- llvm::Constant *Casted =
- llvm::ConstantExpr::getBitCast(GetClassName(ID->getIdentifier()),
- ObjCTypes.ClassPtrTy);
- Entry =
- CreateMetadataVar("\01L_OBJC_CLASS_REFERENCES_", Casted,
- "__OBJC,__cls_refs,literal_pointers,no_dead_strip",
- 4, true);
- }
-
- return Builder.CreateLoad(Entry, "tmp");
-}
-
-llvm::Value *CGObjCMac::EmitSelector(CGBuilderTy &Builder, Selector Sel,
- bool lvalue) {
- llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
-
- if (!Entry) {
- llvm::Constant *Casted =
- llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
- ObjCTypes.SelectorPtrTy);
- Entry =
- CreateMetadataVar("\01L_OBJC_SELECTOR_REFERENCES_", Casted,
- "__OBJC,__message_refs,literal_pointers,no_dead_strip",
- 4, true);
- }
-
- if (lvalue)
- return Entry;
- return Builder.CreateLoad(Entry, "tmp");
-}
-
-llvm::Constant *CGObjCCommonMac::GetClassName(IdentifierInfo *Ident) {
- llvm::GlobalVariable *&Entry = ClassNames[Ident];
-
- if (!Entry)
- Entry = CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
- llvm::ConstantArray::get(VMContext,
- Ident->getNameStart()),
- "__TEXT,__cstring,cstring_literals",
- 1, true);
-
- return getConstantGEP(VMContext, Entry, 0, 0);
-}
-
-/// GetIvarLayoutName - Returns a unique constant for the given
-/// ivar layout bitmap.
-llvm::Constant *CGObjCCommonMac::GetIvarLayoutName(IdentifierInfo *Ident,
- const ObjCCommonTypesHelper &ObjCTypes) {
- return llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
-}
-
-static Qualifiers::GC GetGCAttrTypeForType(ASTContext &Ctx, QualType FQT) {
- if (FQT.isObjCGCStrong())
- return Qualifiers::Strong;
-
- if (FQT.isObjCGCWeak())
- return Qualifiers::Weak;
-
- if (FQT->isObjCObjectPointerType() || FQT->isBlockPointerType())
- return Qualifiers::Strong;
-
- if (const PointerType *PT = FQT->getAs<PointerType>())
- return GetGCAttrTypeForType(Ctx, PT->getPointeeType());
-
- return Qualifiers::GCNone;
-}
-
-void CGObjCCommonMac::BuildAggrIvarRecordLayout(const RecordType *RT,
- unsigned int BytePos,
- bool ForStrongLayout,
- bool &HasUnion) {
- const RecordDecl *RD = RT->getDecl();
- // FIXME - Use iterator.
- llvm::SmallVector<FieldDecl*, 16> Fields(RD->field_begin(), RD->field_end());
- const llvm::Type *Ty = CGM.getTypes().ConvertType(QualType(RT, 0));
- const llvm::StructLayout *RecLayout =
- CGM.getTargetData().getStructLayout(cast<llvm::StructType>(Ty));
-
- BuildAggrIvarLayout(0, RecLayout, RD, Fields, BytePos,
- ForStrongLayout, HasUnion);
-}
-
-void CGObjCCommonMac::BuildAggrIvarLayout(const ObjCImplementationDecl *OI,
- const llvm::StructLayout *Layout,
- const RecordDecl *RD,
- const llvm::SmallVectorImpl<FieldDecl*> &RecFields,
- unsigned int BytePos, bool ForStrongLayout,
- bool &HasUnion) {
- bool IsUnion = (RD && RD->isUnion());
- uint64_t MaxUnionIvarSize = 0;
- uint64_t MaxSkippedUnionIvarSize = 0;
- FieldDecl *MaxField = 0;
- FieldDecl *MaxSkippedField = 0;
- FieldDecl *LastFieldBitfield = 0;
- uint64_t MaxFieldOffset = 0;
- uint64_t MaxSkippedFieldOffset = 0;
- uint64_t LastBitfieldOffset = 0;
-
- if (RecFields.empty())
- return;
- unsigned WordSizeInBits = CGM.getContext().Target.getPointerWidth(0);
- unsigned ByteSizeInBits = CGM.getContext().Target.getCharWidth();
-
- for (unsigned i = 0, e = RecFields.size(); i != e; ++i) {
- FieldDecl *Field = RecFields[i];
- uint64_t FieldOffset;
- if (RD) {
- // Note that 'i' here is actually the field index inside RD of Field,
- // although this dependency is hidden.
- const ASTRecordLayout &RL = CGM.getContext().getASTRecordLayout(RD);
- FieldOffset = RL.getFieldOffset(i) / 8;
- } else
- FieldOffset = ComputeIvarBaseOffset(CGM, OI, cast<ObjCIvarDecl>(Field));
-
- // Skip over unnamed or bitfields
- if (!Field->getIdentifier() || Field->isBitField()) {
- LastFieldBitfield = Field;
- LastBitfieldOffset = FieldOffset;
- continue;
- }
-
- LastFieldBitfield = 0;
- QualType FQT = Field->getType();
- if (FQT->isRecordType() || FQT->isUnionType()) {
- if (FQT->isUnionType())
- HasUnion = true;
-
- BuildAggrIvarRecordLayout(FQT->getAs<RecordType>(),
- BytePos + FieldOffset,
- ForStrongLayout, HasUnion);
- continue;
- }
-
- if (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
- const ConstantArrayType *CArray =
- dyn_cast_or_null<ConstantArrayType>(Array);
- uint64_t ElCount = CArray->getSize().getZExtValue();
- assert(CArray && "only array with known element size is supported");
- FQT = CArray->getElementType();
- while (const ArrayType *Array = CGM.getContext().getAsArrayType(FQT)) {
- const ConstantArrayType *CArray =
- dyn_cast_or_null<ConstantArrayType>(Array);
- ElCount *= CArray->getSize().getZExtValue();
- FQT = CArray->getElementType();
- }
-
- assert(!FQT->isUnionType() &&
- "layout for array of unions not supported");
- if (FQT->isRecordType()) {
- int OldIndex = IvarsInfo.size() - 1;
- int OldSkIndex = SkipIvars.size() -1;
-
- const RecordType *RT = FQT->getAs<RecordType>();
- BuildAggrIvarRecordLayout(RT, BytePos + FieldOffset,
- ForStrongLayout, HasUnion);
-
- // Replicate layout information for each array element. Note that
- // one element is already done.
- uint64_t ElIx = 1;
- for (int FirstIndex = IvarsInfo.size() - 1,
- FirstSkIndex = SkipIvars.size() - 1 ;ElIx < ElCount; ElIx++) {
- uint64_t Size = CGM.getContext().getTypeSize(RT)/ByteSizeInBits;
- for (int i = OldIndex+1; i <= FirstIndex; ++i)
- IvarsInfo.push_back(GC_IVAR(IvarsInfo[i].ivar_bytepos + Size*ElIx,
- IvarsInfo[i].ivar_size));
- for (int i = OldSkIndex+1; i <= FirstSkIndex; ++i)
- SkipIvars.push_back(GC_IVAR(SkipIvars[i].ivar_bytepos + Size*ElIx,
- SkipIvars[i].ivar_size));
- }
- continue;
- }
- }
- // At this point, we are done with Record/Union and array there of.
- // For other arrays we are down to its element type.
- Qualifiers::GC GCAttr = GetGCAttrTypeForType(CGM.getContext(), FQT);
-
- unsigned FieldSize = CGM.getContext().getTypeSize(Field->getType());
- if ((ForStrongLayout && GCAttr == Qualifiers::Strong)
- || (!ForStrongLayout && GCAttr == Qualifiers::Weak)) {
- if (IsUnion) {
- uint64_t UnionIvarSize = FieldSize / WordSizeInBits;
- if (UnionIvarSize > MaxUnionIvarSize) {
- MaxUnionIvarSize = UnionIvarSize;
- MaxField = Field;
- MaxFieldOffset = FieldOffset;
- }
- } else {
- IvarsInfo.push_back(GC_IVAR(BytePos + FieldOffset,
- FieldSize / WordSizeInBits));
- }
- } else if ((ForStrongLayout &&
- (GCAttr == Qualifiers::GCNone || GCAttr == Qualifiers::Weak))
- || (!ForStrongLayout && GCAttr != Qualifiers::Weak)) {
- if (IsUnion) {
- // FIXME: Why the asymmetry? We divide by word size in bits on other
- // side.
- uint64_t UnionIvarSize = FieldSize;
- if (UnionIvarSize > MaxSkippedUnionIvarSize) {
- MaxSkippedUnionIvarSize = UnionIvarSize;
- MaxSkippedField = Field;
- MaxSkippedFieldOffset = FieldOffset;
- }
- } else {
- // FIXME: Why the asymmetry, we divide by byte size in bits here?
- SkipIvars.push_back(GC_IVAR(BytePos + FieldOffset,
- FieldSize / ByteSizeInBits));
- }
- }
- }
-
- if (LastFieldBitfield) {
- // Last field was a bitfield. Must update skip info.
- Expr *BitWidth = LastFieldBitfield->getBitWidth();
- uint64_t BitFieldSize =
- BitWidth->EvaluateAsInt(CGM.getContext()).getZExtValue();
- GC_IVAR skivar;
- skivar.ivar_bytepos = BytePos + LastBitfieldOffset;
- skivar.ivar_size = (BitFieldSize / ByteSizeInBits)
- + ((BitFieldSize % ByteSizeInBits) != 0);
- SkipIvars.push_back(skivar);
- }
-
- if (MaxField)
- IvarsInfo.push_back(GC_IVAR(BytePos + MaxFieldOffset,
- MaxUnionIvarSize));
- if (MaxSkippedField)
- SkipIvars.push_back(GC_IVAR(BytePos + MaxSkippedFieldOffset,
- MaxSkippedUnionIvarSize));
-}
-
-/// BuildIvarLayout - Builds ivar layout bitmap for the class
-/// implementation for the __strong or __weak case.
-/// The layout map displays which words in ivar list must be skipped
-/// and which must be scanned by GC (see below). String is built of bytes.
-/// Each byte is divided up in two nibbles (4-bit each). Left nibble is count
-/// of words to skip and right nibble is count of words to scan. So, each
-/// nibble represents up to 15 workds to skip or scan. Skipping the rest is
-/// represented by a 0x00 byte which also ends the string.
-/// 1. when ForStrongLayout is true, following ivars are scanned:
-/// - id, Class
-/// - object *
-/// - __strong anything
-///
-/// 2. When ForStrongLayout is false, following ivars are scanned:
-/// - __weak anything
-///
-llvm::Constant *CGObjCCommonMac::BuildIvarLayout(
- const ObjCImplementationDecl *OMD,
- bool ForStrongLayout) {
- bool hasUnion = false;
-
- unsigned int WordsToScan, WordsToSkip;
- const llvm::Type *PtrTy = llvm::Type::getInt8PtrTy(VMContext);
- if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC)
- return llvm::Constant::getNullValue(PtrTy);
-
- llvm::SmallVector<FieldDecl*, 32> RecFields;
- const ObjCInterfaceDecl *OI = OMD->getClassInterface();
- CGM.getContext().CollectObjCIvars(OI, RecFields);
-
- // Add this implementations synthesized ivars.
- llvm::SmallVector<ObjCIvarDecl*, 16> Ivars;
- CGM.getContext().CollectNonClassIvars(OI, Ivars);
- for (unsigned k = 0, e = Ivars.size(); k != e; ++k)
- RecFields.push_back(cast<FieldDecl>(Ivars[k]));
-
- if (RecFields.empty())
- return llvm::Constant::getNullValue(PtrTy);
-
- SkipIvars.clear();
- IvarsInfo.clear();
-
- BuildAggrIvarLayout(OMD, 0, 0, RecFields, 0, ForStrongLayout, hasUnion);
- if (IvarsInfo.empty())
- return llvm::Constant::getNullValue(PtrTy);
-
- // Sort on byte position in case we encounterred a union nested in
- // the ivar list.
- if (hasUnion && !IvarsInfo.empty())
- std::sort(IvarsInfo.begin(), IvarsInfo.end());
- if (hasUnion && !SkipIvars.empty())
- std::sort(SkipIvars.begin(), SkipIvars.end());
-
- // Build the string of skip/scan nibbles
- llvm::SmallVector<SKIP_SCAN, 32> SkipScanIvars;
- unsigned int WordSize =
- CGM.getTypes().getTargetData().getTypeAllocSize(PtrTy);
- if (IvarsInfo[0].ivar_bytepos == 0) {
- WordsToSkip = 0;
- WordsToScan = IvarsInfo[0].ivar_size;
- } else {
- WordsToSkip = IvarsInfo[0].ivar_bytepos/WordSize;
- WordsToScan = IvarsInfo[0].ivar_size;
- }
- for (unsigned int i=1, Last=IvarsInfo.size(); i != Last; i++) {
- unsigned int TailPrevGCObjC =
- IvarsInfo[i-1].ivar_bytepos + IvarsInfo[i-1].ivar_size * WordSize;
- if (IvarsInfo[i].ivar_bytepos == TailPrevGCObjC) {
- // consecutive 'scanned' object pointers.
- WordsToScan += IvarsInfo[i].ivar_size;
- } else {
- // Skip over 'gc'able object pointer which lay over each other.
- if (TailPrevGCObjC > IvarsInfo[i].ivar_bytepos)
- continue;
- // Must skip over 1 or more words. We save current skip/scan values
- // and start a new pair.
- SKIP_SCAN SkScan;
- SkScan.skip = WordsToSkip;
- SkScan.scan = WordsToScan;
- SkipScanIvars.push_back(SkScan);
-
- // Skip the hole.
- SkScan.skip = (IvarsInfo[i].ivar_bytepos - TailPrevGCObjC) / WordSize;
- SkScan.scan = 0;
- SkipScanIvars.push_back(SkScan);
- WordsToSkip = 0;
- WordsToScan = IvarsInfo[i].ivar_size;
- }
- }
- if (WordsToScan > 0) {
- SKIP_SCAN SkScan;
- SkScan.skip = WordsToSkip;
- SkScan.scan = WordsToScan;
- SkipScanIvars.push_back(SkScan);
- }
-
- if (!SkipIvars.empty()) {
- unsigned int LastIndex = SkipIvars.size()-1;
- int LastByteSkipped =
- SkipIvars[LastIndex].ivar_bytepos + SkipIvars[LastIndex].ivar_size;
- LastIndex = IvarsInfo.size()-1;
- int LastByteScanned =
- IvarsInfo[LastIndex].ivar_bytepos +
- IvarsInfo[LastIndex].ivar_size * WordSize;
- // Compute number of bytes to skip at the tail end of the last ivar scanned.
- if (LastByteSkipped > LastByteScanned) {
- unsigned int TotalWords = (LastByteSkipped + (WordSize -1)) / WordSize;
- SKIP_SCAN SkScan;
- SkScan.skip = TotalWords - (LastByteScanned/WordSize);
- SkScan.scan = 0;
- SkipScanIvars.push_back(SkScan);
- }
- }
- // Mini optimization of nibbles such that an 0xM0 followed by 0x0N is produced
- // as 0xMN.
- int SkipScan = SkipScanIvars.size()-1;
- for (int i = 0; i <= SkipScan; i++) {
- if ((i < SkipScan) && SkipScanIvars[i].skip && SkipScanIvars[i].scan == 0
- && SkipScanIvars[i+1].skip == 0 && SkipScanIvars[i+1].scan) {
- // 0xM0 followed by 0x0N detected.
- SkipScanIvars[i].scan = SkipScanIvars[i+1].scan;
- for (int j = i+1; j < SkipScan; j++)
- SkipScanIvars[j] = SkipScanIvars[j+1];
- --SkipScan;
- }
- }
-
- // Generate the string.
- std::string BitMap;
- for (int i = 0; i <= SkipScan; i++) {
- unsigned char byte;
- unsigned int skip_small = SkipScanIvars[i].skip % 0xf;
- unsigned int scan_small = SkipScanIvars[i].scan % 0xf;
- unsigned int skip_big = SkipScanIvars[i].skip / 0xf;
- unsigned int scan_big = SkipScanIvars[i].scan / 0xf;
-
- // first skip big.
- for (unsigned int ix = 0; ix < skip_big; ix++)
- BitMap += (unsigned char)(0xf0);
-
- // next (skip small, scan)
- if (skip_small) {
- byte = skip_small << 4;
- if (scan_big > 0) {
- byte |= 0xf;
- --scan_big;
- } else if (scan_small) {
- byte |= scan_small;
- scan_small = 0;
- }
- BitMap += byte;
- }
- // next scan big
- for (unsigned int ix = 0; ix < scan_big; ix++)
- BitMap += (unsigned char)(0x0f);
- // last scan small
- if (scan_small) {
- byte = scan_small;
- BitMap += byte;
- }
- }
- // null terminate string.
- unsigned char zero = 0;
- BitMap += zero;
-
- if (CGM.getLangOptions().ObjCGCBitmapPrint) {
- printf("\n%s ivar layout for class '%s': ",
- ForStrongLayout ? "strong" : "weak",
- OMD->getClassInterface()->getNameAsCString());
- const unsigned char *s = (unsigned char*)BitMap.c_str();
- for (unsigned i = 0; i < BitMap.size(); i++)
- if (!(s[i] & 0xf0))
- printf("0x0%x%s", s[i], s[i] != 0 ? ", " : "");
- else
- printf("0x%x%s", s[i], s[i] != 0 ? ", " : "");
- printf("\n");
- }
- llvm::GlobalVariable * Entry =
- CreateMetadataVar("\01L_OBJC_CLASS_NAME_",
- llvm::ConstantArray::get(VMContext, BitMap.c_str()),
- "__TEXT,__cstring,cstring_literals",
- 1, true);
- return getConstantGEP(VMContext, Entry, 0, 0);
-}
-
-llvm::Constant *CGObjCCommonMac::GetMethodVarName(Selector Sel) {
- llvm::GlobalVariable *&Entry = MethodVarNames[Sel];
-
- // FIXME: Avoid std::string copying.
- if (!Entry)
- Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_NAME_",
- llvm::ConstantArray::get(VMContext, Sel.getAsString()),
- "__TEXT,__cstring,cstring_literals",
- 1, true);
-
- return getConstantGEP(VMContext, Entry, 0, 0);
-}
-
-// FIXME: Merge into a single cstring creation function.
-llvm::Constant *CGObjCCommonMac::GetMethodVarName(IdentifierInfo *ID) {
- return GetMethodVarName(CGM.getContext().Selectors.getNullarySelector(ID));
-}
-
-// FIXME: Merge into a single cstring creation function.
-llvm::Constant *CGObjCCommonMac::GetMethodVarName(const std::string &Name) {
- return GetMethodVarName(&CGM.getContext().Idents.get(Name));
-}
-
-llvm::Constant *CGObjCCommonMac::GetMethodVarType(const FieldDecl *Field) {
- std::string TypeStr;
- CGM.getContext().getObjCEncodingForType(Field->getType(), TypeStr, Field);
-
- llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
-
- if (!Entry)
- Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
- llvm::ConstantArray::get(VMContext, TypeStr),
- "__TEXT,__cstring,cstring_literals",
- 1, true);
-
- return getConstantGEP(VMContext, Entry, 0, 0);
-}
-
-llvm::Constant *CGObjCCommonMac::GetMethodVarType(const ObjCMethodDecl *D) {
- std::string TypeStr;
- CGM.getContext().getObjCEncodingForMethodDecl(const_cast<ObjCMethodDecl*>(D),
- TypeStr);
-
- llvm::GlobalVariable *&Entry = MethodVarTypes[TypeStr];
-
- if (!Entry)
- Entry = CreateMetadataVar("\01L_OBJC_METH_VAR_TYPE_",
- llvm::ConstantArray::get(VMContext, TypeStr),
- "__TEXT,__cstring,cstring_literals",
- 1, true);
-
- return getConstantGEP(VMContext, Entry, 0, 0);
-}
-
-// FIXME: Merge into a single cstring creation function.
-llvm::Constant *CGObjCCommonMac::GetPropertyName(IdentifierInfo *Ident) {
- llvm::GlobalVariable *&Entry = PropertyNames[Ident];
-
- if (!Entry)
- Entry = CreateMetadataVar("\01L_OBJC_PROP_NAME_ATTR_",
- llvm::ConstantArray::get(VMContext,
- Ident->getNameStart()),
- "__TEXT,__cstring,cstring_literals",
- 1, true);
-
- return getConstantGEP(VMContext, Entry, 0, 0);
-}
-
-// FIXME: Merge into a single cstring creation function.
-// FIXME: This Decl should be more precise.
-llvm::Constant *
-CGObjCCommonMac::GetPropertyTypeString(const ObjCPropertyDecl *PD,
- const Decl *Container) {
- std::string TypeStr;
- CGM.getContext().getObjCEncodingForPropertyDecl(PD, Container, TypeStr);
- return GetPropertyName(&CGM.getContext().Idents.get(TypeStr));
-}
-
-void CGObjCCommonMac::GetNameForMethod(const ObjCMethodDecl *D,
- const ObjCContainerDecl *CD,
- llvm::SmallVectorImpl<char> &Name) {
- llvm::raw_svector_ostream OS(Name);
- assert (CD && "Missing container decl in GetNameForMethod");
- OS << '\01' << (D->isInstanceMethod() ? '-' : '+')
- << '[' << CD->getName();
- if (const ObjCCategoryImplDecl *CID =
- dyn_cast<ObjCCategoryImplDecl>(D->getDeclContext()))
- OS << '(' << CID << ')';
- OS << ' ' << D->getSelector().getAsString() << ']';
-}
-
-void CGObjCMac::FinishModule() {
- EmitModuleInfo();
-
- // Emit the dummy bodies for any protocols which were referenced but
- // never defined.
- for (llvm::DenseMap<IdentifierInfo*, llvm::GlobalVariable*>::iterator
- I = Protocols.begin(), e = Protocols.end(); I != e; ++I) {
- if (I->second->hasInitializer())
- continue;
-
- std::vector<llvm::Constant*> Values(5);
- Values[0] = llvm::Constant::getNullValue(ObjCTypes.ProtocolExtensionPtrTy);
- Values[1] = GetClassName(I->first);
- Values[2] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListPtrTy);
- Values[3] = Values[4] =
- llvm::Constant::getNullValue(ObjCTypes.MethodDescriptionListPtrTy);
- I->second->setLinkage(llvm::GlobalValue::InternalLinkage);
- I->second->setInitializer(llvm::ConstantStruct::get(ObjCTypes.ProtocolTy,
- Values));
- CGM.AddUsedGlobal(I->second);
- }
-
- // Add assembler directives to add lazy undefined symbol references
- // for classes which are referenced but not defined. This is
- // important for correct linker interaction.
- //
- // FIXME: It would be nice if we had an LLVM construct for this.
- if (!LazySymbols.empty() || !DefinedSymbols.empty()) {
- llvm::SmallString<256> Asm;
- Asm += CGM.getModule().getModuleInlineAsm();
- if (!Asm.empty() && Asm.back() != '\n')
- Asm += '\n';
-
- llvm::raw_svector_ostream OS(Asm);
- for (llvm::SetVector<IdentifierInfo*>::iterator I = DefinedSymbols.begin(),
- e = DefinedSymbols.end(); I != e; ++I)
- OS << "\t.objc_class_name_" << (*I)->getName() << "=0\n"
- << "\t.globl .objc_class_name_" << (*I)->getName() << "\n";
- for (llvm::SetVector<IdentifierInfo*>::iterator I = LazySymbols.begin(),
- e = LazySymbols.end(); I != e; ++I) {
- OS << "\t.lazy_reference .objc_class_name_" << (*I)->getName() << "\n";
- }
-
- for (size_t i = 0; i < DefinedCategoryNames.size(); ++i) {
- OS << "\t.objc_category_name_" << DefinedCategoryNames[i] << "=0\n"
- << "\t.globl .objc_category_name_" << DefinedCategoryNames[i] << "\n";
- }
-
- CGM.getModule().setModuleInlineAsm(OS.str());
- }
-}
-
-CGObjCNonFragileABIMac::CGObjCNonFragileABIMac(CodeGen::CodeGenModule &cgm)
- : CGObjCCommonMac(cgm),
- ObjCTypes(cgm) {
- ObjCEmptyCacheVar = ObjCEmptyVtableVar = NULL;
- ObjCABI = 2;
-}
-
-/* *** */
-
-ObjCCommonTypesHelper::ObjCCommonTypesHelper(CodeGen::CodeGenModule &cgm)
- : VMContext(cgm.getLLVMContext()), CGM(cgm) {
- CodeGen::CodeGenTypes &Types = CGM.getTypes();
- ASTContext &Ctx = CGM.getContext();
-
- ShortTy = Types.ConvertType(Ctx.ShortTy);
- IntTy = Types.ConvertType(Ctx.IntTy);
- LongTy = Types.ConvertType(Ctx.LongTy);
- LongLongTy = Types.ConvertType(Ctx.LongLongTy);
- Int8PtrTy = llvm::Type::getInt8PtrTy(VMContext);
-
- ObjectPtrTy = Types.ConvertType(Ctx.getObjCIdType());
- PtrObjectPtrTy = llvm::PointerType::getUnqual(ObjectPtrTy);
- SelectorPtrTy = Types.ConvertType(Ctx.getObjCSelType());
-
- // FIXME: It would be nice to unify this with the opaque type, so that the IR
- // comes out a bit cleaner.
- const llvm::Type *T = Types.ConvertType(Ctx.getObjCProtoType());
- ExternalProtocolPtrTy = llvm::PointerType::getUnqual(T);
-
- // I'm not sure I like this. The implicit coordination is a bit
- // gross. We should solve this in a reasonable fashion because this
- // is a pretty common task (match some runtime data structure with
- // an LLVM data structure).
-
- // FIXME: This is leaked.
- // FIXME: Merge with rewriter code?
-
- // struct _objc_super {
- // id self;
- // Class cls;
- // }
- RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
- Ctx.getTranslationUnitDecl(),
- SourceLocation(),
- &Ctx.Idents.get("_objc_super"));
- RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
- Ctx.getObjCIdType(), 0, 0, false));
- RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
- Ctx.getObjCClassType(), 0, 0, false));
- RD->completeDefinition();
-
- SuperCTy = Ctx.getTagDeclType(RD);
- SuperPtrCTy = Ctx.getPointerType(SuperCTy);
-
- SuperTy = cast<llvm::StructType>(Types.ConvertType(SuperCTy));
- SuperPtrTy = llvm::PointerType::getUnqual(SuperTy);
-
- // struct _prop_t {
- // char *name;
- // char *attributes;
- // }
- PropertyTy = llvm::StructType::get(VMContext, Int8PtrTy, Int8PtrTy, NULL);
- CGM.getModule().addTypeName("struct._prop_t",
- PropertyTy);
-
- // struct _prop_list_t {
- // uint32_t entsize; // sizeof(struct _prop_t)
- // uint32_t count_of_properties;
- // struct _prop_t prop_list[count_of_properties];
- // }
- PropertyListTy = llvm::StructType::get(VMContext, IntTy,
- IntTy,
- llvm::ArrayType::get(PropertyTy, 0),
- NULL);
- CGM.getModule().addTypeName("struct._prop_list_t",
- PropertyListTy);
- // struct _prop_list_t *
- PropertyListPtrTy = llvm::PointerType::getUnqual(PropertyListTy);
-
- // struct _objc_method {
- // SEL _cmd;
- // char *method_type;
- // char *_imp;
- // }
- MethodTy = llvm::StructType::get(VMContext, SelectorPtrTy,
- Int8PtrTy,
- Int8PtrTy,
- NULL);
- CGM.getModule().addTypeName("struct._objc_method", MethodTy);
-
- // struct _objc_cache *
- CacheTy = llvm::OpaqueType::get(VMContext);
- CGM.getModule().addTypeName("struct._objc_cache", CacheTy);
- CachePtrTy = llvm::PointerType::getUnqual(CacheTy);
-}
-
-ObjCTypesHelper::ObjCTypesHelper(CodeGen::CodeGenModule &cgm)
- : ObjCCommonTypesHelper(cgm) {
- // struct _objc_method_description {
- // SEL name;
- // char *types;
- // }
- MethodDescriptionTy =
- llvm::StructType::get(VMContext, SelectorPtrTy,
- Int8PtrTy,
- NULL);
- CGM.getModule().addTypeName("struct._objc_method_description",
- MethodDescriptionTy);
-
- // struct _objc_method_description_list {
- // int count;
- // struct _objc_method_description[1];
- // }
- MethodDescriptionListTy =
- llvm::StructType::get(VMContext, IntTy,
- llvm::ArrayType::get(MethodDescriptionTy, 0),
- NULL);
- CGM.getModule().addTypeName("struct._objc_method_description_list",
- MethodDescriptionListTy);
-
- // struct _objc_method_description_list *
- MethodDescriptionListPtrTy =
- llvm::PointerType::getUnqual(MethodDescriptionListTy);
-
- // Protocol description structures
-
- // struct _objc_protocol_extension {
- // uint32_t size; // sizeof(struct _objc_protocol_extension)
- // struct _objc_method_description_list *optional_instance_methods;
- // struct _objc_method_description_list *optional_class_methods;
- // struct _objc_property_list *instance_properties;
- // }
- ProtocolExtensionTy =
- llvm::StructType::get(VMContext, IntTy,
- MethodDescriptionListPtrTy,
- MethodDescriptionListPtrTy,
- PropertyListPtrTy,
- NULL);
- CGM.getModule().addTypeName("struct._objc_protocol_extension",
- ProtocolExtensionTy);
-
- // struct _objc_protocol_extension *
- ProtocolExtensionPtrTy = llvm::PointerType::getUnqual(ProtocolExtensionTy);
-
- // Handle recursive construction of Protocol and ProtocolList types
-
- llvm::PATypeHolder ProtocolTyHolder = llvm::OpaqueType::get(VMContext);
- llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext);
-
- const llvm::Type *T =
- llvm::StructType::get(VMContext,
- llvm::PointerType::getUnqual(ProtocolListTyHolder),
- LongTy,
- llvm::ArrayType::get(ProtocolTyHolder, 0),
- NULL);
- cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(T);
-
- // struct _objc_protocol {
- // struct _objc_protocol_extension *isa;
- // char *protocol_name;
- // struct _objc_protocol **_objc_protocol_list;
- // struct _objc_method_description_list *instance_methods;
- // struct _objc_method_description_list *class_methods;
- // }
- T = llvm::StructType::get(VMContext, ProtocolExtensionPtrTy,
- Int8PtrTy,
- llvm::PointerType::getUnqual(ProtocolListTyHolder),
- MethodDescriptionListPtrTy,
- MethodDescriptionListPtrTy,
- NULL);
- cast<llvm::OpaqueType>(ProtocolTyHolder.get())->refineAbstractTypeTo(T);
-
- ProtocolListTy = cast<llvm::StructType>(ProtocolListTyHolder.get());
- CGM.getModule().addTypeName("struct._objc_protocol_list",
- ProtocolListTy);
- // struct _objc_protocol_list *
- ProtocolListPtrTy = llvm::PointerType::getUnqual(ProtocolListTy);
-
- ProtocolTy = cast<llvm::StructType>(ProtocolTyHolder.get());
- CGM.getModule().addTypeName("struct._objc_protocol", ProtocolTy);
- ProtocolPtrTy = llvm::PointerType::getUnqual(ProtocolTy);
-
- // Class description structures
-
- // struct _objc_ivar {
- // char *ivar_name;
- // char *ivar_type;
- // int ivar_offset;
- // }
- IvarTy = llvm::StructType::get(VMContext, Int8PtrTy,
- Int8PtrTy,
- IntTy,
- NULL);
- CGM.getModule().addTypeName("struct._objc_ivar", IvarTy);
-
- // struct _objc_ivar_list *
- IvarListTy = llvm::OpaqueType::get(VMContext);
- CGM.getModule().addTypeName("struct._objc_ivar_list", IvarListTy);
- IvarListPtrTy = llvm::PointerType::getUnqual(IvarListTy);
-
- // struct _objc_method_list *
- MethodListTy = llvm::OpaqueType::get(VMContext);
- CGM.getModule().addTypeName("struct._objc_method_list", MethodListTy);
- MethodListPtrTy = llvm::PointerType::getUnqual(MethodListTy);
-
- // struct _objc_class_extension *
- ClassExtensionTy =
- llvm::StructType::get(VMContext, IntTy,
- Int8PtrTy,
- PropertyListPtrTy,
- NULL);
- CGM.getModule().addTypeName("struct._objc_class_extension", ClassExtensionTy);
- ClassExtensionPtrTy = llvm::PointerType::getUnqual(ClassExtensionTy);
-
- llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext);
-
- // struct _objc_class {
- // Class isa;
- // Class super_class;
- // char *name;
- // long version;
- // long info;
- // long instance_size;
- // struct _objc_ivar_list *ivars;
- // struct _objc_method_list *methods;
- // struct _objc_cache *cache;
- // struct _objc_protocol_list *protocols;
- // char *ivar_layout;
- // struct _objc_class_ext *ext;
- // };
- T = llvm::StructType::get(VMContext,
- llvm::PointerType::getUnqual(ClassTyHolder),
- llvm::PointerType::getUnqual(ClassTyHolder),
- Int8PtrTy,
- LongTy,
- LongTy,
- LongTy,
- IvarListPtrTy,
- MethodListPtrTy,
- CachePtrTy,
- ProtocolListPtrTy,
- Int8PtrTy,
- ClassExtensionPtrTy,
- NULL);
- cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(T);
-
- ClassTy = cast<llvm::StructType>(ClassTyHolder.get());
- CGM.getModule().addTypeName("struct._objc_class", ClassTy);
- ClassPtrTy = llvm::PointerType::getUnqual(ClassTy);
-
- // struct _objc_category {
- // char *category_name;
- // char *class_name;
- // struct _objc_method_list *instance_method;
- // struct _objc_method_list *class_method;
- // uint32_t size; // sizeof(struct _objc_category)
- // struct _objc_property_list *instance_properties;// category's @property
- // }
- CategoryTy = llvm::StructType::get(VMContext, Int8PtrTy,
- Int8PtrTy,
- MethodListPtrTy,
- MethodListPtrTy,
- ProtocolListPtrTy,
- IntTy,
- PropertyListPtrTy,
- NULL);
- CGM.getModule().addTypeName("struct._objc_category", CategoryTy);
-
- // Global metadata structures
-
- // struct _objc_symtab {
- // long sel_ref_cnt;
- // SEL *refs;
- // short cls_def_cnt;
- // short cat_def_cnt;
- // char *defs[cls_def_cnt + cat_def_cnt];
- // }
- SymtabTy = llvm::StructType::get(VMContext, LongTy,
- SelectorPtrTy,
- ShortTy,
- ShortTy,
- llvm::ArrayType::get(Int8PtrTy, 0),
- NULL);
- CGM.getModule().addTypeName("struct._objc_symtab", SymtabTy);
- SymtabPtrTy = llvm::PointerType::getUnqual(SymtabTy);
-
- // struct _objc_module {
- // long version;
- // long size; // sizeof(struct _objc_module)
- // char *name;
- // struct _objc_symtab* symtab;
- // }
- ModuleTy =
- llvm::StructType::get(VMContext, LongTy,
- LongTy,
- Int8PtrTy,
- SymtabPtrTy,
- NULL);
- CGM.getModule().addTypeName("struct._objc_module", ModuleTy);
-
-
- // FIXME: This is the size of the setjmp buffer and should be target
- // specific. 18 is what's used on 32-bit X86.
- uint64_t SetJmpBufferSize = 18;
-
- // Exceptions
- const llvm::Type *StackPtrTy = llvm::ArrayType::get(
- llvm::Type::getInt8PtrTy(VMContext), 4);
-
- ExceptionDataTy =
- llvm::StructType::get(VMContext,
- llvm::ArrayType::get(llvm::Type::getInt32Ty(VMContext),
- SetJmpBufferSize),
- StackPtrTy, NULL);
- CGM.getModule().addTypeName("struct._objc_exception_data",
- ExceptionDataTy);
-
-}
-
-ObjCNonFragileABITypesHelper::ObjCNonFragileABITypesHelper(CodeGen::CodeGenModule &cgm)
- : ObjCCommonTypesHelper(cgm) {
- // struct _method_list_t {
- // uint32_t entsize; // sizeof(struct _objc_method)
- // uint32_t method_count;
- // struct _objc_method method_list[method_count];
- // }
- MethodListnfABITy = llvm::StructType::get(VMContext, IntTy,
- IntTy,
- llvm::ArrayType::get(MethodTy, 0),
- NULL);
- CGM.getModule().addTypeName("struct.__method_list_t",
- MethodListnfABITy);
- // struct method_list_t *
- MethodListnfABIPtrTy = llvm::PointerType::getUnqual(MethodListnfABITy);
-
- // struct _protocol_t {
- // id isa; // NULL
- // const char * const protocol_name;
- // const struct _protocol_list_t * protocol_list; // super protocols
- // const struct method_list_t * const instance_methods;
- // const struct method_list_t * const class_methods;
- // const struct method_list_t *optionalInstanceMethods;
- // const struct method_list_t *optionalClassMethods;
- // const struct _prop_list_t * properties;
- // const uint32_t size; // sizeof(struct _protocol_t)
- // const uint32_t flags; // = 0
- // }
-
- // Holder for struct _protocol_list_t *
- llvm::PATypeHolder ProtocolListTyHolder = llvm::OpaqueType::get(VMContext);
-
- ProtocolnfABITy = llvm::StructType::get(VMContext, ObjectPtrTy,
- Int8PtrTy,
- llvm::PointerType::getUnqual(
- ProtocolListTyHolder),
- MethodListnfABIPtrTy,
- MethodListnfABIPtrTy,
- MethodListnfABIPtrTy,
- MethodListnfABIPtrTy,
- PropertyListPtrTy,
- IntTy,
- IntTy,
- NULL);
- CGM.getModule().addTypeName("struct._protocol_t",
- ProtocolnfABITy);
-
- // struct _protocol_t*
- ProtocolnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolnfABITy);
-
- // struct _protocol_list_t {
- // long protocol_count; // Note, this is 32/64 bit
- // struct _protocol_t *[protocol_count];
- // }
- ProtocolListnfABITy = llvm::StructType::get(VMContext, LongTy,
- llvm::ArrayType::get(
- ProtocolnfABIPtrTy, 0),
- NULL);
- CGM.getModule().addTypeName("struct._objc_protocol_list",
- ProtocolListnfABITy);
- cast<llvm::OpaqueType>(ProtocolListTyHolder.get())->refineAbstractTypeTo(
- ProtocolListnfABITy);
-
- // struct _objc_protocol_list*
- ProtocolListnfABIPtrTy = llvm::PointerType::getUnqual(ProtocolListnfABITy);
-
- // struct _ivar_t {
- // unsigned long int *offset; // pointer to ivar offset location
- // char *name;
- // char *type;
- // uint32_t alignment;
- // uint32_t size;
- // }
- IvarnfABITy = llvm::StructType::get(VMContext,
- llvm::PointerType::getUnqual(LongTy),
- Int8PtrTy,
- Int8PtrTy,
- IntTy,
- IntTy,
- NULL);
- CGM.getModule().addTypeName("struct._ivar_t", IvarnfABITy);
-
- // struct _ivar_list_t {
- // uint32 entsize; // sizeof(struct _ivar_t)
- // uint32 count;
- // struct _iver_t list[count];
- // }
- IvarListnfABITy = llvm::StructType::get(VMContext, IntTy,
- IntTy,
- llvm::ArrayType::get(
- IvarnfABITy, 0),
- NULL);
- CGM.getModule().addTypeName("struct._ivar_list_t", IvarListnfABITy);
-
- IvarListnfABIPtrTy = llvm::PointerType::getUnqual(IvarListnfABITy);
-
- // struct _class_ro_t {
- // uint32_t const flags;
- // uint32_t const instanceStart;
- // uint32_t const instanceSize;
- // uint32_t const reserved; // only when building for 64bit targets
- // const uint8_t * const ivarLayout;
- // const char *const name;
- // const struct _method_list_t * const baseMethods;
- // const struct _objc_protocol_list *const baseProtocols;
- // const struct _ivar_list_t *const ivars;
- // const uint8_t * const weakIvarLayout;
- // const struct _prop_list_t * const properties;
- // }
-
- // FIXME. Add 'reserved' field in 64bit abi mode!
- ClassRonfABITy = llvm::StructType::get(VMContext, IntTy,
- IntTy,
- IntTy,
- Int8PtrTy,
- Int8PtrTy,
- MethodListnfABIPtrTy,
- ProtocolListnfABIPtrTy,
- IvarListnfABIPtrTy,
- Int8PtrTy,
- PropertyListPtrTy,
- NULL);
- CGM.getModule().addTypeName("struct._class_ro_t",
- ClassRonfABITy);
-
- // ImpnfABITy - LLVM for id (*)(id, SEL, ...)
- std::vector<const llvm::Type*> Params;
- Params.push_back(ObjectPtrTy);
- Params.push_back(SelectorPtrTy);
- ImpnfABITy = llvm::PointerType::getUnqual(
- llvm::FunctionType::get(ObjectPtrTy, Params, false));
-
- // struct _class_t {
- // struct _class_t *isa;
- // struct _class_t * const superclass;
- // void *cache;
- // IMP *vtable;
- // struct class_ro_t *ro;
- // }
-
- llvm::PATypeHolder ClassTyHolder = llvm::OpaqueType::get(VMContext);
- ClassnfABITy =
- llvm::StructType::get(VMContext,
- llvm::PointerType::getUnqual(ClassTyHolder),
- llvm::PointerType::getUnqual(ClassTyHolder),
- CachePtrTy,
- llvm::PointerType::getUnqual(ImpnfABITy),
- llvm::PointerType::getUnqual(ClassRonfABITy),
- NULL);
- CGM.getModule().addTypeName("struct._class_t", ClassnfABITy);
-
- cast<llvm::OpaqueType>(ClassTyHolder.get())->refineAbstractTypeTo(
- ClassnfABITy);
-
- // LLVM for struct _class_t *
- ClassnfABIPtrTy = llvm::PointerType::getUnqual(ClassnfABITy);
-
- // struct _category_t {
- // const char * const name;
- // struct _class_t *const cls;
- // const struct _method_list_t * const instance_methods;
- // const struct _method_list_t * const class_methods;
- // const struct _protocol_list_t * const protocols;
- // const struct _prop_list_t * const properties;
- // }
- CategorynfABITy = llvm::StructType::get(VMContext, Int8PtrTy,
- ClassnfABIPtrTy,
- MethodListnfABIPtrTy,
- MethodListnfABIPtrTy,
- ProtocolListnfABIPtrTy,
- PropertyListPtrTy,
- NULL);
- CGM.getModule().addTypeName("struct._category_t", CategorynfABITy);
-
- // New types for nonfragile abi messaging.
- CodeGen::CodeGenTypes &Types = CGM.getTypes();
- ASTContext &Ctx = CGM.getContext();
-
- // MessageRefTy - LLVM for:
- // struct _message_ref_t {
- // IMP messenger;
- // SEL name;
- // };
-
- // First the clang type for struct _message_ref_t
- RecordDecl *RD = RecordDecl::Create(Ctx, TTK_Struct,
- Ctx.getTranslationUnitDecl(),
- SourceLocation(),
- &Ctx.Idents.get("_message_ref_t"));
- RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
- Ctx.VoidPtrTy, 0, 0, false));
- RD->addDecl(FieldDecl::Create(Ctx, RD, SourceLocation(), 0,
- Ctx.getObjCSelType(), 0, 0, false));
- RD->completeDefinition();
-
- MessageRefCTy = Ctx.getTagDeclType(RD);
- MessageRefCPtrTy = Ctx.getPointerType(MessageRefCTy);
- MessageRefTy = cast<llvm::StructType>(Types.ConvertType(MessageRefCTy));
-
- // MessageRefPtrTy - LLVM for struct _message_ref_t*
- MessageRefPtrTy = llvm::PointerType::getUnqual(MessageRefTy);
-
- // SuperMessageRefTy - LLVM for:
- // struct _super_message_ref_t {
- // SUPER_IMP messenger;
- // SEL name;
- // };
- SuperMessageRefTy = llvm::StructType::get(VMContext, ImpnfABITy,
- SelectorPtrTy,
- NULL);
- CGM.getModule().addTypeName("struct._super_message_ref_t", SuperMessageRefTy);
-
- // SuperMessageRefPtrTy - LLVM for struct _super_message_ref_t*
- SuperMessageRefPtrTy = llvm::PointerType::getUnqual(SuperMessageRefTy);
-
-
- // struct objc_typeinfo {
- // const void** vtable; // objc_ehtype_vtable + 2
- // const char* name; // c++ typeinfo string
- // Class cls;
- // };
- EHTypeTy = llvm::StructType::get(VMContext,
- llvm::PointerType::getUnqual(Int8PtrTy),
- Int8PtrTy,
- ClassnfABIPtrTy,
- NULL);
- CGM.getModule().addTypeName("struct._objc_typeinfo", EHTypeTy);
- EHTypePtrTy = llvm::PointerType::getUnqual(EHTypeTy);
-}
-
-llvm::Function *CGObjCNonFragileABIMac::ModuleInitFunction() {
- FinishNonFragileABIModule();
-
- return NULL;
-}
-
-void CGObjCNonFragileABIMac::AddModuleClassList(const
- std::vector<llvm::GlobalValue*>
- &Container,
- const char *SymbolName,
- const char *SectionName) {
- unsigned NumClasses = Container.size();
-
- if (!NumClasses)
- return;
-
- std::vector<llvm::Constant*> Symbols(NumClasses);
- for (unsigned i=0; i<NumClasses; i++)
- Symbols[i] = llvm::ConstantExpr::getBitCast(Container[i],
- ObjCTypes.Int8PtrTy);
- llvm::Constant* Init =
- llvm::ConstantArray::get(llvm::ArrayType::get(ObjCTypes.Int8PtrTy,
- NumClasses),
- Symbols);
-
- llvm::GlobalVariable *GV =
- new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
- llvm::GlobalValue::InternalLinkage,
- Init,
- SymbolName);
- GV->setAlignment(CGM.getTargetData().getABITypeAlignment(Init->getType()));
- GV->setSection(SectionName);
- CGM.AddUsedGlobal(GV);
-}
-
-void CGObjCNonFragileABIMac::FinishNonFragileABIModule() {
- // nonfragile abi has no module definition.
-
- // Build list of all implemented class addresses in array
- // L_OBJC_LABEL_CLASS_$.
- AddModuleClassList(DefinedClasses,
- "\01L_OBJC_LABEL_CLASS_$",
- "__DATA, __objc_classlist, regular, no_dead_strip");
-
- for (unsigned i = 0; i < DefinedClasses.size(); i++) {
- llvm::GlobalValue *IMPLGV = DefinedClasses[i];
- if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
- continue;
- IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
- }
-
- for (unsigned i = 0; i < DefinedMetaClasses.size(); i++) {
- llvm::GlobalValue *IMPLGV = DefinedMetaClasses[i];
- if (IMPLGV->getLinkage() != llvm::GlobalValue::ExternalWeakLinkage)
- continue;
- IMPLGV->setLinkage(llvm::GlobalValue::ExternalLinkage);
- }
-
- AddModuleClassList(DefinedNonLazyClasses,
- "\01L_OBJC_LABEL_NONLAZY_CLASS_$",
- "__DATA, __objc_nlclslist, regular, no_dead_strip");
-
- // Build list of all implemented category addresses in array
- // L_OBJC_LABEL_CATEGORY_$.
- AddModuleClassList(DefinedCategories,
- "\01L_OBJC_LABEL_CATEGORY_$",
- "__DATA, __objc_catlist, regular, no_dead_strip");
- AddModuleClassList(DefinedNonLazyCategories,
- "\01L_OBJC_LABEL_NONLAZY_CATEGORY_$",
- "__DATA, __objc_nlcatlist, regular, no_dead_strip");
-
- EmitImageInfo();
-}
-
-/// LegacyDispatchedSelector - Returns true if SEL is not in the list of
-/// NonLegacyDispatchMethods; false otherwise. What this means is that
-/// except for the 19 selectors in the list, we generate 32bit-style
-/// message dispatch call for all the rest.
-///
-bool CGObjCNonFragileABIMac::LegacyDispatchedSelector(Selector Sel) {
- switch (CGM.getCodeGenOpts().getObjCDispatchMethod()) {
- default:
- assert(0 && "Invalid dispatch method!");
- case CodeGenOptions::Legacy:
- return true;
- case CodeGenOptions::NonLegacy:
- return false;
- case CodeGenOptions::Mixed:
- break;
- }
-
- // If so, see whether this selector is in the white-list of things which must
- // use the new dispatch convention. We lazily build a dense set for this.
- if (NonLegacyDispatchMethods.empty()) {
- NonLegacyDispatchMethods.insert(GetNullarySelector("alloc"));
- NonLegacyDispatchMethods.insert(GetNullarySelector("class"));
- NonLegacyDispatchMethods.insert(GetNullarySelector("self"));
- NonLegacyDispatchMethods.insert(GetNullarySelector("isFlipped"));
- NonLegacyDispatchMethods.insert(GetNullarySelector("length"));
- NonLegacyDispatchMethods.insert(GetNullarySelector("count"));
- NonLegacyDispatchMethods.insert(GetNullarySelector("retain"));
- NonLegacyDispatchMethods.insert(GetNullarySelector("release"));
- NonLegacyDispatchMethods.insert(GetNullarySelector("autorelease"));
- NonLegacyDispatchMethods.insert(GetNullarySelector("hash"));
-
- NonLegacyDispatchMethods.insert(GetUnarySelector("allocWithZone"));
- NonLegacyDispatchMethods.insert(GetUnarySelector("isKindOfClass"));
- NonLegacyDispatchMethods.insert(GetUnarySelector("respondsToSelector"));
- NonLegacyDispatchMethods.insert(GetUnarySelector("objectForKey"));
- NonLegacyDispatchMethods.insert(GetUnarySelector("objectAtIndex"));
- NonLegacyDispatchMethods.insert(GetUnarySelector("isEqualToString"));
- NonLegacyDispatchMethods.insert(GetUnarySelector("isEqual"));
- NonLegacyDispatchMethods.insert(GetUnarySelector("addObject"));
- // "countByEnumeratingWithState:objects:count"
- IdentifierInfo *KeyIdents[] = {
- &CGM.getContext().Idents.get("countByEnumeratingWithState"),
- &CGM.getContext().Idents.get("objects"),
- &CGM.getContext().Idents.get("count")
- };
- NonLegacyDispatchMethods.insert(
- CGM.getContext().Selectors.getSelector(3, KeyIdents));
- }
-
- return (NonLegacyDispatchMethods.count(Sel) == 0);
-}
-
-// Metadata flags
-enum MetaDataDlags {
- CLS = 0x0,
- CLS_META = 0x1,
- CLS_ROOT = 0x2,
- OBJC2_CLS_HIDDEN = 0x10,
- CLS_EXCEPTION = 0x20
-};
-/// BuildClassRoTInitializer - generate meta-data for:
-/// struct _class_ro_t {
-/// uint32_t const flags;
-/// uint32_t const instanceStart;
-/// uint32_t const instanceSize;
-/// uint32_t const reserved; // only when building for 64bit targets
-/// const uint8_t * const ivarLayout;
-/// const char *const name;
-/// const struct _method_list_t * const baseMethods;
-/// const struct _protocol_list_t *const baseProtocols;
-/// const struct _ivar_list_t *const ivars;
-/// const uint8_t * const weakIvarLayout;
-/// const struct _prop_list_t * const properties;
-/// }
-///
-llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassRoTInitializer(
- unsigned flags,
- unsigned InstanceStart,
- unsigned InstanceSize,
- const ObjCImplementationDecl *ID) {
- std::string ClassName = ID->getNameAsString();
- std::vector<llvm::Constant*> Values(10); // 11 for 64bit targets!
- Values[ 0] = llvm::ConstantInt::get(ObjCTypes.IntTy, flags);
- Values[ 1] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceStart);
- Values[ 2] = llvm::ConstantInt::get(ObjCTypes.IntTy, InstanceSize);
- // FIXME. For 64bit targets add 0 here.
- Values[ 3] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
- : BuildIvarLayout(ID, true);
- Values[ 4] = GetClassName(ID->getIdentifier());
- // const struct _method_list_t * const baseMethods;
- std::vector<llvm::Constant*> Methods;
- std::string MethodListName("\01l_OBJC_$_");
- if (flags & CLS_META) {
- MethodListName += "CLASS_METHODS_" + ID->getNameAsString();
- for (ObjCImplementationDecl::classmeth_iterator
- i = ID->classmeth_begin(), e = ID->classmeth_end(); i != e; ++i) {
- // Class methods should always be defined.
- Methods.push_back(GetMethodConstant(*i));
- }
- } else {
- MethodListName += "INSTANCE_METHODS_" + ID->getNameAsString();
- for (ObjCImplementationDecl::instmeth_iterator
- i = ID->instmeth_begin(), e = ID->instmeth_end(); i != e; ++i) {
- // Instance methods should always be defined.
- Methods.push_back(GetMethodConstant(*i));
- }
- for (ObjCImplementationDecl::propimpl_iterator
- i = ID->propimpl_begin(), e = ID->propimpl_end(); i != e; ++i) {
- ObjCPropertyImplDecl *PID = *i;
-
- if (PID->getPropertyImplementation() == ObjCPropertyImplDecl::Synthesize){
- ObjCPropertyDecl *PD = PID->getPropertyDecl();
-
- if (ObjCMethodDecl *MD = PD->getGetterMethodDecl())
- if (llvm::Constant *C = GetMethodConstant(MD))
- Methods.push_back(C);
- if (ObjCMethodDecl *MD = PD->getSetterMethodDecl())
- if (llvm::Constant *C = GetMethodConstant(MD))
- Methods.push_back(C);
- }
- }
- }
- Values[ 5] = EmitMethodList(MethodListName,
- "__DATA, __objc_const", Methods);
-
- const ObjCInterfaceDecl *OID = ID->getClassInterface();
- assert(OID && "CGObjCNonFragileABIMac::BuildClassRoTInitializer");
- Values[ 6] = EmitProtocolList("\01l_OBJC_CLASS_PROTOCOLS_$_"
- + OID->getName(),
- OID->protocol_begin(),
- OID->protocol_end());
-
- if (flags & CLS_META)
- Values[ 7] = llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
- else
- Values[ 7] = EmitIvarList(ID);
- Values[ 8] = (flags & CLS_META) ? GetIvarLayoutName(0, ObjCTypes)
- : BuildIvarLayout(ID, false);
- if (flags & CLS_META)
- Values[ 9] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
- else
- Values[ 9] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ID->getName(),
- ID, ID->getClassInterface(), ObjCTypes);
- llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassRonfABITy,
- Values);
- llvm::GlobalVariable *CLASS_RO_GV =
- new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassRonfABITy, false,
- llvm::GlobalValue::InternalLinkage,
- Init,
- (flags & CLS_META) ?
- std::string("\01l_OBJC_METACLASS_RO_$_")+ClassName :
- std::string("\01l_OBJC_CLASS_RO_$_")+ClassName);
- CLASS_RO_GV->setAlignment(
- CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassRonfABITy));
- CLASS_RO_GV->setSection("__DATA, __objc_const");
- return CLASS_RO_GV;
-
-}
-
-/// BuildClassMetaData - This routine defines that to-level meta-data
-/// for the given ClassName for:
-/// struct _class_t {
-/// struct _class_t *isa;
-/// struct _class_t * const superclass;
-/// void *cache;
-/// IMP *vtable;
-/// struct class_ro_t *ro;
-/// }
-///
-llvm::GlobalVariable * CGObjCNonFragileABIMac::BuildClassMetaData(
- std::string &ClassName,
- llvm::Constant *IsAGV,
- llvm::Constant *SuperClassGV,
- llvm::Constant *ClassRoGV,
- bool HiddenVisibility) {
- std::vector<llvm::Constant*> Values(5);
- Values[0] = IsAGV;
- Values[1] = SuperClassGV;
- if (!Values[1])
- Values[1] = llvm::Constant::getNullValue(ObjCTypes.ClassnfABIPtrTy);
- Values[2] = ObjCEmptyCacheVar; // &ObjCEmptyCacheVar
- Values[3] = ObjCEmptyVtableVar; // &ObjCEmptyVtableVar
- Values[4] = ClassRoGV; // &CLASS_RO_GV
- llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ClassnfABITy,
- Values);
- llvm::GlobalVariable *GV = GetClassGlobal(ClassName);
- GV->setInitializer(Init);
- GV->setSection("__DATA, __objc_data");
- GV->setAlignment(
- CGM.getTargetData().getABITypeAlignment(ObjCTypes.ClassnfABITy));
- if (HiddenVisibility)
- GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
- return GV;
-}
-
-bool
-CGObjCNonFragileABIMac::ImplementationIsNonLazy(const ObjCImplDecl *OD) const {
- return OD->getClassMethod(GetNullarySelector("load")) != 0;
-}
-
-void CGObjCNonFragileABIMac::GetClassSizeInfo(const ObjCImplementationDecl *OID,
- uint32_t &InstanceStart,
- uint32_t &InstanceSize) {
- const ASTRecordLayout &RL =
- CGM.getContext().getASTObjCImplementationLayout(OID);
-
- // InstanceSize is really instance end.
- InstanceSize = llvm::RoundUpToAlignment(RL.getDataSize(), 8) / 8;
-
- // If there are no fields, the start is the same as the end.
- if (!RL.getFieldCount())
- InstanceStart = InstanceSize;
- else
- InstanceStart = RL.getFieldOffset(0) / 8;
-}
-
-void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
- std::string ClassName = ID->getNameAsString();
- if (!ObjCEmptyCacheVar) {
- ObjCEmptyCacheVar = new llvm::GlobalVariable(
- CGM.getModule(),
- ObjCTypes.CacheTy,
- false,
- llvm::GlobalValue::ExternalLinkage,
- 0,
- "_objc_empty_cache");
-
- ObjCEmptyVtableVar = new llvm::GlobalVariable(
- CGM.getModule(),
- ObjCTypes.ImpnfABITy,
- false,
- llvm::GlobalValue::ExternalLinkage,
- 0,
- "_objc_empty_vtable");
- }
- assert(ID->getClassInterface() &&
- "CGObjCNonFragileABIMac::GenerateClass - class is 0");
- // FIXME: Is this correct (that meta class size is never computed)?
- uint32_t InstanceStart =
- CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassnfABITy);
- uint32_t InstanceSize = InstanceStart;
- uint32_t flags = CLS_META;
- std::string ObjCMetaClassName(getMetaclassSymbolPrefix());
- std::string ObjCClassName(getClassSymbolPrefix());
-
- llvm::GlobalVariable *SuperClassGV, *IsAGV;
-
- bool classIsHidden =
- CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden;
- if (classIsHidden)
- flags |= OBJC2_CLS_HIDDEN;
- if (ID->getNumIvarInitializers())
- flags |= eClassFlags_ABI2_HasCXXStructors;
- if (!ID->getClassInterface()->getSuperClass()) {
- // class is root
- flags |= CLS_ROOT;
- SuperClassGV = GetClassGlobal(ObjCClassName + ClassName);
- IsAGV = GetClassGlobal(ObjCMetaClassName + ClassName);
- } else {
- // Has a root. Current class is not a root.
- const ObjCInterfaceDecl *Root = ID->getClassInterface();
- while (const ObjCInterfaceDecl *Super = Root->getSuperClass())
- Root = Super;
- IsAGV = GetClassGlobal(ObjCMetaClassName + Root->getNameAsString());
- if (Root->hasAttr<WeakImportAttr>())
- IsAGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
- // work on super class metadata symbol.
- std::string SuperClassName =
- ObjCMetaClassName +
- ID->getClassInterface()->getSuperClass()->getNameAsString();
- SuperClassGV = GetClassGlobal(SuperClassName);
- if (ID->getClassInterface()->getSuperClass()->hasAttr<WeakImportAttr>())
- SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
- }
- llvm::GlobalVariable *CLASS_RO_GV = BuildClassRoTInitializer(flags,
- InstanceStart,
- InstanceSize,ID);
- std::string TClassName = ObjCMetaClassName + ClassName;
- llvm::GlobalVariable *MetaTClass =
- BuildClassMetaData(TClassName, IsAGV, SuperClassGV, CLASS_RO_GV,
- classIsHidden);
- DefinedMetaClasses.push_back(MetaTClass);
-
- // Metadata for the class
- flags = CLS;
- if (classIsHidden)
- flags |= OBJC2_CLS_HIDDEN;
- if (ID->getNumIvarInitializers())
- flags |= eClassFlags_ABI2_HasCXXStructors;
-
- if (hasObjCExceptionAttribute(CGM.getContext(), ID->getClassInterface()))
- flags |= CLS_EXCEPTION;
-
- if (!ID->getClassInterface()->getSuperClass()) {
- flags |= CLS_ROOT;
- SuperClassGV = 0;
- } else {
- // Has a root. Current class is not a root.
- std::string RootClassName =
- ID->getClassInterface()->getSuperClass()->getNameAsString();
- SuperClassGV = GetClassGlobal(ObjCClassName + RootClassName);
- if (ID->getClassInterface()->getSuperClass()->hasAttr<WeakImportAttr>())
- SuperClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
- }
- GetClassSizeInfo(ID, InstanceStart, InstanceSize);
- CLASS_RO_GV = BuildClassRoTInitializer(flags,
- InstanceStart,
- InstanceSize,
- ID);
-
- TClassName = ObjCClassName + ClassName;
- llvm::GlobalVariable *ClassMD =
- BuildClassMetaData(TClassName, MetaTClass, SuperClassGV, CLASS_RO_GV,
- classIsHidden);
- DefinedClasses.push_back(ClassMD);
-
- // Determine if this class is also "non-lazy".
- if (ImplementationIsNonLazy(ID))
- DefinedNonLazyClasses.push_back(ClassMD);
-
- // Force the definition of the EHType if necessary.
- if (flags & CLS_EXCEPTION)
- GetInterfaceEHType(ID->getClassInterface(), true);
-}
-
-/// GenerateProtocolRef - This routine is called to generate code for
-/// a protocol reference expression; as in:
-/// @code
-/// @protocol(Proto1);
-/// @endcode
-/// It generates a weak reference to l_OBJC_PROTOCOL_REFERENCE_$_Proto1
-/// which will hold address of the protocol meta-data.
-///
-llvm::Value *CGObjCNonFragileABIMac::GenerateProtocolRef(CGBuilderTy &Builder,
- const ObjCProtocolDecl *PD) {
-
- // This routine is called for @protocol only. So, we must build definition
- // of protocol's meta-data (not a reference to it!)
- //
- llvm::Constant *Init =
- llvm::ConstantExpr::getBitCast(GetOrEmitProtocol(PD),
- ObjCTypes.ExternalProtocolPtrTy);
-
- std::string ProtocolName("\01l_OBJC_PROTOCOL_REFERENCE_$_");
- ProtocolName += PD->getNameAsCString();
-
- llvm::GlobalVariable *PTGV = CGM.getModule().getGlobalVariable(ProtocolName);
- if (PTGV)
- return Builder.CreateLoad(PTGV, "tmp");
- PTGV = new llvm::GlobalVariable(
- CGM.getModule(),
- Init->getType(), false,
- llvm::GlobalValue::WeakAnyLinkage,
- Init,
- ProtocolName);
- PTGV->setSection("__DATA, __objc_protorefs, coalesced, no_dead_strip");
- PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
- CGM.AddUsedGlobal(PTGV);
- return Builder.CreateLoad(PTGV, "tmp");
-}
-
-/// GenerateCategory - Build metadata for a category implementation.
-/// struct _category_t {
-/// const char * const name;
-/// struct _class_t *const cls;
-/// const struct _method_list_t * const instance_methods;
-/// const struct _method_list_t * const class_methods;
-/// const struct _protocol_list_t * const protocols;
-/// const struct _prop_list_t * const properties;
-/// }
-///
-void CGObjCNonFragileABIMac::GenerateCategory(const ObjCCategoryImplDecl *OCD) {
- const ObjCInterfaceDecl *Interface = OCD->getClassInterface();
- const char *Prefix = "\01l_OBJC_$_CATEGORY_";
- std::string ExtCatName(Prefix + Interface->getNameAsString()+
- "_$_" + OCD->getNameAsString());
- std::string ExtClassName(getClassSymbolPrefix() +
- Interface->getNameAsString());
-
- std::vector<llvm::Constant*> Values(6);
- Values[0] = GetClassName(OCD->getIdentifier());
- // meta-class entry symbol
- llvm::GlobalVariable *ClassGV = GetClassGlobal(ExtClassName);
- if (Interface->hasAttr<WeakImportAttr>())
- ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
-
- Values[1] = ClassGV;
- std::vector<llvm::Constant*> Methods;
- std::string MethodListName(Prefix);
- MethodListName += "INSTANCE_METHODS_" + Interface->getNameAsString() +
- "_$_" + OCD->getNameAsString();
-
- for (ObjCCategoryImplDecl::instmeth_iterator
- i = OCD->instmeth_begin(), e = OCD->instmeth_end(); i != e; ++i) {
- // Instance methods should always be defined.
- Methods.push_back(GetMethodConstant(*i));
- }
-
- Values[2] = EmitMethodList(MethodListName,
- "__DATA, __objc_const",
- Methods);
-
- MethodListName = Prefix;
- MethodListName += "CLASS_METHODS_" + Interface->getNameAsString() + "_$_" +
- OCD->getNameAsString();
- Methods.clear();
- for (ObjCCategoryImplDecl::classmeth_iterator
- i = OCD->classmeth_begin(), e = OCD->classmeth_end(); i != e; ++i) {
- // Class methods should always be defined.
- Methods.push_back(GetMethodConstant(*i));
- }
-
- Values[3] = EmitMethodList(MethodListName,
- "__DATA, __objc_const",
- Methods);
- const ObjCCategoryDecl *Category =
- Interface->FindCategoryDeclaration(OCD->getIdentifier());
- if (Category) {
- llvm::SmallString<256> ExtName;
- llvm::raw_svector_ostream(ExtName) << Interface->getName() << "_$_"
- << OCD->getName();
- Values[4] = EmitProtocolList("\01l_OBJC_CATEGORY_PROTOCOLS_$_"
- + Interface->getName() + "_$_"
- + Category->getName(),
- Category->protocol_begin(),
- Category->protocol_end());
- Values[5] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + ExtName.str(),
- OCD, Category, ObjCTypes);
- } else {
- Values[4] = llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
- Values[5] = llvm::Constant::getNullValue(ObjCTypes.PropertyListPtrTy);
- }
-
- llvm::Constant *Init =
- llvm::ConstantStruct::get(ObjCTypes.CategorynfABITy,
- Values);
- llvm::GlobalVariable *GCATV
- = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.CategorynfABITy,
- false,
- llvm::GlobalValue::InternalLinkage,
- Init,
- ExtCatName);
- GCATV->setAlignment(
- CGM.getTargetData().getABITypeAlignment(ObjCTypes.CategorynfABITy));
- GCATV->setSection("__DATA, __objc_const");
- CGM.AddUsedGlobal(GCATV);
- DefinedCategories.push_back(GCATV);
-
- // Determine if this category is also "non-lazy".
- if (ImplementationIsNonLazy(OCD))
- DefinedNonLazyCategories.push_back(GCATV);
-}
-
-/// GetMethodConstant - Return a struct objc_method constant for the
-/// given method if it has been defined. The result is null if the
-/// method has not been defined. The return value has type MethodPtrTy.
-llvm::Constant *CGObjCNonFragileABIMac::GetMethodConstant(
- const ObjCMethodDecl *MD) {
- // FIXME: Use DenseMap::lookup
- llvm::Function *Fn = MethodDefinitions[MD];
- if (!Fn)
- return 0;
-
- std::vector<llvm::Constant*> Method(3);
- Method[0] =
- llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
- ObjCTypes.SelectorPtrTy);
- Method[1] = GetMethodVarType(MD);
- Method[2] = llvm::ConstantExpr::getBitCast(Fn, ObjCTypes.Int8PtrTy);
- return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Method);
-}
-
-/// EmitMethodList - Build meta-data for method declarations
-/// struct _method_list_t {
-/// uint32_t entsize; // sizeof(struct _objc_method)
-/// uint32_t method_count;
-/// struct _objc_method method_list[method_count];
-/// }
-///
-llvm::Constant *CGObjCNonFragileABIMac::EmitMethodList(llvm::Twine Name,
- const char *Section,
- const ConstantVector &Methods) {
- // Return null for empty list.
- if (Methods.empty())
- return llvm::Constant::getNullValue(ObjCTypes.MethodListnfABIPtrTy);
-
- std::vector<llvm::Constant*> Values(3);
- // sizeof(struct _objc_method)
- unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.MethodTy);
- Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
- // method_count
- Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Methods.size());
- llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.MethodTy,
- Methods.size());
- Values[2] = llvm::ConstantArray::get(AT, Methods);
- llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
-
- llvm::GlobalVariable *GV =
- new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
- llvm::GlobalValue::InternalLinkage,
- Init,
- Name);
- GV->setAlignment(
- CGM.getTargetData().getABITypeAlignment(Init->getType()));
- GV->setSection(Section);
- CGM.AddUsedGlobal(GV);
- return llvm::ConstantExpr::getBitCast(GV,
- ObjCTypes.MethodListnfABIPtrTy);
-}
-
-/// ObjCIvarOffsetVariable - Returns the ivar offset variable for
-/// the given ivar.
-llvm::GlobalVariable *
-CGObjCNonFragileABIMac::ObjCIvarOffsetVariable(const ObjCInterfaceDecl *ID,
- const ObjCIvarDecl *Ivar) {
- const ObjCInterfaceDecl *Container = Ivar->getContainingInterface();
- std::string Name = "OBJC_IVAR_$_" + Container->getNameAsString() +
- '.' + Ivar->getNameAsString();
- llvm::GlobalVariable *IvarOffsetGV =
- CGM.getModule().getGlobalVariable(Name);
- if (!IvarOffsetGV)
- IvarOffsetGV =
- new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.LongTy,
- false,
- llvm::GlobalValue::ExternalLinkage,
- 0,
- Name);
- return IvarOffsetGV;
-}
-
-llvm::Constant *
-CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
- const ObjCIvarDecl *Ivar,
- unsigned long int Offset) {
- llvm::GlobalVariable *IvarOffsetGV = ObjCIvarOffsetVariable(ID, Ivar);
- IvarOffsetGV->setInitializer(llvm::ConstantInt::get(ObjCTypes.LongTy,
- Offset));
- IvarOffsetGV->setAlignment(
- CGM.getTargetData().getABITypeAlignment(ObjCTypes.LongTy));
-
- // FIXME: This matches gcc, but shouldn't the visibility be set on the use as
- // well (i.e., in ObjCIvarOffsetVariable).
- if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
- Ivar->getAccessControl() == ObjCIvarDecl::Package ||
- CGM.getDeclVisibilityMode(ID) == LangOptions::Hidden)
- IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
- else
- IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
- IvarOffsetGV->setSection("__DATA, __objc_const");
- return IvarOffsetGV;
-}
-
-/// EmitIvarList - Emit the ivar list for the given
-/// implementation. The return value has type
-/// IvarListnfABIPtrTy.
-/// struct _ivar_t {
-/// unsigned long int *offset; // pointer to ivar offset location
-/// char *name;
-/// char *type;
-/// uint32_t alignment;
-/// uint32_t size;
-/// }
-/// struct _ivar_list_t {
-/// uint32 entsize; // sizeof(struct _ivar_t)
-/// uint32 count;
-/// struct _iver_t list[count];
-/// }
-///
-
-llvm::Constant *CGObjCNonFragileABIMac::EmitIvarList(
- const ObjCImplementationDecl *ID) {
-
- std::vector<llvm::Constant*> Ivars, Ivar(5);
-
- const ObjCInterfaceDecl *OID = ID->getClassInterface();
- assert(OID && "CGObjCNonFragileABIMac::EmitIvarList - null interface");
-
- // FIXME. Consolidate this with similar code in GenerateClass.
-
- // Collect declared and synthesized ivars in a small vector.
- llvm::SmallVector<ObjCIvarDecl*, 16> OIvars;
- CGM.getContext().ShallowCollectObjCIvars(OID, OIvars);
-
- for (unsigned i = 0, e = OIvars.size(); i != e; ++i) {
- ObjCIvarDecl *IVD = OIvars[i];
- // Ignore unnamed bit-fields.
- if (!IVD->getDeclName())
- continue;
- Ivar[0] = EmitIvarOffsetVar(ID->getClassInterface(), IVD,
- ComputeIvarBaseOffset(CGM, ID, IVD));
- Ivar[1] = GetMethodVarName(IVD->getIdentifier());
- Ivar[2] = GetMethodVarType(IVD);
- const llvm::Type *FieldTy =
- CGM.getTypes().ConvertTypeForMem(IVD->getType());
- unsigned Size = CGM.getTargetData().getTypeAllocSize(FieldTy);
- unsigned Align = CGM.getContext().getPreferredTypeAlign(
- IVD->getType().getTypePtr()) >> 3;
- Align = llvm::Log2_32(Align);
- Ivar[3] = llvm::ConstantInt::get(ObjCTypes.IntTy, Align);
- // NOTE. Size of a bitfield does not match gcc's, because of the
- // way bitfields are treated special in each. But I am told that
- // 'size' for bitfield ivars is ignored by the runtime so it does
- // not matter. If it matters, there is enough info to get the
- // bitfield right!
- Ivar[4] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
- Ivars.push_back(llvm::ConstantStruct::get(ObjCTypes.IvarnfABITy, Ivar));
- }
- // Return null for empty list.
- if (Ivars.empty())
- return llvm::Constant::getNullValue(ObjCTypes.IvarListnfABIPtrTy);
- std::vector<llvm::Constant*> Values(3);
- unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.IvarnfABITy);
- Values[0] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
- Values[1] = llvm::ConstantInt::get(ObjCTypes.IntTy, Ivars.size());
- llvm::ArrayType *AT = llvm::ArrayType::get(ObjCTypes.IvarnfABITy,
- Ivars.size());
- Values[2] = llvm::ConstantArray::get(AT, Ivars);
- llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
- const char *Prefix = "\01l_OBJC_$_INSTANCE_VARIABLES_";
- llvm::GlobalVariable *GV =
- new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
- llvm::GlobalValue::InternalLinkage,
- Init,
- Prefix + OID->getName());
- GV->setAlignment(
- CGM.getTargetData().getABITypeAlignment(Init->getType()));
- GV->setSection("__DATA, __objc_const");
-
- CGM.AddUsedGlobal(GV);
- return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.IvarListnfABIPtrTy);
-}
-
-llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocolRef(
- const ObjCProtocolDecl *PD) {
- llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
-
- if (!Entry) {
- // We use the initializer as a marker of whether this is a forward
- // reference or not. At module finalization we add the empty
- // contents for protocols which were referenced but never defined.
- Entry =
- new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy, false,
- llvm::GlobalValue::ExternalLinkage,
- 0,
- "\01l_OBJC_PROTOCOL_$_" + PD->getName());
- Entry->setSection("__DATA,__datacoal_nt,coalesced");
- }
-
- return Entry;
-}
-
-/// GetOrEmitProtocol - Generate the protocol meta-data:
-/// @code
-/// struct _protocol_t {
-/// id isa; // NULL
-/// const char * const protocol_name;
-/// const struct _protocol_list_t * protocol_list; // super protocols
-/// const struct method_list_t * const instance_methods;
-/// const struct method_list_t * const class_methods;
-/// const struct method_list_t *optionalInstanceMethods;
-/// const struct method_list_t *optionalClassMethods;
-/// const struct _prop_list_t * properties;
-/// const uint32_t size; // sizeof(struct _protocol_t)
-/// const uint32_t flags; // = 0
-/// }
-/// @endcode
-///
-
-llvm::Constant *CGObjCNonFragileABIMac::GetOrEmitProtocol(
- const ObjCProtocolDecl *PD) {
- llvm::GlobalVariable *&Entry = Protocols[PD->getIdentifier()];
-
- // Early exit if a defining object has already been generated.
- if (Entry && Entry->hasInitializer())
- return Entry;
-
- // Construct method lists.
- std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
- std::vector<llvm::Constant*> OptInstanceMethods, OptClassMethods;
- for (ObjCProtocolDecl::instmeth_iterator
- i = PD->instmeth_begin(), e = PD->instmeth_end(); i != e; ++i) {
- ObjCMethodDecl *MD = *i;
- llvm::Constant *C = GetMethodDescriptionConstant(MD);
- if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
- OptInstanceMethods.push_back(C);
- } else {
- InstanceMethods.push_back(C);
- }
- }
-
- for (ObjCProtocolDecl::classmeth_iterator
- i = PD->classmeth_begin(), e = PD->classmeth_end(); i != e; ++i) {
- ObjCMethodDecl *MD = *i;
- llvm::Constant *C = GetMethodDescriptionConstant(MD);
- if (MD->getImplementationControl() == ObjCMethodDecl::Optional) {
- OptClassMethods.push_back(C);
- } else {
- ClassMethods.push_back(C);
- }
- }
-
- std::vector<llvm::Constant*> Values(10);
- // isa is NULL
- Values[0] = llvm::Constant::getNullValue(ObjCTypes.ObjectPtrTy);
- Values[1] = GetClassName(PD->getIdentifier());
- Values[2] = EmitProtocolList("\01l_OBJC_$_PROTOCOL_REFS_" + PD->getName(),
- PD->protocol_begin(),
- PD->protocol_end());
-
- Values[3] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_"
- + PD->getName(),
- "__DATA, __objc_const",
- InstanceMethods);
- Values[4] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_"
- + PD->getName(),
- "__DATA, __objc_const",
- ClassMethods);
- Values[5] = EmitMethodList("\01l_OBJC_$_PROTOCOL_INSTANCE_METHODS_OPT_"
- + PD->getName(),
- "__DATA, __objc_const",
- OptInstanceMethods);
- Values[6] = EmitMethodList("\01l_OBJC_$_PROTOCOL_CLASS_METHODS_OPT_"
- + PD->getName(),
- "__DATA, __objc_const",
- OptClassMethods);
- Values[7] = EmitPropertyList("\01l_OBJC_$_PROP_LIST_" + PD->getName(),
- 0, PD, ObjCTypes);
- uint32_t Size =
- CGM.getTargetData().getTypeAllocSize(ObjCTypes.ProtocolnfABITy);
- Values[8] = llvm::ConstantInt::get(ObjCTypes.IntTy, Size);
- Values[9] = llvm::Constant::getNullValue(ObjCTypes.IntTy);
- llvm::Constant *Init = llvm::ConstantStruct::get(ObjCTypes.ProtocolnfABITy,
- Values);
-
- if (Entry) {
- // Already created, fix the linkage and update the initializer.
- Entry->setLinkage(llvm::GlobalValue::WeakAnyLinkage);
- Entry->setInitializer(Init);
- } else {
- Entry =
- new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABITy,
- false, llvm::GlobalValue::WeakAnyLinkage, Init,
- "\01l_OBJC_PROTOCOL_$_" + PD->getName());
- Entry->setAlignment(
- CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABITy));
- Entry->setSection("__DATA,__datacoal_nt,coalesced");
- }
- Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
- CGM.AddUsedGlobal(Entry);
-
- // Use this protocol meta-data to build protocol list table in section
- // __DATA, __objc_protolist
- llvm::GlobalVariable *PTGV =
- new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ProtocolnfABIPtrTy,
- false, llvm::GlobalValue::WeakAnyLinkage, Entry,
- "\01l_OBJC_LABEL_PROTOCOL_$_" + PD->getName());
- PTGV->setAlignment(
- CGM.getTargetData().getABITypeAlignment(ObjCTypes.ProtocolnfABIPtrTy));
- PTGV->setSection("__DATA, __objc_protolist, coalesced, no_dead_strip");
- PTGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
- CGM.AddUsedGlobal(PTGV);
- return Entry;
-}
-
-/// EmitProtocolList - Generate protocol list meta-data:
-/// @code
-/// struct _protocol_list_t {
-/// long protocol_count; // Note, this is 32/64 bit
-/// struct _protocol_t[protocol_count];
-/// }
-/// @endcode
-///
-llvm::Constant *
-CGObjCNonFragileABIMac::EmitProtocolList(llvm::Twine Name,
- ObjCProtocolDecl::protocol_iterator begin,
- ObjCProtocolDecl::protocol_iterator end) {
- std::vector<llvm::Constant*> ProtocolRefs;
-
- // Just return null for empty protocol lists
- if (begin == end)
- return llvm::Constant::getNullValue(ObjCTypes.ProtocolListnfABIPtrTy);
-
- // FIXME: We shouldn't need to do this lookup here, should we?
- llvm::SmallString<256> TmpName;
- Name.toVector(TmpName);
- llvm::GlobalVariable *GV =
- CGM.getModule().getGlobalVariable(TmpName.str(), true);
- if (GV)
- return llvm::ConstantExpr::getBitCast(GV, ObjCTypes.ProtocolListnfABIPtrTy);
-
- for (; begin != end; ++begin)
- ProtocolRefs.push_back(GetProtocolRef(*begin)); // Implemented???
-
- // This list is null terminated.
- ProtocolRefs.push_back(llvm::Constant::getNullValue(
- ObjCTypes.ProtocolnfABIPtrTy));
-
- std::vector<llvm::Constant*> Values(2);
- Values[0] =
- llvm::ConstantInt::get(ObjCTypes.LongTy, ProtocolRefs.size() - 1);
- Values[1] =
- llvm::ConstantArray::get(
- llvm::ArrayType::get(ObjCTypes.ProtocolnfABIPtrTy,
- ProtocolRefs.size()),
- ProtocolRefs);
-
- llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
- GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
- llvm::GlobalValue::InternalLinkage,
- Init,
- Name);
- GV->setSection("__DATA, __objc_const");
- GV->setAlignment(
- CGM.getTargetData().getABITypeAlignment(Init->getType()));
- CGM.AddUsedGlobal(GV);
- return llvm::ConstantExpr::getBitCast(GV,
- ObjCTypes.ProtocolListnfABIPtrTy);
-}
-
-/// GetMethodDescriptionConstant - This routine build following meta-data:
-/// struct _objc_method {
-/// SEL _cmd;
-/// char *method_type;
-/// char *_imp;
-/// }
-
-llvm::Constant *
-CGObjCNonFragileABIMac::GetMethodDescriptionConstant(const ObjCMethodDecl *MD) {
- std::vector<llvm::Constant*> Desc(3);
- Desc[0] =
- llvm::ConstantExpr::getBitCast(GetMethodVarName(MD->getSelector()),
- ObjCTypes.SelectorPtrTy);
- Desc[1] = GetMethodVarType(MD);
- // Protocol methods have no implementation. So, this entry is always NULL.
- Desc[2] = llvm::Constant::getNullValue(ObjCTypes.Int8PtrTy);
- return llvm::ConstantStruct::get(ObjCTypes.MethodTy, Desc);
-}
-
-/// EmitObjCValueForIvar - Code Gen for nonfragile ivar reference.
-/// This code gen. amounts to generating code for:
-/// @code
-/// (type *)((char *)base + _OBJC_IVAR_$_.ivar;
-/// @encode
-///
-LValue CGObjCNonFragileABIMac::EmitObjCValueForIvar(
- CodeGen::CodeGenFunction &CGF,
- QualType ObjectTy,
- llvm::Value *BaseValue,
- const ObjCIvarDecl *Ivar,
- unsigned CVRQualifiers) {
- ObjCInterfaceDecl *ID = ObjectTy->getAs<ObjCObjectType>()->getInterface();
- return EmitValueForIvarAtOffset(CGF, ID, BaseValue, Ivar, CVRQualifiers,
- EmitIvarOffset(CGF, ID, Ivar));
-}
-
-llvm::Value *CGObjCNonFragileABIMac::EmitIvarOffset(
- CodeGen::CodeGenFunction &CGF,
- const ObjCInterfaceDecl *Interface,
- const ObjCIvarDecl *Ivar) {
- return CGF.Builder.CreateLoad(ObjCIvarOffsetVariable(Interface, Ivar),"ivar");
-}
-
-CodeGen::RValue CGObjCNonFragileABIMac::EmitMessageSend(
- CodeGen::CodeGenFunction &CGF,
- ReturnValueSlot Return,
- QualType ResultType,
- Selector Sel,
- llvm::Value *Receiver,
- QualType Arg0Ty,
- bool IsSuper,
- const CallArgList &CallArgs) {
- // FIXME. Even though IsSuper is passes. This function doese not handle calls
- // to 'super' receivers.
- CodeGenTypes &Types = CGM.getTypes();
- llvm::Value *Arg0 = Receiver;
- if (!IsSuper)
- Arg0 = CGF.Builder.CreateBitCast(Arg0, ObjCTypes.ObjectPtrTy, "tmp");
-
- // Find the message function name.
- // FIXME. This is too much work to get the ABI-specific result type needed to
- // find the message name.
- const CGFunctionInfo &FnInfo
- = Types.getFunctionInfo(ResultType, CallArgList(),
- FunctionType::ExtInfo());
- llvm::Constant *Fn = 0;
- std::string Name("\01l_");
- if (CGM.ReturnTypeUsesSRet(FnInfo)) {
-#if 0
- // unlike what is documented. gcc never generates this API!!
- if (Receiver->getType() == ObjCTypes.ObjectPtrTy) {
- Fn = ObjCTypes.getMessageSendIdStretFixupFn();
- // FIXME. Is there a better way of getting these names.
- // They are available in RuntimeFunctions vector pair.
- Name += "objc_msgSendId_stret_fixup";
- } else
-#endif
- if (IsSuper) {
- Fn = ObjCTypes.getMessageSendSuper2StretFixupFn();
- Name += "objc_msgSendSuper2_stret_fixup";
- } else {
- Fn = ObjCTypes.getMessageSendStretFixupFn();
- Name += "objc_msgSend_stret_fixup";
- }
- } else if (!IsSuper && CGM.ReturnTypeUsesFPRet(ResultType)) {
- Fn = ObjCTypes.getMessageSendFpretFixupFn();
- Name += "objc_msgSend_fpret_fixup";
- } else {
-#if 0
-// unlike what is documented. gcc never generates this API!!
- if (Receiver->getType() == ObjCTypes.ObjectPtrTy) {
- Fn = ObjCTypes.getMessageSendIdFixupFn();
- Name += "objc_msgSendId_fixup";
- } else
-#endif
- if (IsSuper) {
- Fn = ObjCTypes.getMessageSendSuper2FixupFn();
- Name += "objc_msgSendSuper2_fixup";
- } else {
- Fn = ObjCTypes.getMessageSendFixupFn();
- Name += "objc_msgSend_fixup";
- }
- }
- assert(Fn && "CGObjCNonFragileABIMac::EmitMessageSend");
- Name += '_';
- std::string SelName(Sel.getAsString());
- // Replace all ':' in selector name with '_' ouch!
- for (unsigned i = 0; i < SelName.size(); i++)
- if (SelName[i] == ':')
- SelName[i] = '_';
- Name += SelName;
- llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
- if (!GV) {
- // Build message ref table entry.
- std::vector<llvm::Constant*> Values(2);
- Values[0] = Fn;
- Values[1] = GetMethodVarName(Sel);
- llvm::Constant *Init = llvm::ConstantStruct::get(VMContext, Values, false);
- GV = new llvm::GlobalVariable(CGM.getModule(), Init->getType(), false,
- llvm::GlobalValue::WeakAnyLinkage,
- Init,
- Name);
- GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
- GV->setAlignment(16);
- GV->setSection("__DATA, __objc_msgrefs, coalesced");
- }
- llvm::Value *Arg1 = CGF.Builder.CreateBitCast(GV, ObjCTypes.MessageRefPtrTy);
-
- CallArgList ActualArgs;
- ActualArgs.push_back(std::make_pair(RValue::get(Arg0), Arg0Ty));
- ActualArgs.push_back(std::make_pair(RValue::get(Arg1),
- ObjCTypes.MessageRefCPtrTy));
- ActualArgs.insert(ActualArgs.end(), CallArgs.begin(), CallArgs.end());
- const CGFunctionInfo &FnInfo1 = Types.getFunctionInfo(ResultType, ActualArgs,
- FunctionType::ExtInfo());
- llvm::Value *Callee = CGF.Builder.CreateStructGEP(Arg1, 0);
- Callee = CGF.Builder.CreateLoad(Callee);
- const llvm::FunctionType *FTy = Types.GetFunctionType(FnInfo1, true);
- Callee = CGF.Builder.CreateBitCast(Callee,
- llvm::PointerType::getUnqual(FTy));
- return CGF.EmitCall(FnInfo1, Callee, Return, ActualArgs);
-}
-
-/// Generate code for a message send expression in the nonfragile abi.
-CodeGen::RValue
-CGObjCNonFragileABIMac::GenerateMessageSend(CodeGen::CodeGenFunction &CGF,
- ReturnValueSlot Return,
- QualType ResultType,
- Selector Sel,
- llvm::Value *Receiver,
- const CallArgList &CallArgs,
- const ObjCInterfaceDecl *Class,
- const ObjCMethodDecl *Method) {
- return LegacyDispatchedSelector(Sel)
- ? EmitLegacyMessageSend(CGF, Return, ResultType,
- EmitSelector(CGF.Builder, Sel),
- Receiver, CGF.getContext().getObjCIdType(),
- false, CallArgs, Method, ObjCTypes)
- : EmitMessageSend(CGF, Return, ResultType, Sel,
- Receiver, CGF.getContext().getObjCIdType(),
- false, CallArgs);
-}
-
-llvm::GlobalVariable *
-CGObjCNonFragileABIMac::GetClassGlobal(const std::string &Name) {
- llvm::GlobalVariable *GV = CGM.getModule().getGlobalVariable(Name);
-
- if (!GV) {
- GV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABITy,
- false, llvm::GlobalValue::ExternalLinkage,
- 0, Name);
- }
-
- return GV;
-}
-
-llvm::Value *CGObjCNonFragileABIMac::EmitClassRef(CGBuilderTy &Builder,
- const ObjCInterfaceDecl *ID) {
- llvm::GlobalVariable *&Entry = ClassReferences[ID->getIdentifier()];
-
- if (!Entry) {
- std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
- llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
- Entry =
- new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
- false, llvm::GlobalValue::InternalLinkage,
- ClassGV,
- "\01L_OBJC_CLASSLIST_REFERENCES_$_");
- Entry->setAlignment(
- CGM.getTargetData().getABITypeAlignment(
- ObjCTypes.ClassnfABIPtrTy));
- Entry->setSection("__DATA, __objc_classrefs, regular, no_dead_strip");
- CGM.AddUsedGlobal(Entry);
- }
-
- return Builder.CreateLoad(Entry, "tmp");
-}
-
-llvm::Value *
-CGObjCNonFragileABIMac::EmitSuperClassRef(CGBuilderTy &Builder,
- const ObjCInterfaceDecl *ID) {
- llvm::GlobalVariable *&Entry = SuperClassReferences[ID->getIdentifier()];
-
- if (!Entry) {
- std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
- llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
- Entry =
- new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy,
- false, llvm::GlobalValue::InternalLinkage,
- ClassGV,
- "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
- Entry->setAlignment(
- CGM.getTargetData().getABITypeAlignment(
- ObjCTypes.ClassnfABIPtrTy));
- Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
- CGM.AddUsedGlobal(Entry);
- }
-
- return Builder.CreateLoad(Entry, "tmp");
-}
-
-/// EmitMetaClassRef - Return a Value * of the address of _class_t
-/// meta-data
-///
-llvm::Value *CGObjCNonFragileABIMac::EmitMetaClassRef(CGBuilderTy &Builder,
- const ObjCInterfaceDecl *ID) {
- llvm::GlobalVariable * &Entry = MetaClassReferences[ID->getIdentifier()];
- if (Entry)
- return Builder.CreateLoad(Entry, "tmp");
-
- std::string MetaClassName(getMetaclassSymbolPrefix() + ID->getNameAsString());
- llvm::GlobalVariable *MetaClassGV = GetClassGlobal(MetaClassName);
- Entry =
- new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.ClassnfABIPtrTy, false,
- llvm::GlobalValue::InternalLinkage,
- MetaClassGV,
- "\01L_OBJC_CLASSLIST_SUP_REFS_$_");
- Entry->setAlignment(
- CGM.getTargetData().getABITypeAlignment(
- ObjCTypes.ClassnfABIPtrTy));
-
- Entry->setSection("__DATA, __objc_superrefs, regular, no_dead_strip");
- CGM.AddUsedGlobal(Entry);
-
- return Builder.CreateLoad(Entry, "tmp");
-}
-
-/// GetClass - Return a reference to the class for the given interface
-/// decl.
-llvm::Value *CGObjCNonFragileABIMac::GetClass(CGBuilderTy &Builder,
- const ObjCInterfaceDecl *ID) {
- if (ID->hasAttr<WeakImportAttr>()) {
- std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
- llvm::GlobalVariable *ClassGV = GetClassGlobal(ClassName);
- ClassGV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
- }
-
- return EmitClassRef(Builder, ID);
-}
-
-/// Generates a message send where the super is the receiver. This is
-/// a message send to self with special delivery semantics indicating
-/// which class's method should be called.
-CodeGen::RValue
-CGObjCNonFragileABIMac::GenerateMessageSendSuper(CodeGen::CodeGenFunction &CGF,
- ReturnValueSlot Return,
- QualType ResultType,
- Selector Sel,
- const ObjCInterfaceDecl *Class,
- bool isCategoryImpl,
- llvm::Value *Receiver,
- bool IsClassMessage,
- const CodeGen::CallArgList &CallArgs,
- const ObjCMethodDecl *Method) {
- // ...
- // Create and init a super structure; this is a (receiver, class)
- // pair we will pass to objc_msgSendSuper.
- llvm::Value *ObjCSuper =
- CGF.Builder.CreateAlloca(ObjCTypes.SuperTy, 0, "objc_super");
-
- llvm::Value *ReceiverAsObject =
- CGF.Builder.CreateBitCast(Receiver, ObjCTypes.ObjectPtrTy);
- CGF.Builder.CreateStore(ReceiverAsObject,
- CGF.Builder.CreateStructGEP(ObjCSuper, 0));
-
- // If this is a class message the metaclass is passed as the target.
- llvm::Value *Target;
- if (IsClassMessage) {
- if (isCategoryImpl) {
- // Message sent to "super' in a class method defined in
- // a category implementation.
- Target = EmitClassRef(CGF.Builder, Class);
- Target = CGF.Builder.CreateStructGEP(Target, 0);
- Target = CGF.Builder.CreateLoad(Target);
- } else
- Target = EmitMetaClassRef(CGF.Builder, Class);
- } else
- Target = EmitSuperClassRef(CGF.Builder, Class);
-
- // FIXME: We shouldn't need to do this cast, rectify the ASTContext and
- // ObjCTypes types.
- const llvm::Type *ClassTy =
- CGM.getTypes().ConvertType(CGF.getContext().getObjCClassType());
- Target = CGF.Builder.CreateBitCast(Target, ClassTy);
- CGF.Builder.CreateStore(Target,
- CGF.Builder.CreateStructGEP(ObjCSuper, 1));
-
- return (LegacyDispatchedSelector(Sel))
- ? EmitLegacyMessageSend(CGF, Return, ResultType,
- EmitSelector(CGF.Builder, Sel),
- ObjCSuper, ObjCTypes.SuperPtrCTy,
- true, CallArgs, Method, ObjCTypes)
- : EmitMessageSend(CGF, Return, ResultType, Sel,
- ObjCSuper, ObjCTypes.SuperPtrCTy,
- true, CallArgs);
-}
-
-llvm::Value *CGObjCNonFragileABIMac::EmitSelector(CGBuilderTy &Builder,
- Selector Sel, bool lval) {
- llvm::GlobalVariable *&Entry = SelectorReferences[Sel];
-
- if (!Entry) {
- llvm::Constant *Casted =
- llvm::ConstantExpr::getBitCast(GetMethodVarName(Sel),
- ObjCTypes.SelectorPtrTy);
- Entry =
- new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.SelectorPtrTy, false,
- llvm::GlobalValue::InternalLinkage,
- Casted, "\01L_OBJC_SELECTOR_REFERENCES_");
- Entry->setSection("__DATA, __objc_selrefs, literal_pointers, no_dead_strip");
- CGM.AddUsedGlobal(Entry);
- }
-
- if (lval)
- return Entry;
- return Builder.CreateLoad(Entry, "tmp");
-}
-/// EmitObjCIvarAssign - Code gen for assigning to a __strong object.
-/// objc_assign_ivar (id src, id *dst, ptrdiff_t)
-///
-void CGObjCNonFragileABIMac::EmitObjCIvarAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src,
- llvm::Value *dst,
- llvm::Value *ivarOffset) {
- const llvm::Type * SrcTy = src->getType();
- if (!isa<llvm::PointerType>(SrcTy)) {
- unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
- assert(Size <= 8 && "does not support size > 8");
- src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
- : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
- src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
- }
- src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
- dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
- CGF.Builder.CreateCall3(ObjCTypes.getGcAssignIvarFn(),
- src, dst, ivarOffset);
- return;
-}
-
-/// EmitObjCStrongCastAssign - Code gen for assigning to a __strong cast object.
-/// objc_assign_strongCast (id src, id *dst)
-///
-void CGObjCNonFragileABIMac::EmitObjCStrongCastAssign(
- CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dst) {
- const llvm::Type * SrcTy = src->getType();
- if (!isa<llvm::PointerType>(SrcTy)) {
- unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
- assert(Size <= 8 && "does not support size > 8");
- src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
- : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
- src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
- }
- src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
- dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
- CGF.Builder.CreateCall2(ObjCTypes.getGcAssignStrongCastFn(),
- src, dst, "weakassign");
- return;
-}
-
-void CGObjCNonFragileABIMac::EmitGCMemmoveCollectable(
- CodeGen::CodeGenFunction &CGF,
- llvm::Value *DestPtr,
- llvm::Value *SrcPtr,
- llvm::Value *Size) {
- SrcPtr = CGF.Builder.CreateBitCast(SrcPtr, ObjCTypes.Int8PtrTy);
- DestPtr = CGF.Builder.CreateBitCast(DestPtr, ObjCTypes.Int8PtrTy);
- CGF.Builder.CreateCall3(ObjCTypes.GcMemmoveCollectableFn(),
- DestPtr, SrcPtr, Size);
- return;
-}
-
-/// EmitObjCWeakRead - Code gen for loading value of a __weak
-/// object: objc_read_weak (id *src)
-///
-llvm::Value * CGObjCNonFragileABIMac::EmitObjCWeakRead(
- CodeGen::CodeGenFunction &CGF,
- llvm::Value *AddrWeakObj) {
- const llvm::Type* DestTy =
- cast<llvm::PointerType>(AddrWeakObj->getType())->getElementType();
- AddrWeakObj = CGF.Builder.CreateBitCast(AddrWeakObj, ObjCTypes.PtrObjectPtrTy);
- llvm::Value *read_weak = CGF.Builder.CreateCall(ObjCTypes.getGcReadWeakFn(),
- AddrWeakObj, "weakread");
- read_weak = CGF.Builder.CreateBitCast(read_weak, DestTy);
- return read_weak;
-}
-
-/// EmitObjCWeakAssign - Code gen for assigning to a __weak object.
-/// objc_assign_weak (id src, id *dst)
-///
-void CGObjCNonFragileABIMac::EmitObjCWeakAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dst) {
- const llvm::Type * SrcTy = src->getType();
- if (!isa<llvm::PointerType>(SrcTy)) {
- unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
- assert(Size <= 8 && "does not support size > 8");
- src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
- : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
- src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
- }
- src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
- dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
- CGF.Builder.CreateCall2(ObjCTypes.getGcAssignWeakFn(),
- src, dst, "weakassign");
- return;
-}
-
-/// EmitObjCGlobalAssign - Code gen for assigning to a __strong object.
-/// objc_assign_global (id src, id *dst)
-///
-void CGObjCNonFragileABIMac::EmitObjCGlobalAssign(CodeGen::CodeGenFunction &CGF,
- llvm::Value *src, llvm::Value *dst,
- bool threadlocal) {
- const llvm::Type * SrcTy = src->getType();
- if (!isa<llvm::PointerType>(SrcTy)) {
- unsigned Size = CGM.getTargetData().getTypeAllocSize(SrcTy);
- assert(Size <= 8 && "does not support size > 8");
- src = (Size == 4 ? CGF.Builder.CreateBitCast(src, ObjCTypes.IntTy)
- : CGF.Builder.CreateBitCast(src, ObjCTypes.LongTy));
- src = CGF.Builder.CreateIntToPtr(src, ObjCTypes.Int8PtrTy);
- }
- src = CGF.Builder.CreateBitCast(src, ObjCTypes.ObjectPtrTy);
- dst = CGF.Builder.CreateBitCast(dst, ObjCTypes.PtrObjectPtrTy);
- if (!threadlocal)
- CGF.Builder.CreateCall2(ObjCTypes.getGcAssignGlobalFn(),
- src, dst, "globalassign");
- else
- CGF.Builder.CreateCall2(ObjCTypes.getGcAssignThreadLocalFn(),
- src, dst, "threadlocalassign");
- return;
-}
-
-namespace {
- struct CallSyncExit : EHScopeStack::Cleanup {
- llvm::Value *SyncExitFn;
- llvm::Value *SyncArg;
- CallSyncExit(llvm::Value *SyncExitFn, llvm::Value *SyncArg)
- : SyncExitFn(SyncExitFn), SyncArg(SyncArg) {}
-
- void Emit(CodeGenFunction &CGF, bool IsForEHCleanup) {
- CGF.Builder.CreateCall(SyncExitFn, SyncArg)->setDoesNotThrow();
- }
- };
-}
-
-void
-CGObjCNonFragileABIMac::EmitSynchronizedStmt(CodeGen::CodeGenFunction &CGF,
- const ObjCAtSynchronizedStmt &S) {
- // Evaluate the lock operand. This should dominate the cleanup.
- llvm::Value *SyncArg = CGF.EmitScalarExpr(S.getSynchExpr());
-
- // Acquire the lock.
- SyncArg = CGF.Builder.CreateBitCast(SyncArg, ObjCTypes.ObjectPtrTy);
- CGF.Builder.CreateCall(ObjCTypes.getSyncEnterFn(), SyncArg)
- ->setDoesNotThrow();
-
- // Register an all-paths cleanup to release the lock.
- CGF.EHStack.pushCleanup<CallSyncExit>(NormalAndEHCleanup,
- ObjCTypes.getSyncExitFn(),
- SyncArg);
-
- // Emit the body of the statement.
- CGF.EmitStmt(S.getSynchBody());
-
- // Pop the lock-release cleanup.
- CGF.PopCleanupBlock();
-}
-
-namespace {
- struct CatchHandler {
- const VarDecl *Variable;
- const Stmt *Body;
- llvm::BasicBlock *Block;
- llvm::Value *TypeInfo;
- };
-
- struct CallObjCEndCatch : EHScopeStack::Cleanup {
- CallObjCEndCatch(bool MightThrow, llvm::Value *Fn) :
- MightThrow(MightThrow), Fn(Fn) {}
- bool MightThrow;
- llvm::Value *Fn;
-
- void Emit(CodeGenFunction &CGF, bool IsForEH) {
- if (!MightThrow) {
- CGF.Builder.CreateCall(Fn)->setDoesNotThrow();
- return;
- }
-
- CGF.EmitCallOrInvoke(Fn, 0, 0);
- }
- };
-}
-
-llvm::Constant *
-CGObjCNonFragileABIMac::GetEHType(QualType T) {
- // There's a particular fixed type info for 'id'.
- if (T->isObjCIdType() ||
- T->isObjCQualifiedIdType()) {
- llvm::Constant *IDEHType =
- CGM.getModule().getGlobalVariable("OBJC_EHTYPE_id");
- if (!IDEHType)
- IDEHType =
- new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy,
- false,
- llvm::GlobalValue::ExternalLinkage,
- 0, "OBJC_EHTYPE_id");
- return IDEHType;
- }
-
- // All other types should be Objective-C interface pointer types.
- const ObjCObjectPointerType *PT =
- T->getAs<ObjCObjectPointerType>();
- assert(PT && "Invalid @catch type.");
- const ObjCInterfaceType *IT = PT->getInterfaceType();
- assert(IT && "Invalid @catch type.");
- return GetInterfaceEHType(IT->getDecl(), false);
-}
-
-void CGObjCNonFragileABIMac::EmitTryStmt(CodeGen::CodeGenFunction &CGF,
- const ObjCAtTryStmt &S) {
- // Jump destination for falling out of catch bodies.
- CodeGenFunction::JumpDest Cont;
- if (S.getNumCatchStmts())
- Cont = CGF.getJumpDestInCurrentScope("eh.cont");
-
- CodeGenFunction::FinallyInfo FinallyInfo;
- if (const ObjCAtFinallyStmt *Finally = S.getFinallyStmt())
- FinallyInfo = CGF.EnterFinallyBlock(Finally->getFinallyBody(),
- ObjCTypes.getObjCBeginCatchFn(),
- ObjCTypes.getObjCEndCatchFn(),
- ObjCTypes.getExceptionRethrowFn());
-
- llvm::SmallVector<CatchHandler, 8> Handlers;
-
- // Enter the catch, if there is one.
- if (S.getNumCatchStmts()) {
- for (unsigned I = 0, N = S.getNumCatchStmts(); I != N; ++I) {
- const ObjCAtCatchStmt *CatchStmt = S.getCatchStmt(I);
- const VarDecl *CatchDecl = CatchStmt->getCatchParamDecl();
-
- Handlers.push_back(CatchHandler());
- CatchHandler &Handler = Handlers.back();
- Handler.Variable = CatchDecl;
- Handler.Body = CatchStmt->getCatchBody();
- Handler.Block = CGF.createBasicBlock("catch");
-
- // @catch(...) always matches.
- if (!CatchDecl) {
- Handler.TypeInfo = 0; // catch-all
- // Don't consider any other catches.
- break;
- }
-
- Handler.TypeInfo = GetEHType(CatchDecl->getType());
- }
-
- EHCatchScope *Catch = CGF.EHStack.pushCatch(Handlers.size());
- for (unsigned I = 0, E = Handlers.size(); I != E; ++I)
- Catch->setHandler(I, Handlers[I].TypeInfo, Handlers[I].Block);
- }
-
- // Emit the try body.
- CGF.EmitStmt(S.getTryBody());
-
- // Leave the try.
- if (S.getNumCatchStmts())
- CGF.EHStack.popCatch();
-
- // Remember where we were.
- CGBuilderTy::InsertPoint SavedIP = CGF.Builder.saveAndClearIP();
-
- // Emit the handlers.
- for (unsigned I = 0, E = Handlers.size(); I != E; ++I) {
- CatchHandler &Handler = Handlers[I];
-
- CGF.EmitBlock(Handler.Block);
- llvm::Value *RawExn = CGF.Builder.CreateLoad(CGF.getExceptionSlot());
-
- // Enter the catch.
- llvm::CallInst *Exn =
- CGF.Builder.CreateCall(ObjCTypes.getObjCBeginCatchFn(), RawExn,
- "exn.adjusted");
- Exn->setDoesNotThrow();
-
- // Add a cleanup to leave the catch.
- bool EndCatchMightThrow = (Handler.Variable == 0);
- CGF.EHStack.pushCleanup<CallObjCEndCatch>(NormalAndEHCleanup,
- EndCatchMightThrow,
- ObjCTypes.getObjCEndCatchFn());
-
- // Bind the catch parameter if it exists.
- if (const VarDecl *CatchParam = Handler.Variable) {
- const llvm::Type *CatchType = CGF.ConvertType(CatchParam->getType());
- llvm::Value *CastExn = CGF.Builder.CreateBitCast(Exn, CatchType);
-
- CGF.EmitLocalBlockVarDecl(*CatchParam);
- CGF.Builder.CreateStore(CastExn, CGF.GetAddrOfLocalVar(CatchParam));
- }
-
- CGF.ObjCEHValueStack.push_back(Exn);
- CGF.EmitStmt(Handler.Body);
- CGF.ObjCEHValueStack.pop_back();
-
- // Leave the earlier cleanup.
- CGF.PopCleanupBlock();
-
- CGF.EmitBranchThroughCleanup(Cont);
- }
-
- // Go back to the try-statement fallthrough.
- CGF.Builder.restoreIP(SavedIP);
-
- // Pop out of the normal cleanup on the finally.
- if (S.getFinallyStmt())
- CGF.ExitFinallyBlock(FinallyInfo);
-
- if (Cont.isValid())
- CGF.EmitBlock(Cont.getBlock());
-}
-
-/// EmitThrowStmt - Generate code for a throw statement.
-void CGObjCNonFragileABIMac::EmitThrowStmt(CodeGen::CodeGenFunction &CGF,
- const ObjCAtThrowStmt &S) {
- llvm::Value *Exception;
- llvm::Constant *FunctionThrowOrRethrow;
- if (const Expr *ThrowExpr = S.getThrowExpr()) {
- Exception = CGF.EmitScalarExpr(ThrowExpr);
- FunctionThrowOrRethrow = ObjCTypes.getExceptionThrowFn();
- } else {
- assert((!CGF.ObjCEHValueStack.empty() && CGF.ObjCEHValueStack.back()) &&
- "Unexpected rethrow outside @catch block.");
- Exception = CGF.ObjCEHValueStack.back();
- FunctionThrowOrRethrow = ObjCTypes.getExceptionRethrowFn();
- }
-
- llvm::Value *ExceptionAsObject =
- CGF.Builder.CreateBitCast(Exception, ObjCTypes.ObjectPtrTy, "tmp");
- llvm::BasicBlock *InvokeDest = CGF.getInvokeDest();
- if (InvokeDest) {
- CGF.Builder.CreateInvoke(FunctionThrowOrRethrow,
- CGF.getUnreachableBlock(), InvokeDest,
- &ExceptionAsObject, &ExceptionAsObject + 1);
- } else {
- CGF.Builder.CreateCall(FunctionThrowOrRethrow, ExceptionAsObject)
- ->setDoesNotReturn();
- CGF.Builder.CreateUnreachable();
- }
-
- // Clear the insertion point to indicate we are in unreachable code.
- CGF.Builder.ClearInsertionPoint();
-}
-
-llvm::Constant *
-CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
- bool ForDefinition) {
- llvm::GlobalVariable * &Entry = EHTypeReferences[ID->getIdentifier()];
-
- // If we don't need a definition, return the entry if found or check
- // if we use an external reference.
- if (!ForDefinition) {
- if (Entry)
- return Entry;
-
- // If this type (or a super class) has the __objc_exception__
- // attribute, emit an external reference.
- if (hasObjCExceptionAttribute(CGM.getContext(), ID))
- return Entry =
- new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
- llvm::GlobalValue::ExternalLinkage,
- 0,
- ("OBJC_EHTYPE_$_" +
- ID->getIdentifier()->getName()));
- }
-
- // Otherwise we need to either make a new entry or fill in the
- // initializer.
- assert((!Entry || !Entry->hasInitializer()) && "Duplicate EHType definition");
- std::string ClassName(getClassSymbolPrefix() + ID->getNameAsString());
- std::string VTableName = "objc_ehtype_vtable";
- llvm::GlobalVariable *VTableGV =
- CGM.getModule().getGlobalVariable(VTableName);
- if (!VTableGV)
- VTableGV = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.Int8PtrTy,
- false,
- llvm::GlobalValue::ExternalLinkage,
- 0, VTableName);
-
- llvm::Value *VTableIdx =
- llvm::ConstantInt::get(llvm::Type::getInt32Ty(VMContext), 2);
-
- std::vector<llvm::Constant*> Values(3);
- Values[0] = llvm::ConstantExpr::getGetElementPtr(VTableGV, &VTableIdx, 1);
- Values[1] = GetClassName(ID->getIdentifier());
- Values[2] = GetClassGlobal(ClassName);
- llvm::Constant *Init =
- llvm::ConstantStruct::get(ObjCTypes.EHTypeTy, Values);
-
- if (Entry) {
- Entry->setInitializer(Init);
- } else {
- Entry = new llvm::GlobalVariable(CGM.getModule(), ObjCTypes.EHTypeTy, false,
- llvm::GlobalValue::WeakAnyLinkage,
- Init,
- ("OBJC_EHTYPE_$_" +
- ID->getIdentifier()->getName()));
- }
-
- if (CGM.getLangOptions().getVisibilityMode() == LangOptions::Hidden)
- Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
- Entry->setAlignment(CGM.getTargetData().getABITypeAlignment(
- ObjCTypes.EHTypeTy));
-
- if (ForDefinition) {
- Entry->setSection("__DATA,__objc_const");
- Entry->setLinkage(llvm::GlobalValue::ExternalLinkage);
- } else {
- Entry->setSection("__DATA,__datacoal_nt,coalesced");
- }
-
- return Entry;
-}
-
-/* *** */
-
-CodeGen::CGObjCRuntime *
-CodeGen::CreateMacObjCRuntime(CodeGen::CodeGenModule &CGM) {
- return new CGObjCMac(CGM);
-}
-
-CodeGen::CGObjCRuntime *
-CodeGen::CreateMacNonFragileABIObjCRuntime(CodeGen::CodeGenModule &CGM) {
- return new CGObjCNonFragileABIMac(CGM);
-}
Removed: cfe/branches/Apple/williamson/lib/Frontend/CompilerInvocation.cpp.orig
URL: http://llvm.org/viewvc/llvm-project/cfe/branches/Apple/williamson/lib/Frontend/CompilerInvocation.cpp.orig?rev=111417&view=auto
==============================================================================
--- cfe/branches/Apple/williamson/lib/Frontend/CompilerInvocation.cpp.orig (original)
+++ cfe/branches/Apple/williamson/lib/Frontend/CompilerInvocation.cpp.orig (removed)
@@ -1,1481 +0,0 @@
-//===--- CompilerInvocation.cpp -------------------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/Frontend/CompilerInvocation.h"
-#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/Version.h"
-#include "clang/Driver/Arg.h"
-#include "clang/Driver/ArgList.h"
-#include "clang/Driver/CC1Options.h"
-#include "clang/Driver/DriverDiagnostic.h"
-#include "clang/Driver/OptTable.h"
-#include "clang/Driver/Option.h"
-#include "clang/Frontend/CompilerInvocation.h"
-#include "clang/Frontend/LangStandard.h"
-#include "clang/Frontend/PCHReader.h"
-#include "llvm/ADT/OwningPtr.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/System/Host.h"
-#include "llvm/System/Path.h"
-using namespace clang;
-
-static const char *getAnalysisName(Analyses Kind) {
- switch (Kind) {
- default:
- llvm_unreachable("Unknown analysis kind!");
-#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE)\
- case NAME: return "-" CMDFLAG;
-#include "clang/Frontend/Analyses.def"
- }
-}
-
-static const char *getAnalysisStoreName(AnalysisStores Kind) {
- switch (Kind) {
- default:
- llvm_unreachable("Unknown analysis store!");
-#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) \
- case NAME##Model: return CMDFLAG;
-#include "clang/Frontend/Analyses.def"
- }
-}
-
-static const char *getAnalysisConstraintName(AnalysisConstraints Kind) {
- switch (Kind) {
- default:
- llvm_unreachable("Unknown analysis constraints!");
-#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \
- case NAME##Model: return CMDFLAG;
-#include "clang/Frontend/Analyses.def"
- }
-}
-
-static const char *getAnalysisDiagClientName(AnalysisDiagClients Kind) {
- switch (Kind) {
- default:
- llvm_unreachable("Unknown analysis client!");
-#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREATE) \
- case PD_##NAME: return CMDFLAG;
-#include "clang/Frontend/Analyses.def"
- }
-}
-
-//===----------------------------------------------------------------------===//
-// Serialization (to args)
-//===----------------------------------------------------------------------===//
-
-static void AnalyzerOptsToArgs(const AnalyzerOptions &Opts,
- std::vector<std::string> &Res) {
- for (unsigned i = 0, e = Opts.AnalysisList.size(); i != e; ++i)
- Res.push_back(getAnalysisName(Opts.AnalysisList[i]));
- if (Opts.AnalysisStoreOpt != BasicStoreModel) {
- Res.push_back("-analyzer-store");
- Res.push_back(getAnalysisStoreName(Opts.AnalysisStoreOpt));
- }
- if (Opts.AnalysisConstraintsOpt != RangeConstraintsModel) {
- Res.push_back("-analyzer-constraints");
- Res.push_back(getAnalysisConstraintName(Opts.AnalysisConstraintsOpt));
- }
- if (Opts.AnalysisDiagOpt != PD_HTML) {
- Res.push_back("-analyzer-output");
- Res.push_back(getAnalysisDiagClientName(Opts.AnalysisDiagOpt));
- }
- if (!Opts.AnalyzeSpecificFunction.empty()) {
- Res.push_back("-analyze-function");
- Res.push_back(Opts.AnalyzeSpecificFunction);
- }
- if (Opts.AnalyzeAll)
- Res.push_back("-analyzer-opt-analyze-headers");
- if (Opts.AnalyzerDisplayProgress)
- Res.push_back("-analyzer-display-progress");
- if (Opts.AnalyzeNestedBlocks)
- Res.push_back("-analyzer-opt-analyze-nested-blocks");
- if (Opts.EagerlyAssume)
- Res.push_back("-analyzer-eagerly-assume");
- if (!Opts.PurgeDead)
- Res.push_back("-analyzer-no-purge-dead");
- if (Opts.TrimGraph)
- Res.push_back("-trim-egraph");
- if (Opts.VisualizeEGDot)
- Res.push_back("-analyzer-viz-egraph-graphviz");
- if (Opts.VisualizeEGDot)
- Res.push_back("-analyzer-viz-egraph-ubigraph");
- if (Opts.EnableExperimentalChecks)
- Res.push_back("-analyzer-experimental-checks");
- if (Opts.EnableExperimentalInternalChecks)
- Res.push_back("-analyzer-experimental-internal-checks");
-}
-
-static void CodeGenOptsToArgs(const CodeGenOptions &Opts,
- std::vector<std::string> &Res) {
- if (Opts.DebugInfo)
- Res.push_back("-g");
- if (Opts.DisableLLVMOpts)
- Res.push_back("-disable-llvm-optzns");
- if (Opts.DisableRedZone)
- Res.push_back("-disable-red-zone");
- if (!Opts.DwarfDebugFlags.empty()) {
- Res.push_back("-dwarf-debug-flags");
- Res.push_back(Opts.DwarfDebugFlags);
- }
- if (!Opts.MergeAllConstants)
- Res.push_back("-fno-merge-all-constants");
- if (Opts.NoCommon)
- Res.push_back("-fno-common");
- if (Opts.NoImplicitFloat)
- Res.push_back("-no-implicit-float");
- if (Opts.OmitLeafFramePointer)
- Res.push_back("-momit-leaf-frame-pointer");
- if (Opts.OptimizeSize) {
- assert(Opts.OptimizationLevel == 2 && "Invalid options!");
- Res.push_back("-Os");
- } else if (Opts.OptimizationLevel != 0)
- Res.push_back("-O" + llvm::utostr(Opts.OptimizationLevel));
- if (!Opts.MainFileName.empty()) {
- Res.push_back("-main-file-name");
- Res.push_back(Opts.MainFileName);
- }
- // SimplifyLibCalls is only derived.
- // TimePasses is only derived.
- // UnitAtATime is unused.
- // UnrollLoops is only derived.
- // Inlining is only derived.
-
- if (Opts.DataSections)
- Res.push_back("-fdata-sections");
- if (Opts.FunctionSections)
- Res.push_back("-ffunction-sections");
- if (Opts.AsmVerbose)
- Res.push_back("-masm-verbose");
- if (!Opts.CodeModel.empty()) {
- Res.push_back("-mcode-model");
- Res.push_back(Opts.CodeModel);
- }
- if (!Opts.CXAAtExit)
- Res.push_back("-fno-use-cxa-atexit");
- if (Opts.CXXCtorDtorAliases)
- Res.push_back("-mconstructor-aliases");
- if (!Opts.DebugPass.empty()) {
- Res.push_back("-mdebug-pass");
- Res.push_back(Opts.DebugPass);
- }
- if (Opts.DisableFPElim)
- Res.push_back("-mdisable-fp-elim");
- if (!Opts.FloatABI.empty()) {
- Res.push_back("-mfloat-abi");
- Res.push_back(Opts.FloatABI);
- }
- if (!Opts.LimitFloatPrecision.empty()) {
- Res.push_back("-mlimit-float-precision");
- Res.push_back(Opts.LimitFloatPrecision);
- }
- if (Opts.NoZeroInitializedInBSS)
- Res.push_back("-mno-zero-initialized-bss");
- switch (Opts.getObjCDispatchMethod()) {
- case CodeGenOptions::Legacy:
- break;
- case CodeGenOptions::Mixed:
- Res.push_back("-fobjc-dispatch-method=mixed");
- break;
- case CodeGenOptions::NonLegacy:
- Res.push_back("-fobjc-dispatch-method=non-legacy");
- break;
- }
- if (Opts.RelaxAll)
- Res.push_back("-mrelax-all");
- if (Opts.SoftFloat)
- Res.push_back("-msoft-float");
- if (Opts.UnwindTables)
- Res.push_back("-munwind-tables");
- if (Opts.RelocationModel != "pic") {
- Res.push_back("-mrelocation-model");
- Res.push_back(Opts.RelocationModel);
- }
- if (!Opts.VerifyModule)
- Res.push_back("-disable-llvm-verifier");
-}
-
-static void DependencyOutputOptsToArgs(const DependencyOutputOptions &Opts,
- std::vector<std::string> &Res) {
- if (Opts.IncludeSystemHeaders)
- Res.push_back("-sys-header-deps");
- if (Opts.UsePhonyTargets)
- Res.push_back("-MP");
- if (!Opts.OutputFile.empty()) {
- Res.push_back("-dependency-file");
- Res.push_back(Opts.OutputFile);
- }
- for (unsigned i = 0, e = Opts.Targets.size(); i != e; ++i) {
- Res.push_back("-MT");
- Res.push_back(Opts.Targets[i]);
- }
-}
-
-static void DiagnosticOptsToArgs(const DiagnosticOptions &Opts,
- std::vector<std::string> &Res) {
- if (Opts.IgnoreWarnings)
- Res.push_back("-w");
- if (Opts.NoRewriteMacros)
- Res.push_back("-Wno-rewrite-macros");
- if (Opts.Pedantic)
- Res.push_back("-pedantic");
- if (Opts.PedanticErrors)
- Res.push_back("-pedantic-errors");
- if (!Opts.ShowColumn)
- Res.push_back("-fno-show-column");
- if (!Opts.ShowLocation)
- Res.push_back("-fno-show-source-location");
- if (!Opts.ShowCarets)
- Res.push_back("-fno-caret-diagnostics");
- if (!Opts.ShowFixits)
- Res.push_back("-fno-diagnostics-fixit-info");
- if (Opts.ShowSourceRanges)
- Res.push_back("-fdiagnostics-print-source-range-info");
- if (Opts.ShowColors)
- Res.push_back("-fcolor-diagnostics");
- if (Opts.VerifyDiagnostics)
- Res.push_back("-verify");
- if (Opts.BinaryOutput)
- Res.push_back("-fdiagnostics-binary");
- if (Opts.ShowOptionNames)
- Res.push_back("-fdiagnostics-show-option");
- if (Opts.ShowCategories == 1)
- Res.push_back("-fdiagnostics-show-category=id");
- else if (Opts.ShowCategories == 2)
- Res.push_back("-fdiagnostics-show-category=name");
- if (Opts.ErrorLimit) {
- Res.push_back("-ferror-limit");
- Res.push_back(llvm::utostr(Opts.ErrorLimit));
- }
- if (Opts.MacroBacktraceLimit
- != DiagnosticOptions::DefaultMacroBacktraceLimit) {
- Res.push_back("-fmacro-backtrace-limit");
- Res.push_back(llvm::utostr(Opts.MacroBacktraceLimit));
- }
- if (Opts.TemplateBacktraceLimit
- != DiagnosticOptions::DefaultTemplateBacktraceLimit) {
- Res.push_back("-ftemplate-backtrace-limit");
- Res.push_back(llvm::utostr(Opts.TemplateBacktraceLimit));
- }
-
- if (Opts.TabStop != DiagnosticOptions::DefaultTabStop) {
- Res.push_back("-ftabstop");
- Res.push_back(llvm::utostr(Opts.TabStop));
- }
- if (Opts.MessageLength) {
- Res.push_back("-fmessage-length");
- Res.push_back(llvm::utostr(Opts.MessageLength));
- }
- if (!Opts.DumpBuildInformation.empty()) {
- Res.push_back("-dump-build-information");
- Res.push_back(Opts.DumpBuildInformation);
- }
- for (unsigned i = 0, e = Opts.Warnings.size(); i != e; ++i)
- Res.push_back("-W" + Opts.Warnings[i]);
-}
-
-static const char *getInputKindName(InputKind Kind) {
- switch (Kind) {
- case IK_None: break;
- case IK_AST: return "ast";
- case IK_Asm: return "assembler-with-cpp";
- case IK_C: return "c";
- case IK_CXX: return "c++";
- case IK_LLVM_IR: return "ir";
- case IK_ObjC: return "objective-c";
- case IK_ObjCXX: return "objective-c++";
- case IK_OpenCL: return "cl";
- case IK_PreprocessedC: return "cpp-output";
- case IK_PreprocessedCXX: return "c++-cpp-output";
- case IK_PreprocessedObjC: return "objective-c-cpp-output";
- case IK_PreprocessedObjCXX:return "objective-c++-cpp-output";
- }
-
- llvm_unreachable("Unexpected language kind!");
- return 0;
-}
-
-static const char *getActionName(frontend::ActionKind Kind) {
- switch (Kind) {
- case frontend::PluginAction:
- case frontend::InheritanceView:
- llvm_unreachable("Invalid kind!");
-
- case frontend::ASTDump: return "-ast-dump";
- case frontend::ASTPrint: return "-ast-print";
- case frontend::ASTPrintXML: return "-ast-print-xml";
- case frontend::ASTView: return "-ast-view";
- case frontend::BoostCon: return "-boostcon";
- case frontend::DumpRawTokens: return "-dump-raw-tokens";
- case frontend::DumpTokens: return "-dump-tokens";
- case frontend::EmitAssembly: return "-S";
- case frontend::EmitBC: return "-emit-llvm-bc";
- case frontend::EmitHTML: return "-emit-html";
- case frontend::EmitLLVM: return "-emit-llvm";
- case frontend::EmitLLVMOnly: return "-emit-llvm-only";
- case frontend::EmitCodeGenOnly: return "-emit-codegen-only";
- case frontend::EmitObj: return "-emit-obj";
- case frontend::FixIt: return "-fixit";
- case frontend::GeneratePCH: return "-emit-pch";
- case frontend::GeneratePTH: return "-emit-pth";
- case frontend::InitOnly: return "-init-only";
- case frontend::ParseSyntaxOnly: return "-fsyntax-only";
- case frontend::PrintDeclContext: return "-print-decl-contexts";
- case frontend::PrintPreamble: return "-print-preamble";
- case frontend::PrintPreprocessedInput: return "-E";
- case frontend::RewriteMacros: return "-rewrite-macros";
- case frontend::RewriteObjC: return "-rewrite-objc";
- case frontend::RewriteTest: return "-rewrite-test";
- case frontend::RunAnalysis: return "-analyze";
- case frontend::RunPreprocessorOnly: return "-Eonly";
- }
-
- llvm_unreachable("Unexpected language kind!");
- return 0;
-}
-
-static void FrontendOptsToArgs(const FrontendOptions &Opts,
- std::vector<std::string> &Res) {
- if (!Opts.DebugCodeCompletionPrinter)
- Res.push_back("-no-code-completion-debug-printer");
- if (Opts.DisableFree)
- Res.push_back("-disable-free");
- if (Opts.RelocatablePCH)
- Res.push_back("-relocatable-pch");
- if (Opts.ChainedPCH)
- Res.push_back("-chained-pch");
- if (Opts.ShowHelp)
- Res.push_back("-help");
- if (Opts.ShowMacrosInCodeCompletion)
- Res.push_back("-code-completion-macros");
- if (Opts.ShowCodePatternsInCodeCompletion)
- Res.push_back("-code-completion-patterns");
- if (Opts.ShowStats)
- Res.push_back("-print-stats");
- if (Opts.ShowTimers)
- Res.push_back("-ftime-report");
- if (Opts.ShowVersion)
- Res.push_back("-version");
-
- bool NeedLang = false;
- for (unsigned i = 0, e = Opts.Inputs.size(); i != e; ++i)
- if (FrontendOptions::getInputKindForExtension(Opts.Inputs[i].second) !=
- Opts.Inputs[i].first)
- NeedLang = true;
- if (NeedLang) {
- Res.push_back("-x");
- Res.push_back(getInputKindName(Opts.Inputs[0].first));
- }
- for (unsigned i = 0, e = Opts.Inputs.size(); i != e; ++i) {
- assert((!NeedLang || Opts.Inputs[i].first == Opts.Inputs[0].first) &&
- "Unable to represent this input vector!");
- Res.push_back(Opts.Inputs[i].second);
- }
-
- if (!Opts.OutputFile.empty()) {
- Res.push_back("-o");
- Res.push_back(Opts.OutputFile);
- }
- if (!Opts.ViewClassInheritance.empty()) {
- Res.push_back("-cxx-inheritance-view");
- Res.push_back(Opts.ViewClassInheritance);
- }
- if (!Opts.CodeCompletionAt.FileName.empty()) {
- Res.push_back("-code-completion-at");
- Res.push_back(Opts.CodeCompletionAt.FileName + ":" +
- llvm::utostr(Opts.CodeCompletionAt.Line) + ":" +
- llvm::utostr(Opts.CodeCompletionAt.Column));
- }
- if (Opts.ProgramAction != frontend::InheritanceView &&
- Opts.ProgramAction != frontend::PluginAction)
- Res.push_back(getActionName(Opts.ProgramAction));
- if (!Opts.ActionName.empty()) {
- Res.push_back("-plugin");
- Res.push_back(Opts.ActionName);
- for(unsigned i = 0, e = Opts.PluginArgs.size(); i != e; ++i) {
- Res.push_back("-plugin-arg-" + Opts.ActionName);
- Res.push_back(Opts.PluginArgs[i]);
- }
- }
- for (unsigned i = 0, e = Opts.Plugins.size(); i != e; ++i) {
- Res.push_back("-load");
- Res.push_back(Opts.Plugins[i]);
- }
- for (unsigned i = 0, e = Opts.ASTMergeFiles.size(); i != e; ++i) {
- Res.push_back("-ast-merge");
- Res.push_back(Opts.ASTMergeFiles[i]);
- }
- for (unsigned i = 0, e = Opts.LLVMArgs.size(); i != e; ++i) {
- Res.push_back("-mllvm");
- Res.push_back(Opts.LLVMArgs[i]);
- }
-}
-
-static void HeaderSearchOptsToArgs(const HeaderSearchOptions &Opts,
- std::vector<std::string> &Res) {
- if (Opts.Sysroot != "/") {
- Res.push_back("-isysroot");
- Res.push_back(Opts.Sysroot);
- }
-
- /// User specified include entries.
- for (unsigned i = 0, e = Opts.UserEntries.size(); i != e; ++i) {
- const HeaderSearchOptions::Entry &E = Opts.UserEntries[i];
- if (E.IsFramework && (E.Group != frontend::Angled || !E.IsUserSupplied))
- llvm::report_fatal_error("Invalid option set!");
- if (E.IsUserSupplied) {
- if (E.Group == frontend::After) {
- Res.push_back("-idirafter");
- } else if (E.Group == frontend::Quoted) {
- Res.push_back("-iquote");
- } else if (E.Group == frontend::System) {
- Res.push_back("-isystem");
- } else {
- assert(E.Group == frontend::Angled && "Invalid group!");
- Res.push_back(E.IsFramework ? "-F" : "-I");
- }
- } else {
- if (E.Group != frontend::Angled && E.Group != frontend::System)
- llvm::report_fatal_error("Invalid option set!");
- Res.push_back(E.Group == frontend::Angled ? "-iwithprefixbefore" :
- "-iwithprefix");
- }
- Res.push_back(E.Path);
- }
-
- if (!Opts.EnvIncPath.empty()) {
- // FIXME: Provide an option for this, and move env detection to driver.
- llvm::report_fatal_error("Not yet implemented!");
- }
- if (!Opts.CEnvIncPath.empty()) {
- // FIXME: Provide an option for this, and move env detection to driver.
- llvm::report_fatal_error("Not yet implemented!");
- }
- if (!Opts.ObjCEnvIncPath.empty()) {
- // FIXME: Provide an option for this, and move env detection to driver.
- llvm::report_fatal_error("Not yet implemented!");
- }
- if (!Opts.CXXEnvIncPath.empty()) {
- // FIXME: Provide an option for this, and move env detection to driver.
- llvm::report_fatal_error("Not yet implemented!");
- }
- if (!Opts.ObjCXXEnvIncPath.empty()) {
- // FIXME: Provide an option for this, and move env detection to driver.
- llvm::report_fatal_error("Not yet implemented!");
- }
- if (!Opts.ResourceDir.empty()) {
- Res.push_back("-resource-dir");
- Res.push_back(Opts.ResourceDir);
- }
- if (!Opts.UseStandardIncludes)
- Res.push_back("-nostdinc");
- if (!Opts.UseStandardCXXIncludes)
- Res.push_back("-nostdinc++");
- if (Opts.Verbose)
- Res.push_back("-v");
-}
-
-static void LangOptsToArgs(const LangOptions &Opts,
- std::vector<std::string> &Res) {
- LangOptions DefaultLangOpts;
-
- // FIXME: Need to set -std to get all the implicit options.
-
- // FIXME: We want to only pass options relative to the defaults, which
- // requires constructing a target. :(
- //
- // It would be better to push the all target specific choices into the driver,
- // so that everything below that was more uniform.
-
- if (Opts.Trigraphs)
- Res.push_back("-trigraphs");
- // Implicit based on the input kind:
- // AsmPreprocessor, CPlusPlus, ObjC1, ObjC2, OpenCL
- // Implicit based on the input language standard:
- // BCPLComment, C99, CPlusPlus0x, Digraphs, GNUInline, ImplicitInt, GNUMode
- if (Opts.DollarIdents)
- Res.push_back("-fdollars-in-identifiers");
- if (Opts.GNUMode && !Opts.GNUKeywords)
- Res.push_back("-fno-gnu-keywords");
- if (!Opts.GNUMode && Opts.GNUKeywords)
- Res.push_back("-fgnu-keywords");
- if (Opts.Microsoft)
- Res.push_back("-fms-extensions");
- if (Opts.ObjCNonFragileABI)
- Res.push_back("-fobjc-nonfragile-abi");
- if (Opts.ObjCNonFragileABI2)
- Res.push_back("-fobjc-nonfragile-abi2");
- // NoInline is implicit.
- if (!Opts.CXXOperatorNames)
- Res.push_back("-fno-operator-names");
- if (Opts.PascalStrings)
- Res.push_back("-fpascal-strings");
- if (Opts.CatchUndefined)
- Res.push_back("-fcatch-undefined-behavior");
- if (Opts.WritableStrings)
- Res.push_back("-fwritable-strings");
- if (Opts.ConstStrings)
- Res.push_back("-Wwrite-strings");
- if (!Opts.LaxVectorConversions)
- Res.push_back("-fno-lax-vector-conversions");
- if (Opts.AltiVec)
- Res.push_back("-faltivec");
- if (Opts.Exceptions)
- Res.push_back("-fexceptions");
- if (Opts.SjLjExceptions)
- Res.push_back("-fsjlj-exceptions");
- if (!Opts.RTTI)
- Res.push_back("-fno-rtti");
- if (!Opts.NeXTRuntime)
- Res.push_back("-fgnu-runtime");
- if (Opts.Freestanding)
- Res.push_back("-ffreestanding");
- if (Opts.NoBuiltin)
- Res.push_back("-fno-builtin");
- if (!Opts.AssumeSaneOperatorNew)
- Res.push_back("-fno-assume-sane-operator-new");
- if (!Opts.ThreadsafeStatics)
- Res.push_back("-fno-threadsafe-statics");
- if (Opts.POSIXThreads)
- Res.push_back("-pthread");
- if (Opts.Blocks)
- Res.push_back("-fblocks");
- if (Opts.EmitAllDecls)
- Res.push_back("-femit-all-decls");
- if (Opts.MathErrno)
- Res.push_back("-fmath-errno");
- switch (Opts.getSignedOverflowBehavior()) {
- case LangOptions::SOB_Undefined: break;
- case LangOptions::SOB_Defined: Res.push_back("-fwrapv"); break;
- case LangOptions::SOB_Trapping: Res.push_back("-ftrapv"); break;
- }
- if (Opts.HeinousExtensions)
- Res.push_back("-fheinous-gnu-extensions");
- // Optimize is implicit.
- // OptimizeSize is implicit.
- if (Opts.Static)
- Res.push_back("-static-define");
- if (Opts.DumpRecordLayouts)
- Res.push_back("-fdump-record-layouts");
- if (Opts.DumpVTableLayouts)
- Res.push_back("-fdump-vtable-layouts");
- if (Opts.NoBitFieldTypeAlign)
- Res.push_back("-fno-bitfield-type-alignment");
- if (Opts.SjLjExceptions)
- Res.push_back("-fsjlj-exceptions");
- if (Opts.PICLevel) {
- Res.push_back("-pic-level");
- Res.push_back(llvm::utostr(Opts.PICLevel));
- }
- if (Opts.ObjCGCBitmapPrint)
- Res.push_back("-print-ivar-layout");
- if (Opts.NoConstantCFStrings)
- Res.push_back("-fno-constant-cfstrings");
- if (!Opts.AccessControl)
- Res.push_back("-fno-access-control");
- if (!Opts.CharIsSigned)
- Res.push_back("-fno-signed-char");
- if (Opts.ShortWChar)
- Res.push_back("-fshort-wchar");
- if (!Opts.ElideConstructors)
- Res.push_back("-fno-elide-constructors");
- if (Opts.getGCMode() != LangOptions::NonGC) {
- if (Opts.getGCMode() == LangOptions::HybridGC) {
- Res.push_back("-fobjc-gc");
- } else {
- assert(Opts.getGCMode() == LangOptions::GCOnly && "Invalid GC mode!");
- Res.push_back("-fobjc-gc-only");
- }
- }
- if (Opts.getVisibilityMode() != LangOptions::Default) {
- Res.push_back("-fvisibility");
- if (Opts.getVisibilityMode() == LangOptions::Hidden) {
- Res.push_back("hidden");
- } else {
- assert(Opts.getVisibilityMode() == LangOptions::Protected &&
- "Invalid visibility!");
- Res.push_back("protected");
- }
- }
- if (Opts.InlineVisibilityHidden)
- Res.push_back("-fvisibility-inlines-hidden");
-
- if (Opts.getStackProtectorMode() != 0) {
- Res.push_back("-stack-protector");
- Res.push_back(llvm::utostr(Opts.getStackProtectorMode()));
- }
- if (Opts.InstantiationDepth != DefaultLangOpts.InstantiationDepth) {
- Res.push_back("-ftemplate-depth");
- Res.push_back(llvm::utostr(Opts.InstantiationDepth));
- }
- if (!Opts.ObjCConstantStringClass.empty()) {
- Res.push_back("-fconstant-string-class");
- Res.push_back(Opts.ObjCConstantStringClass);
- }
-}
-
-static void PreprocessorOptsToArgs(const PreprocessorOptions &Opts,
- std::vector<std::string> &Res) {
- for (unsigned i = 0, e = Opts.Macros.size(); i != e; ++i)
- Res.push_back(std::string(Opts.Macros[i].second ? "-U" : "-D") +
- Opts.Macros[i].first);
- for (unsigned i = 0, e = Opts.Includes.size(); i != e; ++i) {
- // FIXME: We need to avoid reincluding the implicit PCH and PTH includes.
- Res.push_back("-include");
- Res.push_back(Opts.Includes[i]);
- }
- for (unsigned i = 0, e = Opts.MacroIncludes.size(); i != e; ++i) {
- Res.push_back("-imacros");
- Res.push_back(Opts.MacroIncludes[i]);
- }
- if (!Opts.UsePredefines)
- Res.push_back("-undef");
- if (Opts.DetailedRecord)
- Res.push_back("-detailed-preprocessing-record");
- if (!Opts.ImplicitPCHInclude.empty()) {
- Res.push_back("-include-pch");
- Res.push_back(Opts.ImplicitPCHInclude);
- }
- if (!Opts.ImplicitPTHInclude.empty()) {
- Res.push_back("-include-pth");
- Res.push_back(Opts.ImplicitPTHInclude);
- }
- if (!Opts.TokenCache.empty()) {
- if (Opts.ImplicitPTHInclude.empty()) {
- Res.push_back("-token-cache");
- Res.push_back(Opts.TokenCache);
- } else
- assert(Opts.ImplicitPTHInclude == Opts.TokenCache &&
- "Unsupported option combination!");
- }
- for (unsigned i = 0, e = Opts.RemappedFiles.size(); i != e; ++i) {
- Res.push_back("-remap-file");
- Res.push_back(Opts.RemappedFiles[i].first + ";" +
- Opts.RemappedFiles[i].second);
- }
-}
-
-static void PreprocessorOutputOptsToArgs(const PreprocessorOutputOptions &Opts,
- std::vector<std::string> &Res) {
- if (!Opts.ShowCPP && !Opts.ShowMacros)
- llvm::report_fatal_error("Invalid option combination!");
-
- if (Opts.ShowCPP && Opts.ShowMacros)
- Res.push_back("-dD");
- else if (!Opts.ShowCPP && Opts.ShowMacros)
- Res.push_back("-dM");
-
- if (!Opts.ShowLineMarkers)
- Res.push_back("-P");
- if (Opts.ShowComments)
- Res.push_back("-C");
- if (Opts.ShowMacroComments)
- Res.push_back("-CC");
-}
-
-static void TargetOptsToArgs(const TargetOptions &Opts,
- std::vector<std::string> &Res) {
- Res.push_back("-triple");
- Res.push_back(Opts.Triple);
- if (!Opts.CPU.empty()) {
- Res.push_back("-target-cpu");
- Res.push_back(Opts.CPU);
- }
- if (!Opts.ABI.empty()) {
- Res.push_back("-target-abi");
- Res.push_back(Opts.ABI);
- }
- Res.push_back("-cxx-abi");
- Res.push_back(Opts.CXXABI);
- for (unsigned i = 0, e = Opts.Features.size(); i != e; ++i) {
- Res.push_back("-target-feature");
- Res.push_back(Opts.Features[i]);
- }
-}
-
-void CompilerInvocation::toArgs(std::vector<std::string> &Res) {
- AnalyzerOptsToArgs(getAnalyzerOpts(), Res);
- CodeGenOptsToArgs(getCodeGenOpts(), Res);
- DependencyOutputOptsToArgs(getDependencyOutputOpts(), Res);
- DiagnosticOptsToArgs(getDiagnosticOpts(), Res);
- FrontendOptsToArgs(getFrontendOpts(), Res);
- HeaderSearchOptsToArgs(getHeaderSearchOpts(), Res);
- LangOptsToArgs(getLangOpts(), Res);
- PreprocessorOptsToArgs(getPreprocessorOpts(), Res);
- PreprocessorOutputOptsToArgs(getPreprocessorOutputOpts(), Res);
- TargetOptsToArgs(getTargetOpts(), Res);
-}
-
-//===----------------------------------------------------------------------===//
-// Deserialization (to args)
-//===----------------------------------------------------------------------===//
-
-using namespace clang::driver;
-using namespace clang::driver::cc1options;
-
-//
-
-static void ParseAnalyzerArgs(AnalyzerOptions &Opts, ArgList &Args,
- Diagnostic &Diags) {
- using namespace cc1options;
-
- Opts.AnalysisList.clear();
-#define ANALYSIS(NAME, CMDFLAG, DESC, SCOPE) \
- if (Args.hasArg(OPT_analysis_##NAME)) Opts.AnalysisList.push_back(NAME);
-#include "clang/Frontend/Analyses.def"
-
- if (Arg *A = Args.getLastArg(OPT_analyzer_store)) {
- llvm::StringRef Name = A->getValue(Args);
- AnalysisStores Value = llvm::StringSwitch<AnalysisStores>(Name)
-#define ANALYSIS_STORE(NAME, CMDFLAG, DESC, CREATFN) \
- .Case(CMDFLAG, NAME##Model)
-#include "clang/Frontend/Analyses.def"
- .Default(NumStores);
- // FIXME: Error handling.
- if (Value == NumStores)
- Diags.Report(diag::err_drv_invalid_value)
- << A->getAsString(Args) << Name;
- else
- Opts.AnalysisStoreOpt = Value;
- }
-
- if (Arg *A = Args.getLastArg(OPT_analyzer_constraints)) {
- llvm::StringRef Name = A->getValue(Args);
- AnalysisConstraints Value = llvm::StringSwitch<AnalysisConstraints>(Name)
-#define ANALYSIS_CONSTRAINTS(NAME, CMDFLAG, DESC, CREATFN) \
- .Case(CMDFLAG, NAME##Model)
-#include "clang/Frontend/Analyses.def"
- .Default(NumConstraints);
- // FIXME: Error handling.
- if (Value == NumConstraints)
- Diags.Report(diag::err_drv_invalid_value)
- << A->getAsString(Args) << Name;
- else
- Opts.AnalysisConstraintsOpt = Value;
- }
-
- if (Arg *A = Args.getLastArg(OPT_analyzer_output)) {
- llvm::StringRef Name = A->getValue(Args);
- AnalysisDiagClients Value = llvm::StringSwitch<AnalysisDiagClients>(Name)
-#define ANALYSIS_DIAGNOSTICS(NAME, CMDFLAG, DESC, CREATFN, AUTOCREAT) \
- .Case(CMDFLAG, PD_##NAME)
-#include "clang/Frontend/Analyses.def"
- .Default(NUM_ANALYSIS_DIAG_CLIENTS);
- // FIXME: Error handling.
- if (Value == NUM_ANALYSIS_DIAG_CLIENTS)
- Diags.Report(diag::err_drv_invalid_value)
- << A->getAsString(Args) << Name;
- else
- Opts.AnalysisDiagOpt = Value;
- }
-
- Opts.VisualizeEGDot = Args.hasArg(OPT_analyzer_viz_egraph_graphviz);
- Opts.VisualizeEGUbi = Args.hasArg(OPT_analyzer_viz_egraph_ubigraph);
- Opts.AnalyzeAll = Args.hasArg(OPT_analyzer_opt_analyze_headers);
- Opts.AnalyzerDisplayProgress = Args.hasArg(OPT_analyzer_display_progress);
- Opts.AnalyzeNestedBlocks =
- Args.hasArg(OPT_analyzer_opt_analyze_nested_blocks);
- Opts.PurgeDead = !Args.hasArg(OPT_analyzer_no_purge_dead);
- Opts.EagerlyAssume = Args.hasArg(OPT_analyzer_eagerly_assume);
- Opts.AnalyzeSpecificFunction = Args.getLastArgValue(OPT_analyze_function);
- Opts.EnableExperimentalChecks = Args.hasArg(OPT_analyzer_experimental_checks);
- Opts.EnableExperimentalInternalChecks =
- Args.hasArg(OPT_analyzer_experimental_internal_checks);
- Opts.TrimGraph = Args.hasArg(OPT_trim_egraph);
- Opts.MaxNodes = Args.getLastArgIntValue(OPT_analyzer_max_nodes, 150000,Diags);
- Opts.MaxLoop = Args.getLastArgIntValue(OPT_analyzer_max_loop, 3, Diags);
- Opts.InlineCall = Args.hasArg(OPT_analyzer_inline_call);
-}
-
-static void ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args,
- Diagnostic &Diags) {
- using namespace cc1options;
- // -Os implies -O2
- if (Args.hasArg(OPT_Os))
- Opts.OptimizationLevel = 2;
- else {
- Opts.OptimizationLevel = Args.getLastArgIntValue(OPT_O, 0, Diags);
- if (Opts.OptimizationLevel > 3) {
- Diags.Report(diag::err_drv_invalid_value)
- << Args.getLastArg(OPT_O)->getAsString(Args) << Opts.OptimizationLevel;
- Opts.OptimizationLevel = 3;
- }
- }
-
- // We must always run at least the always inlining pass.
- Opts.Inlining = (Opts.OptimizationLevel > 1) ? CodeGenOptions::NormalInlining
- : CodeGenOptions::OnlyAlwaysInlining;
-
- Opts.DebugInfo = Args.hasArg(OPT_g);
- Opts.DisableLLVMOpts = Args.hasArg(OPT_disable_llvm_optzns);
- Opts.DisableRedZone = Args.hasArg(OPT_disable_red_zone);
- Opts.DwarfDebugFlags = Args.getLastArgValue(OPT_dwarf_debug_flags);
- Opts.MergeAllConstants = !Args.hasArg(OPT_fno_merge_all_constants);
- Opts.NoCommon = Args.hasArg(OPT_fno_common);
- Opts.NoImplicitFloat = Args.hasArg(OPT_no_implicit_float);
- Opts.OptimizeSize = Args.hasArg(OPT_Os);
- Opts.SimplifyLibCalls = !(Args.hasArg(OPT_fno_builtin) ||
- Args.hasArg(OPT_ffreestanding));
- Opts.UnrollLoops = (Opts.OptimizationLevel > 1 && !Opts.OptimizeSize);
-
- Opts.AsmVerbose = Args.hasArg(OPT_masm_verbose);
- Opts.CXAAtExit = !Args.hasArg(OPT_fno_use_cxa_atexit);
- Opts.CXXCtorDtorAliases = Args.hasArg(OPT_mconstructor_aliases);
- Opts.CodeModel = Args.getLastArgValue(OPT_mcode_model);
- Opts.DebugPass = Args.getLastArgValue(OPT_mdebug_pass);
- Opts.DisableFPElim = Args.hasArg(OPT_mdisable_fp_elim);
- Opts.FloatABI = Args.getLastArgValue(OPT_mfloat_abi);
- Opts.LimitFloatPrecision = Args.getLastArgValue(OPT_mlimit_float_precision);
- Opts.NoZeroInitializedInBSS = Args.hasArg(OPT_mno_zero_initialized_in_bss);
- Opts.RelaxAll = Args.hasArg(OPT_mrelax_all);
- Opts.OmitLeafFramePointer = Args.hasArg(OPT_momit_leaf_frame_pointer);
- Opts.SoftFloat = Args.hasArg(OPT_msoft_float);
- Opts.UnwindTables = Args.hasArg(OPT_munwind_tables);
- Opts.RelocationModel = Args.getLastArgValue(OPT_mrelocation_model, "pic");
-
- Opts.FunctionSections = Args.hasArg(OPT_ffunction_sections);
- Opts.DataSections = Args.hasArg(OPT_fdata_sections);
-
- Opts.MainFileName = Args.getLastArgValue(OPT_main_file_name);
- Opts.VerifyModule = !Args.hasArg(OPT_disable_llvm_verifier);
-
- Opts.InstrumentFunctions = Args.hasArg(OPT_finstrument_functions);
-
- if (Arg *A = Args.getLastArg(OPT_fobjc_dispatch_method_EQ)) {
- llvm::StringRef Name = A->getValue(Args);
- unsigned Method = llvm::StringSwitch<unsigned>(Name)
- .Case("legacy", CodeGenOptions::Legacy)
- .Case("non-legacy", CodeGenOptions::NonLegacy)
- .Case("mixed", CodeGenOptions::Mixed)
- .Default(~0U);
- if (Method == ~0U)
- Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Name;
- else
- Opts.ObjCDispatchMethod = Method;
- }
-}
-
-static void ParseDependencyOutputArgs(DependencyOutputOptions &Opts,
- ArgList &Args) {
- using namespace cc1options;
- Opts.OutputFile = Args.getLastArgValue(OPT_dependency_file);
- Opts.Targets = Args.getAllArgValues(OPT_MT);
- Opts.IncludeSystemHeaders = Args.hasArg(OPT_sys_header_deps);
- Opts.UsePhonyTargets = Args.hasArg(OPT_MP);
-}
-
-static void ParseDiagnosticArgs(DiagnosticOptions &Opts, ArgList &Args,
- Diagnostic &Diags) {
- using namespace cc1options;
- Opts.IgnoreWarnings = Args.hasArg(OPT_w);
- Opts.NoRewriteMacros = Args.hasArg(OPT_Wno_rewrite_macros);
- Opts.Pedantic = Args.hasArg(OPT_pedantic);
- Opts.PedanticErrors = Args.hasArg(OPT_pedantic_errors);
- Opts.ShowCarets = !Args.hasArg(OPT_fno_caret_diagnostics);
- Opts.ShowColors = Args.hasArg(OPT_fcolor_diagnostics);
- Opts.ShowColumn = !Args.hasArg(OPT_fno_show_column);
- Opts.ShowFixits = !Args.hasArg(OPT_fno_diagnostics_fixit_info);
- Opts.ShowLocation = !Args.hasArg(OPT_fno_show_source_location);
- Opts.ShowOptionNames = Args.hasArg(OPT_fdiagnostics_show_option);
-
- llvm::StringRef ShowOverloads =
- Args.getLastArgValue(OPT_fshow_overloads_EQ, "all");
- if (ShowOverloads == "best")
- Opts.ShowOverloads = Diagnostic::Ovl_Best;
- else if (ShowOverloads == "all")
- Opts.ShowOverloads = Diagnostic::Ovl_All;
- else
- Diags.Report(diag::err_drv_invalid_value)
- << Args.getLastArg(OPT_fshow_overloads_EQ)->getAsString(Args)
- << ShowOverloads;
-
- llvm::StringRef ShowCategory =
- Args.getLastArgValue(OPT_fdiagnostics_show_category, "none");
- if (ShowCategory == "none")
- Opts.ShowCategories = 0;
- else if (ShowCategory == "id")
- Opts.ShowCategories = 1;
- else if (ShowCategory == "name")
- Opts.ShowCategories = 2;
- else
- Diags.Report(diag::err_drv_invalid_value)
- << Args.getLastArg(OPT_fdiagnostics_show_category)->getAsString(Args)
- << ShowCategory;
-
- Opts.ShowSourceRanges = Args.hasArg(OPT_fdiagnostics_print_source_range_info);
- Opts.VerifyDiagnostics = Args.hasArg(OPT_verify);
- Opts.BinaryOutput = Args.hasArg(OPT_fdiagnostics_binary);
- Opts.ErrorLimit = Args.getLastArgIntValue(OPT_ferror_limit, 0, Diags);
- Opts.MacroBacktraceLimit
- = Args.getLastArgIntValue(OPT_fmacro_backtrace_limit,
- DiagnosticOptions::DefaultMacroBacktraceLimit, Diags);
- Opts.TemplateBacktraceLimit
- = Args.getLastArgIntValue(OPT_ftemplate_backtrace_limit,
- DiagnosticOptions::DefaultTemplateBacktraceLimit,
- Diags);
- Opts.TabStop = Args.getLastArgIntValue(OPT_ftabstop,
- DiagnosticOptions::DefaultTabStop, Diags);
- if (Opts.TabStop == 0 || Opts.TabStop > DiagnosticOptions::MaxTabStop) {
- Diags.Report(diag::warn_ignoring_ftabstop_value)
- << Opts.TabStop << DiagnosticOptions::DefaultTabStop;
- Opts.TabStop = DiagnosticOptions::DefaultTabStop;
- }
- Opts.MessageLength = Args.getLastArgIntValue(OPT_fmessage_length, 0, Diags);
- Opts.DumpBuildInformation = Args.getLastArgValue(OPT_dump_build_information);
- Opts.Warnings = Args.getAllArgValues(OPT_W);
-}
-
-static InputKind ParseFrontendArgs(FrontendOptions &Opts, ArgList &Args,
- Diagnostic &Diags) {
- using namespace cc1options;
- Opts.ProgramAction = frontend::ParseSyntaxOnly;
- if (const Arg *A = Args.getLastArg(OPT_Action_Group)) {
- switch (A->getOption().getID()) {
- default:
- assert(0 && "Invalid option in group!");
- case OPT_ast_dump:
- Opts.ProgramAction = frontend::ASTDump; break;
- case OPT_ast_print:
- Opts.ProgramAction = frontend::ASTPrint; break;
- case OPT_ast_print_xml:
- Opts.ProgramAction = frontend::ASTPrintXML; break;
- case OPT_ast_view:
- Opts.ProgramAction = frontend::ASTView; break;
- case OPT_boostcon:
- Opts.ProgramAction = frontend::BoostCon; break;
- case OPT_dump_raw_tokens:
- Opts.ProgramAction = frontend::DumpRawTokens; break;
- case OPT_dump_tokens:
- Opts.ProgramAction = frontend::DumpTokens; break;
- case OPT_S:
- Opts.ProgramAction = frontend::EmitAssembly; break;
- case OPT_emit_llvm_bc:
- Opts.ProgramAction = frontend::EmitBC; break;
- case OPT_emit_html:
- Opts.ProgramAction = frontend::EmitHTML; break;
- case OPT_emit_llvm:
- Opts.ProgramAction = frontend::EmitLLVM; break;
- case OPT_emit_llvm_only:
- Opts.ProgramAction = frontend::EmitLLVMOnly; break;
- case OPT_emit_codegen_only:
- Opts.ProgramAction = frontend::EmitCodeGenOnly; break;
- case OPT_emit_obj:
- Opts.ProgramAction = frontend::EmitObj; break;
- case OPT_fixit_EQ:
- Opts.FixItSuffix = A->getValue(Args);
- // fall-through!
- case OPT_fixit:
- Opts.ProgramAction = frontend::FixIt; break;
- case OPT_emit_pch:
- Opts.ProgramAction = frontend::GeneratePCH; break;
- case OPT_emit_pth:
- Opts.ProgramAction = frontend::GeneratePTH; break;
- case OPT_init_only:
- Opts.ProgramAction = frontend::InitOnly; break;
- case OPT_fsyntax_only:
- Opts.ProgramAction = frontend::ParseSyntaxOnly; break;
- case OPT_print_decl_contexts:
- Opts.ProgramAction = frontend::PrintDeclContext; break;
- case OPT_print_preamble:
- Opts.ProgramAction = frontend::PrintPreamble; break;
- case OPT_E:
- Opts.ProgramAction = frontend::PrintPreprocessedInput; break;
- case OPT_rewrite_macros:
- Opts.ProgramAction = frontend::RewriteMacros; break;
- case OPT_rewrite_objc:
- Opts.ProgramAction = frontend::RewriteObjC; break;
- case OPT_rewrite_test:
- Opts.ProgramAction = frontend::RewriteTest; break;
- case OPT_analyze:
- Opts.ProgramAction = frontend::RunAnalysis; break;
- case OPT_Eonly:
- Opts.ProgramAction = frontend::RunPreprocessorOnly; break;
- }
- }
-
- if (const Arg* A = Args.getLastArg(OPT_plugin)) {
- Opts.Plugins.push_back(A->getValue(Args,0));
- Opts.ProgramAction = frontend::PluginAction;
- Opts.ActionName = A->getValue(Args);
-
- for (arg_iterator it = Args.filtered_begin(OPT_plugin_arg),
- end = Args.filtered_end(); it != end; ++it) {
- if ((*it)->getValue(Args, 0) == Opts.ActionName)
- Opts.PluginArgs.push_back((*it)->getValue(Args, 1));
- }
- }
-
- if (const Arg *A = Args.getLastArg(OPT_code_completion_at)) {
- Opts.CodeCompletionAt =
- ParsedSourceLocation::FromString(A->getValue(Args));
- if (Opts.CodeCompletionAt.FileName.empty())
- Diags.Report(diag::err_drv_invalid_value)
- << A->getAsString(Args) << A->getValue(Args);
- }
- Opts.DebugCodeCompletionPrinter =
- !Args.hasArg(OPT_no_code_completion_debug_printer);
- Opts.DisableFree = Args.hasArg(OPT_disable_free);
-
- Opts.OutputFile = Args.getLastArgValue(OPT_o);
- Opts.Plugins = Args.getAllArgValues(OPT_load);
- Opts.RelocatablePCH = Args.hasArg(OPT_relocatable_pch);
- Opts.ChainedPCH = Args.hasArg(OPT_chained_pch);
- Opts.ShowHelp = Args.hasArg(OPT_help);
- Opts.ShowMacrosInCodeCompletion = Args.hasArg(OPT_code_completion_macros);
- Opts.ShowCodePatternsInCodeCompletion
- = Args.hasArg(OPT_code_completion_patterns);
- Opts.ShowStats = Args.hasArg(OPT_print_stats);
- Opts.ShowTimers = Args.hasArg(OPT_ftime_report);
- Opts.ShowVersion = Args.hasArg(OPT_version);
- Opts.ViewClassInheritance = Args.getLastArgValue(OPT_cxx_inheritance_view);
- Opts.ASTMergeFiles = Args.getAllArgValues(OPT_ast_merge);
- Opts.LLVMArgs = Args.getAllArgValues(OPT_mllvm);
-
- InputKind DashX = IK_None;
- if (const Arg *A = Args.getLastArg(OPT_x)) {
- DashX = llvm::StringSwitch<InputKind>(A->getValue(Args))
- .Case("c", IK_C)
- .Case("cl", IK_OpenCL)
- .Case("c", IK_C)
- .Case("cl", IK_OpenCL)
- .Case("c++", IK_CXX)
- .Case("objective-c", IK_ObjC)
- .Case("objective-c++", IK_ObjCXX)
- .Case("cpp-output", IK_PreprocessedC)
- .Case("assembler-with-cpp", IK_Asm)
- .Case("c++-cpp-output", IK_PreprocessedCXX)
- .Case("objective-c-cpp-output", IK_PreprocessedObjC)
- .Case("objective-c++-cpp-output", IK_PreprocessedObjCXX)
- .Case("c-header", IK_C)
- .Case("objective-c-header", IK_ObjC)
- .Case("c++-header", IK_CXX)
- .Case("objective-c++-header", IK_ObjCXX)
- .Case("ast", IK_AST)
- .Case("ir", IK_LLVM_IR)
- .Default(IK_None);
- if (DashX == IK_None)
- Diags.Report(diag::err_drv_invalid_value)
- << A->getAsString(Args) << A->getValue(Args);
- }
-
- // '-' is the default input if none is given.
- std::vector<std::string> Inputs = Args.getAllArgValues(OPT_INPUT);
- Opts.Inputs.clear();
- if (Inputs.empty())
- Inputs.push_back("-");
- for (unsigned i = 0, e = Inputs.size(); i != e; ++i) {
- InputKind IK = DashX;
- if (IK == IK_None) {
- IK = FrontendOptions::getInputKindForExtension(
- llvm::StringRef(Inputs[i]).rsplit('.').second);
- // FIXME: Remove this hack.
- if (i == 0)
- DashX = IK;
- }
- Opts.Inputs.push_back(std::make_pair(IK, Inputs[i]));
- }
-
- return DashX;
-}
-
-std::string CompilerInvocation::GetResourcesPath(const char *Argv0,
- void *MainAddr) {
- llvm::sys::Path P = llvm::sys::Path::GetMainExecutable(Argv0, MainAddr);
-
- if (!P.isEmpty()) {
- P.eraseComponent(); // Remove /clang from foo/bin/clang
- P.eraseComponent(); // Remove /bin from foo/bin
-
- // Get foo/lib/clang/<version>/include
- P.appendComponent("lib");
- P.appendComponent("clang");
- P.appendComponent(CLANG_VERSION_STRING);
- }
-
- return P.str();
-}
-
-static void ParseHeaderSearchArgs(HeaderSearchOptions &Opts, ArgList &Args) {
- using namespace cc1options;
- Opts.Sysroot = Args.getLastArgValue(OPT_isysroot, "/");
- Opts.Verbose = Args.hasArg(OPT_v);
- Opts.UseBuiltinIncludes = !Args.hasArg(OPT_nobuiltininc);
- Opts.UseStandardIncludes = !Args.hasArg(OPT_nostdinc);
- Opts.UseStandardCXXIncludes = !Args.hasArg(OPT_nostdincxx);
- Opts.ResourceDir = Args.getLastArgValue(OPT_resource_dir);
-
- // Add -I... and -F... options in order.
- for (arg_iterator it = Args.filtered_begin(OPT_I, OPT_F),
- ie = Args.filtered_end(); it != ie; ++it)
- Opts.AddPath((*it)->getValue(Args), frontend::Angled, true,
- /*IsFramework=*/ (*it)->getOption().matches(OPT_F));
-
- // Add -iprefix/-iwith-prefix/-iwithprefixbefore options.
- llvm::StringRef Prefix = ""; // FIXME: This isn't the correct default prefix.
- for (arg_iterator it = Args.filtered_begin(OPT_iprefix, OPT_iwithprefix,
- OPT_iwithprefixbefore),
- ie = Args.filtered_end(); it != ie; ++it) {
- const Arg *A = *it;
- if (A->getOption().matches(OPT_iprefix))
- Prefix = A->getValue(Args);
- else if (A->getOption().matches(OPT_iwithprefix))
- Opts.AddPath(Prefix.str() + A->getValue(Args),
- frontend::System, false, false);
- else
- Opts.AddPath(Prefix.str() + A->getValue(Args),
- frontend::Angled, false, false);
- }
-
- for (arg_iterator it = Args.filtered_begin(OPT_idirafter),
- ie = Args.filtered_end(); it != ie; ++it)
- Opts.AddPath((*it)->getValue(Args), frontend::After, true, false);
- for (arg_iterator it = Args.filtered_begin(OPT_iquote),
- ie = Args.filtered_end(); it != ie; ++it)
- Opts.AddPath((*it)->getValue(Args), frontend::Quoted, true, false);
- for (arg_iterator it = Args.filtered_begin(OPT_isystem),
- ie = Args.filtered_end(); it != ie; ++it)
- Opts.AddPath((*it)->getValue(Args), frontend::System, true, false);
-
- // FIXME: Need options for the various environment variables!
-}
-
-static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
- Diagnostic &Diags) {
- // FIXME: Cleanup per-file based stuff.
-
- // Set some properties which depend soley on the input kind; it would be nice
- // to move these to the language standard, and have the driver resolve the
- // input kind + language standard.
- if (IK == IK_Asm) {
- Opts.AsmPreprocessor = 1;
- } else if (IK == IK_ObjC ||
- IK == IK_ObjCXX ||
- IK == IK_PreprocessedObjC ||
- IK == IK_PreprocessedObjCXX) {
- Opts.ObjC1 = Opts.ObjC2 = 1;
- }
-
- LangStandard::Kind LangStd = LangStandard::lang_unspecified;
- if (const Arg *A = Args.getLastArg(OPT_std_EQ)) {
- LangStd = llvm::StringSwitch<LangStandard::Kind>(A->getValue(Args))
-#define LANGSTANDARD(id, name, desc, features) \
- .Case(name, LangStandard::lang_##id)
-#include "clang/Frontend/LangStandards.def"
- .Default(LangStandard::lang_unspecified);
- if (LangStd == LangStandard::lang_unspecified)
- Diags.Report(diag::err_drv_invalid_value)
- << A->getAsString(Args) << A->getValue(Args);
- }
-
- if (LangStd == LangStandard::lang_unspecified) {
- // Based on the base language, pick one.
- switch (IK) {
- case IK_None:
- case IK_AST:
- case IK_LLVM_IR:
- assert(0 && "Invalid input kind!");
- case IK_OpenCL:
- LangStd = LangStandard::lang_opencl;
- break;
- case IK_Asm:
- case IK_C:
- case IK_PreprocessedC:
- case IK_ObjC:
- case IK_PreprocessedObjC:
- LangStd = LangStandard::lang_gnu99;
- break;
- case IK_CXX:
- case IK_PreprocessedCXX:
- case IK_ObjCXX:
- case IK_PreprocessedObjCXX:
- LangStd = LangStandard::lang_gnucxx98;
- break;
- }
- }
-
- const LangStandard &Std = LangStandard::getLangStandardForKind(LangStd);
- Opts.BCPLComment = Std.hasBCPLComments();
- Opts.C99 = Std.isC99();
- Opts.CPlusPlus = Std.isCPlusPlus();
- Opts.CPlusPlus0x = Std.isCPlusPlus0x();
- Opts.Digraphs = Std.hasDigraphs();
- Opts.GNUMode = Std.isGNUMode();
- Opts.GNUInline = !Std.isC99();
- Opts.HexFloats = Std.hasHexFloats();
- Opts.ImplicitInt = Std.hasImplicitInt();
-
- // OpenCL has some additional defaults.
- if (LangStd == LangStandard::lang_opencl) {
- Opts.OpenCL = 1;
- Opts.AltiVec = 1;
- Opts.CXXOperatorNames = 1;
- Opts.LaxVectorConversions = 1;
- }
-
- // OpenCL and C++ both have bool, true, false keywords.
- Opts.Bool = Opts.OpenCL || Opts.CPlusPlus;
-
- // We abuse '-f[no-]gnu-keywords' to force overriding all GNU-extension
- // keywords. This behavior is provided by GCC's poorly named '-fasm' flag,
- // while a subset (the non-C++ GNU keywords) is provided by GCC's
- // '-fgnu-keywords'. Clang conflates the two for simplicity under the single
- // name, as it doesn't seem a useful distinction.
- Opts.GNUKeywords = Args.hasFlag(OPT_fgnu_keywords, OPT_fno_gnu_keywords,
- Opts.GNUMode);
-
- if (Opts.CPlusPlus)
- Opts.CXXOperatorNames = !Args.hasArg(OPT_fno_operator_names);
-
- if (Args.hasArg(OPT_fobjc_gc_only))
- Opts.setGCMode(LangOptions::GCOnly);
- else if (Args.hasArg(OPT_fobjc_gc))
- Opts.setGCMode(LangOptions::HybridGC);
-
- if (Args.hasArg(OPT_print_ivar_layout))
- Opts.ObjCGCBitmapPrint = 1;
- if (Args.hasArg(OPT_fno_constant_cfstrings))
- Opts.NoConstantCFStrings = 1;
-
- if (Args.hasArg(OPT_faltivec))
- Opts.AltiVec = 1;
-
- if (Args.hasArg(OPT_pthread))
- Opts.POSIXThreads = 1;
-
- llvm::StringRef Vis = Args.getLastArgValue(OPT_fvisibility, "default");
- if (Vis == "default")
- Opts.setVisibilityMode(LangOptions::Default);
- else if (Vis == "hidden")
- Opts.setVisibilityMode(LangOptions::Hidden);
- else if (Vis == "protected")
- Opts.setVisibilityMode(LangOptions::Protected);
- else
- Diags.Report(diag::err_drv_invalid_value)
- << Args.getLastArg(OPT_fvisibility)->getAsString(Args) << Vis;
-
- if (Args.hasArg(OPT_fvisibility_inlines_hidden))
- Opts.InlineVisibilityHidden = 1;
-
- if (Args.hasArg(OPT_ftrapv))
- Opts.setSignedOverflowBehavior(LangOptions::SOB_Trapping);
- else if (Args.hasArg(OPT_fwrapv))
- Opts.setSignedOverflowBehavior(LangOptions::SOB_Defined);
-
- // Mimicing gcc's behavior, trigraphs are only enabled if -trigraphs
- // is specified, or -std is set to a conforming mode.
- Opts.Trigraphs = !Opts.GNUMode;
- if (Args.hasArg(OPT_trigraphs))
- Opts.Trigraphs = 1;
-
- Opts.DollarIdents = Args.hasFlag(OPT_fdollars_in_identifiers,
- OPT_fno_dollars_in_identifiers,
- !Opts.AsmPreprocessor);
- Opts.PascalStrings = Args.hasArg(OPT_fpascal_strings);
- Opts.Microsoft = Args.hasArg(OPT_fms_extensions);
- Opts.WritableStrings = Args.hasArg(OPT_fwritable_strings);
- Opts.ConstStrings = Args.hasArg(OPT_Wwrite_strings);
- if (Args.hasArg(OPT_fno_lax_vector_conversions))
- Opts.LaxVectorConversions = 0;
- if (Args.hasArg(OPT_fno_threadsafe_statics))
- Opts.ThreadsafeStatics = 0;
- Opts.Exceptions = Args.hasArg(OPT_fexceptions);
- Opts.RTTI = !Args.hasArg(OPT_fno_rtti);
- Opts.Blocks = Args.hasArg(OPT_fblocks);
- Opts.CharIsSigned = !Args.hasArg(OPT_fno_signed_char);
- Opts.ShortWChar = Args.hasArg(OPT_fshort_wchar);
- Opts.Freestanding = Args.hasArg(OPT_ffreestanding);
- Opts.NoBuiltin = Args.hasArg(OPT_fno_builtin) || Opts.Freestanding;
- Opts.AssumeSaneOperatorNew = !Args.hasArg(OPT_fno_assume_sane_operator_new);
- Opts.HeinousExtensions = Args.hasArg(OPT_fheinous_gnu_extensions);
- Opts.AccessControl = !Args.hasArg(OPT_fno_access_control);
- Opts.ElideConstructors = !Args.hasArg(OPT_fno_elide_constructors);
- Opts.MathErrno = Args.hasArg(OPT_fmath_errno);
- Opts.InstantiationDepth = Args.getLastArgIntValue(OPT_ftemplate_depth, 1024,
- Diags);
- Opts.NeXTRuntime = !Args.hasArg(OPT_fgnu_runtime);
- Opts.ObjCConstantStringClass =
- Args.getLastArgValue(OPT_fconstant_string_class);
- Opts.ObjCNonFragileABI = Args.hasArg(OPT_fobjc_nonfragile_abi);
- Opts.ObjCNonFragileABI2 = Args.hasArg(OPT_fobjc_nonfragile_abi2);
- if (Opts.ObjCNonFragileABI2)
- Opts.ObjCNonFragileABI = true;
- Opts.CatchUndefined = Args.hasArg(OPT_fcatch_undefined_behavior);
- Opts.EmitAllDecls = Args.hasArg(OPT_femit_all_decls);
- Opts.PICLevel = Args.getLastArgIntValue(OPT_pic_level, 0, Diags);
- Opts.SjLjExceptions = Args.hasArg(OPT_fsjlj_exceptions);
- Opts.Static = Args.hasArg(OPT_static_define);
- Opts.DumpRecordLayouts = Args.hasArg(OPT_fdump_record_layouts);
- Opts.DumpVTableLayouts = Args.hasArg(OPT_fdump_vtable_layouts);
- Opts.SpellChecking = !Args.hasArg(OPT_fno_spell_checking);
- Opts.NoBitFieldTypeAlign = Args.hasArg(OPT_fno_bitfield_type_align);
- Opts.OptimizeSize = 0;
-
- // FIXME: Eliminate this dependency.
- unsigned Opt =
- Args.hasArg(OPT_Os) ? 2 : Args.getLastArgIntValue(OPT_O, 0, Diags);
- Opts.Optimize = Opt != 0;
-
- // This is the __NO_INLINE__ define, which just depends on things like the
- // optimization level and -fno-inline, not actually whether the backend has
- // inlining enabled.
- //
- // FIXME: This is affected by other options (-fno-inline).
- Opts.NoInline = !Opt;
-
- unsigned SSP = Args.getLastArgIntValue(OPT_stack_protector, 0, Diags);
- switch (SSP) {
- default:
- Diags.Report(diag::err_drv_invalid_value)
- << Args.getLastArg(OPT_stack_protector)->getAsString(Args) << SSP;
- break;
- case 0: Opts.setStackProtectorMode(LangOptions::SSPOff); break;
- case 1: Opts.setStackProtectorMode(LangOptions::SSPOn); break;
- case 2: Opts.setStackProtectorMode(LangOptions::SSPReq); break;
- }
-}
-
-static void ParsePreprocessorArgs(PreprocessorOptions &Opts, ArgList &Args,
- Diagnostic &Diags) {
- using namespace cc1options;
- Opts.ImplicitPCHInclude = Args.getLastArgValue(OPT_include_pch);
- Opts.ImplicitPTHInclude = Args.getLastArgValue(OPT_include_pth);
- if (const Arg *A = Args.getLastArg(OPT_token_cache))
- Opts.TokenCache = A->getValue(Args);
- else
- Opts.TokenCache = Opts.ImplicitPTHInclude;
- Opts.UsePredefines = !Args.hasArg(OPT_undef);
- Opts.DetailedRecord = Args.hasArg(OPT_detailed_preprocessing_record);
- Opts.DisablePCHValidation = Args.hasArg(OPT_fno_validate_pch);
-
- if (const Arg *A = Args.getLastArg(OPT_preamble_bytes_EQ)) {
- llvm::StringRef Value(A->getValue(Args));
- size_t Comma = Value.find(',');
- unsigned Bytes = 0;
- unsigned EndOfLine = 0;
-
- if (Comma == llvm::StringRef::npos ||
- Value.substr(0, Comma).getAsInteger(10, Bytes) ||
- Value.substr(Comma + 1).getAsInteger(10, EndOfLine))
- Diags.Report(diag::err_drv_preamble_format);
- else {
- Opts.PrecompiledPreambleBytes.first = Bytes;
- Opts.PrecompiledPreambleBytes.second = (EndOfLine != 0);
- }
- }
-
- // Add macros from the command line.
- for (arg_iterator it = Args.filtered_begin(OPT_D, OPT_U),
- ie = Args.filtered_end(); it != ie; ++it) {
- if ((*it)->getOption().matches(OPT_D))
- Opts.addMacroDef((*it)->getValue(Args));
- else
- Opts.addMacroUndef((*it)->getValue(Args));
- }
-
- Opts.MacroIncludes = Args.getAllArgValues(OPT_imacros);
-
- // Add the ordered list of -includes.
- for (arg_iterator it = Args.filtered_begin(OPT_include, OPT_include_pch,
- OPT_include_pth),
- ie = Args.filtered_end(); it != ie; ++it) {
- const Arg *A = *it;
- // PCH is handled specially, we need to extra the original include path.
- if (A->getOption().matches(OPT_include_pch)) {
- std::string OriginalFile =
- PCHReader::getOriginalSourceFile(A->getValue(Args), Diags);
- if (OriginalFile.empty())
- continue;
-
- Opts.Includes.push_back(OriginalFile);
- } else
- Opts.Includes.push_back(A->getValue(Args));
- }
-
- // Include 'altivec.h' if -faltivec option present
- if (Args.hasArg(OPT_faltivec))
- Opts.Includes.push_back("altivec.h");
-
- for (arg_iterator it = Args.filtered_begin(OPT_remap_file),
- ie = Args.filtered_end(); it != ie; ++it) {
- const Arg *A = *it;
- std::pair<llvm::StringRef,llvm::StringRef> Split =
- llvm::StringRef(A->getValue(Args)).split(';');
-
- if (Split.second.empty()) {
- Diags.Report(diag::err_drv_invalid_remap_file) << A->getAsString(Args);
- continue;
- }
-
- Opts.addRemappedFile(Split.first, Split.second);
- }
-}
-
-static void ParsePreprocessorOutputArgs(PreprocessorOutputOptions &Opts,
- ArgList &Args) {
- using namespace cc1options;
- Opts.ShowCPP = !Args.hasArg(OPT_dM);
- Opts.ShowMacros = Args.hasArg(OPT_dM) || Args.hasArg(OPT_dD);
- Opts.ShowLineMarkers = !Args.hasArg(OPT_P);
- Opts.ShowComments = Args.hasArg(OPT_C);
- Opts.ShowMacroComments = Args.hasArg(OPT_CC);
-}
-
-static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args) {
- using namespace cc1options;
- Opts.ABI = Args.getLastArgValue(OPT_target_abi);
- Opts.CXXABI = Args.getLastArgValue(OPT_cxx_abi);
- Opts.CPU = Args.getLastArgValue(OPT_target_cpu);
- Opts.Triple = Args.getLastArgValue(OPT_triple);
- Opts.Features = Args.getAllArgValues(OPT_target_feature);
-
- // Use the host triple if unspecified.
- if (Opts.Triple.empty())
- Opts.Triple = llvm::sys::getHostTriple();
-
- // Use the Itanium C++ ABI if unspecified.
- if (Opts.CXXABI.empty())
- Opts.CXXABI = "itanium";
-}
-
-//
-
-void CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
- const char **ArgBegin,
- const char **ArgEnd,
- Diagnostic &Diags) {
- // Parse the arguments.
- llvm::OwningPtr<OptTable> Opts(createCC1OptTable());
- unsigned MissingArgIndex, MissingArgCount;
- llvm::OwningPtr<InputArgList> Args(
- Opts->ParseArgs(ArgBegin, ArgEnd,MissingArgIndex, MissingArgCount));
-
- // Check for missing argument error.
- if (MissingArgCount)
- Diags.Report(diag::err_drv_missing_argument)
- << Args->getArgString(MissingArgIndex) << MissingArgCount;
-
- // Issue errors on unknown arguments.
- for (arg_iterator it = Args->filtered_begin(OPT_UNKNOWN),
- ie = Args->filtered_end(); it != ie; ++it)
- Diags.Report(diag::err_drv_unknown_argument) << (*it)->getAsString(*Args);
-
- ParseAnalyzerArgs(Res.getAnalyzerOpts(), *Args, Diags);
- ParseCodeGenArgs(Res.getCodeGenOpts(), *Args, Diags);
- ParseDependencyOutputArgs(Res.getDependencyOutputOpts(), *Args);
- ParseDiagnosticArgs(Res.getDiagnosticOpts(), *Args, Diags);
- InputKind DashX = ParseFrontendArgs(Res.getFrontendOpts(), *Args, Diags);
- ParseHeaderSearchArgs(Res.getHeaderSearchOpts(), *Args);
- if (DashX != IK_AST && DashX != IK_LLVM_IR)
- ParseLangArgs(Res.getLangOpts(), *Args, DashX, Diags);
- ParsePreprocessorArgs(Res.getPreprocessorOpts(), *Args, Diags);
- ParsePreprocessorOutputArgs(Res.getPreprocessorOutputOpts(), *Args);
- ParseTargetArgs(Res.getTargetOpts(), *Args);
-}
More information about the llvm-branch-commits
mailing list