--- /dev/null
+function(flang_tablegen)
+ # Syntax:
+ # flang_tablegen output-file [tablegen-arg ...] SOURCE source-file
+ # [[TARGET cmake-target-name] [DEPENDS extra-dependency ...]]
+ #
+ # Generates a custom command for invoking tblgen as
+ #
+ # tblgen source-file -o=output-file tablegen-arg ...
+ #
+ # and, if cmake-target-name is provided, creates a custom target for
+ # executing the custom command depending on output-file. It is
+ # possible to list more files to depend after DEPENDS.
+
+ cmake_parse_arguments(CTG "" "SOURCE;TARGET" "" ${ARGN})
+
+ if( NOT CTG_SOURCE )
+ message(FATAL_ERROR "SOURCE source-file required by flang_tablegen")
+ endif()
+
+ set( LLVM_TARGET_DEFINITIONS ${CTG_SOURCE} )
+ tablegen(FLANG ${CTG_UNPARSED_ARGUMENTS})
+
+ if(CTG_TARGET)
+ add_public_tablegen_target(${CTG_TARGET})
+ set_target_properties( ${CTG_TARGET} PROPERTIES FOLDER "FLANG tablegenning")
+ set_property(GLOBAL APPEND PROPERTY FLANG_TABLEGEN_TARGETS ${CTG_TARGET})
+ endif()
+endfunction(flang_tablegen)
+
+macro(set_flang_windows_version_resource_properties name)
+ if(DEFINED windows_resource_file)
+ set_windows_version_resource_properties(${name} ${windows_resource_file}
+ VERSION_MAJOR ${FLANG_VERSION_MAJOR}
+ VERSION_MINOR ${FLANG_VERSION_MINOR}
+ VERSION_PATCHLEVEL ${FLANG_VERSION_PATCHLEVEL}
+ VERSION_STRING "${FLANG_VERSION} (${BACKEND_PACKAGE_STRING})"
+ PRODUCT_NAME "flang")
+ endif()
+endmacro()
+
+macro(add_flang_subdirectory name)
+ add_llvm_subdirectory(FLANG TOOL ${name})
+endmacro()
+
+macro(add_flang_library name)
+ cmake_parse_arguments(ARG
+ "SHARED"
+ ""
+ "ADDITIONAL_HEADERS"
+ ${ARGN})
+ set(srcs)
+ if(MSVC_IDE OR XCODE)
+ # Add public headers
+ file(RELATIVE_PATH lib_path
+ ${FLANG_SOURCE_DIR}/lib/
+ ${CMAKE_CURRENT_SOURCE_DIR}
+ )
+ if(NOT lib_path MATCHES "^[.][.]")
+ file( GLOB_RECURSE headers
+ ${FLANG_SOURCE_DIR}/include/flang/${lib_path}/*.h
+ ${FLANG_SOURCE_DIR}/include/flang/${lib_path}/*.def
+ )
+ set_source_files_properties(${headers} PROPERTIES HEADER_FILE_ONLY ON)
+
+ file( GLOB_RECURSE tds
+ ${FLANG_SOURCE_DIR}/include/flang/${lib_path}/*.td
+ )
+ source_group("TableGen descriptions" FILES ${tds})
+ set_source_files_properties(${tds}} PROPERTIES HEADER_FILE_ONLY ON)
+
+ if(headers OR tds)
+ set(srcs ${headers} ${tds})
+ endif()
+ endif()
+ endif(MSVC_IDE OR XCODE)
+ if(srcs OR ARG_ADDITIONAL_HEADERS)
+ set(srcs
+ ADDITIONAL_HEADERS
+ ${srcs}
+ ${ARG_ADDITIONAL_HEADERS} # It may contain unparsed unknown args.
+ )
+ endif()
+ if(ARG_SHARED)
+ set(ARG_ENABLE_SHARED SHARED)
+ endif()
+ llvm_add_library(${name} ${ARG_ENABLE_SHARED} ${ARG_UNPARSED_ARGUMENTS} ${srcs})
+
+ if(TARGET ${name})
+ target_link_libraries(${name} INTERFACE ${LLVM_COMMON_LIBS})
+
+ if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY OR ${name} STREQUAL "libflang")
+
+ if(${name} IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR
+ NOT LLVM_DISTRIBUTION_COMPONENTS)
+ set(export_to_flangtargets EXPORT FlangTargets)
+ set_property(GLOBAL PROPERTY FLANG_HAS_EXPORTS True)
+ endif()
+
+ install(TARGETS ${name}
+ COMPONENT ${name}
+ ${export_to_flangtargets}
+ LIBRARY DESTINATION lib${LLVM_LIBDIR_SUFFIX}
+ ARCHIVE DESTINATION lib${LLVM_LIBDIR_SUFFIX}
+ RUNTIME DESTINATION bin)
+
+ if (${ARG_SHARED} AND NOT CMAKE_CONFIGURATION_TYPES)
+ add_custom_target(install-${name}
+ DEPENDS ${name}
+ COMMAND "${CMAKE_COMMAND}"
+ -DCMAKE_INSTALL_COMPONENT=${name}
+ -P "${CMAKE_BINARY_DIR}/cmake_install.cmake")
+ endif()
+ endif()
+ set_property(GLOBAL APPEND PROPERTY FLANG_EXPORTS ${name})
+ else()
+ # Add empty "phony" target
+ add_custom_target(${name})
+ endif()
+
+ set_target_properties(${name} PROPERTIES FOLDER "FLANG libraries")
+ set_flang_windows_version_resource_properties(${name})
+endmacro(add_flang_library)
+
+macro(add_flang_executable name)
+ add_llvm_executable( ${name} ${ARGN} )
+ set_target_properties(${name} PROPERTIES FOLDER "FLANG executables")
+ set_flang_windows_version_resource_properties(${name})
+endmacro(add_flang_executable)
+
+macro(add_flang_tool name)
+ if (NOT FLANG_BUILD_TOOLS)
+ set(EXCLUDE_FROM_ALL ON)
+ endif()
+
+ add_flang_executable(${name} ${ARGN})
+
+ if (FLANG_BUILD_TOOLS)
+ if(${name} IN_LIST LLVM_DISTRIBUTION_COMPONENTS OR
+ NOT LLVM_DISTRIBUTION_COMPONENTS)
+ set(export_to_flangtargets EXPORT FlangTargets)
+ set_property(GLOBAL PROPERTY FLANG_HAS_EXPORTS True)
+ endif()
+
+ install(TARGETS ${name}
+ ${export_to_flangtargets}
+ RUNTIME DESTINATION bin
+ COMPONENT ${name})
+
+ if(NOT CMAKE_CONFIGURATION_TYPES)
+ add_custom_target(install-${name}
+ DEPENDS ${name}
+ COMMAND "${CMAKE_COMMAND}"
+ -DCMAKE_INSTALL_COMPONENT=${name}
+ -P "${CMAKE_BINARY_DIR}/cmake_install.cmake")
+ endif()
+ set_property(GLOBAL APPEND PROPERTY FLANG_EXPORTS ${name})
+ endif()
+endmacro()
+
+macro(add_flang_symlink name dest)
+ add_llvm_tool_symlink(${name} ${dest} ALWAYS_GENERATE)
+ # Always generate install targets
+ llvm_install_symlink(${name} ${dest} ALWAYS_GENERATE)
+endmacro()
--- /dev/null
+# Generate a list of CMake library targets so that other CMake projects can
+# link against them. LLVM calls its version of this file LLVMExports.cmake, but
+# the usual CMake convention seems to be ${Project}Targets.cmake.
+set(FLANG_INSTALL_PACKAGE_DIR lib${LLVM_LIBDIR_SUFFIX}/cmake/flang)
+set(flang_cmake_builddir "${CMAKE_BINARY_DIR}/${FLANG_INSTALL_PACKAGE_DIR}")
+
+# Keep this in sync with llvm/cmake/CMakeLists.txt!
+set(LLVM_INSTALL_PACKAGE_DIR lib${LLVM_LIBDIR_SUFFIX}/cmake/llvm)
+set(llvm_cmake_builddir "${LLVM_BINARY_DIR}/${LLVM_INSTALL_PACKAGE_DIR}")
+
+get_property(FLANG_EXPORTS GLOBAL PROPERTY FLANG_EXPORTS)
+export(TARGETS ${FLANG_EXPORTS} FILE ${flang_cmake_builddir}/FlangTargets.cmake)
+
+# Generate FlangConfig.cmake for the build tree.
+set(FLANG_CONFIG_CMAKE_DIR "${flang_cmake_builddir}")
+set(FLANG_CONFIG_LLVM_CMAKE_DIR "${llvm_cmake_builddir}")
+set(FLANG_CONFIG_EXPORTS_FILE "${flang_cmake_builddir}/FlangTargets.cmake")
+set(FLANG_CONFIG_INCLUDE_DIRS
+ "${FLANG_SOURCE_DIR}/include"
+ "${FLANG_BINARY_DIR}/include"
+ )
+configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/FlangConfig.cmake.in
+ ${flang_cmake_builddir}/FlangConfig.cmake
+ @ONLY)
+set(FLANG_CONFIG_CMAKE_DIR)
+set(FLANG_CONFIG_LLVM_CMAKE_DIR)
+set(FLANG_CONFIG_EXPORTS_FILE)
+
+# Generate FlangConfig.cmake for the install tree.
+set(FLANG_CONFIG_CODE "
+# Compute the installation prefix from this LLVMConfig.cmake file location.
+get_filename_component(FLANG_INSTALL_PREFIX \"\${CMAKE_CURRENT_LIST_FILE}\" PATH)")
+# Construct the proper number of get_filename_component(... PATH)
+# calls to compute the installation prefix.
+string(REGEX REPLACE "/" ";" _count "${FLANG_INSTALL_PACKAGE_DIR}")
+foreach(p ${_count})
+ set(FLANG_CONFIG_CODE "${FLANG_CONFIG_CODE}
+get_filename_component(FLANG_INSTALL_PREFIX \"\${FLANG_INSTALL_PREFIX}\" PATH)")
+endforeach(p)
+set(FLANG_CONFIG_CMAKE_DIR "\${FLANG_INSTALL_PREFIX}/${FLANG_INSTALL_PACKAGE_DIR}")
+set(FLANG_CONFIG_LLVM_CMAKE_DIR "\${FLANG_INSTALL_PREFIX}/${LLVM_INSTALL_PACKAGE_DIR}")
+set(FLANG_CONFIG_EXPORTS_FILE "\${FLANG_CMAKE_DIR}/FlangTargets.cmake")
+set(FLANG_CONFIG_INCLUDE_DIRS
+ "\${FLANG_INSTALL_PREFIX}/include"
+ )
+configure_file(
+ ${CMAKE_CURRENT_SOURCE_DIR}/FlangConfig.cmake.in
+ ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/FlangConfig.cmake
+ @ONLY)
+set(FLANG_CONFIG_CODE)
+set(FLANG_CONFIG_CMAKE_DIR)
+set(FLANG_CONFIG_EXPORTS_FILE)
+
+if (NOT LLVM_INSTALL_TOOLCHAIN_ONLY)
+ get_property(flang_has_exports GLOBAL PROPERTY FLANG_HAS_EXPORTS)
+ if(flang_has_exports)
+ install(EXPORT FlangTargets DESTINATION ${FLANG_INSTALL_PACKAGE_DIR})
+ endif()
+
+ install(FILES
+ ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/FlangConfig.cmake
+ DESTINATION ${FLANG_INSTALL_PACKAGE_DIR})
+endif()
--- /dev/null
+find_path(Z3_INCLUDE_DIR NAMES z3.h
+ PATH_SUFFIXES libz3 z3
+ )
+
+find_library(Z3_LIBRARIES NAMES z3 libz3
+ )
+
+find_program(Z3_EXECUTABLE z3)
+
+if(Z3_INCLUDE_DIR AND Z3_EXECUTABLE)
+ execute_process (COMMAND ${Z3_EXECUTABLE} -version
+ OUTPUT_VARIABLE libz3_version_str
+ ERROR_QUIET
+ OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+ string(REGEX REPLACE "^Z3 version ([0-9.]+)" "\\1"
+ Z3_VERSION_STRING "${libz3_version_str}")
+ unset(libz3_version_str)
+endif()
+
+# handle the QUIETLY and REQUIRED arguments and set Z3_FOUND to TRUE if
+# all listed variables are TRUE
+include(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(Z3
+ REQUIRED_VARS Z3_LIBRARIES Z3_INCLUDE_DIR
+ VERSION_VAR Z3_VERSION_STRING)
+
+mark_as_advanced(Z3_INCLUDE_DIR Z3_LIBRARIES)
--- /dev/null
+# This file allows users to call find_package(FLANG) and pick up our targets.
+
+@FLANG_CONFIG_CODE@
+
+find_package(LLVM REQUIRED CONFIG
+ HINTS "@FLANG_CONFIG_LLVM_CMAKE_DIR@")
+
+set(FLANG_EXPORTED_TARGETS "@FLANG_EXPORTS@")
+set(FLANG_CMAKE_DIR "@FLANG_CONFIG_CMAKE_DIR@")
+set(FLANG_INCLUDE_DIRS "@FLANG_CONFIG_INCLUDE_DIRS@")
+
+# Provide all our library targets to users.
+include("@FLANG_CONFIG_EXPORTS_FILE@")
--- /dev/null
+add_subdirectory(flang)
--- /dev/null
+# README: The content of the various .td tiles was copied verbatim from Clang.
+# The purpose is to show how TableGen can be used to create include files.
+# If we decide to reuse the same diagnostic infrastrure than Clang then the
+# .td files will eventually be adapted for Flang.
+# The directory .../clang/include/clang/Basic contains more examples.
+# The generated file can be found in .../build/include/flang/Basic/
+#
+
+macro(flang_diag_gen component)
+ flang_tablegen(Diagnostic${component}Kinds.inc
+ -gen-flang-diags-defs -flang-component=${component}
+ SOURCE Diagnostic.td
+ TARGET FlangDiagnostic${component})
+endmacro(flang_diag_gen)
+
+flang_diag_gen(Common)
+
+
--- /dev/null
+//===--- Diagnostic.td - C Language Family Diagnostic Handling ------------===//
+//
+// 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 TableGen core definitions for the diagnostics
+// and diagnostic control.
+//
+//===----------------------------------------------------------------------===//
+
+// See the Internals Manual, section The Diagnostics Subsystem for an overview.
+
+// Define the diagnostic severities.
+class Severity<string N> {
+ string Name = N;
+}
+def SEV_Ignored : Severity<"Ignored">;
+def SEV_Remark : Severity<"Remark">;
+def SEV_Warning : Severity<"Warning">;
+def SEV_Error : Severity<"Error">;
+def SEV_Fatal : Severity<"Fatal">;
+
+// Define the diagnostic classes.
+class DiagClass;
+def CLASS_NOTE : DiagClass;
+def CLASS_REMARK : DiagClass;
+def CLASS_WARNING : DiagClass;
+def CLASS_EXTENSION : DiagClass;
+def CLASS_ERROR : DiagClass;
+
+// Responses to a diagnostic in a SFINAE context.
+class SFINAEResponse;
+def SFINAE_SubstitutionFailure : SFINAEResponse;
+def SFINAE_Suppress : SFINAEResponse;
+def SFINAE_Report : SFINAEResponse;
+def SFINAE_AccessControl : SFINAEResponse;
+
+// Diagnostic Categories. These can be applied to groups or individual
+// diagnostics to specify a category.
+class DiagCategory<string Name> {
+ string CategoryName = Name;
+}
+
+// Diagnostic Groups.
+class DiagGroup<string Name, list<DiagGroup> subgroups = []> {
+ string GroupName = Name;
+ list<DiagGroup> SubGroups = subgroups;
+ string CategoryName = "";
+ code Documentation = [{}];
+}
+class InGroup<DiagGroup G> { DiagGroup Group = G; }
+//class IsGroup<string Name> { DiagGroup Group = DiagGroup<Name>; }
+
+// This defines documentation for diagnostic groups.
+include "DiagnosticDocs.td"
+
+// This defines all of the named diagnostic categories.
+include "DiagnosticCategories.td"
+
+// This defines all of the named diagnostic groups.
+include "DiagnosticGroups.td"
+
+
+// All diagnostics emitted by the compiler are an indirect subclass of this.
+class Diagnostic<string text, DiagClass DC, Severity defaultmapping> {
+ /// Component is specified by the file with a big let directive.
+ string Component = ?;
+ string Text = text;
+ DiagClass Class = DC;
+ SFINAEResponse SFINAE = SFINAE_Suppress;
+ bit AccessControl = 0;
+ bit WarningNoWerror = 0;
+ bit ShowInSystemHeader = 0;
+ Severity DefaultSeverity = defaultmapping;
+ DiagGroup Group;
+ string CategoryName = "";
+}
+
+class SFINAEFailure {
+ SFINAEResponse SFINAE = SFINAE_SubstitutionFailure;
+}
+class NoSFINAE {
+ SFINAEResponse SFINAE = SFINAE_Report;
+}
+class AccessControl {
+ SFINAEResponse SFINAE = SFINAE_AccessControl;
+}
+
+class ShowInSystemHeader {
+ bit ShowInSystemHeader = 1;
+}
+
+class SuppressInSystemHeader {
+ bit ShowInSystemHeader = 0;
+}
+
+// FIXME: ExtWarn and Extension should also be SFINAEFailure by default.
+class Error<string str> : Diagnostic<str, CLASS_ERROR, SEV_Error>, SFINAEFailure {
+ bit ShowInSystemHeader = 1;
+}
+// Warnings default to on (but can be default-off'd with DefaultIgnore).
+// This is used for warnings about questionable code; warnings about
+// accepted language extensions should use Extension or ExtWarn below instead.
+class Warning<string str> : Diagnostic<str, CLASS_WARNING, SEV_Warning>;
+// Remarks can be turned on with -R flags and provide commentary, e.g. on
+// optimizer decisions.
+class Remark<string str> : Diagnostic<str, CLASS_REMARK, SEV_Ignored>;
+// Extensions are warnings about accepted language extensions.
+// Extension warnings are default-off but enabled by -pedantic.
+class Extension<string str> : Diagnostic<str, CLASS_EXTENSION, SEV_Ignored>;
+// ExtWarns are warnings about accepted language extensions.
+// ExtWarn warnings are default-on.
+class ExtWarn<string str> : Diagnostic<str, CLASS_EXTENSION, SEV_Warning>;
+// Notes can provide supplementary information on errors, warnings, and remarks.
+class Note<string str> : Diagnostic<str, CLASS_NOTE, SEV_Fatal/*ignored*/>;
+
+
+class DefaultIgnore { Severity DefaultSeverity = SEV_Ignored; }
+class DefaultWarn { Severity DefaultSeverity = SEV_Warning; }
+class DefaultError { Severity DefaultSeverity = SEV_Error; }
+class DefaultFatal { Severity DefaultSeverity = SEV_Fatal; }
+class DefaultWarnNoWerror {
+ bit WarningNoWerror = 1;
+}
+class DefaultRemark { Severity DefaultSeverity = SEV_Remark; }
+
+// Definitions for Diagnostics.
+//include "DiagnosticASTKinds.td"
+//include "DiagnosticAnalysisKinds.td"
+//include "DiagnosticCommentKinds.td"
+include "DiagnosticCommonKinds.td"
+//include "DiagnosticDriverKinds.td"
+//include "DiagnosticFrontendKinds.td"
+//include "DiagnosticLexKinds.td"
+//include "DiagnosticParseKinds.td"
+//include "DiagnosticSemaKinds.td"
+//include "DiagnosticSerializationKinds.td"
+
--- /dev/null
+//==--- DiagnosticCategories.td - Diagnostic Category Definitions ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+class CatInlineAsm : DiagCategory<"Inline Assembly Issue">;
+class CatBackend : DiagCategory<"Backend Issue">;
--- /dev/null
+//==--- DiagnosticCommonKinds.td - common diagnostics ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+//===----------------------------------------------------------------------===//
+// Common Helpers
+//===----------------------------------------------------------------------===//
+
+let Component = "Common" in {
+
+// Basic.
+
+def fatal_too_many_errors
+ : Error<"too many errors emitted, stopping now">, DefaultFatal;
+
+def note_declared_at : Note<"declared here">;
+def note_previous_definition : Note<"previous definition is here">;
+def note_previous_declaration : Note<"previous declaration is here">;
+def note_previous_implicit_declaration : Note<
+ "previous implicit declaration is here">;
+def note_previous_use : Note<"previous use is here">;
+def note_duplicate_case_prev : Note<"previous case defined here">;
+def note_forward_declaration : Note<"forward declaration of %0">;
+def note_type_being_defined : Note<
+ "definition of %0 is not complete until the closing '}'">;
+/// note_matching - this is used as a continuation of a previous diagnostic,
+/// e.g. to specify the '(' when we expected a ')'.
+def note_matching : Note<"to match this %0">;
+
+def note_using : Note<"using">;
+def note_possibility : Note<"one possibility">;
+def note_also_found : Note<"also found">;
+
+// Parse && Lex
+
+let CategoryName = "Lexical or Preprocessor Issue" in {
+
+def err_expected_colon_after_setter_name : Error<
+ "method name referenced in property setter attribute "
+ "must end with ':'">;
+def err_expected_string_literal : Error<"expected string literal "
+ "%select{in %1|for diagnostic message in static_assert|"
+ "for optional message in 'availability' attribute|"
+ "for %select{language|source container}1 name in "
+ "'external_source_symbol' attribute}0">;
+def err_invalid_string_udl : Error<
+ "string literal with user-defined suffix cannot be used here">;
+def err_invalid_character_udl : Error<
+ "character literal with user-defined suffix cannot be used here">;
+def err_invalid_numeric_udl : Error<
+ "numeric literal with user-defined suffix cannot be used here">;
+
+}
+
+// Parse && Sema
+
+let CategoryName = "Parse Issue" in {
+
+def err_expected : Error<"expected %0">;
+def err_expected_either : Error<"expected %0 or %1">;
+def err_expected_after : Error<"expected %1 after %0">;
+
+def err_param_redefinition : Error<"redefinition of parameter %0">;
+def warn_method_param_redefinition : Warning<"redefinition of method parameter %0">;
+def warn_method_param_declaration : Warning<"redeclaration of method parameter %0">,
+ InGroup<DuplicateArgDecl>, DefaultIgnore;
+def err_invalid_storage_class_in_func_decl : Error<
+ "invalid storage class specifier in function declarator">;
+def err_expected_namespace_name : Error<"expected namespace name">;
+def ext_variadic_templates : ExtWarn<
+ "variadic templates are a C++11 extension">, InGroup<CXX11>;
+def warn_cxx98_compat_variadic_templates :
+ Warning<"variadic templates are incompatible with C++98">,
+ InGroup<CXX98Compat>, DefaultIgnore;
+def err_default_special_members : Error<
+ "only special member functions may be defaulted">;
+def err_deleted_non_function : Error<
+ "only functions can have deleted definitions">;
+def err_module_not_found : Error<"module '%0' not found">, DefaultFatal;
+def err_module_not_built : Error<"could not build module '%0'">, DefaultFatal;
+def err_module_build_disabled: Error<
+ "module '%0' is needed but has not been provided, and implicit use of module "
+ "files is disabled">, DefaultFatal;
+def err_module_unavailable : Error<
+ "module '%0' %select{is incompatible with|requires}1 feature '%2'">;
+def err_module_header_missing : Error<
+ "%select{|umbrella }0header '%1' not found">;
+def remark_module_lock_failure : Remark<
+ "could not acquire lock file for module '%0': %1">, InGroup<ModuleBuild>;
+def remark_module_lock_timeout : Remark<
+ "timed out waiting to acquire lock file for module '%0'">, InGroup<ModuleBuild>;
+def err_module_cycle : Error<"cyclic dependency in module '%0': %1">,
+ DefaultFatal;
+def err_module_prebuilt : Error<
+ "error in loading module '%0' from prebuilt module path">, DefaultFatal;
+def note_pragma_entered_here : Note<"#pragma entered here">;
+def note_decl_hiding_tag_type : Note<
+ "%1 %0 is hidden by a non-type declaration of %0 here">;
+def err_attribute_not_type_attr : Error<
+ "%0 attribute cannot be applied to types">;
+def err_enum_template : Error<"enumeration cannot be a template">;
+
+}
+
+let CategoryName = "Nullability Issue" in {
+
+def warn_nullability_duplicate : Warning<
+ "duplicate nullability specifier %0">,
+ InGroup<Nullability>;
+
+def warn_conflicting_nullability_attr_overriding_ret_types : Warning<
+ "conflicting nullability specifier on return types, %0 "
+ "conflicts with existing specifier %1">,
+ InGroup<Nullability>;
+
+def warn_conflicting_nullability_attr_overriding_param_types : Warning<
+ "conflicting nullability specifier on parameter types, %0 "
+ "conflicts with existing specifier %1">,
+ InGroup<Nullability>;
+
+def err_nullability_conflicting : Error<
+ "nullability specifier %0 conflicts with existing specifier %1">;
+
+}
+
+// Sema && Lex
+def ext_c99_longlong : Extension<
+ "'long long' is an extension when C99 mode is not enabled">,
+ InGroup<LongLong>;
+def ext_cxx11_longlong : Extension<
+ "'long long' is a C++11 extension">,
+ InGroup<CXX11LongLong>;
+def warn_cxx98_compat_longlong : Warning<
+ "'long long' is incompatible with C++98">,
+ InGroup<CXX98CompatPedantic>, DefaultIgnore;
+def err_integer_literal_too_large : Error<
+ "integer literal is too large to be represented in any %select{signed |}0"
+ "integer type">;
+def ext_integer_literal_too_large_for_signed : ExtWarn<
+ "integer literal is too large to be represented in a signed integer type, "
+ "interpreting as unsigned">,
+ InGroup<ImplicitlyUnsignedLiteral>;
+def warn_old_implicitly_unsigned_long : Warning<
+ "integer literal is too large to be represented in type 'long', "
+ "interpreting as 'unsigned long' per C89; this literal will "
+ "%select{have type 'long long'|be ill-formed}0 in C99 onwards">,
+ InGroup<C99Compat>;
+def warn_old_implicitly_unsigned_long_cxx : Warning<
+ "integer literal is too large to be represented in type 'long', "
+ "interpreting as 'unsigned long' per C++98; this literal will "
+ "%select{have type 'long long'|be ill-formed}0 in C++11 onwards">,
+ InGroup<CXX11Compat>;
+def ext_old_implicitly_unsigned_long_cxx : ExtWarn<
+ "integer literal is too large to be represented in type 'long' and is "
+ "subject to undefined behavior under C++98, interpreting as 'unsigned long'; "
+ "this literal will %select{have type 'long long'|be ill-formed}0 "
+ "in C++11 onwards">,
+ InGroup<CXX11Compat>;
+def ext_clang_enable_if : Extension<"'enable_if' is a clang extension">,
+ InGroup<GccCompat>;
+def ext_clang_diagnose_if : Extension<"'diagnose_if' is a clang extension">,
+ InGroup<GccCompat>;
+
+// SEH
+def err_seh_expected_handler : Error<
+ "expected '__except' or '__finally' block">;
+def err_seh___except_block : Error<
+ "%0 only allowed in __except block or filter expression">;
+def err_seh___except_filter : Error<
+ "%0 only allowed in __except filter expression">;
+def err_seh___finally_block : Error<
+ "%0 only allowed in __finally block">;
+
+// Sema && AST
+def note_invalid_subexpr_in_const_expr : Note<
+ "subexpression not valid in a constant expression">;
+
+// Targets
+
+def err_target_unknown_triple : Error<
+ "unknown target triple '%0', please use -triple or -arch">;
+def err_target_unknown_cpu : Error<"unknown target CPU '%0'">;
+def err_target_unknown_abi : Error<"unknown target ABI '%0'">;
+def err_target_unsupported_abi : Error<"ABI '%0' is not supported on CPU '%1'">;
+def err_target_unsupported_abi_for_triple : Error<
+ "ABI '%0' is not supported for '%1'">;
+def err_target_unknown_fpmath : Error<"unknown FP unit '%0'">;
+def err_target_unsupported_fpmath : Error<
+ "the '%0' unit is not supported with this instruction set">;
+def err_target_unsupported_unaligned : Error<
+ "the %0 sub-architecture does not support unaligned accesses">;
+def err_target_unsupported_execute_only : Error<
+ "execute only is not supported for the %0 sub-architecture">;
+def err_opt_not_valid_with_opt : Error<
+ "option '%0' cannot be specified with '%1'">;
+
+// Source manager
+def err_cannot_open_file : Error<"cannot open file '%0': %1">, DefaultFatal;
+def err_file_modified : Error<
+ "file '%0' modified since it was first processed">, DefaultFatal;
+def err_unsupported_bom : Error<"%0 byte order mark detected in '%1', but "
+ "encoding is not supported">, DefaultFatal;
+def err_unable_to_rename_temp : Error<
+ "unable to rename temporary '%0' to output file '%1': '%2'">;
+def err_unable_to_make_temp : Error<
+ "unable to make temporary file: %0">;
+
+// Modules
+def err_module_format_unhandled : Error<
+ "no handler registered for module format '%0'">, DefaultFatal;
+
+// TransformActions
+// TODO: Use a custom category name to distinguish rewriter errors.
+def err_mt_message : Error<"[rewriter] %0">, SuppressInSystemHeader;
+def warn_mt_message : Warning<"[rewriter] %0">;
+def note_mt_message : Note<"[rewriter] %0">;
+
+// ARCMigrate
+def warn_arcmt_nsalloc_realloc : Warning<"[rewriter] call returns pointer to GC managed memory; it will become unmanaged in ARC">;
+def err_arcmt_nsinvocation_ownership : Error<"NSInvocation's %0 is not safe to be used with an object with ownership other than __unsafe_unretained">;
+
+// OpenMP
+def err_omp_more_one_clause : Error<
+ "directive '#pragma omp %0' cannot contain more than one '%1' clause%select{| with '%3' name modifier| with 'source' dependence}2">;
+}
--- /dev/null
+//==--- DiagnosticDocs.td - Diagnostic documentation ---------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+def GlobalDocumentation {
+ code Intro =[{..
+ -------------------------------------------------------------------
+ NOTE: This file is automatically generated by running clang-tblgen
+ -gen-diag-docs. Do not edit this file by hand!!
+ -------------------------------------------------------------------
+
+.. Add custom CSS to output. FIXME: This should be put into <head> rather
+ than the start of <body>.
+.. raw:: html
+
+ <style>
+ table.docutils {
+ width: 1px;
+ }
+ table.docutils td {
+ border: none;
+ padding: 0 0 0 0.2em;
+ vertical-align: middle;
+ white-space: nowrap;
+ width: 1px;
+ font-family: monospace;
+ }
+ table.docutils tr + tr {
+ border-top: 0.2em solid #aaa;
+ }
+ .error {
+ font-family: monospace;
+ font-weight: bold;
+ color: #c00;
+ }
+ .warning {
+ font-family: monospace;
+ font-weight: bold;
+ color: #80a;
+ }
+ .remark {
+ font-family: monospace;
+ font-weight: bold;
+ color: #00c;
+ }
+ .diagtext {
+ font-family: monospace;
+ font-weight: bold;
+ }
+ </style>
+
+.. FIXME: rST doesn't support formatting this, so we format all <td> elements
+ as monospace font face instead.
+.. |nbsp| unicode:: 0xA0
+ :trim:
+
+.. Roles generated by clang-tblgen.
+.. role:: error
+.. role:: warning
+.. role:: remark
+.. role:: diagtext
+.. role:: placeholder(emphasis)
+
+=========================
+Diagnostic flags in Clang
+=========================
+.. contents::
+ :local:
+
+Introduction
+============
+
+This page lists the diagnostic flags currently supported by Clang.
+
+Diagnostic flags
+================
+}];
+}
+
--- /dev/null
+//==--- DiagnosticGroups.td - Diagnostic Group Definitions ----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+def ImplicitFunctionDeclare : DiagGroup<"implicit-function-declaration">;
+def ImplicitInt : DiagGroup<"implicit-int">;
+
+// Aggregation warning settings.
+def Implicit : DiagGroup<"implicit", [
+ ImplicitFunctionDeclare,
+ ImplicitInt
+]>;
+
+// Empty DiagGroups are recognized by clang but ignored.
+def : DiagGroup<"abi">;
+def AbsoluteValue : DiagGroup<"absolute-value">;
+def AddressOfTemporary : DiagGroup<"address-of-temporary">;
+def : DiagGroup<"aggregate-return">;
+def GNUAlignofExpression : DiagGroup<"gnu-alignof-expression">;
+def AmbigMemberTemplate : DiagGroup<"ambiguous-member-template">;
+def GNUAnonymousStruct : DiagGroup<"gnu-anonymous-struct">;
+def GNUAutoType : DiagGroup<"gnu-auto-type">;
+def ArrayBounds : DiagGroup<"array-bounds">;
+def ArrayBoundsPointerArithmetic : DiagGroup<"array-bounds-pointer-arithmetic">;
+def Availability : DiagGroup<"availability">;
+def Section : DiagGroup<"section">;
+def AutoImport : DiagGroup<"auto-import">;
+def CXX14BinaryLiteral : DiagGroup<"c++14-binary-literal">;
+def GNUBinaryLiteral : DiagGroup<"gnu-binary-literal">;
+def GNUCompoundLiteralInitializer : DiagGroup<"gnu-compound-literal-initializer">;
+def BitFieldConstantConversion : DiagGroup<"bitfield-constant-conversion">;
+def BitFieldEnumConversion : DiagGroup<"bitfield-enum-conversion">;
+def BitFieldWidth : DiagGroup<"bitfield-width">;
+def CoroutineMissingUnhandledException :
+ DiagGroup<"coroutine-missing-unhandled-exception">;
+def Coroutine : DiagGroup<"coroutine", [CoroutineMissingUnhandledException]>;
+def ConstantConversion :
+ DiagGroup<"constant-conversion", [ BitFieldConstantConversion ] >;
+def LiteralConversion : DiagGroup<"literal-conversion">;
+def StringConversion : DiagGroup<"string-conversion">;
+def SignConversion : DiagGroup<"sign-conversion">;
+def PointerBoolConversion : DiagGroup<"pointer-bool-conversion">;
+def UndefinedBoolConversion : DiagGroup<"undefined-bool-conversion">;
+def BoolConversion : DiagGroup<"bool-conversion", [PointerBoolConversion,
+ UndefinedBoolConversion]>;
+def IntConversion : DiagGroup<"int-conversion">;
+def EnumConversion : DiagGroup<"enum-conversion">;
+
+def FloatOverflowConversion : DiagGroup<"float-overflow-conversion">;
+def FloatZeroConversion : DiagGroup<"float-zero-conversion">;
+def FloatConversion :
+ DiagGroup<"float-conversion", [FloatOverflowConversion,
+ FloatZeroConversion]>;
+
+def DoublePromotion : DiagGroup<"double-promotion">;
+def EnumTooLarge : DiagGroup<"enum-too-large">;
+def UnsupportedNan : DiagGroup<"unsupported-nan">;
+def UnsupportedCB : DiagGroup<"unsupported-cb">;
+def NonLiteralNullConversion : DiagGroup<"non-literal-null-conversion">;
+def NullConversion : DiagGroup<"null-conversion">;
+def ImplicitConversionFloatingPointToBool :
+ DiagGroup<"implicit-conversion-floating-point-to-bool">;
+def ObjCLiteralConversion : DiagGroup<"objc-literal-conversion">;
+def MacroRedefined : DiagGroup<"macro-redefined">;
+def BuiltinMacroRedefined : DiagGroup<"builtin-macro-redefined">;
+def BuiltinRequiresHeader : DiagGroup<"builtin-requires-header">;
+def C99Compat : DiagGroup<"c99-compat">;
+def CXXCompat: DiagGroup<"c++-compat">;
+def ExternCCompat : DiagGroup<"extern-c-compat">;
+def KeywordCompat : DiagGroup<"keyword-compat">;
+def GNUCaseRange : DiagGroup<"gnu-case-range">;
+def CastAlign : DiagGroup<"cast-align">;
+def CastQual : DiagGroup<"cast-qual">;
+def : DiagGroup<"char-align">;
+def Comment : DiagGroup<"comment">;
+def GNUComplexInteger : DiagGroup<"gnu-complex-integer">;
+def GNUConditionalOmittedOperand : DiagGroup<"gnu-conditional-omitted-operand">;
+def ConfigMacros : DiagGroup<"config-macros">;
+def : DiagGroup<"ctor-dtor-privacy">;
+def GNUDesignator : DiagGroup<"gnu-designator">;
+def GNUStringLiteralOperatorTemplate :
+ DiagGroup<"gnu-string-literal-operator-template">;
+def UndefinedVarTemplate : DiagGroup<"undefined-var-template">;
+def UndefinedFuncTemplate : DiagGroup<"undefined-func-template">;
+
+def DeleteIncomplete : DiagGroup<"delete-incomplete">;
+def DeleteNonVirtualDtor : DiagGroup<"delete-non-virtual-dtor">;
+def AbstractFinalClass : DiagGroup<"abstract-final-class">;
+
+def CXX11CompatDeprecatedWritableStr :
+ DiagGroup<"c++11-compat-deprecated-writable-strings">;
+
+def DeprecatedAttributes : DiagGroup<"deprecated-attributes">;
+def DeprecatedDeclarations : DiagGroup<"deprecated-declarations">;
+def UnavailableDeclarations : DiagGroup<"unavailable-declarations">;
+def UnguardedAvailabilityNew : DiagGroup<"unguarded-availability-new">;
+def UnguardedAvailability : DiagGroup<"unguarded-availability",
+ [UnguardedAvailabilityNew]>;
+// partial-availability is an alias of unguarded-availability.
+def : DiagGroup<"partial-availability", [UnguardedAvailability]>;
+def DeprecatedDynamicExceptionSpec
+ : DiagGroup<"deprecated-dynamic-exception-spec">;
+def DeprecatedImplementations :DiagGroup<"deprecated-implementations">;
+def DeprecatedIncrementBool : DiagGroup<"deprecated-increment-bool">;
+def DeprecatedRegister : DiagGroup<"deprecated-register">;
+def DeprecatedWritableStr : DiagGroup<"deprecated-writable-strings",
+ [CXX11CompatDeprecatedWritableStr]>;
+// FIXME: Why is DeprecatedImplementations not in this group?
+def Deprecated : DiagGroup<"deprecated", [DeprecatedAttributes,
+ DeprecatedDeclarations,
+ DeprecatedDynamicExceptionSpec,
+ DeprecatedIncrementBool,
+ DeprecatedRegister,
+ DeprecatedWritableStr]>,
+ DiagCategory<"Deprecations">;
+
+def DynamicExceptionSpec
+ : DiagGroup<"dynamic-exception-spec", [DeprecatedDynamicExceptionSpec]>;
+
+def LibLTO : DiagGroup<"liblto">;
+def : DiagGroup<"disabled-optimization">;
+def : DiagGroup<"discard-qual">;
+def DivZero : DiagGroup<"division-by-zero">;
+def : DiagGroup<"div-by-zero", [DivZero]>;
+
+def DocumentationHTML : DiagGroup<"documentation-html">;
+def DocumentationUnknownCommand : DiagGroup<"documentation-unknown-command">;
+def DocumentationPedantic : DiagGroup<"documentation-pedantic",
+ [DocumentationUnknownCommand]>;
+def DocumentationDeprecatedSync : DiagGroup<"documentation-deprecated-sync">;
+def Documentation : DiagGroup<"documentation",
+ [DocumentationHTML,
+ DocumentationDeprecatedSync]>;
+
+def EmptyBody : DiagGroup<"empty-body">;
+def Exceptions : DiagGroup<"exceptions">;
+
+def GNUEmptyInitializer : DiagGroup<"gnu-empty-initializer">;
+def GNUEmptyStruct : DiagGroup<"gnu-empty-struct">;
+def ExtraTokens : DiagGroup<"extra-tokens">;
+def CXX11ExtraSemi : DiagGroup<"c++11-extra-semi">;
+def ExtraSemi : DiagGroup<"extra-semi", [CXX11ExtraSemi]>;
+
+def GNUFlexibleArrayInitializer : DiagGroup<"gnu-flexible-array-initializer">;
+def GNUFlexibleArrayUnionMember : DiagGroup<"gnu-flexible-array-union-member">;
+def GNUFoldingConstant : DiagGroup<"gnu-folding-constant">;
+def FormatExtraArgs : DiagGroup<"format-extra-args">;
+def FormatZeroLength : DiagGroup<"format-zero-length">;
+
+def InvalidIOSDeploymentTarget : DiagGroup<"invalid-ios-deployment-target">;
+
+def CXX17CompatMangling : DiagGroup<"c++17-compat-mangling">;
+def : DiagGroup<"c++1z-compat-mangling", [CXX17CompatMangling]>;
+// Name of this warning in GCC.
+def NoexceptType : DiagGroup<"noexcept-type", [CXX17CompatMangling]>;
+
+// Warnings for C++1y code which is not compatible with prior C++ standards.
+def CXXPre14Compat : DiagGroup<"c++98-c++11-compat">;
+def CXXPre14CompatPedantic : DiagGroup<"c++98-c++11-compat-pedantic",
+ [CXXPre14Compat]>;
+def CXXPre1zCompat : DiagGroup<"c++98-c++11-c++14-compat">;
+def CXXPre1zCompatPedantic : DiagGroup<"c++98-c++11-c++14-compat-pedantic",
+ [CXXPre1zCompat]>;
+
+def CXX98CompatBindToTemporaryCopy :
+ DiagGroup<"c++98-compat-bind-to-temporary-copy">;
+def CXX98CompatLocalTypeTemplateArgs :
+ DiagGroup<"c++98-compat-local-type-template-args">;
+def CXX98CompatUnnamedTypeTemplateArgs :
+ DiagGroup<"c++98-compat-unnamed-type-template-args">;
+
+def CXX98Compat : DiagGroup<"c++98-compat",
+ [CXX98CompatLocalTypeTemplateArgs,
+ CXX98CompatUnnamedTypeTemplateArgs,
+ CXXPre14Compat,
+ CXXPre1zCompat]>;
+// Warnings for C++11 features which are Extensions in C++98 mode.
+def CXX98CompatPedantic : DiagGroup<"c++98-compat-pedantic",
+ [CXX98Compat,
+ CXX98CompatBindToTemporaryCopy,
+ CXXPre14CompatPedantic,
+ CXXPre1zCompatPedantic]>;
+
+def CXX11Narrowing : DiagGroup<"c++11-narrowing">;
+
+def CXX11WarnOverrideDestructor :
+ DiagGroup<"inconsistent-missing-destructor-override">;
+def CXX11WarnOverrideMethod : DiagGroup<"inconsistent-missing-override">;
+
+// Original name of this warning in Clang
+def : DiagGroup<"c++0x-narrowing", [CXX11Narrowing]>;
+
+// Name of this warning in GCC
+def : DiagGroup<"narrowing", [CXX11Narrowing]>;
+
+def CXX11CompatReservedUserDefinedLiteral :
+ DiagGroup<"c++11-compat-reserved-user-defined-literal">;
+def ReservedUserDefinedLiteral :
+ DiagGroup<"reserved-user-defined-literal",
+ [CXX11CompatReservedUserDefinedLiteral]>;
+
+def CXX11Compat : DiagGroup<"c++11-compat",
+ [CXX11Narrowing,
+ CXX11CompatReservedUserDefinedLiteral,
+ CXX11CompatDeprecatedWritableStr,
+ CXXPre14Compat,
+ CXXPre1zCompat]>;
+def : DiagGroup<"c++0x-compat", [CXX11Compat]>;
+def CXX11CompatPedantic : DiagGroup<"c++11-compat-pedantic",
+ [CXXPre14CompatPedantic,
+ CXXPre1zCompatPedantic]>;
+
+def CXX14Compat : DiagGroup<"c++14-compat", [CXXPre1zCompat]>;
+def CXX14CompatPedantic : DiagGroup<"c++14-compat-pedantic",
+ [CXXPre1zCompatPedantic]>;
+
+def CXX17Compat : DiagGroup<"c++17-compat", [DeprecatedRegister,
+ DeprecatedIncrementBool,
+ CXX17CompatMangling]>;
+def : DiagGroup<"c++1z-compat", [CXX17Compat]>;
+
+def ExitTimeDestructors : DiagGroup<"exit-time-destructors">;
+def FlexibleArrayExtensions : DiagGroup<"flexible-array-extensions">;
+def FourByteMultiChar : DiagGroup<"four-char-constants">;
+def GlobalConstructors : DiagGroup<"global-constructors">;
+def BitwiseOpParentheses: DiagGroup<"bitwise-op-parentheses">;
+def LogicalOpParentheses: DiagGroup<"logical-op-parentheses">;
+def LogicalNotParentheses: DiagGroup<"logical-not-parentheses">;
+def ShiftOpParentheses: DiagGroup<"shift-op-parentheses">;
+def OverloadedShiftOpParentheses: DiagGroup<"overloaded-shift-op-parentheses">;
+def DanglingElse: DiagGroup<"dangling-else">;
+def DanglingField : DiagGroup<"dangling-field">;
+def DistributedObjectModifiers : DiagGroup<"distributed-object-modifiers">;
+def ExpansionToDefined : DiagGroup<"expansion-to-defined">;
+def FlagEnum : DiagGroup<"flag-enum">;
+def IncrementBool : DiagGroup<"increment-bool", [DeprecatedIncrementBool]>;
+def InfiniteRecursion : DiagGroup<"infinite-recursion">;
+def GNUImaginaryConstant : DiagGroup<"gnu-imaginary-constant">;
+def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">;
+def : DiagGroup<"import">;
+def GNUIncludeNext : DiagGroup<"gnu-include-next">;
+def IncompatibleMSStruct : DiagGroup<"incompatible-ms-struct">;
+def IncompatiblePointerTypesDiscardsQualifiers
+ : DiagGroup<"incompatible-pointer-types-discards-qualifiers">;
+def IncompatibleFunctionPointerTypes
+ : DiagGroup<"incompatible-function-pointer-types">;
+def IncompatiblePointerTypes
+ : DiagGroup<"incompatible-pointer-types",
+ [IncompatiblePointerTypesDiscardsQualifiers,
+ IncompatibleFunctionPointerTypes]>;
+def IncompleteUmbrella : DiagGroup<"incomplete-umbrella">;
+def NonModularIncludeInFrameworkModule
+ : DiagGroup<"non-modular-include-in-framework-module">;
+def NonModularIncludeInModule : DiagGroup<"non-modular-include-in-module",
+ [NonModularIncludeInFrameworkModule]>;
+def IncompleteModule : DiagGroup<"incomplete-module",
+ [IncompleteUmbrella, NonModularIncludeInModule]>;
+def PrivateModule : DiagGroup<"private-module">;
+
+def CXX11InlineNamespace : DiagGroup<"c++11-inline-namespace">;
+def InvalidNoreturn : DiagGroup<"invalid-noreturn">;
+def InvalidSourceEncoding : DiagGroup<"invalid-source-encoding">;
+def KNRPromotedParameter : DiagGroup<"knr-promoted-parameter">;
+def : DiagGroup<"init-self">;
+def : DiagGroup<"inline">;
+def : DiagGroup<"invalid-pch">;
+def GNULabelsAsValue : DiagGroup<"gnu-label-as-value">;
+def LiteralRange : DiagGroup<"literal-range">;
+def LocalTypeTemplateArgs : DiagGroup<"local-type-template-args",
+ [CXX98CompatLocalTypeTemplateArgs]>;
+def RangeLoopAnalysis : DiagGroup<"range-loop-analysis">;
+def ForLoopAnalysis : DiagGroup<"for-loop-analysis">;
+def LoopAnalysis : DiagGroup<"loop-analysis", [ForLoopAnalysis,
+ RangeLoopAnalysis]>;
+def MalformedWarningCheck : DiagGroup<"malformed-warning-check">;
+def Main : DiagGroup<"main">;
+def MainReturnType : DiagGroup<"main-return-type">;
+def MaxUnsignedZero : DiagGroup<"max-unsigned-zero">;
+def MissingBraces : DiagGroup<"missing-braces">;
+def MissingDeclarations: DiagGroup<"missing-declarations">;
+def : DiagGroup<"missing-format-attribute">;
+def : DiagGroup<"missing-include-dirs">;
+def MissingNoreturn : DiagGroup<"missing-noreturn">;
+def MultiChar : DiagGroup<"multichar">;
+def : DiagGroup<"nested-externs">;
+def CXX11LongLong : DiagGroup<"c++11-long-long">;
+def LongLong : DiagGroup<"long-long", [CXX11LongLong]>;
+def ImplicitlyUnsignedLiteral : DiagGroup<"implicitly-unsigned-literal">;
+def MethodSignatures : DiagGroup<"method-signatures">;
+def MismatchedParameterTypes : DiagGroup<"mismatched-parameter-types">;
+def MismatchedReturnTypes : DiagGroup<"mismatched-return-types">;
+def MismatchedTags : DiagGroup<"mismatched-tags">;
+def MissingFieldInitializers : DiagGroup<"missing-field-initializers">;
+def ModuleBuild : DiagGroup<"module-build">;
+def ModuleConflict : DiagGroup<"module-conflict">;
+def ModuleFileExtension : DiagGroup<"module-file-extension">;
+def NewlineEOF : DiagGroup<"newline-eof">;
+def Nullability : DiagGroup<"nullability">;
+def NullabilityDeclSpec : DiagGroup<"nullability-declspec">;
+def NullabilityInferredOnNestedType : DiagGroup<"nullability-inferred-on-nested-type">;
+def NullableToNonNullConversion : DiagGroup<"nullable-to-nonnull-conversion">;
+def NullabilityCompletenessOnArrays : DiagGroup<"nullability-completeness-on-arrays">;
+def NullabilityCompleteness : DiagGroup<"nullability-completeness",
+ [NullabilityCompletenessOnArrays]>;
+def NullArithmetic : DiagGroup<"null-arithmetic">;
+def NullCharacter : DiagGroup<"null-character">;
+def NullDereference : DiagGroup<"null-dereference">;
+def InitializerOverrides : DiagGroup<"initializer-overrides">;
+def NonNull : DiagGroup<"nonnull">;
+def NonPODVarargs : DiagGroup<"non-pod-varargs">;
+def ClassVarargs : DiagGroup<"class-varargs", [NonPODVarargs]>;
+def : DiagGroup<"nonportable-cfstrings">;
+def NonVirtualDtor : DiagGroup<"non-virtual-dtor">;
+def : DiagGroup<"effc++", [NonVirtualDtor]>;
+def OveralignedType : DiagGroup<"over-aligned">;
+def AlignedAllocationUnavailable : DiagGroup<"aligned-allocation-unavailable">;
+def OldStyleCast : DiagGroup<"old-style-cast">;
+def : DiagGroup<"old-style-definition">;
+def OutOfLineDeclaration : DiagGroup<"out-of-line-declaration">;
+def : DiagGroup<"overflow">;
+def ForwardClassReceiver : DiagGroup<"receiver-forward-class">;
+def MethodAccess : DiagGroup<"objc-method-access">;
+def ObjCReceiver : DiagGroup<"receiver-expr">;
+def OperatorNewReturnsNull : DiagGroup<"new-returns-null">;
+def OverlengthStrings : DiagGroup<"overlength-strings">;
+def OverloadedVirtual : DiagGroup<"overloaded-virtual">;
+def PrivateExtern : DiagGroup<"private-extern">;
+def SelTypeCast : DiagGroup<"cast-of-sel-type">;
+def FunctionDefInObjCContainer : DiagGroup<"function-def-in-objc-container">;
+def BadFunctionCast : DiagGroup<"bad-function-cast">;
+def ObjCPropertyImpl : DiagGroup<"objc-property-implementation">;
+def ObjCPropertyNoAttribute : DiagGroup<"objc-property-no-attribute">;
+def ObjCProtocolQualifiers : DiagGroup<"objc-protocol-qualifiers">;
+def ObjCMissingSuperCalls : DiagGroup<"objc-missing-super-calls">;
+def ObjCDesignatedInit : DiagGroup<"objc-designated-initializers">;
+def ObjCRetainBlockProperty : DiagGroup<"objc-noncopy-retain-block-property">;
+def ObjCReadonlyPropertyHasSetter : DiagGroup<"objc-readonly-with-setter-property">;
+def ObjCInvalidIBOutletProperty : DiagGroup<"invalid-iboutlet">;
+def ObjCRootClass : DiagGroup<"objc-root-class">;
+def ObjCPointerIntrospectPerformSelector : DiagGroup<"deprecated-objc-pointer-introspection-performSelector">;
+def ObjCPointerIntrospect : DiagGroup<"deprecated-objc-pointer-introspection", [ObjCPointerIntrospectPerformSelector]>;
+def ObjCMultipleMethodNames : DiagGroup<"objc-multiple-method-names">;
+def OpenCLUnsupportedRGBA: DiagGroup<"opencl-unsupported-rgba">;
+def DeprecatedObjCIsaUsage : DiagGroup<"deprecated-objc-isa-usage">;
+def ExplicitInitializeCall : DiagGroup<"explicit-initialize-call">;
+def Packed : DiagGroup<"packed">;
+def Padded : DiagGroup<"padded">;
+def PessimizingMove : DiagGroup<"pessimizing-move">;
+def PointerArith : DiagGroup<"pointer-arith">;
+def PoundWarning : DiagGroup<"#warnings">;
+def PoundPragmaMessage : DiagGroup<"#pragma-messages">,
+ DiagCategory<"#pragma message Directive">;
+def : DiagGroup<"pointer-to-int-cast">;
+def : DiagGroup<"redundant-decls">;
+def RedeclaredClassMember : DiagGroup<"redeclared-class-member">;
+def GNURedeclaredEnum : DiagGroup<"gnu-redeclared-enum">;
+def RedundantMove : DiagGroup<"redundant-move">;
+def Register : DiagGroup<"register", [DeprecatedRegister]>;
+def ReturnStackAddress : DiagGroup<"return-stack-address">;
+def ReturnTypeCLinkage : DiagGroup<"return-type-c-linkage">;
+def ReturnType : DiagGroup<"return-type", [ReturnTypeCLinkage]>;
+def BindToTemporaryCopy : DiagGroup<"bind-to-temporary-copy",
+ [CXX98CompatBindToTemporaryCopy]>;
+def SelfAssignmentField : DiagGroup<"self-assign-field">;
+def SelfAssignment : DiagGroup<"self-assign", [SelfAssignmentField]>;
+def SelfMove : DiagGroup<"self-move">;
+def SemiBeforeMethodBody : DiagGroup<"semicolon-before-method-body">;
+def Sentinel : DiagGroup<"sentinel">;
+def MissingMethodReturnType : DiagGroup<"missing-method-return-type">;
+
+def ShadowField : DiagGroup<"shadow-field">;
+def ShadowFieldInConstructorModified : DiagGroup<"shadow-field-in-constructor-modified">;
+def ShadowFieldInConstructor : DiagGroup<"shadow-field-in-constructor",
+ [ShadowFieldInConstructorModified]>;
+def ShadowIvar : DiagGroup<"shadow-ivar">;
+def ShadowUncapturedLocal : DiagGroup<"shadow-uncaptured-local">;
+
+// -Wshadow-all is a catch-all for all shadowing. -Wshadow is just the
+// shadowing that we think is unsafe.
+def Shadow : DiagGroup<"shadow", [ShadowFieldInConstructorModified,
+ ShadowIvar]>;
+def ShadowAll : DiagGroup<"shadow-all", [Shadow, ShadowFieldInConstructor,
+ ShadowUncapturedLocal, ShadowField]>;
+
+def Shorten64To32 : DiagGroup<"shorten-64-to-32">;
+def : DiagGroup<"sign-promo">;
+def SignCompare : DiagGroup<"sign-compare">;
+def : DiagGroup<"stack-protector">;
+def : DiagGroup<"switch-default">;
+def : DiagGroup<"synth">;
+def SizeofArrayArgument : DiagGroup<"sizeof-array-argument">;
+def SizeofArrayDecay : DiagGroup<"sizeof-array-decay">;
+def SizeofPointerMemaccess : DiagGroup<"sizeof-pointer-memaccess">;
+def StaticInInline : DiagGroup<"static-in-inline">;
+def StaticLocalInInline : DiagGroup<"static-local-in-inline">;
+def GNUStaticFloatInit : DiagGroup<"gnu-static-float-init">;
+def StaticFloatInit : DiagGroup<"static-float-init", [GNUStaticFloatInit]>;
+def GNUStatementExpression : DiagGroup<"gnu-statement-expression">;
+def StringCompare : DiagGroup<"string-compare">;
+def StringPlusInt : DiagGroup<"string-plus-int">;
+def StringPlusChar : DiagGroup<"string-plus-char">;
+def StrncatSize : DiagGroup<"strncat-size">;
+def TautologicalOutOfRangeCompare : DiagGroup<"tautological-constant-out-of-range-compare">;
+def TautologicalPointerCompare : DiagGroup<"tautological-pointer-compare">;
+def TautologicalOverlapCompare : DiagGroup<"tautological-overlap-compare">;
+def TautologicalUndefinedCompare : DiagGroup<"tautological-undefined-compare">;
+def TautologicalCompare : DiagGroup<"tautological-compare",
+ [TautologicalOutOfRangeCompare,
+ TautologicalPointerCompare,
+ TautologicalOverlapCompare,
+ TautologicalUndefinedCompare]>;
+def HeaderHygiene : DiagGroup<"header-hygiene">;
+def DuplicateDeclSpecifier : DiagGroup<"duplicate-decl-specifier">;
+def CompareDistinctPointerType : DiagGroup<"compare-distinct-pointer-types">;
+def GNUUnionCast : DiagGroup<"gnu-union-cast">;
+def GNUVariableSizedTypeNotAtEnd : DiagGroup<"gnu-variable-sized-type-not-at-end">;
+def Varargs : DiagGroup<"varargs">;
+
+def Unsequenced : DiagGroup<"unsequenced">;
+// GCC name for -Wunsequenced
+def : DiagGroup<"sequence-point", [Unsequenced]>;
+
+// Preprocessor warnings.
+def AmbiguousMacro : DiagGroup<"ambiguous-macro">;
+def KeywordAsMacro : DiagGroup<"keyword-macro">;
+def ReservedIdAsMacro : DiagGroup<"reserved-id-macro">;
+
+// Just silence warnings about -Wstrict-aliasing for now.
+def : DiagGroup<"strict-aliasing=0">;
+def : DiagGroup<"strict-aliasing=1">;
+def : DiagGroup<"strict-aliasing=2">;
+def : DiagGroup<"strict-aliasing">;
+
+// Just silence warnings about -Wstrict-overflow for now.
+def : DiagGroup<"strict-overflow=0">;
+def : DiagGroup<"strict-overflow=1">;
+def : DiagGroup<"strict-overflow=2">;
+def : DiagGroup<"strict-overflow=3">;
+def : DiagGroup<"strict-overflow=4">;
+def : DiagGroup<"strict-overflow=5">;
+def : DiagGroup<"strict-overflow">;
+
+def InvalidOffsetof : DiagGroup<"invalid-offsetof">;
+def : DiagGroup<"strict-prototypes">;
+def StrictSelector : DiagGroup<"strict-selector-match">;
+def MethodDuplicate : DiagGroup<"duplicate-method-match">;
+def ObjCCStringFormat : DiagGroup<"cstring-format-directive">;
+def CoveredSwitchDefault : DiagGroup<"covered-switch-default">;
+def SwitchBool : DiagGroup<"switch-bool">;
+def SwitchEnum : DiagGroup<"switch-enum">;
+def Switch : DiagGroup<"switch">;
+def ImplicitFallthroughPerFunction :
+ DiagGroup<"implicit-fallthrough-per-function">;
+def ImplicitFallthrough : DiagGroup<"implicit-fallthrough",
+ [ImplicitFallthroughPerFunction]>;
+def InvalidPPToken : DiagGroup<"invalid-pp-token">;
+def Trigraphs : DiagGroup<"trigraphs">;
+
+def : DiagGroup<"type-limits">;
+def UndefinedReinterpretCast : DiagGroup<"undefined-reinterpret-cast">;
+def ReinterpretBaseClass : DiagGroup<"reinterpret-base-class">;
+def Unicode : DiagGroup<"unicode">;
+def UninitializedMaybe : DiagGroup<"conditional-uninitialized">;
+def UninitializedSometimes : DiagGroup<"sometimes-uninitialized">;
+def UninitializedStaticSelfInit : DiagGroup<"static-self-init">;
+def Uninitialized : DiagGroup<"uninitialized", [UninitializedSometimes,
+ UninitializedStaticSelfInit]>;
+def IgnoredPragmaIntrinsic : DiagGroup<"ignored-pragma-intrinsic">;
+def UnknownPragmas : DiagGroup<"unknown-pragmas">;
+def IgnoredPragmas : DiagGroup<"ignored-pragmas", [IgnoredPragmaIntrinsic]>;
+def PragmaClangAttribute : DiagGroup<"pragma-clang-attribute">;
+def Pragmas : DiagGroup<"pragmas", [UnknownPragmas, IgnoredPragmas,
+ PragmaClangAttribute]>;
+def UnknownWarningOption : DiagGroup<"unknown-warning-option">;
+def NSobjectAttribute : DiagGroup<"NSObject-attribute">;
+def IndependentClassAttribute : DiagGroup<"IndependentClass-attribute">;
+def UnknownAttributes : DiagGroup<"unknown-attributes">;
+def IgnoredAttributes : DiagGroup<"ignored-attributes">;
+def Attributes : DiagGroup<"attributes", [UnknownAttributes,
+ IgnoredAttributes]>;
+def UnknownSanitizers : DiagGroup<"unknown-sanitizers">;
+def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args",
+ [CXX98CompatUnnamedTypeTemplateArgs]>;
+def UnsupportedFriend : DiagGroup<"unsupported-friend">;
+def UnusedArgument : DiagGroup<"unused-argument">;
+def UnusedCommandLineArgument : DiagGroup<"unused-command-line-argument">;
+def IgnoredOptimizationArgument : DiagGroup<"ignored-optimization-argument">;
+def InvalidCommandLineArgument : DiagGroup<"invalid-command-line-argument",
+ [IgnoredOptimizationArgument]>;
+def UnusedComparison : DiagGroup<"unused-comparison">;
+def UnusedExceptionParameter : DiagGroup<"unused-exception-parameter">;
+def UnneededInternalDecl : DiagGroup<"unneeded-internal-declaration">;
+def UnneededMemberFunction : DiagGroup<"unneeded-member-function">;
+def UnusedPrivateField : DiagGroup<"unused-private-field">;
+def UnusedFunction : DiagGroup<"unused-function", [UnneededInternalDecl]>;
+def UnusedTemplate : DiagGroup<"unused-template", [UnneededInternalDecl]>;
+def UnusedMemberFunction : DiagGroup<"unused-member-function",
+ [UnneededMemberFunction]>;
+def UnusedLabel : DiagGroup<"unused-label">;
+def UnusedLambdaCapture : DiagGroup<"unused-lambda-capture">;
+def UnusedParameter : DiagGroup<"unused-parameter">;
+def UnusedResult : DiagGroup<"unused-result">;
+def PotentiallyEvaluatedExpression : DiagGroup<"potentially-evaluated-expression">;
+def UnevaluatedExpression : DiagGroup<"unevaluated-expression",
+ [PotentiallyEvaluatedExpression]>;
+def UnusedValue : DiagGroup<"unused-value", [UnusedComparison, UnusedResult,
+ UnevaluatedExpression]>;
+def UnusedConstVariable : DiagGroup<"unused-const-variable">;
+def UnusedVariable : DiagGroup<"unused-variable",
+ [UnusedConstVariable]>;
+def UnusedLocalTypedef : DiagGroup<"unused-local-typedef">;
+def UnusedPropertyIvar : DiagGroup<"unused-property-ivar">;
+def UnusedGetterReturnValue : DiagGroup<"unused-getter-return-value">;
+def UsedButMarkedUnused : DiagGroup<"used-but-marked-unused">;
+def UserDefinedLiterals : DiagGroup<"user-defined-literals">;
+def UserDefinedWarnings : DiagGroup<"user-defined-warnings">;
+def Reorder : DiagGroup<"reorder">;
+def UndeclaredSelector : DiagGroup<"undeclared-selector">;
+def ImplicitAtomic : DiagGroup<"implicit-atomic-properties">;
+def CustomAtomic : DiagGroup<"custom-atomic-properties">;
+def AtomicProperties : DiagGroup<"atomic-properties",
+ [ImplicitAtomic, CustomAtomic]>;
+def ARCUnsafeRetainedAssign : DiagGroup<"arc-unsafe-retained-assign">;
+def ARCRetainCycles : DiagGroup<"arc-retain-cycles">;
+def ARCNonPodMemAccess : DiagGroup<"arc-non-pod-memaccess">;
+def AutomaticReferenceCounting : DiagGroup<"arc",
+ [ARCUnsafeRetainedAssign,
+ ARCRetainCycles,
+ ARCNonPodMemAccess]>;
+def ARCRepeatedUseOfWeakMaybe : DiagGroup<"arc-maybe-repeated-use-of-weak">;
+def ARCRepeatedUseOfWeak : DiagGroup<"arc-repeated-use-of-weak",
+ [ARCRepeatedUseOfWeakMaybe]>;
+def BlockCaptureAutoReleasing : DiagGroup<"block-capture-autoreleasing">;
+def ObjCBridge : DiagGroup<"bridge-cast">;
+
+def DeallocInCategory:DiagGroup<"dealloc-in-category">;
+def SelectorTypeMismatch : DiagGroup<"selector-type-mismatch">;
+def Selector : DiagGroup<"selector", [SelectorTypeMismatch]>;
+def Protocol : DiagGroup<"protocol">;
+def AtProtocol : DiagGroup<"at-protocol">;
+def PropertyAccessDotSyntax: DiagGroup<"property-access-dot-syntax">;
+def PropertyAttr : DiagGroup<"property-attribute-mismatch">;
+def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">;
+def OverridingMethodMismatch : DiagGroup<"overriding-method-mismatch">;
+def VariadicMacros : DiagGroup<"variadic-macros">;
+def VectorConversion : DiagGroup<"vector-conversion">; // clang specific
+def VexingParse : DiagGroup<"vexing-parse">;
+def VLA : DiagGroup<"vla">;
+def VLAExtension : DiagGroup<"vla-extension">;
+def VolatileRegisterVar : DiagGroup<"volatile-register-var">;
+def Visibility : DiagGroup<"visibility">;
+def ZeroLengthArray : DiagGroup<"zero-length-array">;
+def GNUZeroLineDirective : DiagGroup<"gnu-zero-line-directive">;
+def GNUZeroVariadicMacroArguments : DiagGroup<"gnu-zero-variadic-macro-arguments">;
+def Fallback : DiagGroup<"fallback">;
+
+// This covers both the deprecated case (in C++98)
+// and the extension case (in C++11 onwards).
+def WritableStrings : DiagGroup<"writable-strings", [DeprecatedWritableStr]>;
+
+// GCC calls -Wdeprecated-writable-strings -Wwrite-strings.
+//
+// Bizarrely, this warning flag enables -fconst-strings in C. This is
+// GCC-compatible, but really weird.
+//
+// FIXME: Should this affect C++11 (where this is an error,
+// not just deprecated) or not?
+def GCCWriteStrings : DiagGroup<"write-strings" , [WritableStrings]>;
+
+def CharSubscript : DiagGroup<"char-subscripts">;
+def LargeByValueCopy : DiagGroup<"large-by-value-copy">;
+def DuplicateArgDecl : DiagGroup<"duplicate-method-arg">;
+def SignedEnumBitfield : DiagGroup<"signed-enum-bitfield">;
+
+// Unreachable code warning groups.
+//
+// The goal is make -Wunreachable-code on by default, in -Wall, or at
+// least actively used, with more noisy versions of the warning covered
+// under separate flags.
+//
+def UnreachableCodeLoopIncrement : DiagGroup<"unreachable-code-loop-increment">;
+def UnreachableCode : DiagGroup<"unreachable-code",
+ [UnreachableCodeLoopIncrement]>;
+def UnreachableCodeBreak : DiagGroup<"unreachable-code-break">;
+def UnreachableCodeReturn : DiagGroup<"unreachable-code-return">;
+def UnreachableCodeAggressive : DiagGroup<"unreachable-code-aggressive",
+ [UnreachableCode,
+ UnreachableCodeBreak,
+ UnreachableCodeReturn]>;
+
+// Aggregation warning settings.
+
+// Populate -Waddress with warnings from other groups.
+def : DiagGroup<"address", [PointerBoolConversion,
+ StringCompare,
+ TautologicalPointerCompare]>;
+
+// -Widiomatic-parentheses contains warnings about 'idiomatic'
+// missing parentheses; it is off by default. We do not include it
+// in -Wparentheses because most users who use -Wparentheses explicitly
+// do not want these warnings.
+def ParenthesesOnEquality : DiagGroup<"parentheses-equality">;
+def Parentheses : DiagGroup<"parentheses",
+ [LogicalOpParentheses,
+ LogicalNotParentheses,
+ BitwiseOpParentheses,
+ ShiftOpParentheses,
+ OverloadedShiftOpParentheses,
+ ParenthesesOnEquality,
+ DanglingElse]>;
+
+// -Wconversion has its own warnings, but we split a few out for
+// legacy reasons:
+// - some people want just 64-to-32 warnings
+// - conversion warnings with constant sources are on by default
+// - conversion warnings for literals are on by default
+// - bool-to-pointer conversion warnings are on by default
+// - __null-to-integer conversion warnings are on by default
+def Conversion : DiagGroup<"conversion",
+ [BoolConversion,
+ ConstantConversion,
+ EnumConversion,
+ BitFieldEnumConversion,
+ FloatConversion,
+ Shorten64To32,
+ IntConversion,
+ LiteralConversion,
+ NonLiteralNullConversion, // (1-1)->pointer (etc)
+ NullConversion, // NULL->non-pointer
+ ObjCLiteralConversion,
+ SignConversion,
+ StringConversion]>,
+ DiagCategory<"Value Conversion Issue">;
+
+def Unused : DiagGroup<"unused",
+ [UnusedArgument, UnusedFunction, UnusedLabel,
+ // UnusedParameter, (matches GCC's behavior)
+ // UnusedTemplate, (clean-up libc++ before enabling)
+ // UnusedMemberFunction, (clean-up llvm before enabling)
+ UnusedPrivateField, UnusedLambdaCapture,
+ UnusedLocalTypedef, UnusedValue, UnusedVariable,
+ UnusedPropertyIvar]>,
+ DiagCategory<"Unused Entity Issue">;
+
+// Format settings.
+def FormatInvalidSpecifier : DiagGroup<"format-invalid-specifier">;
+def FormatSecurity : DiagGroup<"format-security">;
+def FormatNonStandard : DiagGroup<"format-non-iso">;
+def FormatY2K : DiagGroup<"format-y2k">;
+def FormatPedantic : DiagGroup<"format-pedantic">;
+def Format : DiagGroup<"format",
+ [FormatExtraArgs, FormatZeroLength, NonNull,
+ FormatSecurity, FormatY2K, FormatInvalidSpecifier]>,
+ DiagCategory<"Format String Issue">;
+def FormatNonLiteral : DiagGroup<"format-nonliteral">;
+def Format2 : DiagGroup<"format=2",
+ [FormatNonLiteral, FormatSecurity, FormatY2K]>;
+
+def TypeSafety : DiagGroup<"type-safety">;
+
+def IncompatibleExceptionSpec : DiagGroup<"incompatible-exception-spec">;
+
+def IntToVoidPointerCast : DiagGroup<"int-to-void-pointer-cast">;
+def IntToPointerCast : DiagGroup<"int-to-pointer-cast",
+ [IntToVoidPointerCast]>;
+
+def Move : DiagGroup<"move", [PessimizingMove, RedundantMove, SelfMove]>;
+
+def Extra : DiagGroup<"extra", [
+ MissingFieldInitializers,
+ IgnoredQualifiers,
+ InitializerOverrides,
+ SemiBeforeMethodBody,
+ MissingMethodReturnType,
+ SignCompare,
+ UnusedParameter
+ ]>;
+
+def Most : DiagGroup<"most", [
+ CharSubscript,
+ Comment,
+ DeleteNonVirtualDtor,
+ ForLoopAnalysis,
+ Format,
+ Implicit,
+ InfiniteRecursion,
+ MismatchedTags,
+ MissingBraces,
+ Move,
+ MultiChar,
+ Reorder,
+ ReturnType,
+ SelfAssignment,
+ SelfMove,
+ SizeofArrayArgument,
+ SizeofArrayDecay,
+ StringPlusInt,
+ Trigraphs,
+ Uninitialized,
+ UnknownPragmas,
+ Unused,
+ VolatileRegisterVar,
+ ObjCMissingSuperCalls,
+ ObjCDesignatedInit,
+ OverloadedVirtual,
+ PrivateExtern,
+ SelTypeCast,
+ ExternCCompat,
+ UserDefinedWarnings
+ ]>;
+
+// Thread Safety warnings
+def ThreadSafetyAttributes : DiagGroup<"thread-safety-attributes">;
+def ThreadSafetyAnalysis : DiagGroup<"thread-safety-analysis">;
+def ThreadSafetyPrecise : DiagGroup<"thread-safety-precise">;
+def ThreadSafetyReference : DiagGroup<"thread-safety-reference">;
+def ThreadSafetyNegative : DiagGroup<"thread-safety-negative">;
+def ThreadSafety : DiagGroup<"thread-safety",
+ [ThreadSafetyAttributes,
+ ThreadSafetyAnalysis,
+ ThreadSafetyPrecise,
+ ThreadSafetyReference]>;
+def ThreadSafetyVerbose : DiagGroup<"thread-safety-verbose">;
+def ThreadSafetyBeta : DiagGroup<"thread-safety-beta">;
+
+// Uniqueness Analysis warnings
+def Consumed : DiagGroup<"consumed">;
+
+// Note that putting warnings in -Wall will not disable them by default. If a
+// warning should be active _only_ when -Wall is passed in, mark it as
+// DefaultIgnore in addition to putting it here.
+def All : DiagGroup<"all", [Most, Parentheses, Switch, SwitchBool]>;
+
+// Warnings that should be in clang-cl /w4.
+def : DiagGroup<"CL4", [All, Extra]>;
+
+// Warnings enabled by -pedantic. This is magically filled in by TableGen.
+def Pedantic : DiagGroup<"pedantic">;
+
+// Aliases.
+def : DiagGroup<"", [Extra]>; // -W = -Wextra
+def : DiagGroup<"endif-labels", [ExtraTokens]>; // -Wendif-labels=-Wextra-tokens
+def : DiagGroup<"cpp", [PoundWarning]>; // -Wcpp = -W#warnings
+def : DiagGroup<"comments", [Comment]>; // -Wcomments = -Wcomment
+def : DiagGroup<"conversion-null",
+ [NullConversion]>; // -Wconversion-null = -Wnull-conversion
+def : DiagGroup<"bool-conversions",
+ [BoolConversion]>; // -Wbool-conversions = -Wbool-conversion
+def : DiagGroup<"int-conversions",
+ [IntConversion]>; // -Wint-conversions = -Wint-conversion
+def : DiagGroup<"vector-conversions",
+ [VectorConversion]>; // -Wvector-conversions = -Wvector-conversion
+def : DiagGroup<"unused-local-typedefs", [UnusedLocalTypedef]>;
+ // -Wunused-local-typedefs = -Wunused-local-typedef
+
+// A warning group for warnings that we want to have on by default in clang,
+// but which aren't on by default in GCC.
+def NonGCC : DiagGroup<"non-gcc",
+ [SignCompare, Conversion, LiteralRange]>;
+
+// A warning group for warnings about using C++11 features as extensions in
+// earlier C++ versions.
+def CXX11 : DiagGroup<"c++11-extensions", [CXX11ExtraSemi, CXX11InlineNamespace,
+ CXX11LongLong]>;
+
+// A warning group for warnings about using C++14 features as extensions in
+// earlier C++ versions.
+def CXX14 : DiagGroup<"c++14-extensions", [CXX14BinaryLiteral]>;
+
+// A warning group for warnings about using C++1z features as extensions in
+// earlier C++ versions.
+def CXX17 : DiagGroup<"c++17-extensions">;
+
+def : DiagGroup<"c++0x-extensions", [CXX11]>;
+def : DiagGroup<"c++1y-extensions", [CXX14]>;
+def : DiagGroup<"c++1z-extensions", [CXX17]>;
+
+def DelegatingCtorCycles :
+ DiagGroup<"delegating-ctor-cycles">;
+
+// A warning group for warnings about using C11 features as extensions.
+def C11 : DiagGroup<"c11-extensions">;
+
+// A warning group for warnings about using C99 features as extensions.
+def C99 : DiagGroup<"c99-extensions">;
+
+// A warning group for warnings about GCC extensions.
+def GNU : DiagGroup<"gnu", [GNUAlignofExpression, GNUAnonymousStruct,
+ GNUAutoType,
+ GNUBinaryLiteral, GNUCaseRange,
+ GNUComplexInteger, GNUCompoundLiteralInitializer,
+ GNUConditionalOmittedOperand, GNUDesignator,
+ GNUEmptyInitializer, GNUEmptyStruct,
+ VLAExtension, GNUFlexibleArrayInitializer,
+ GNUFlexibleArrayUnionMember, GNUFoldingConstant,
+ GNUImaginaryConstant, GNUIncludeNext,
+ GNULabelsAsValue,
+ RedeclaredClassMember, GNURedeclaredEnum,
+ GNUStatementExpression, GNUStaticFloatInit,
+ GNUStringLiteralOperatorTemplate,
+ GNUUnionCast, GNUVariableSizedTypeNotAtEnd,
+ ZeroLengthArray, GNUZeroLineDirective,
+ GNUZeroVariadicMacroArguments]>;
+// A warning group for warnings about code that clang accepts but gcc doesn't.
+def GccCompat : DiagGroup<"gcc-compat">;
+
+// Warnings for Microsoft extensions.
+def MicrosoftCharize : DiagGroup<"microsoft-charize">;
+def MicrosoftInclude : DiagGroup<"microsoft-include">;
+def MicrosoftCppMacro : DiagGroup<"microsoft-cpp-macro">;
+def MicrosoftFixedEnum : DiagGroup<"microsoft-fixed-enum">;
+def MicrosoftSealed : DiagGroup<"microsoft-sealed">;
+def MicrosoftUnqualifiedFriend : DiagGroup<"microsoft-unqualified-friend">;
+def MicrosoftExceptionSpec : DiagGroup<"microsoft-exception-spec">;
+def MicrosoftUsingDecl : DiagGroup<"microsoft-using-decl">;
+def MicrosoftMutableReference : DiagGroup<"microsoft-mutable-reference">;
+def MicrosoftPureDefinition : DiagGroup<"microsoft-pure-definition">;
+def MicrosoftUnionMemberReference : DiagGroup<
+ "microsoft-union-member-reference">;
+def MicrosoftExplicitConstructorCall : DiagGroup<
+ "microsoft-explicit-constructor-call">;
+def MicrosoftEnumValue : DiagGroup<"microsoft-enum-value">;
+def MicrosoftDefaultArgRedefinition :
+ DiagGroup<"microsoft-default-arg-redefinition">;
+def MicrosoftTemplate : DiagGroup<"microsoft-template">;
+def MicrosoftInconsistentDllImport : DiagGroup<"inconsistent-dllimport">;
+def MicrosoftRedeclareStatic : DiagGroup<"microsoft-redeclare-static">;
+def MicrosoftEnumForwardReference :
+ DiagGroup<"microsoft-enum-forward-reference">;
+def MicrosoftGoto : DiagGroup<"microsoft-goto">;
+def MicrosoftFlexibleArray : DiagGroup<"microsoft-flexible-array">;
+def MicrosoftExtraQualification : DiagGroup<"microsoft-extra-qualification">;
+def MicrosoftCast : DiagGroup<"microsoft-cast">;
+def MicrosoftConstInit : DiagGroup<"microsoft-const-init">;
+def MicrosoftVoidPseudoDtor : DiagGroup<"microsoft-void-pseudo-dtor">;
+def MicrosoftAnonTag : DiagGroup<"microsoft-anon-tag">;
+def MicrosoftCommentPaste : DiagGroup<"microsoft-comment-paste">;
+def MicrosoftEndOfFile : DiagGroup<"microsoft-end-of-file">;
+// Aliases.
+def : DiagGroup<"msvc-include", [MicrosoftInclude]>;
+ // -Wmsvc-include = -Wmicrosoft-include
+
+// Warnings group for warnings about Microsoft extensions.
+def Microsoft : DiagGroup<"microsoft",
+ [MicrosoftCharize, MicrosoftInclude, MicrosoftCppMacro, MicrosoftFixedEnum,
+ MicrosoftSealed, MicrosoftUnqualifiedFriend, MicrosoftExceptionSpec,
+ MicrosoftUsingDecl, MicrosoftMutableReference, MicrosoftPureDefinition,
+ MicrosoftUnionMemberReference, MicrosoftExplicitConstructorCall,
+ MicrosoftEnumValue, MicrosoftDefaultArgRedefinition, MicrosoftTemplate,
+ MicrosoftRedeclareStatic, MicrosoftEnumForwardReference, MicrosoftGoto,
+ MicrosoftFlexibleArray, MicrosoftExtraQualification, MicrosoftCast,
+ MicrosoftConstInit, MicrosoftVoidPseudoDtor, MicrosoftAnonTag,
+ MicrosoftCommentPaste, MicrosoftEndOfFile,
+ MicrosoftInconsistentDllImport]>;
+
+def ClangClPch : DiagGroup<"clang-cl-pch">;
+
+def ObjCNonUnifiedException : DiagGroup<"objc-nonunified-exceptions">;
+
+def ObjCProtocolMethodImpl : DiagGroup<"objc-protocol-method-implementation">;
+
+def ObjCNoPropertyAutoSynthesis : DiagGroup<"objc-property-synthesis">;
+
+// ObjC API warning groups.
+def ObjCRedundantLiteralUse : DiagGroup<"objc-redundant-literal-use">;
+def ObjCRedundantAPIUse : DiagGroup<"objc-redundant-api-use", [
+ ObjCRedundantLiteralUse
+ ]>;
+
+def ObjCCocoaAPI : DiagGroup<"objc-cocoa-api", [
+ ObjCRedundantAPIUse
+ ]>;
+
+def ObjCStringComparison : DiagGroup<"objc-string-compare">;
+def ObjCStringConcatenation : DiagGroup<"objc-string-concatenation">;
+def ObjCLiteralComparison : DiagGroup<"objc-literal-compare", [
+ ObjCStringComparison
+ ]>;
+
+// Inline ASM warnings.
+def ASMOperandWidths : DiagGroup<"asm-operand-widths">;
+def ASMIgnoredQualifier : DiagGroup<"asm-ignored-qualifier">;
+def ASM : DiagGroup<"asm", [
+ ASMOperandWidths, ASMIgnoredQualifier
+ ]>;
+
+// OpenMP warnings.
+def SourceUsesOpenMP : DiagGroup<"source-uses-openmp">;
+def OpenMPClauses : DiagGroup<"openmp-clauses">;
+def OpenMPLoopForm : DiagGroup<"openmp-loop-form">;
+def OpenMPTarget : DiagGroup<"openmp-target">;
+
+// Backend warnings.
+def BackendInlineAsm : DiagGroup<"inline-asm">;
+def BackendFrameLargerThanEQ : DiagGroup<"frame-larger-than=">;
+def BackendPlugin : DiagGroup<"backend-plugin">;
+def RemarkBackendPlugin : DiagGroup<"remark-backend-plugin">;
+def BackendOptimizationRemark : DiagGroup<"pass">;
+def BackendOptimizationRemarkMissed : DiagGroup<"pass-missed">;
+def BackendOptimizationRemarkAnalysis : DiagGroup<"pass-analysis">;
+def BackendOptimizationFailure : DiagGroup<"pass-failed">;
+
+// Instrumentation based profiling warnings.
+def ProfileInstrMissing : DiagGroup<"profile-instr-missing">;
+def ProfileInstrOutOfDate : DiagGroup<"profile-instr-out-of-date">;
+def ProfileInstrUnprofiled : DiagGroup<"profile-instr-unprofiled">;
+
+// AddressSanitizer frontend instrumentation remarks.
+def SanitizeAddressRemarks : DiagGroup<"sanitize-address">;
+
+// Issues with serialized diagnostics.
+def SerializedDiagnostics : DiagGroup<"serialized-diagnostics">;
+
+// A warning group for warnings about code that clang accepts when
+// compiling CUDA C/C++ but which is not compatible with the CUDA spec.
+def CudaCompat : DiagGroup<"cuda-compat">;
+
+// A warning group for things that will change semantics in the future.
+def FutureCompat : DiagGroup<"future-compat">;
+
+def InvalidOrNonExistentDirectory : DiagGroup<"invalid-or-nonexistent-directory">;
+
+def OptionIgnored : DiagGroup<"option-ignored">;
+
+def UnknownArgument : DiagGroup<"unknown-argument">;
+
+// A warning group for warnings about code that clang accepts when
+// compiling OpenCL C/C++ but which is not compatible with the SPIR spec.
+def SpirCompat : DiagGroup<"spir-compat">;
--- /dev/null
+//===--- LLVM.h - Import various common LLVM datatypes ----------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+/// \file
+/// \brief Forward-declares and imports various common LLVM datatypes that
+/// flang wants to use unqualified.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_FLANG_BASIC_LLVM_H
+#define LLVM_FLANG_BASIC_LLVM_H
+
+// Do not proliferate #includes here, require clients to #include their
+// dependencies.
+// Casting.h has complex templates that cannot be easily forward declared.
+#include "llvm/Support/Casting.h"
+// None.h includes an enumerator that is desired & cannot be forward declared
+// without a definition of NoneType.
+#include "llvm/ADT/None.h"
+
+namespace llvm {
+ // ADT's.
+ class StringRef;
+ class Twine;
+ template<typename T> class ArrayRef;
+ template<typename T> class MutableArrayRef;
+ template<typename T> class OwningArrayRef;
+ template<unsigned InternalLen> class SmallString;
+ template<typename T, unsigned N> class SmallVector;
+ template<typename T> class SmallVectorImpl;
+ template<typename T> class Optional;
+
+ template<typename T>
+ struct SaveAndRestore;
+
+ // Reference counting.
+ template <typename T> class IntrusiveRefCntPtr;
+ template <typename T> struct IntrusiveRefCntPtrInfo;
+ template <class Derived> class RefCountedBase;
+
+ class raw_ostream;
+ class raw_pwrite_stream;
+ // TODO: DenseMap, ...
+}
+
+
+namespace flang {
+ // Casting operators.
+ using llvm::isa;
+ using llvm::cast;
+ using llvm::dyn_cast;
+ using llvm::dyn_cast_or_null;
+ using llvm::cast_or_null;
+
+ // ADT's.
+ using llvm::None;
+ using llvm::Optional;
+ using llvm::StringRef;
+ using llvm::Twine;
+ using llvm::ArrayRef;
+ using llvm::MutableArrayRef;
+ using llvm::OwningArrayRef;
+ using llvm::SmallString;
+ using llvm::SmallVector;
+ using llvm::SmallVectorImpl;
+ using llvm::SaveAndRestore;
+
+ // Reference counting.
+ using llvm::IntrusiveRefCntPtr;
+ using llvm::IntrusiveRefCntPtrInfo;
+ using llvm::RefCountedBase;
+
+ using llvm::raw_ostream;
+ using llvm::raw_pwrite_stream;
+} // end namespace flang.
+
+#endif
--- /dev/null
+//===- Version.h - Flang Version Number -------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// \brief Defines version macros and version-related utility functions
+/// for Flang.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_FLANG_BASIC_VERSION_H
+#define LLVM_FLANG_BASIC_VERSION_H
+
+#include "flang/Basic/Version.inc"
+#include "llvm/ADT/StringRef.h"
+
+namespace flang {
+ /// \brief Retrieves the repository path (e.g., Subversion path) that
+ /// identifies the particular Flang branch, tag, or trunk from which this
+ /// Flang was built.
+ std::string getFlangRepositoryPath();
+
+ /// \brief Retrieves the repository path from which LLVM was built.
+ ///
+ /// This supports LLVM residing in a separate repository from flang.
+ std::string getLLVMRepositoryPath();
+
+ /// \brief Retrieves the repository revision number (or identifer) from which
+ /// this Flang was built.
+ std::string getFlangRevision();
+
+ /// \brief Retrieves the repository revision number (or identifer) from which
+ /// LLVM was built.
+ ///
+ /// If Flang and LLVM are in the same repository, this returns the same
+ /// string as getFlangRevision.
+ std::string getLLVMRevision();
+
+ /// \brief Retrieves the full repository version that is an amalgamation of
+ /// the information in getFlangRepositoryPath() and getFlangRevision().
+ std::string getFlangFullRepositoryVersion();
+
+ /// \brief Retrieves a string representing the complete flang version,
+ /// which includes the flang version number, the repository version,
+ /// and the vendor tag.
+ std::string getFlangFullVersion();
+
+ /// \brief Like getFlangFullVersion(), but with a custom tool name.
+ std::string getFlangToolFullVersion(llvm::StringRef ToolName);
+
+ /// \brief Retrieves a string representing the complete flang version suitable
+ /// for use in the CPP __VERSION__ macro, which includes the flang version
+ /// number, the repository version, and the vendor tag.
+ std::string getFlangFullCPPVersion();
+}
+
+#endif // LLVM_FLANG_BASIC_VERSION_H
--- /dev/null
+#define FLANG_VERSION @FLANG_VERSION@
+#define FLANG_VERSION_STRING "@FLANG_VERSION@"
+#define FLANG_VERSION_MAJOR @FLANG_VERSION_MAJOR@
+#define FLANG_VERSION_MINOR @FLANG_VERSION_MINOR@
+#define FLANG_VERSION_PATCHLEVEL @FLANG_VERSION_PATCHLEVEL@
--- /dev/null
+#!! add_subdirectory(AST)
+add_subdirectory(Basic)
+#!! add_subdirectory(Driver)
+#!! add_subdirectory(Parse)
+#!! add_subdirectory(Sema)
+
--- /dev/null
+/* This generated file is for internal use. Do not include it from headers. */
+
+#ifdef FLANG_CONFIG_H
+#error config.h can only be included once
+#else
+#define FLANG_CONFIG_H
+
+/* Bug report URL. */
+#define BUG_REPORT_URL "${BUG_REPORT_URL}"
+
+/* Default linker to use. */
+#define FLANG_DEFAULT_LINKER "${FLANG_DEFAULT_LINKER}"
+
+/* Default C++ stdlib to use. */
+#define FLANG_DEFAULT_CXX_STDLIB "${FLANG_DEFAULT_CXX_STDLIB}"
+
+/* Default runtime library to use. */
+#define FLANG_DEFAULT_RTLIB "${FLANG_DEFAULT_RTLIB}"
+
+/* Default OpenMP runtime used by -fopenmp. */
+#define FLANG_DEFAULT_OPENMP_RUNTIME "${FLANG_DEFAULT_OPENMP_RUNTIME}"
+
+/* Multilib suffix for libdir. */
+#define FLANG_LIBDIR_SUFFIX "${FLANG_LIBDIR_SUFFIX}"
+
+/* Relative directory for resource files */
+#define FLANG_RESOURCE_DIR "${FLANG_RESOURCE_DIR}"
+
+/* Directories clang will search for headers */
+#define C_INCLUDE_DIRS "${C_INCLUDE_DIRS}"
+
+/* Default <path> to all compiler invocations for --sysroot=<path>. */
+#define DEFAULT_SYSROOT "${DEFAULT_SYSROOT}"
+
+/* Directory where gcc is installed. */
+#define GCC_INSTALL_PREFIX "${GCC_INSTALL_PREFIX}"
+
+/* Define if we have libxml2 */
+#cmakedefine FLANG_HAVE_LIBXML ${FLANG_HAVE_LIBXML}
+
+/* Define if we have z3 and want to build it */
+#cmakedefine FLANG_ANALYZER_WITH_Z3 ${FLANG_ANALYZER_WITH_Z3}
+
+/* Define if we have sys/resource.h (rlimits) */
+#cmakedefine FLANG_HAVE_RLIMITS ${FLANG_HAVE_RLIMITS}
+
+/* The LLVM product name and version */
+#define BACKEND_PACKAGE_STRING "${BACKEND_PACKAGE_STRING}"
+
+/* Linker version detected at compile time. */
+#cmakedefine HOST_LINK_VERSION "${HOST_LINK_VERSION}"
+
+/* pass --build-id to ld */
+#cmakedefine ENABLE_LINKER_BUILD_ID
+
+/* enable x86 relax relocations by default */
+#cmakedefine01 ENABLE_X86_RELAX_RELOCATIONS
+
+/* Enable each functionality of modules */
+#cmakedefine FLANG_ENABLE_ARCMT
+#cmakedefine FLANG_ENABLE_OBJC_REWRITER
+#cmakedefine FLANG_ENABLE_STATIC_ANALYZER
+
+#endif
--- /dev/null
+//===--- Sema.h - Semantic Analysis & AST Building --------------*- 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 Sema class, which performs semantic analysis
+// for Fortran.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_SEMA_SEMA_H
+#define LLVM_CLANG_SEMA_SEMA_H
+
+#include "clang/Basic/Version.h"
+#include "clang/Sema/Scope.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SetVector.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/TinyPtrVector.h"
+#include <deque>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace llvm {
+ // Put here the required forward declarations for LLVM
+ class APSInt;
+ template <typename ValueT> struct DenseMapInfo;
+ template <typename ValueT, typename ValueInfoT> class DenseSet;
+ class SmallBitVector;
+ class InlineAsmIdentifierInfo;
+}
+
+namespace flang {
+
+ // Put here the required forward declarations for flang
+ class SourceLocation;
+
+namespace sema {
+ // Put here the forward declarations of the inner classes of the Sema library
+ class ProgramScope;
+ class FunctionScope;
+} // end namespace flang::sema
+
+/// Sema - This implements semantic analysis for Fortran
+class Sema {
+public:
+ Sema();
+}; // end class Sema
+
+} // end namespace flang
+
+#endif
+
--- /dev/null
+set(LLVM_LINK_COMPONENTS
+ Core
+ MC
+ Support
+ )
+
+# Figure out if we can track VC revisions.
+function(find_first_existing_file out_var)
+ foreach(file ${ARGN})
+ if(EXISTS "${file}")
+ set(${out_var} "${file}" PARENT_SCOPE)
+ return()
+ endif()
+ endforeach()
+endfunction()
+
+macro(find_first_existing_vc_file out_var path)
+ set(git_path "${path}/.git")
+
+ # Normally '.git' is a directory that contains a 'logs/HEAD' file that
+ # is updated as modifications are made to the repository. In case the
+ # repository is a Git submodule, '.git' is a file that contains text that
+ # indicates where the repository's Git directory exists.
+ if (EXISTS "${git_path}" AND NOT IS_DIRECTORY "${git_path}")
+ FILE(READ "${git_path}" file_contents)
+ if("${file_contents}" MATCHES "^gitdir: ([^\n]+)")
+ # '.git' is indeed a link to the submodule's Git directory.
+ # Use the path to that Git directory.
+ set(git_path "${path}/${CMAKE_MATCH_1}")
+ endif()
+ endif()
+
+ find_first_existing_file(${out_var}
+ "${git_path}/logs/HEAD" # Git or Git submodule
+ "${path}/.svn/wc.db" # SVN 1.7
+ "${path}/.svn/entries" # SVN 1.6
+ )
+endmacro()
+
+find_first_existing_vc_file(llvm_vc "${LLVM_MAIN_SRC_DIR}")
+find_first_existing_vc_file(flang_vc "${FLANG_SOURCE_DIR}")
+
+# The VC revision include that we want to generate.
+set(version_inc "${CMAKE_CURRENT_BINARY_DIR}/SVNVersion.inc")
+
+set(get_svn_script "${LLVM_CMAKE_PATH}/GetSVN.cmake")
+
+if(DEFINED llvm_vc AND DEFINED flang_vc)
+ # Create custom target to generate the VC revision include.
+ add_custom_command(OUTPUT "${version_inc}"
+ DEPENDS "${llvm_vc}" "${flang_vc}" "${get_svn_script}"
+ COMMAND
+ ${CMAKE_COMMAND} "-DFIRST_SOURCE_DIR=${LLVM_MAIN_SRC_DIR}"
+ "-DFIRST_NAME=LLVM"
+ "-DSECOND_SOURCE_DIR=${FLANG_SOURCE_DIR}"
+ "-DSECOND_NAME=SVN"
+ "-DHEADER_FILE=${version_inc}"
+ -P "${get_svn_script}")
+
+ # Mark the generated header as being generated.
+ set_source_files_properties("${version_inc}"
+ PROPERTIES GENERATED TRUE
+ HEADER_FILE_ONLY TRUE)
+
+ # Tell Version.cpp that it needs to build with -DHAVE_SVN_VERSION_INC.
+ set_source_files_properties(Version.cpp
+ PROPERTIES COMPILE_DEFINITIONS "HAVE_SVN_VERSION_INC")
+else()
+ # Not producing a VC revision include.
+ set(version_inc)
+
+ # Being able to force-set the SVN revision in cases where it isn't available
+ # is useful for performance tracking, and matches compatibility from autoconf.
+ if(SVN_REVISION)
+ set_source_files_properties(Version.cpp
+ PROPERTIES COMPILE_DEFINITIONS "SVN_REVISION=\"${SVN_REVISION}\"")
+ endif()
+endif()
+
+add_flang_library(flangBasic
+ LangOptions.cpp
+ Version.cpp
+ ${version_inc}
+ )
+
--- /dev/null
+//===- Version.cpp - Flang Version Number -----------------------*- 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 several version-related utility functions for Flang.
+//
+//===----------------------------------------------------------------------===//
+
+#include "flang/Basic/Version.h"
+#include "flang/Basic/LLVM.h"
+#include "flang/Config/config.h"
+#include "llvm/Support/raw_ostream.h"
+#include <cstdlib>
+#include <cstring>
+
+#ifdef HAVE_SVN_VERSION_INC
+# include "SVNVersion.inc"
+#endif
+
+namespace flang {
+
+std::string getFlangRepositoryPath() {
+#if defined(FLANG_REPOSITORY_STRING)
+ return FLANG_REPOSITORY_STRING;
+#else
+#ifdef SVN_REPOSITORY
+ StringRef URL(SVN_REPOSITORY);
+#else
+ StringRef URL("");
+#endif
+
+ // If the SVN_REPOSITORY is empty, try to use the SVN keyword. This helps us
+ // pick up a tag in an SVN export, for example.
+ StringRef SVNRepository("$URL$");
+ if (URL.empty()) {
+ URL = SVNRepository.slice(SVNRepository.find(':'),
+ SVNRepository.find("/lib/Basic"));
+ }
+
+ // Strip off version from a build from an integration branch.
+ URL = URL.slice(0, URL.find("/src/tools/flang"));
+
+ // Trim path prefix off, assuming path came from standard cfe path.
+ size_t Start = URL.find("cfe/");
+ if (Start != StringRef::npos)
+ URL = URL.substr(Start + 4);
+
+ return URL;
+#endif
+}
+
+std::string getLLVMRepositoryPath() {
+#ifdef LLVM_REPOSITORY
+ StringRef URL(LLVM_REPOSITORY);
+#else
+ StringRef URL("");
+#endif
+
+ // Trim path prefix off, assuming path came from standard llvm path.
+ // Leave "llvm/" prefix to distinguish the following llvm revision from the
+ // flang revision.
+ size_t Start = URL.find("llvm/");
+ if (Start != StringRef::npos)
+ URL = URL.substr(Start);
+
+ return URL;
+}
+
+std::string getFlangRevision() {
+#ifdef SVN_REVISION
+ return SVN_REVISION;
+#else
+ return "";
+#endif
+}
+
+std::string getLLVMRevision() {
+#ifdef LLVM_REVISION
+ return LLVM_REVISION;
+#else
+ return "";
+#endif
+}
+
+std::string getFlangFullRepositoryVersion() {
+ std::string buf;
+ llvm::raw_string_ostream OS(buf);
+ std::string Path = getFlangRepositoryPath();
+ std::string Revision = getFlangRevision();
+ if (!Path.empty() || !Revision.empty()) {
+ OS << '(';
+ if (!Path.empty())
+ OS << Path;
+ if (!Revision.empty()) {
+ if (!Path.empty())
+ OS << ' ';
+ OS << Revision;
+ }
+ OS << ')';
+ }
+ // Support LLVM in a separate repository.
+ std::string LLVMRev = getLLVMRevision();
+ if (!LLVMRev.empty() && LLVMRev != Revision) {
+ OS << " (";
+ std::string LLVMRepo = getLLVMRepositoryPath();
+ if (!LLVMRepo.empty())
+ OS << LLVMRepo << ' ';
+ OS << LLVMRev << ')';
+ }
+ return OS.str();
+}
+
+std::string getFlangFullVersion() {
+ return getFlangToolFullVersion("flang");
+}
+
+std::string getFlangToolFullVersion(StringRef ToolName) {
+ std::string buf;
+ llvm::raw_string_ostream OS(buf);
+#ifdef FLANG_VENDOR
+ OS << FLANG_VENDOR;
+#endif
+ OS << ToolName << " version " FLANG_VERSION_STRING " "
+ << getFlangFullRepositoryVersion();
+
+ // If vendor supplied, include the base LLVM version as well.
+#ifdef FLANG_VENDOR
+ OS << " (based on " << BACKEND_PACKAGE_STRING << ")";
+#endif
+
+ return OS.str();
+}
+
+std::string getFlangFullCPPVersion() {
+ // The version string we report in __VERSION__ is just a compacted version of
+ // the one we report on the command line.
+ std::string buf;
+ llvm::raw_string_ostream OS(buf);
+#ifdef FLANG_VENDOR
+ OS << FLANG_VENDOR;
+#endif
+ OS << "Flang " FLANG_VERSION_STRING " " << getFlangFullRepositoryVersion();
+ return OS.str();
+}
+
+} // end namespace flang
--- /dev/null
+add_subdirectory(Basic)
--- /dev/null
+set(LLVM_LINK_COMPONENTS
+ Support
+ )
+
+if (MSVC)
+ set_source_files_properties(SemaExpr.cpp PROPERTIES COMPILE_FLAGS /bigobj)
+endif()
+
+add_clang_library(clangSema
+ Scope.cpp
+ Sema.cpp
+ SemaExpr.cpp
+
+ LINK_LIBS
+ clangBasic
+ )
--- /dev/null
+create_subdirectory_options(FLANG TOOL)
+
+add_flang_subdirectory(flang-info)
+
+#!! add_flang_subdirectory(f18)
+
+#!! if(FLANG_ENABLE_XXXX)
+#!! add_flang_subdirectory(xxxx)
+#!! endif()
+
+
--- /dev/null
+set( LLVM_LINK_COMPONENTS
+ ${LLVM_TARGETS_TO_BUILD}
+ Option
+ Support
+ )
+
+add_flang_executable(flang-info
+ FlangInfo.cpp
+ )
+
+target_link_libraries(flang-info
+ flangBasic
+ )
+
+install(TARGETS flang-info
+ RUNTIME DESTINATION bin)
--- /dev/null
+//===--- tools/clang-check/ClangCheck.cpp - Clang check tool --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a playground to test the build infrastucture and the new APIs.
+// It will eventually disapear.
+//
+//
+// PLEASE DO NOT REPORT CODING STYLE VIOLATIONS ON THAT FILE!
+// THIS IS A TEMPORARY PLAYGROUND!
+//
+//
+//===----------------------------------------------------------------------===//
+
+#include "flang/Basic/Version.h"
+
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Option/OptTable.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/TargetSelect.h"
+
+using namespace llvm;
+using namespace flang;
+
+#include <iostream>
+
+int main(int argc, const char **argv) {
+
+ std::cout << "Flang Repository = '" << getFlangRepositoryPath() << "'\n";
+ std::cout << "Flang Version = '" << getFlangFullVersion() << "'\n";
+
+ std::cout << "LLVM Repository = '" << getLLVMRepositoryPath() << "'\n";
+
+ return 1 ;
+}
--- /dev/null
+set(LLVM_LINK_COMPONENTS Support)
+
+add_tablegen(flang-tblgen FLANG
+ FlangDiagnosticsEmitter.cpp
+ FlangOptionDocEmitter.cpp
+ TableGen.cpp
+ )
--- /dev/null
+//=- FlangDiagnosticsEmitter.cpp - Generate Flang diagnostics tables -*- C++ -*-
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// These tablegen backends emit Flang diagnostics tables.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/PointerUnion.h"
+#include "llvm/ADT/SmallPtrSet.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/StringToOffsetTable.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include <algorithm>
+#include <cctype>
+#include <functional>
+#include <map>
+#include <set>
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// Diagnostic category computation code.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class DiagGroupParentMap {
+ RecordKeeper &Records;
+ std::map<const Record*, std::vector<Record*> > Mapping;
+public:
+ DiagGroupParentMap(RecordKeeper &records) : Records(records) {
+ std::vector<Record*> DiagGroups
+ = Records.getAllDerivedDefinitions("DiagGroup");
+ for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
+ std::vector<Record*> SubGroups =
+ DiagGroups[i]->getValueAsListOfDefs("SubGroups");
+ for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
+ Mapping[SubGroups[j]].push_back(DiagGroups[i]);
+ }
+ }
+
+ const std::vector<Record*> &getParents(const Record *Group) {
+ return Mapping[Group];
+ }
+};
+} // end anonymous namespace.
+
+static std::string
+getCategoryFromDiagGroup(const Record *Group,
+ DiagGroupParentMap &DiagGroupParents) {
+ // If the DiagGroup has a category, return it.
+ std::string CatName = Group->getValueAsString("CategoryName");
+ if (!CatName.empty()) return CatName;
+
+ // The diag group may the subgroup of one or more other diagnostic groups,
+ // check these for a category as well.
+ const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
+ for (unsigned i = 0, e = Parents.size(); i != e; ++i) {
+ CatName = getCategoryFromDiagGroup(Parents[i], DiagGroupParents);
+ if (!CatName.empty()) return CatName;
+ }
+ return "";
+}
+
+/// getDiagnosticCategory - Return the category that the specified diagnostic
+/// lives in.
+static std::string getDiagnosticCategory(const Record *R,
+ DiagGroupParentMap &DiagGroupParents) {
+ // If the diagnostic is in a group, and that group has a category, use it.
+ if (DefInit *Group = dyn_cast<DefInit>(R->getValueInit("Group"))) {
+ // Check the diagnostic's diag group for a category.
+ std::string CatName = getCategoryFromDiagGroup(Group->getDef(),
+ DiagGroupParents);
+ if (!CatName.empty()) return CatName;
+ }
+
+ // If the diagnostic itself has a category, get it.
+ return R->getValueAsString("CategoryName");
+}
+
+namespace {
+ class DiagCategoryIDMap {
+ RecordKeeper &Records;
+ StringMap<unsigned> CategoryIDs;
+ std::vector<std::string> CategoryStrings;
+ public:
+ DiagCategoryIDMap(RecordKeeper &records) : Records(records) {
+ DiagGroupParentMap ParentInfo(Records);
+
+ // The zero'th category is "".
+ CategoryStrings.push_back("");
+ CategoryIDs[""] = 0;
+
+ std::vector<Record*> Diags =
+ Records.getAllDerivedDefinitions("Diagnostic");
+ for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
+ std::string Category = getDiagnosticCategory(Diags[i], ParentInfo);
+ if (Category.empty()) continue; // Skip diags with no category.
+
+ unsigned &ID = CategoryIDs[Category];
+ if (ID != 0) continue; // Already seen.
+
+ ID = CategoryStrings.size();
+ CategoryStrings.push_back(Category);
+ }
+ }
+
+ unsigned getID(StringRef CategoryString) {
+ return CategoryIDs[CategoryString];
+ }
+
+ typedef std::vector<std::string>::const_iterator const_iterator;
+ const_iterator begin() const { return CategoryStrings.begin(); }
+ const_iterator end() const { return CategoryStrings.end(); }
+ };
+
+ struct GroupInfo {
+ std::vector<const Record*> DiagsInGroup;
+ std::vector<std::string> SubGroups;
+ unsigned IDNo;
+
+ const Record *ExplicitDef;
+
+ GroupInfo() : ExplicitDef(nullptr) {}
+ };
+} // end anonymous namespace.
+
+static bool beforeThanCompare(const Record *LHS, const Record *RHS) {
+ assert(!LHS->getLoc().empty() && !RHS->getLoc().empty());
+ return
+ LHS->getLoc().front().getPointer() < RHS->getLoc().front().getPointer();
+}
+
+static bool diagGroupBeforeByName(const Record *LHS, const Record *RHS) {
+ return LHS->getValueAsString("GroupName") <
+ RHS->getValueAsString("GroupName");
+}
+
+static bool beforeThanCompareGroups(const GroupInfo *LHS, const GroupInfo *RHS){
+ assert(!LHS->DiagsInGroup.empty() && !RHS->DiagsInGroup.empty());
+ return beforeThanCompare(LHS->DiagsInGroup.front(),
+ RHS->DiagsInGroup.front());
+}
+
+static SMRange findSuperClassRange(const Record *R, StringRef SuperName) {
+ ArrayRef<std::pair<Record *, SMRange>> Supers = R->getSuperClasses();
+ auto I = std::find_if(Supers.begin(), Supers.end(),
+ [&](const std::pair<Record *, SMRange> &SuperPair) {
+ return SuperPair.first->getName() == SuperName;
+ });
+ return (I != Supers.end()) ? I->second : SMRange();
+}
+
+/// \brief Invert the 1-[0/1] mapping of diags to group into a one to many
+/// mapping of groups to diags in the group.
+static void groupDiagnostics(const std::vector<Record*> &Diags,
+ const std::vector<Record*> &DiagGroups,
+ std::map<std::string, GroupInfo> &DiagsInGroup) {
+
+ for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
+ const Record *R = Diags[i];
+ DefInit *DI = dyn_cast<DefInit>(R->getValueInit("Group"));
+ if (!DI)
+ continue;
+ assert(R->getValueAsDef("Class")->getName() != "CLASS_NOTE" &&
+ "Note can't be in a DiagGroup");
+ std::string GroupName = DI->getDef()->getValueAsString("GroupName");
+ DiagsInGroup[GroupName].DiagsInGroup.push_back(R);
+ }
+
+ typedef SmallPtrSet<GroupInfo *, 16> GroupSetTy;
+ GroupSetTy ImplicitGroups;
+
+ // Add all DiagGroup's to the DiagsInGroup list to make sure we pick up empty
+ // groups (these are warnings that GCC supports that flang never produces).
+ for (unsigned i = 0, e = DiagGroups.size(); i != e; ++i) {
+ Record *Group = DiagGroups[i];
+ GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")];
+ if (Group->isAnonymous()) {
+ if (GI.DiagsInGroup.size() > 1)
+ ImplicitGroups.insert(&GI);
+ } else {
+ if (GI.ExplicitDef)
+ assert(GI.ExplicitDef == Group);
+ else
+ GI.ExplicitDef = Group;
+ }
+
+ std::vector<Record*> SubGroups = Group->getValueAsListOfDefs("SubGroups");
+ for (unsigned j = 0, e = SubGroups.size(); j != e; ++j)
+ GI.SubGroups.push_back(SubGroups[j]->getValueAsString("GroupName"));
+ }
+
+ // Assign unique ID numbers to the groups.
+ unsigned IDNo = 0;
+ for (std::map<std::string, GroupInfo>::iterator
+ I = DiagsInGroup.begin(), E = DiagsInGroup.end(); I != E; ++I, ++IDNo)
+ I->second.IDNo = IDNo;
+
+ // Sort the implicit groups, so we can warn about them deterministically.
+ SmallVector<GroupInfo *, 16> SortedGroups(ImplicitGroups.begin(),
+ ImplicitGroups.end());
+ for (SmallVectorImpl<GroupInfo *>::iterator I = SortedGroups.begin(),
+ E = SortedGroups.end();
+ I != E; ++I) {
+ MutableArrayRef<const Record *> GroupDiags = (*I)->DiagsInGroup;
+ std::sort(GroupDiags.begin(), GroupDiags.end(), beforeThanCompare);
+ }
+ std::sort(SortedGroups.begin(), SortedGroups.end(), beforeThanCompareGroups);
+
+ // Warn about the same group being used anonymously in multiple places.
+ for (SmallVectorImpl<GroupInfo *>::const_iterator I = SortedGroups.begin(),
+ E = SortedGroups.end();
+ I != E; ++I) {
+ ArrayRef<const Record *> GroupDiags = (*I)->DiagsInGroup;
+
+ if ((*I)->ExplicitDef) {
+ std::string Name = (*I)->ExplicitDef->getValueAsString("GroupName");
+ for (ArrayRef<const Record *>::const_iterator DI = GroupDiags.begin(),
+ DE = GroupDiags.end();
+ DI != DE; ++DI) {
+ const DefInit *GroupInit = cast<DefInit>((*DI)->getValueInit("Group"));
+ const Record *NextDiagGroup = GroupInit->getDef();
+ if (NextDiagGroup == (*I)->ExplicitDef)
+ continue;
+
+ SMRange InGroupRange = findSuperClassRange(*DI, "InGroup");
+ SmallString<64> Replacement;
+ if (InGroupRange.isValid()) {
+ Replacement += "InGroup<";
+ Replacement += (*I)->ExplicitDef->getName();
+ Replacement += ">";
+ }
+ SMFixIt FixIt(InGroupRange, Replacement);
+
+ SrcMgr.PrintMessage(NextDiagGroup->getLoc().front(),
+ SourceMgr::DK_Error,
+ Twine("group '") + Name +
+ "' is referred to anonymously",
+ None,
+ InGroupRange.isValid() ? FixIt
+ : ArrayRef<SMFixIt>());
+ SrcMgr.PrintMessage((*I)->ExplicitDef->getLoc().front(),
+ SourceMgr::DK_Note, "group defined here");
+ }
+ } else {
+ // If there's no existing named group, we should just warn once and use
+ // notes to list all the other cases.
+ ArrayRef<const Record *>::const_iterator DI = GroupDiags.begin(),
+ DE = GroupDiags.end();
+ assert(DI != DE && "We only care about groups with multiple uses!");
+
+ const DefInit *GroupInit = cast<DefInit>((*DI)->getValueInit("Group"));
+ const Record *NextDiagGroup = GroupInit->getDef();
+ std::string Name = NextDiagGroup->getValueAsString("GroupName");
+
+ SMRange InGroupRange = findSuperClassRange(*DI, "InGroup");
+ SrcMgr.PrintMessage(NextDiagGroup->getLoc().front(),
+ SourceMgr::DK_Error,
+ Twine("group '") + Name +
+ "' is referred to anonymously",
+ InGroupRange);
+
+ for (++DI; DI != DE; ++DI) {
+ GroupInit = cast<DefInit>((*DI)->getValueInit("Group"));
+ InGroupRange = findSuperClassRange(*DI, "InGroup");
+ SrcMgr.PrintMessage(GroupInit->getDef()->getLoc().front(),
+ SourceMgr::DK_Note, "also referenced here",
+ InGroupRange);
+ }
+ }
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Infer members of -Wpedantic.
+//===----------------------------------------------------------------------===//
+
+typedef std::vector<const Record *> RecordVec;
+typedef llvm::DenseSet<const Record *> RecordSet;
+typedef llvm::PointerUnion<RecordVec*, RecordSet*> VecOrSet;
+
+namespace {
+class InferPedantic {
+ typedef llvm::DenseMap<const Record*,
+ std::pair<unsigned, Optional<unsigned> > > GMap;
+
+ DiagGroupParentMap &DiagGroupParents;
+ const std::vector<Record*> &Diags;
+ const std::vector<Record*> DiagGroups;
+ std::map<std::string, GroupInfo> &DiagsInGroup;
+ llvm::DenseSet<const Record*> DiagsSet;
+ GMap GroupCount;
+public:
+ InferPedantic(DiagGroupParentMap &DiagGroupParents,
+ const std::vector<Record*> &Diags,
+ const std::vector<Record*> &DiagGroups,
+ std::map<std::string, GroupInfo> &DiagsInGroup)
+ : DiagGroupParents(DiagGroupParents),
+ Diags(Diags),
+ DiagGroups(DiagGroups),
+ DiagsInGroup(DiagsInGroup) {}
+
+ /// Compute the set of diagnostics and groups that are immediately
+ /// in -Wpedantic.
+ void compute(VecOrSet DiagsInPedantic,
+ VecOrSet GroupsInPedantic);
+
+private:
+ /// Determine whether a group is a subgroup of another group.
+ bool isSubGroupOfGroup(const Record *Group,
+ llvm::StringRef RootGroupName);
+
+ /// Determine if the diagnostic is an extension.
+ bool isExtension(const Record *Diag);
+
+ /// Determine if the diagnostic is off by default.
+ bool isOffByDefault(const Record *Diag);
+
+ /// Increment the count for a group, and transitively marked
+ /// parent groups when appropriate.
+ void markGroup(const Record *Group);
+
+ /// Return true if the diagnostic is in a pedantic group.
+ bool groupInPedantic(const Record *Group, bool increment = false);
+};
+} // end anonymous namespace
+
+bool InferPedantic::isSubGroupOfGroup(const Record *Group,
+ llvm::StringRef GName) {
+
+ const std::string &GroupName = Group->getValueAsString("GroupName");
+ if (GName == GroupName)
+ return true;
+
+ const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
+ for (unsigned i = 0, e = Parents.size(); i != e; ++i)
+ if (isSubGroupOfGroup(Parents[i], GName))
+ return true;
+
+ return false;
+}
+
+/// Determine if the diagnostic is an extension.
+bool InferPedantic::isExtension(const Record *Diag) {
+ const std::string &ClsName = Diag->getValueAsDef("Class")->getName();
+ return ClsName == "CLASS_EXTENSION";
+}
+
+bool InferPedantic::isOffByDefault(const Record *Diag) {
+ const std::string &DefSeverity =
+ Diag->getValueAsDef("DefaultSeverity")->getValueAsString("Name");
+ return DefSeverity == "Ignored";
+}
+
+bool InferPedantic::groupInPedantic(const Record *Group, bool increment) {
+ GMap::mapped_type &V = GroupCount[Group];
+ // Lazily compute the threshold value for the group count.
+ if (!V.second.hasValue()) {
+ const GroupInfo &GI = DiagsInGroup[Group->getValueAsString("GroupName")];
+ V.second = GI.SubGroups.size() + GI.DiagsInGroup.size();
+ }
+
+ if (increment)
+ ++V.first;
+
+ // Consider a group in -Wpendatic IFF if has at least one diagnostic
+ // or subgroup AND all of those diagnostics and subgroups are covered
+ // by -Wpedantic via our computation.
+ return V.first != 0 && V.first == V.second.getValue();
+}
+
+void InferPedantic::markGroup(const Record *Group) {
+ // If all the diagnostics and subgroups have been marked as being
+ // covered by -Wpedantic, increment the count of parent groups. Once the
+ // group's count is equal to the number of subgroups and diagnostics in
+ // that group, we can safely add this group to -Wpedantic.
+ if (groupInPedantic(Group, /* increment */ true)) {
+ const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
+ for (unsigned i = 0, e = Parents.size(); i != e; ++i)
+ markGroup(Parents[i]);
+ }
+}
+
+void InferPedantic::compute(VecOrSet DiagsInPedantic,
+ VecOrSet GroupsInPedantic) {
+ // All extensions that are not on by default are implicitly in the
+ // "pedantic" group. For those that aren't explicitly included in -Wpedantic,
+ // mark them for consideration to be included in -Wpedantic directly.
+ for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
+ Record *R = Diags[i];
+ if (isExtension(R) && isOffByDefault(R)) {
+ DiagsSet.insert(R);
+ if (DefInit *Group = dyn_cast<DefInit>(R->getValueInit("Group"))) {
+ const Record *GroupRec = Group->getDef();
+ if (!isSubGroupOfGroup(GroupRec, "pedantic")) {
+ markGroup(GroupRec);
+ }
+ }
+ }
+ }
+
+ // Compute the set of diagnostics that are directly in -Wpedantic. We
+ // march through Diags a second time to ensure the results are emitted
+ // in deterministic order.
+ for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
+ Record *R = Diags[i];
+ if (!DiagsSet.count(R))
+ continue;
+ // Check if the group is implicitly in -Wpedantic. If so,
+ // the diagnostic should not be directly included in the -Wpedantic
+ // diagnostic group.
+ if (DefInit *Group = dyn_cast<DefInit>(R->getValueInit("Group")))
+ if (groupInPedantic(Group->getDef()))
+ continue;
+
+ // The diagnostic is not included in a group that is (transitively) in
+ // -Wpedantic. Include it in -Wpedantic directly.
+ if (RecordVec *V = DiagsInPedantic.dyn_cast<RecordVec*>())
+ V->push_back(R);
+ else {
+ DiagsInPedantic.get<RecordSet*>()->insert(R);
+ }
+ }
+
+ if (!GroupsInPedantic)
+ return;
+
+ // Compute the set of groups that are directly in -Wpedantic. We
+ // march through the groups to ensure the results are emitted
+ /// in a deterministc order.
+ for (unsigned i = 0, ei = DiagGroups.size(); i != ei; ++i) {
+ Record *Group = DiagGroups[i];
+ if (!groupInPedantic(Group))
+ continue;
+
+ unsigned ParentsInPedantic = 0;
+ const std::vector<Record*> &Parents = DiagGroupParents.getParents(Group);
+ for (unsigned j = 0, ej = Parents.size(); j != ej; ++j) {
+ if (groupInPedantic(Parents[j]))
+ ++ParentsInPedantic;
+ }
+ // If all the parents are in -Wpedantic, this means that this diagnostic
+ // group will be indirectly included by -Wpedantic already. In that
+ // case, do not add it directly to -Wpedantic. If the group has no
+ // parents, obviously it should go into -Wpedantic.
+ if (Parents.size() > 0 && ParentsInPedantic == Parents.size())
+ continue;
+
+ if (RecordVec *V = GroupsInPedantic.dyn_cast<RecordVec*>())
+ V->push_back(Group);
+ else {
+ GroupsInPedantic.get<RecordSet*>()->insert(Group);
+ }
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Warning Tables (.inc file) generation.
+//===----------------------------------------------------------------------===//
+
+static bool isError(const Record &Diag) {
+ const std::string &ClsName = Diag.getValueAsDef("Class")->getName();
+ return ClsName == "CLASS_ERROR";
+}
+
+static bool isRemark(const Record &Diag) {
+ const std::string &ClsName = Diag.getValueAsDef("Class")->getName();
+ return ClsName == "CLASS_REMARK";
+}
+
+/// FlangDiagsDefsEmitter - The top-level class emits .def files containing
+/// declarations of Flang diagnostics.
+namespace flang {
+void EmitFlangDiagsDefs(RecordKeeper &Records, raw_ostream &OS,
+ const std::string &Component) {
+ // Write the #if guard
+ if (!Component.empty()) {
+ std::string ComponentName = StringRef(Component).upper();
+ OS << "#ifdef " << ComponentName << "START\n";
+ OS << "__" << ComponentName << "START = DIAG_START_" << ComponentName
+ << ",\n";
+ OS << "#undef " << ComponentName << "START\n";
+ OS << "#endif\n\n";
+ }
+
+ const std::vector<Record*> &Diags =
+ Records.getAllDerivedDefinitions("Diagnostic");
+
+ std::vector<Record*> DiagGroups
+ = Records.getAllDerivedDefinitions("DiagGroup");
+
+ std::map<std::string, GroupInfo> DiagsInGroup;
+ groupDiagnostics(Diags, DiagGroups, DiagsInGroup);
+
+ DiagCategoryIDMap CategoryIDs(Records);
+ DiagGroupParentMap DGParentMap(Records);
+
+ // Compute the set of diagnostics that are in -Wpedantic.
+ RecordSet DiagsInPedantic;
+ InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup);
+ inferPedantic.compute(&DiagsInPedantic, (RecordVec*)nullptr);
+
+ for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
+ const Record &R = *Diags[i];
+
+ // Check if this is an error that is accidentally in a warning
+ // group.
+ if (isError(R)) {
+ if (DefInit *Group = dyn_cast<DefInit>(R.getValueInit("Group"))) {
+ const Record *GroupRec = Group->getDef();
+ const std::string &GroupName = GroupRec->getValueAsString("GroupName");
+ PrintFatalError(R.getLoc(), "Error " + R.getName() +
+ " cannot be in a warning group [" + GroupName + "]");
+ }
+ }
+
+ // Check that all remarks have an associated diagnostic group.
+ if (isRemark(R)) {
+ if (!isa<DefInit>(R.getValueInit("Group"))) {
+ PrintFatalError(R.getLoc(), "Error " + R.getName() +
+ " not in any diagnostic group");
+ }
+ }
+
+ // Filter by component.
+ if (!Component.empty() && Component != R.getValueAsString("Component"))
+ continue;
+
+ OS << "DIAG(" << R.getName() << ", ";
+ OS << R.getValueAsDef("Class")->getName();
+ OS << ", (unsigned)diag::Severity::"
+ << R.getValueAsDef("DefaultSeverity")->getValueAsString("Name");
+
+ // Description string.
+ OS << ", \"";
+ OS.write_escaped(R.getValueAsString("Text")) << '"';
+
+ // Warning associated with the diagnostic. This is stored as an index into
+ // the alphabetically sorted warning table.
+ if (DefInit *DI = dyn_cast<DefInit>(R.getValueInit("Group"))) {
+ std::map<std::string, GroupInfo>::iterator I =
+ DiagsInGroup.find(DI->getDef()->getValueAsString("GroupName"));
+ assert(I != DiagsInGroup.end());
+ OS << ", " << I->second.IDNo;
+ } else if (DiagsInPedantic.count(&R)) {
+ std::map<std::string, GroupInfo>::iterator I =
+ DiagsInGroup.find("pedantic");
+ assert(I != DiagsInGroup.end() && "pedantic group not defined");
+ OS << ", " << I->second.IDNo;
+ } else {
+ OS << ", 0";
+ }
+
+ // SFINAE response.
+ OS << ", " << R.getValueAsDef("SFINAE")->getName();
+
+ // Default warning has no Werror bit.
+ if (R.getValueAsBit("WarningNoWerror"))
+ OS << ", true";
+ else
+ OS << ", false";
+
+ if (R.getValueAsBit("ShowInSystemHeader"))
+ OS << ", true";
+ else
+ OS << ", false";
+
+ // Category number.
+ OS << ", " << CategoryIDs.getID(getDiagnosticCategory(&R, DGParentMap));
+ OS << ")\n";
+ }
+}
+} // end namespace flang
+
+//===----------------------------------------------------------------------===//
+// Warning Group Tables generation
+//===----------------------------------------------------------------------===//
+
+static std::string getDiagCategoryEnum(llvm::StringRef name) {
+ if (name.empty())
+ return "DiagCat_None";
+ SmallString<256> enumName = llvm::StringRef("DiagCat_");
+ for (llvm::StringRef::iterator I = name.begin(), E = name.end(); I != E; ++I)
+ enumName += isalnum(*I) ? *I : '_';
+ return enumName.str();
+}
+
+/// \brief Emit the array of diagnostic subgroups.
+///
+/// The array of diagnostic subgroups contains for each group a list of its
+/// subgroups. The individual lists are separated by '-1'. Groups with no
+/// subgroups are skipped.
+///
+/// \code
+/// static const int16_t DiagSubGroups[] = {
+/// /* Empty */ -1,
+/// /* DiagSubGroup0 */ 142, -1,
+/// /* DiagSubGroup13 */ 265, 322, 399, -1
+/// }
+/// \endcode
+///
+static void emitDiagSubGroups(std::map<std::string, GroupInfo> &DiagsInGroup,
+ RecordVec &GroupsInPedantic, raw_ostream &OS) {
+ OS << "static const int16_t DiagSubGroups[] = {\n"
+ << " /* Empty */ -1,\n";
+ for (auto const &I : DiagsInGroup) {
+ const bool IsPedantic = I.first == "pedantic";
+
+ const std::vector<std::string> &SubGroups = I.second.SubGroups;
+ if (!SubGroups.empty() || (IsPedantic && !GroupsInPedantic.empty())) {
+ OS << " /* DiagSubGroup" << I.second.IDNo << " */ ";
+ for (auto const &SubGroup : SubGroups) {
+ std::map<std::string, GroupInfo>::const_iterator RI =
+ DiagsInGroup.find(SubGroup);
+ assert(RI != DiagsInGroup.end() && "Referenced without existing?");
+ OS << RI->second.IDNo << ", ";
+ }
+ // Emit the groups implicitly in "pedantic".
+ if (IsPedantic) {
+ for (auto const &Group : GroupsInPedantic) {
+ const std::string &GroupName = Group->getValueAsString("GroupName");
+ std::map<std::string, GroupInfo>::const_iterator RI =
+ DiagsInGroup.find(GroupName);
+ assert(RI != DiagsInGroup.end() && "Referenced without existing?");
+ OS << RI->second.IDNo << ", ";
+ }
+ }
+
+ OS << "-1,\n";
+ }
+ }
+ OS << "};\n\n";
+}
+
+/// \brief Emit the list of diagnostic arrays.
+///
+/// This data structure is a large array that contains itself arrays of varying
+/// size. Each array represents a list of diagnostics. The different arrays are
+/// separated by the value '-1'.
+///
+/// \code
+/// static const int16_t DiagArrays[] = {
+/// /* Empty */ -1,
+/// /* DiagArray1 */ diag::warn_pragma_message,
+/// -1,
+/// /* DiagArray2 */ diag::warn_abs_too_small,
+/// diag::warn_unsigned_abs,
+/// diag::warn_wrong_absolute_value_type,
+/// -1
+/// };
+/// \endcode
+///
+static void emitDiagArrays(std::map<std::string, GroupInfo> &DiagsInGroup,
+ RecordVec &DiagsInPedantic, raw_ostream &OS) {
+ OS << "static const int16_t DiagArrays[] = {\n"
+ << " /* Empty */ -1,\n";
+ for (auto const &I : DiagsInGroup) {
+ const bool IsPedantic = I.first == "pedantic";
+
+ const std::vector<const Record *> &V = I.second.DiagsInGroup;
+ if (!V.empty() || (IsPedantic && !DiagsInPedantic.empty())) {
+ OS << " /* DiagArray" << I.second.IDNo << " */ ";
+ for (auto *Record : V)
+ OS << "diag::" << Record->getName() << ", ";
+ // Emit the diagnostics implicitly in "pedantic".
+ if (IsPedantic) {
+ for (auto const &Diag : DiagsInPedantic)
+ OS << "diag::" << Diag->getName() << ", ";
+ }
+ OS << "-1,\n";
+ }
+ }
+ OS << "};\n\n";
+}
+
+/// \brief Emit a list of group names.
+///
+/// This creates a long string which by itself contains a list of pascal style
+/// strings, which consist of a length byte directly followed by the string.
+///
+/// \code
+/// static const char DiagGroupNames[] = {
+/// \000\020#pragma-messages\t#warnings\020CFString-literal"
+/// };
+/// \endcode
+static void emitDiagGroupNames(StringToOffsetTable &GroupNames,
+ raw_ostream &OS) {
+ OS << "static const char DiagGroupNames[] = {\n";
+ GroupNames.EmitString(OS);
+ OS << "};\n\n";
+}
+
+/// \brief Emit diagnostic arrays and related data structures.
+///
+/// This creates the actual diagnostic array, an array of diagnostic subgroups
+/// and an array of subgroup names.
+///
+/// \code
+/// #ifdef GET_DIAG_ARRAYS
+/// static const int16_t DiagArrays[];
+/// static const int16_t DiagSubGroups[];
+/// static const char DiagGroupNames[];
+/// #endif
+/// \endcode
+static void emitAllDiagArrays(std::map<std::string, GroupInfo> &DiagsInGroup,
+ RecordVec &DiagsInPedantic,
+ RecordVec &GroupsInPedantic,
+ StringToOffsetTable &GroupNames,
+ raw_ostream &OS) {
+ OS << "\n#ifdef GET_DIAG_ARRAYS\n";
+ emitDiagArrays(DiagsInGroup, DiagsInPedantic, OS);
+ emitDiagSubGroups(DiagsInGroup, GroupsInPedantic, OS);
+ emitDiagGroupNames(GroupNames, OS);
+ OS << "#endif // GET_DIAG_ARRAYS\n\n";
+}
+
+/// \brief Emit diagnostic table.
+///
+/// The table is sorted by the name of the diagnostic group. Each element
+/// consists of the name of the diagnostic group (given as offset in the
+/// group name table), a reference to a list of diagnostics (optional) and a
+/// reference to a set of subgroups (optional).
+///
+/// \code
+/// #ifdef GET_DIAG_TABLE
+/// {/* abi */ 159, /* DiagArray11 */ 19, /* Empty */ 0},
+/// {/* aggregate-return */ 180, /* Empty */ 0, /* Empty */ 0},
+/// {/* all */ 197, /* Empty */ 0, /* DiagSubGroup13 */ 3},
+/// {/* deprecated */ 1981,/* DiagArray1 */ 348, /* DiagSubGroup3 */ 9},
+/// #endif
+/// \endcode
+static void emitDiagTable(std::map<std::string, GroupInfo> &DiagsInGroup,
+ RecordVec &DiagsInPedantic,
+ RecordVec &GroupsInPedantic,
+ StringToOffsetTable &GroupNames, raw_ostream &OS) {
+ unsigned MaxLen = 0;
+
+ for (auto const &I: DiagsInGroup)
+ MaxLen = std::max(MaxLen, (unsigned)I.first.size());
+
+ OS << "\n#ifdef GET_DIAG_TABLE\n";
+ unsigned SubGroupIndex = 1, DiagArrayIndex = 1;
+ for (auto const &I: DiagsInGroup) {
+ // Group option string.
+ OS << " { /* ";
+ if (I.first.find_first_not_of("abcdefghijklmnopqrstuvwxyz"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
+ "0123456789!@#$%^*-+=:?") !=
+ std::string::npos)
+ PrintFatalError("Invalid character in diagnostic group '" + I.first +
+ "'");
+ OS << I.first << " */ " << std::string(MaxLen - I.first.size(), ' ');
+ // Store a pascal-style length byte at the beginning of the string.
+ std::string Name = char(I.first.size()) + I.first;
+ OS << GroupNames.GetOrAddStringOffset(Name, false) << ", ";
+
+ // Special handling for 'pedantic'.
+ const bool IsPedantic = I.first == "pedantic";
+
+ // Diagnostics in the group.
+ const std::vector<const Record *> &V = I.second.DiagsInGroup;
+ const bool hasDiags =
+ !V.empty() || (IsPedantic && !DiagsInPedantic.empty());
+ if (hasDiags) {
+ OS << "/* DiagArray" << I.second.IDNo << " */ " << DiagArrayIndex
+ << ", ";
+ if (IsPedantic)
+ DiagArrayIndex += DiagsInPedantic.size();
+ DiagArrayIndex += V.size() + 1;
+ } else {
+ OS << "/* Empty */ 0, ";
+ }
+
+ // Subgroups.
+ const std::vector<std::string> &SubGroups = I.second.SubGroups;
+ const bool hasSubGroups =
+ !SubGroups.empty() || (IsPedantic && !GroupsInPedantic.empty());
+ if (hasSubGroups) {
+ OS << "/* DiagSubGroup" << I.second.IDNo << " */ " << SubGroupIndex;
+ if (IsPedantic)
+ SubGroupIndex += GroupsInPedantic.size();
+ SubGroupIndex += SubGroups.size() + 1;
+ } else {
+ OS << "/* Empty */ 0";
+ }
+
+ OS << " },\n";
+ }
+ OS << "#endif // GET_DIAG_TABLE\n\n";
+}
+
+/// \brief Emit the table of diagnostic categories.
+///
+/// The table has the form of macro calls that have two parameters. The
+/// category's name as well as an enum that represents the category. The
+/// table can be used by defining the macro 'CATEGORY' and including this
+/// table right after.
+///
+/// \code
+/// #ifdef GET_CATEGORY_TABLE
+/// CATEGORY("Semantic Issue", DiagCat_Semantic_Issue)
+/// CATEGORY("Lambda Issue", DiagCat_Lambda_Issue)
+/// #endif
+/// \endcode
+static void emitCategoryTable(RecordKeeper &Records, raw_ostream &OS) {
+ DiagCategoryIDMap CategoriesByID(Records);
+ OS << "\n#ifdef GET_CATEGORY_TABLE\n";
+ for (auto const &C : CategoriesByID)
+ OS << "CATEGORY(\"" << C << "\", " << getDiagCategoryEnum(C) << ")\n";
+ OS << "#endif // GET_CATEGORY_TABLE\n\n";
+}
+
+namespace flang {
+void EmitFlangDiagGroups(RecordKeeper &Records, raw_ostream &OS) {
+ // Compute a mapping from a DiagGroup to all of its parents.
+ DiagGroupParentMap DGParentMap(Records);
+
+ std::vector<Record *> Diags = Records.getAllDerivedDefinitions("Diagnostic");
+
+ std::vector<Record *> DiagGroups =
+ Records.getAllDerivedDefinitions("DiagGroup");
+
+ std::map<std::string, GroupInfo> DiagsInGroup;
+ groupDiagnostics(Diags, DiagGroups, DiagsInGroup);
+
+ // All extensions are implicitly in the "pedantic" group. Record the
+ // implicit set of groups in the "pedantic" group, and use this information
+ // later when emitting the group information for Pedantic.
+ RecordVec DiagsInPedantic;
+ RecordVec GroupsInPedantic;
+ InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup);
+ inferPedantic.compute(&DiagsInPedantic, &GroupsInPedantic);
+
+ StringToOffsetTable GroupNames;
+ for (std::map<std::string, GroupInfo>::const_iterator
+ I = DiagsInGroup.begin(),
+ E = DiagsInGroup.end();
+ I != E; ++I) {
+ // Store a pascal-style length byte at the beginning of the string.
+ std::string Name = char(I->first.size()) + I->first;
+ GroupNames.GetOrAddStringOffset(Name, false);
+ }
+
+ emitAllDiagArrays(DiagsInGroup, DiagsInPedantic, GroupsInPedantic, GroupNames,
+ OS);
+ emitDiagTable(DiagsInGroup, DiagsInPedantic, GroupsInPedantic, GroupNames,
+ OS);
+ emitCategoryTable(Records, OS);
+}
+} // end namespace flang
+
+//===----------------------------------------------------------------------===//
+// Diagnostic name index generation
+//===----------------------------------------------------------------------===//
+
+namespace {
+struct RecordIndexElement
+{
+ RecordIndexElement() {}
+ explicit RecordIndexElement(Record const &R):
+ Name(R.getName()) {}
+
+ std::string Name;
+};
+} // end anonymous namespace.
+
+namespace flang {
+void EmitFlangDiagsIndexName(RecordKeeper &Records, raw_ostream &OS) {
+ const std::vector<Record*> &Diags =
+ Records.getAllDerivedDefinitions("Diagnostic");
+
+ std::vector<RecordIndexElement> Index;
+ Index.reserve(Diags.size());
+ for (unsigned i = 0, e = Diags.size(); i != e; ++i) {
+ const Record &R = *(Diags[i]);
+ Index.push_back(RecordIndexElement(R));
+ }
+
+ std::sort(Index.begin(), Index.end(),
+ [](const RecordIndexElement &Lhs,
+ const RecordIndexElement &Rhs) { return Lhs.Name < Rhs.Name; });
+
+ for (unsigned i = 0, e = Index.size(); i != e; ++i) {
+ const RecordIndexElement &R = Index[i];
+
+ OS << "DIAG_NAME_INDEX(" << R.Name << ")\n";
+ }
+}
+
+//===----------------------------------------------------------------------===//
+// Diagnostic documentation generation
+//===----------------------------------------------------------------------===//
+
+namespace docs {
+namespace {
+
+/// Diagnostic text, parsed into pieces.
+struct DiagText {
+ struct Piece {
+ // This type and its derived classes are move-only.
+ Piece() {}
+ Piece(Piece &&O) {}
+ Piece &operator=(Piece &&O) { return *this; }
+
+ virtual void print(std::vector<std::string> &RST) = 0;
+ virtual ~Piece() {}
+ };
+ struct TextPiece : Piece {
+ StringRef Role;
+ std::string Text;
+ void print(std::vector<std::string> &RST) override;
+ };
+ struct PlaceholderPiece : Piece {
+ int Index;
+ void print(std::vector<std::string> &RST) override;
+ };
+ struct SelectPiece : Piece {
+ SelectPiece() {}
+ SelectPiece(SelectPiece &&O) noexcept : Options(std::move(O.Options)) {}
+ std::vector<DiagText> Options;
+ void print(std::vector<std::string> &RST) override;
+ };
+
+ std::vector<std::unique_ptr<Piece>> Pieces;
+
+ DiagText();
+ DiagText(DiagText &&O) noexcept : Pieces(std::move(O.Pieces)) {}
+
+ DiagText(StringRef Text);
+ DiagText(StringRef Kind, StringRef Text);
+
+ template<typename P> void add(P Piece) {
+ Pieces.push_back(llvm::make_unique<P>(std::move(Piece)));
+ }
+ void print(std::vector<std::string> &RST);
+};
+
+DiagText parseDiagText(StringRef &Text, bool Nested = false) {
+ DiagText Parsed;
+
+ while (!Text.empty()) {
+ size_t End = (size_t)-2;
+ do
+ End = Nested ? Text.find_first_of("%|}", End + 2)
+ : Text.find_first_of('%', End + 2);
+ while (End < Text.size() - 1 && Text[End] == '%' && Text[End + 1] == '%');
+
+ if (End) {
+ DiagText::TextPiece Piece;
+ Piece.Role = "diagtext";
+ Piece.Text = Text.slice(0, End);
+ Parsed.add(std::move(Piece));
+ Text = Text.slice(End, StringRef::npos);
+ if (Text.empty()) break;
+ }
+
+ if (Text[0] == '|' || Text[0] == '}')
+ break;
+
+ // Drop the '%'.
+ Text = Text.drop_front();
+
+ // Extract the (optional) modifier.
+ size_t ModLength = Text.find_first_of("0123456789{");
+ StringRef Modifier = Text.slice(0, ModLength);
+ Text = Text.slice(ModLength, StringRef::npos);
+
+ // FIXME: Handle %ordinal here.
+ if (Modifier == "select" || Modifier == "plural") {
+ DiagText::SelectPiece Select;
+ do {
+ Text = Text.drop_front();
+ if (Modifier == "plural")
+ while (Text[0] != ':')
+ Text = Text.drop_front();
+ Select.Options.push_back(parseDiagText(Text, true));
+ assert(!Text.empty() && "malformed %select");
+ } while (Text.front() == '|');
+ Parsed.add(std::move(Select));
+
+ // Drop the trailing '}n'.
+ Text = Text.drop_front(2);
+ continue;
+ }
+
+ // For %diff, just take the second alternative (tree diagnostic). It would
+ // be preferable to take the first one, and replace the $ with the suitable
+ // placeholders.
+ if (Modifier == "diff") {
+ Text = Text.drop_front(); // '{'
+ parseDiagText(Text, true);
+ Text = Text.drop_front(); // '|'
+
+ DiagText D = parseDiagText(Text, true);
+ for (auto &P : D.Pieces)
+ Parsed.Pieces.push_back(std::move(P));
+
+ Text = Text.drop_front(4); // '}n,m'
+ continue;
+ }
+
+ if (Modifier == "s") {
+ Text = Text.drop_front();
+ DiagText::SelectPiece Select;
+ Select.Options.push_back(DiagText(""));
+ Select.Options.push_back(DiagText("s"));
+ Parsed.add(std::move(Select));
+ continue;
+ }
+
+ assert(!Text.empty() && isdigit(Text[0]) && "malformed placeholder");
+ DiagText::PlaceholderPiece Placeholder;
+ Placeholder.Index = Text[0] - '0';
+ Parsed.add(std::move(Placeholder));
+ Text = Text.drop_front();
+ continue;
+ }
+ return Parsed;
+}
+
+DiagText::DiagText() {}
+
+DiagText::DiagText(StringRef Text) : DiagText(parseDiagText(Text, false)) {}
+
+DiagText::DiagText(StringRef Kind, StringRef Text) : DiagText(parseDiagText(Text, false)) {
+ TextPiece Prefix;
+ Prefix.Role = Kind;
+ Prefix.Text = Kind;
+ Prefix.Text += ": ";
+ Pieces.insert(Pieces.begin(),
+ llvm::make_unique<TextPiece>(std::move(Prefix)));
+}
+
+void escapeRST(StringRef Str, std::string &Out) {
+ for (auto K : Str) {
+ if (StringRef("`*|_[]\\").count(K))
+ Out.push_back('\\');
+ Out.push_back(K);
+ }
+}
+
+template<typename It> void padToSameLength(It Begin, It End) {
+ size_t Width = 0;
+ for (It I = Begin; I != End; ++I)
+ Width = std::max(Width, I->size());
+ for (It I = Begin; I != End; ++I)
+ (*I) += std::string(Width - I->size(), ' ');
+}
+
+template<typename It> void makeTableRows(It Begin, It End) {
+ if (Begin == End) return;
+ padToSameLength(Begin, End);
+ for (It I = Begin; I != End; ++I)
+ *I = "|" + *I + "|";
+}
+
+void makeRowSeparator(std::string &Str) {
+ for (char &K : Str)
+ K = (K == '|' ? '+' : '-');
+}
+
+void DiagText::print(std::vector<std::string> &RST) {
+ if (Pieces.empty()) {
+ RST.push_back("");
+ return;
+ }
+
+ if (Pieces.size() == 1)
+ return Pieces[0]->print(RST);
+
+ std::string EmptyLinePrefix;
+ size_t Start = RST.size();
+ bool HasMultipleLines = true;
+ for (auto &P : Pieces) {
+ std::vector<std::string> Lines;
+ P->print(Lines);
+ if (Lines.empty())
+ continue;
+
+ // We need a vertical separator if either this or the previous piece is a
+ // multi-line piece, or this is the last piece.
+ const char *Separator = (Lines.size() > 1 || HasMultipleLines) ? "|" : "";
+ HasMultipleLines = Lines.size() > 1;
+
+ if (Start + Lines.size() > RST.size())
+ RST.resize(Start + Lines.size(), EmptyLinePrefix);
+
+ padToSameLength(Lines.begin(), Lines.end());
+ for (size_t I = 0; I != Lines.size(); ++I)
+ RST[Start + I] += Separator + Lines[I];
+ std::string Empty(Lines[0].size(), ' ');
+ for (size_t I = Start + Lines.size(); I != RST.size(); ++I)
+ RST[I] += Separator + Empty;
+ EmptyLinePrefix += Separator + Empty;
+ }
+ for (size_t I = Start; I != RST.size(); ++I)
+ RST[I] += "|";
+ EmptyLinePrefix += "|";
+
+ makeRowSeparator(EmptyLinePrefix);
+ RST.insert(RST.begin() + Start, EmptyLinePrefix);
+ RST.insert(RST.end(), EmptyLinePrefix);
+}
+
+void DiagText::TextPiece::print(std::vector<std::string> &RST) {
+ RST.push_back("");
+ auto &S = RST.back();
+
+ StringRef T = Text;
+ while (!T.empty() && T.front() == ' ') {
+ RST.back() += " |nbsp| ";
+ T = T.drop_front();
+ }
+
+ std::string Suffix;
+ while (!T.empty() && T.back() == ' ') {
+ Suffix += " |nbsp| ";
+ T = T.drop_back();
+ }
+
+ if (!T.empty()) {
+ S += ':';
+ S += Role;
+ S += ":`";
+ escapeRST(T, S);
+ S += '`';
+ }
+
+ S += Suffix;
+}
+
+void DiagText::PlaceholderPiece::print(std::vector<std::string> &RST) {
+ RST.push_back(std::string(":placeholder:`") + char('A' + Index) + "`");
+}
+
+void DiagText::SelectPiece::print(std::vector<std::string> &RST) {
+ std::vector<size_t> SeparatorIndexes;
+ SeparatorIndexes.push_back(RST.size());
+ RST.emplace_back();
+ for (auto &O : Options) {
+ O.print(RST);
+ SeparatorIndexes.push_back(RST.size());
+ RST.emplace_back();
+ }
+
+ makeTableRows(RST.begin() + SeparatorIndexes.front(),
+ RST.begin() + SeparatorIndexes.back() + 1);
+ for (size_t I : SeparatorIndexes)
+ makeRowSeparator(RST[I]);
+}
+
+bool isRemarkGroup(const Record *DiagGroup,
+ const std::map<std::string, GroupInfo> &DiagsInGroup) {
+ bool AnyRemarks = false, AnyNonRemarks = false;
+
+ std::function<void(StringRef)> Visit = [&](StringRef GroupName) {
+ auto &GroupInfo = DiagsInGroup.find(GroupName)->second;
+ for (const Record *Diag : GroupInfo.DiagsInGroup)
+ (isRemark(*Diag) ? AnyRemarks : AnyNonRemarks) = true;
+ for (const auto &Name : GroupInfo.SubGroups)
+ Visit(Name);
+ };
+ Visit(DiagGroup->getValueAsString("GroupName"));
+
+ if (AnyRemarks && AnyNonRemarks)
+ PrintFatalError(
+ DiagGroup->getLoc(),
+ "Diagnostic group contains both remark and non-remark diagnostics");
+ return AnyRemarks;
+}
+
+std::string getDefaultSeverity(const Record *Diag) {
+ return Diag->getValueAsDef("DefaultSeverity")->getValueAsString("Name");
+}
+
+std::set<std::string>
+getDefaultSeverities(const Record *DiagGroup,
+ const std::map<std::string, GroupInfo> &DiagsInGroup) {
+ std::set<std::string> States;
+
+ std::function<void(StringRef)> Visit = [&](StringRef GroupName) {
+ auto &GroupInfo = DiagsInGroup.find(GroupName)->second;
+ for (const Record *Diag : GroupInfo.DiagsInGroup)
+ States.insert(getDefaultSeverity(Diag));
+ for (const auto &Name : GroupInfo.SubGroups)
+ Visit(Name);
+ };
+ Visit(DiagGroup->getValueAsString("GroupName"));
+ return States;
+}
+
+void writeHeader(StringRef Str, raw_ostream &OS, char Kind = '-') {
+ OS << Str << "\n" << std::string(Str.size(), Kind) << "\n";
+}
+
+void writeDiagnosticText(StringRef Role, StringRef Text, raw_ostream &OS) {
+ if (Text == "%0")
+ OS << "The text of this diagnostic is not controlled by Flang.\n\n";
+ else {
+ std::vector<std::string> Out;
+ DiagText(Role, Text).print(Out);
+ for (auto &Line : Out)
+ OS << Line << "\n";
+ OS << "\n";
+ }
+}
+
+} // namespace
+} // namespace docs
+
+void EmitFlangDiagDocs(RecordKeeper &Records, raw_ostream &OS) {
+ using namespace docs;
+
+ // Get the documentation introduction paragraph.
+ const Record *Documentation = Records.getDef("GlobalDocumentation");
+ if (!Documentation) {
+ PrintFatalError("The Documentation top-level definition is missing, "
+ "no documentation will be generated.");
+ return;
+ }
+
+ OS << Documentation->getValueAsString("Intro") << "\n";
+
+ std::vector<Record*> Diags =
+ Records.getAllDerivedDefinitions("Diagnostic");
+ std::vector<Record*> DiagGroups =
+ Records.getAllDerivedDefinitions("DiagGroup");
+ std::sort(DiagGroups.begin(), DiagGroups.end(), diagGroupBeforeByName);
+
+ DiagGroupParentMap DGParentMap(Records);
+
+ std::map<std::string, GroupInfo> DiagsInGroup;
+ groupDiagnostics(Diags, DiagGroups, DiagsInGroup);
+
+ // Compute the set of diagnostics that are in -Wpedantic.
+ {
+ RecordSet DiagsInPedanticSet;
+ RecordSet GroupsInPedanticSet;
+ InferPedantic inferPedantic(DGParentMap, Diags, DiagGroups, DiagsInGroup);
+ inferPedantic.compute(&DiagsInPedanticSet, &GroupsInPedanticSet);
+ auto &PedDiags = DiagsInGroup["pedantic"];
+ // Put the diagnostics into a deterministic order.
+ RecordVec DiagsInPedantic(DiagsInPedanticSet.begin(),
+ DiagsInPedanticSet.end());
+ RecordVec GroupsInPedantic(GroupsInPedanticSet.begin(),
+ GroupsInPedanticSet.end());
+ std::sort(DiagsInPedantic.begin(), DiagsInPedantic.end(),
+ beforeThanCompare);
+ std::sort(GroupsInPedantic.begin(), GroupsInPedantic.end(),
+ beforeThanCompare);
+ PedDiags.DiagsInGroup.insert(PedDiags.DiagsInGroup.end(),
+ DiagsInPedantic.begin(),
+ DiagsInPedantic.end());
+ for (auto *Group : GroupsInPedantic)
+ PedDiags.SubGroups.push_back(Group->getValueAsString("GroupName"));
+ }
+
+ // FIXME: Write diagnostic categories and link to diagnostic groups in each.
+
+ // Write out the diagnostic groups.
+ for (const Record *G : DiagGroups) {
+ bool IsRemarkGroup = isRemarkGroup(G, DiagsInGroup);
+ auto &GroupInfo = DiagsInGroup[G->getValueAsString("GroupName")];
+ bool IsSynonym = GroupInfo.DiagsInGroup.empty() &&
+ GroupInfo.SubGroups.size() == 1;
+
+ writeHeader(((IsRemarkGroup ? "-R" : "-W") +
+ G->getValueAsString("GroupName")).str(),
+ OS);
+
+ if (!IsSynonym) {
+ // FIXME: Ideally, all the diagnostics in a group should have the same
+ // default state, but that is not currently the case.
+ auto DefaultSeverities = getDefaultSeverities(G, DiagsInGroup);
+ if (!DefaultSeverities.empty() && !DefaultSeverities.count("Ignored")) {
+ bool AnyNonErrors = DefaultSeverities.count("Warning") ||
+ DefaultSeverities.count("Remark");
+ if (!AnyNonErrors)
+ OS << "This diagnostic is an error by default, but the flag ``-Wno-"
+ << G->getValueAsString("GroupName") << "`` can be used to disable "
+ << "the error.\n\n";
+ else
+ OS << "This diagnostic is enabled by default.\n\n";
+ } else if (DefaultSeverities.size() > 1) {
+ OS << "Some of the diagnostics controlled by this flag are enabled "
+ << "by default.\n\n";
+ }
+ }
+
+ if (!GroupInfo.SubGroups.empty()) {
+ if (IsSynonym)
+ OS << "Synonym for ";
+ else if (GroupInfo.DiagsInGroup.empty())
+ OS << "Controls ";
+ else
+ OS << "Also controls ";
+
+ bool First = true;
+ std::sort(GroupInfo.SubGroups.begin(), GroupInfo.SubGroups.end());
+ for (const auto &Name : GroupInfo.SubGroups) {
+ if (!First) OS << ", ";
+ OS << "`" << (IsRemarkGroup ? "-R" : "-W") << Name << "`_";
+ First = false;
+ }
+ OS << ".\n\n";
+ }
+
+ if (!GroupInfo.DiagsInGroup.empty()) {
+ OS << "**Diagnostic text:**\n\n";
+ for (const Record *D : GroupInfo.DiagsInGroup) {
+ auto Severity = getDefaultSeverity(D);
+ Severity[0] = tolower(Severity[0]);
+ if (Severity == "ignored")
+ Severity = IsRemarkGroup ? "remark" : "warning";
+ writeDiagnosticText(Severity, D->getValueAsString("Text"), OS);
+ }
+ }
+
+ auto Doc = G->getValueAsString("Documentation");
+ if (!Doc.empty())
+ OS << Doc;
+ else if (GroupInfo.SubGroups.empty() && GroupInfo.DiagsInGroup.empty())
+ OS << "This diagnostic flag exists for GCC compatibility, and has no "
+ "effect in Flang.\n";
+ OS << "\n";
+ }
+}
+
+} // end namespace flang
--- /dev/null
+//===- FlangOptionDocEmitter.cpp - Documentation for command line flags ---===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+// FIXME: Once this has stabilized, consider moving it to LLVM.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/TableGen/Error.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/TableGen/Record.h"
+#include "llvm/TableGen/TableGenBackend.h"
+#include <cctype>
+#include <cstring>
+#include <map>
+
+using namespace llvm;
+
+namespace flang {
+namespace docs {
+namespace {
+struct DocumentedOption {
+ Record *Option;
+ std::vector<Record*> Aliases;
+};
+struct DocumentedGroup;
+struct Documentation {
+ std::vector<DocumentedGroup> Groups;
+ std::vector<DocumentedOption> Options;
+};
+struct DocumentedGroup : Documentation {
+ Record *Group;
+};
+
+// Reorganize the records into a suitable form for emitting documentation.
+Documentation extractDocumentation(RecordKeeper &Records) {
+ Documentation Result;
+
+ // Build the tree of groups. The root in the tree is the fake option group
+ // (Record*)nullptr, which contains all top-level groups and options.
+ std::map<Record*, std::vector<Record*> > OptionsInGroup;
+ std::map<Record*, std::vector<Record*> > GroupsInGroup;
+ std::map<Record*, std::vector<Record*> > Aliases;
+
+ std::map<std::string, Record*> OptionsByName;
+ for (Record *R : Records.getAllDerivedDefinitions("Option"))
+ OptionsByName[R->getValueAsString("Name")] = R;
+
+ auto Flatten = [](Record *R) {
+ return R->getValue("DocFlatten") && R->getValueAsBit("DocFlatten");
+ };
+
+ auto SkipFlattened = [&](Record *R) -> Record* {
+ while (R && Flatten(R)) {
+ auto *G = dyn_cast<DefInit>(R->getValueInit("Group"));
+ if (!G)
+ return nullptr;
+ R = G->getDef();
+ }
+ return R;
+ };
+
+ for (Record *R : Records.getAllDerivedDefinitions("OptionGroup")) {
+ if (Flatten(R))
+ continue;
+
+ Record *Group = nullptr;
+ if (auto *G = dyn_cast<DefInit>(R->getValueInit("Group")))
+ Group = SkipFlattened(G->getDef());
+ GroupsInGroup[Group].push_back(R);
+ }
+
+ for (Record *R : Records.getAllDerivedDefinitions("Option")) {
+ if (auto *A = dyn_cast<DefInit>(R->getValueInit("Alias"))) {
+ Aliases[A->getDef()].push_back(R);
+ continue;
+ }
+
+ // Pretend no-X and Xno-Y options are aliases of X and XY.
+ std::string Name = R->getValueAsString("Name");
+ if (Name.size() >= 4) {
+ if (Name.substr(0, 3) == "no-" && OptionsByName[Name.substr(3)]) {
+ Aliases[OptionsByName[Name.substr(3)]].push_back(R);
+ continue;
+ }
+ if (Name.substr(1, 3) == "no-" && OptionsByName[Name[0] + Name.substr(4)]) {
+ Aliases[OptionsByName[Name[0] + Name.substr(4)]].push_back(R);
+ continue;
+ }
+ }
+
+ Record *Group = nullptr;
+ if (auto *G = dyn_cast<DefInit>(R->getValueInit("Group")))
+ Group = SkipFlattened(G->getDef());
+ OptionsInGroup[Group].push_back(R);
+ }
+
+ auto CompareByName = [](Record *A, Record *B) {
+ return A->getValueAsString("Name") < B->getValueAsString("Name");
+ };
+
+ auto CompareByLocation = [](Record *A, Record *B) {
+ return A->getLoc()[0].getPointer() < B->getLoc()[0].getPointer();
+ };
+
+ auto DocumentationForOption = [&](Record *R) -> DocumentedOption {
+ auto &A = Aliases[R];
+ std::sort(A.begin(), A.end(), CompareByName);
+ return {R, std::move(A)};
+ };
+
+ std::function<Documentation(Record *)> DocumentationForGroup =
+ [&](Record *R) -> Documentation {
+ Documentation D;
+
+ auto &Groups = GroupsInGroup[R];
+ std::sort(Groups.begin(), Groups.end(), CompareByLocation);
+ for (Record *G : Groups) {
+ D.Groups.emplace_back();
+ D.Groups.back().Group = G;
+ Documentation &Base = D.Groups.back();
+ Base = DocumentationForGroup(G);
+ }
+
+ auto &Options = OptionsInGroup[R];
+ std::sort(Options.begin(), Options.end(), CompareByName);
+ for (Record *O : Options)
+ D.Options.push_back(DocumentationForOption(O));
+
+ return D;
+ };
+
+ return DocumentationForGroup(nullptr);
+}
+
+// Get the first and successive separators to use for an OptionKind.
+std::pair<StringRef,StringRef> getSeparatorsForKind(const Record *OptionKind) {
+ return StringSwitch<std::pair<StringRef, StringRef>>(OptionKind->getName())
+ .Cases("KIND_JOINED", "KIND_JOINED_OR_SEPARATE",
+ "KIND_JOINED_AND_SEPARATE",
+ "KIND_REMAINING_ARGS_JOINED", {"", " "})
+ .Case("KIND_COMMAJOINED", {"", ","})
+ .Default({" ", " "});
+}
+
+const unsigned UnlimitedArgs = unsigned(-1);
+
+// Get the number of arguments expected for an option, or -1 if any number of
+// arguments are accepted.
+unsigned getNumArgsForKind(Record *OptionKind, const Record *Option) {
+ return StringSwitch<unsigned>(OptionKind->getName())
+ .Cases("KIND_JOINED", "KIND_JOINED_OR_SEPARATE", "KIND_SEPARATE", 1)
+ .Cases("KIND_REMAINING_ARGS", "KIND_REMAINING_ARGS_JOINED",
+ "KIND_COMMAJOINED", UnlimitedArgs)
+ .Case("KIND_JOINED_AND_SEPARATE", 2)
+ .Case("KIND_MULTIARG", Option->getValueAsInt("NumArgs"))
+ .Default(0);
+}
+
+bool hasFlag(const Record *OptionOrGroup, StringRef OptionFlag) {
+ for (const Record *Flag : OptionOrGroup->getValueAsListOfDefs("Flags"))
+ if (Flag->getName() == OptionFlag)
+ return true;
+ return false;
+}
+
+bool isExcluded(const Record *OptionOrGroup, const Record *DocInfo) {
+ // FIXME: Provide a flag to specify the set of exclusions.
+ for (StringRef Exclusion : DocInfo->getValueAsListOfStrings("ExcludedFlags"))
+ if (hasFlag(OptionOrGroup, Exclusion))
+ return true;
+ return false;
+}
+
+std::string escapeRST(StringRef Str) {
+ std::string Out;
+ for (auto K : Str) {
+ if (StringRef("`*|_[]\\").count(K))
+ Out.push_back('\\');
+ Out.push_back(K);
+ }
+ return Out;
+}
+
+StringRef getSphinxOptionID(StringRef OptionName) {
+ for (auto I = OptionName.begin(), E = OptionName.end(); I != E; ++I)
+ if (!isalnum(*I) && *I != '-')
+ return OptionName.substr(0, I - OptionName.begin());
+ return OptionName;
+}
+
+bool canSphinxCopeWithOption(const Record *Option) {
+ // HACK: Work arond sphinx's inability to cope with punctuation-only options
+ // such as /? by suppressing them from the option list.
+ for (char C : Option->getValueAsString("Name"))
+ if (isalnum(C))
+ return true;
+ return false;
+}
+
+void emitHeading(int Depth, std::string Heading, raw_ostream &OS) {
+ assert(Depth < 8 && "groups nested too deeply");
+ OS << Heading << '\n'
+ << std::string(Heading.size(), "=~-_'+<>"[Depth]) << "\n";
+}
+
+/// Get the value of field \p Primary, if possible. If \p Primary does not
+/// exist, get the value of \p Fallback and escape it for rST emission.
+std::string getRSTStringWithTextFallback(const Record *R, StringRef Primary,
+ StringRef Fallback) {
+ for (auto Field : {Primary, Fallback}) {
+ if (auto *V = R->getValue(Field)) {
+ StringRef Value;
+ if (auto *SV = dyn_cast_or_null<StringInit>(V->getValue()))
+ Value = SV->getValue();
+ else if (auto *CV = dyn_cast_or_null<CodeInit>(V->getValue()))
+ Value = CV->getValue();
+ if (!Value.empty())
+ return Field == Primary ? Value.str() : escapeRST(Value);
+ }
+ }
+ return StringRef();
+}
+
+void emitOptionWithArgs(StringRef Prefix, const Record *Option,
+ ArrayRef<StringRef> Args, raw_ostream &OS) {
+ OS << Prefix << escapeRST(Option->getValueAsString("Name"));
+
+ std::pair<StringRef, StringRef> Separators =
+ getSeparatorsForKind(Option->getValueAsDef("Kind"));
+
+ StringRef Separator = Separators.first;
+ for (auto Arg : Args) {
+ OS << Separator << escapeRST(Arg);
+ Separator = Separators.second;
+ }
+}
+
+void emitOptionName(StringRef Prefix, const Record *Option, raw_ostream &OS) {
+ // Find the arguments to list after the option.
+ unsigned NumArgs = getNumArgsForKind(Option->getValueAsDef("Kind"), Option);
+
+ std::vector<std::string> Args;
+ if (!Option->isValueUnset("MetaVarName"))
+ Args.push_back(Option->getValueAsString("MetaVarName"));
+ else if (NumArgs == 1)
+ Args.push_back("<arg>");
+
+ while (Args.size() < NumArgs) {
+ Args.push_back(("<arg" + Twine(Args.size() + 1) + ">").str());
+ // Use '--args <arg1> <arg2>...' if any number of args are allowed.
+ if (Args.size() == 2 && NumArgs == UnlimitedArgs) {
+ Args.back() += "...";
+ break;
+ }
+ }
+
+ emitOptionWithArgs(Prefix, Option, std::vector<StringRef>(Args.begin(), Args.end()), OS);
+
+ auto AliasArgs = Option->getValueAsListOfStrings("AliasArgs");
+ if (!AliasArgs.empty()) {
+ Record *Alias = Option->getValueAsDef("Alias");
+ OS << " (equivalent to ";
+ emitOptionWithArgs(
+ Alias->getValueAsListOfStrings("Prefixes").front(), Alias,
+ AliasArgs, OS);
+ OS << ")";
+ }
+}
+
+bool emitOptionNames(const Record *Option, raw_ostream &OS, bool EmittedAny) {
+ for (auto &Prefix : Option->getValueAsListOfStrings("Prefixes")) {
+ if (EmittedAny)
+ OS << ", ";
+ emitOptionName(Prefix, Option, OS);
+ EmittedAny = true;
+ }
+ return EmittedAny;
+}
+
+template <typename Fn>
+void forEachOptionName(const DocumentedOption &Option, const Record *DocInfo,
+ Fn F) {
+ F(Option.Option);
+
+ for (auto *Alias : Option.Aliases)
+ if (!isExcluded(Alias, DocInfo) && canSphinxCopeWithOption(Option.Option))
+ F(Alias);
+}
+
+void emitOption(const DocumentedOption &Option, const Record *DocInfo,
+ raw_ostream &OS) {
+ if (isExcluded(Option.Option, DocInfo))
+ return;
+ if (Option.Option->getValueAsDef("Kind")->getName() == "KIND_UNKNOWN" ||
+ Option.Option->getValueAsDef("Kind")->getName() == "KIND_INPUT")
+ return;
+ if (!canSphinxCopeWithOption(Option.Option))
+ return;
+
+ // HACK: Emit a different program name with each option to work around
+ // sphinx's inability to cope with options that differ only by punctuation
+ // (eg -ObjC vs -ObjC++, -G vs -G=).
+ std::vector<std::string> SphinxOptionIDs;
+ forEachOptionName(Option, DocInfo, [&](const Record *Option) {
+ for (auto &Prefix : Option->getValueAsListOfStrings("Prefixes"))
+ SphinxOptionIDs.push_back(
+ getSphinxOptionID((Prefix + Option->getValueAsString("Name")).str()));
+ });
+ assert(!SphinxOptionIDs.empty() && "no flags for option");
+ static std::map<std::string, int> NextSuffix;
+ int SphinxWorkaroundSuffix = NextSuffix[*std::max_element(
+ SphinxOptionIDs.begin(), SphinxOptionIDs.end(),
+ [&](const std::string &A, const std::string &B) {
+ return NextSuffix[A] < NextSuffix[B];
+ })];
+ for (auto &S : SphinxOptionIDs)
+ NextSuffix[S] = SphinxWorkaroundSuffix + 1;
+ if (SphinxWorkaroundSuffix)
+ OS << ".. program:: " << DocInfo->getValueAsString("Program")
+ << SphinxWorkaroundSuffix << "\n";
+
+ // Emit the names of the option.
+ OS << ".. option:: ";
+ bool EmittedAny = false;
+ forEachOptionName(Option, DocInfo, [&](const Record *Option) {
+ EmittedAny = emitOptionNames(Option, OS, EmittedAny);
+ });
+ if (SphinxWorkaroundSuffix)
+ OS << "\n.. program:: " << DocInfo->getValueAsString("Program");
+ OS << "\n\n";
+
+ // Emit the description, if we have one.
+ std::string Description =
+ getRSTStringWithTextFallback(Option.Option, "DocBrief", "HelpText");
+ if (!Description.empty())
+ OS << Description << "\n\n";
+}
+
+void emitDocumentation(int Depth, const Documentation &Doc,
+ const Record *DocInfo, raw_ostream &OS);
+
+void emitGroup(int Depth, const DocumentedGroup &Group, const Record *DocInfo,
+ raw_ostream &OS) {
+ if (isExcluded(Group.Group, DocInfo))
+ return;
+
+ emitHeading(Depth,
+ getRSTStringWithTextFallback(Group.Group, "DocName", "Name"), OS);
+
+ // Emit the description, if we have one.
+ std::string Description =
+ getRSTStringWithTextFallback(Group.Group, "DocBrief", "HelpText");
+ if (!Description.empty())
+ OS << Description << "\n\n";
+
+ // Emit contained options and groups.
+ emitDocumentation(Depth + 1, Group, DocInfo, OS);
+}
+
+void emitDocumentation(int Depth, const Documentation &Doc,
+ const Record *DocInfo, raw_ostream &OS) {
+ for (auto &O : Doc.Options)
+ emitOption(O, DocInfo, OS);
+ for (auto &G : Doc.Groups)
+ emitGroup(Depth, G, DocInfo, OS);
+}
+
+} // namespace
+} // namespace docs
+
+void EmitFlangOptDocs(RecordKeeper &Records, raw_ostream &OS) {
+ using namespace docs;
+
+ const Record *DocInfo = Records.getDef("GlobalDocumentation");
+ if (!DocInfo) {
+ PrintFatalError("The GlobalDocumentation top-level definition is missing, "
+ "no documentation will be generated.");
+ return;
+ }
+ OS << DocInfo->getValueAsString("Intro") << "\n";
+ OS << ".. program:: " << DocInfo->getValueAsString("Program") << "\n";
+
+ emitDocumentation(0, extractDocumentation(Records), DocInfo, OS);
+}
+} // end namespace flang
--- /dev/null
+//===- TableGen.cpp - Top-Level TableGen implementation for Flang ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the main function for Flang's TableGen.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TableGenBackends.h" // Declares all backends.
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/TableGen/Error.h"
+#include "llvm/TableGen/Main.h"
+#include "llvm/TableGen/Record.h"
+
+using namespace llvm;
+using namespace flang;
+
+enum ActionType {
+ GenFlangDiagsDefs,
+ GenFlangDiagGroups,
+ GenFlangDiagsIndexName,
+ GenDiagDocs,
+ GenOptDocs
+};
+
+namespace {
+cl::opt<ActionType> Action(
+ cl::desc("Action to perform:"),
+ cl::values(
+ clEnumValN(GenFlangDiagsDefs, "gen-flang-diags-defs",
+ "Generate Flang diagnostics definitions"),
+ clEnumValN(GenFlangDiagGroups, "gen-flang-diag-groups",
+ "Generate Flang diagnostic groups"),
+ clEnumValN(GenFlangDiagsIndexName, "gen-flang-diags-index-name",
+ "Generate Flang diagnostic name index"),
+ clEnumValN(GenDiagDocs, "gen-diag-docs",
+ "Generate diagnostic documentation"),
+ clEnumValN(GenOptDocs, "gen-opt-docs", "Generate option documentation")));
+
+cl::opt<std::string>
+FlangComponent("flang-component",
+ cl::desc("Only use warnings from specified component"),
+ cl::value_desc("component"), cl::Hidden);
+
+bool FlangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
+ switch (Action) {
+ case GenFlangDiagsDefs:
+ EmitFlangDiagsDefs(Records, OS, FlangComponent);
+ break;
+ case GenFlangDiagGroups:
+ EmitFlangDiagGroups(Records, OS);
+ break;
+ case GenFlangDiagsIndexName:
+ EmitFlangDiagsIndexName(Records, OS);
+ break;
+ case GenDiagDocs:
+ EmitFlangDiagDocs(Records, OS);
+ break;
+ case GenOptDocs:
+ EmitFlangOptDocs(Records, OS);
+ break;
+ }
+
+ return false;
+}
+}
+
+int main(int argc, char **argv) {
+ sys::PrintStackTraceOnErrorSignal(argv[0]);
+ PrettyStackTraceProgram X(argc, argv);
+ cl::ParseCommandLineOptions(argc, argv);
+
+ llvm_shutdown_obj Y;
+
+ return TableGenMain(argv[0], &FlangTableGenMain);
+}
+
+#ifdef __has_feature
+#if __has_feature(address_sanitizer)
+#include <sanitizer/lsan_interface.h>
+// Disable LeakSanitizer for this binary as it has too many leaks that are not
+// very interesting to fix. See compiler-rt/include/sanitizer/lsan_interface.h .
+int __lsan_is_turned_off() { return 1; }
+#endif // __has_feature(address_sanitizer)
+#endif // defined(__has_feature)
--- /dev/null
+//===- TableGenBackends.h - Declarations for Clang TableGen Backends ------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains the declarations for all of the Clang TableGen
+// backends. A "TableGen backend" is just a function. See
+// "$LLVM_ROOT/utils/TableGen/TableGenBackends.h" for more info.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_FLANG_UTILS_TABLEGEN_TABLEGENBACKENDS_H
+#define LLVM_FLANG_UTILS_TABLEGEN_TABLEGENBACKENDS_H
+
+#include <string>
+
+namespace llvm {
+ class raw_ostream;
+ class RecordKeeper;
+}
+
+using llvm::raw_ostream;
+using llvm::RecordKeeper;
+
+namespace flang {
+
+
+// Used by FlangDiagnosticsEmitter.cpp
+void EmitFlangDiagsDefs(RecordKeeper &Records, raw_ostream &OS,
+ const std::string &Component);
+void EmitFlangDiagGroups(RecordKeeper &Records, raw_ostream &OS);
+void EmitFlangDiagsIndexName(RecordKeeper &Records, raw_ostream &OS);
+void EmitFlangDiagDocs(RecordKeeper &Records, raw_ostream &OS);
+
+// Used by FlangOptionDocEmitter.cpp
+void EmitFlangOptDocs(RecordKeeper &Records, raw_ostream &OS);
+
+
+} // end namespace flang
+
+#endif