[flang] Add new global CMakefile infrastructure with examples
authorStephane Chauveau <stephane@chauveau-central.net>
Thu, 8 Feb 2018 13:33:30 +0000 (14:33 +0100)
committerGitHub <noreply@github.com>
Fri, 9 Feb 2018 09:09:20 +0000 (10:09 +0100)
Original-commit: flang-compiler/f18@81b91f327052cd0596e96af9c33b2d0e221d10f5
Reviewed-on: https://github.com/flang-compiler/f18/pull/6
Tree-same-pre-rewrite: false

34 files changed:
flang/cmake/modules/AddFlang.cmake [new file with mode: 0644]
flang/cmake/modules/CMakeLists.txt [new file with mode: 0644]
flang/cmake/modules/FindZ3.cmake [new file with mode: 0644]
flang/cmake/modules/FlangConfig.cmake.in [new file with mode: 0644]
flang/include/CMakeLists.txt [new file with mode: 0644]
flang/include/flang/Basic/CMakeLists.txt [new file with mode: 0644]
flang/include/flang/Basic/Diagnostic.td [new file with mode: 0644]
flang/include/flang/Basic/DiagnosticCategories.td [new file with mode: 0644]
flang/include/flang/Basic/DiagnosticCommonKinds.td [new file with mode: 0644]
flang/include/flang/Basic/DiagnosticDocs.td [new file with mode: 0644]
flang/include/flang/Basic/DiagnosticGroups.td [new file with mode: 0644]
flang/include/flang/Basic/LLVM.h [new file with mode: 0644]
flang/include/flang/Basic/Version.h [new file with mode: 0644]
flang/include/flang/Basic/Version.inc.in [new file with mode: 0644]
flang/include/flang/CMakeLists.txt [new file with mode: 0644]
flang/include/flang/Config/config.h.cmake [new file with mode: 0644]
flang/include/flang/Sema/Scope.h [new file with mode: 0644]
flang/include/flang/Sema/Sema.h [new file with mode: 0644]
flang/lib/Basic/CMakeLists.txt [new file with mode: 0644]
flang/lib/Basic/LangOptions.cpp [new file with mode: 0644]
flang/lib/Basic/Version.cpp [new file with mode: 0644]
flang/lib/CMakeLists.txt [new file with mode: 0644]
flang/lib/Sema/CMakeLists.txt [new file with mode: 0644]
flang/lib/Sema/Scope.cpp [new file with mode: 0644]
flang/lib/Sema/Sema.cpp [new file with mode: 0644]
flang/lib/Sema/SemaExpr.cpp [new file with mode: 0644]
flang/tools/CMakeLists.txt [new file with mode: 0644]
flang/tools/flang-info/CMakeLists.txt [new file with mode: 0644]
flang/tools/flang-info/FlangInfo.cpp [new file with mode: 0644]
flang/utils/TableGen/CMakeLists.txt [new file with mode: 0644]
flang/utils/TableGen/FlangDiagnosticsEmitter.cpp [new file with mode: 0644]
flang/utils/TableGen/FlangOptionDocEmitter.cpp [new file with mode: 0644]
flang/utils/TableGen/TableGen.cpp [new file with mode: 0644]
flang/utils/TableGen/TableGenBackends.h [new file with mode: 0644]

diff --git a/flang/cmake/modules/AddFlang.cmake b/flang/cmake/modules/AddFlang.cmake
new file mode 100644 (file)
index 0000000..e592d8b
--- /dev/null
@@ -0,0 +1,164 @@
+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()
diff --git a/flang/cmake/modules/CMakeLists.txt b/flang/cmake/modules/CMakeLists.txt
new file mode 100644 (file)
index 0000000..5a24521
--- /dev/null
@@ -0,0 +1,64 @@
+# 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()
diff --git a/flang/cmake/modules/FindZ3.cmake b/flang/cmake/modules/FindZ3.cmake
new file mode 100644 (file)
index 0000000..779ef92
--- /dev/null
@@ -0,0 +1,28 @@
+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)
diff --git a/flang/cmake/modules/FlangConfig.cmake.in b/flang/cmake/modules/FlangConfig.cmake.in
new file mode 100644 (file)
index 0000000..2d9a442
--- /dev/null
@@ -0,0 +1,13 @@
+# 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@")
diff --git a/flang/include/CMakeLists.txt b/flang/include/CMakeLists.txt
new file mode 100644 (file)
index 0000000..e6bb9db
--- /dev/null
@@ -0,0 +1 @@
+add_subdirectory(flang)
diff --git a/flang/include/flang/Basic/CMakeLists.txt b/flang/include/flang/Basic/CMakeLists.txt
new file mode 100644 (file)
index 0000000..76a36c8
--- /dev/null
@@ -0,0 +1,18 @@
+# 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)
+
+
diff --git a/flang/include/flang/Basic/Diagnostic.td b/flang/include/flang/Basic/Diagnostic.td
new file mode 100644 (file)
index 0000000..7239c5a
--- /dev/null
@@ -0,0 +1,142 @@
+//===--- 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"
+
diff --git a/flang/include/flang/Basic/DiagnosticCategories.td b/flang/include/flang/Basic/DiagnosticCategories.td
new file mode 100644 (file)
index 0000000..37b8569
--- /dev/null
@@ -0,0 +1,11 @@
+//==--- 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">;
diff --git a/flang/include/flang/Basic/DiagnosticCommonKinds.td b/flang/include/flang/Basic/DiagnosticCommonKinds.td
new file mode 100644 (file)
index 0000000..98fd3c4
--- /dev/null
@@ -0,0 +1,230 @@
+//==--- 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">;
+}
diff --git a/flang/include/flang/Basic/DiagnosticDocs.td b/flang/include/flang/Basic/DiagnosticDocs.td
new file mode 100644 (file)
index 0000000..0a3e1ce
--- /dev/null
@@ -0,0 +1,84 @@
+//==--- 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
+================
+}];
+}
+
diff --git a/flang/include/flang/Basic/DiagnosticGroups.td b/flang/include/flang/Basic/DiagnosticGroups.td
new file mode 100644 (file)
index 0000000..23e4d46
--- /dev/null
@@ -0,0 +1,934 @@
+//==--- 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">;
diff --git a/flang/include/flang/Basic/LLVM.h b/flang/include/flang/Basic/LLVM.h
new file mode 100644 (file)
index 0000000..00ebcc3
--- /dev/null
@@ -0,0 +1,83 @@
+//===--- 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
diff --git a/flang/include/flang/Basic/Version.h b/flang/include/flang/Basic/Version.h
new file mode 100644 (file)
index 0000000..8475c1e
--- /dev/null
@@ -0,0 +1,62 @@
+//===- 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
diff --git a/flang/include/flang/Basic/Version.inc.in b/flang/include/flang/Basic/Version.inc.in
new file mode 100644 (file)
index 0000000..a0eeab2
--- /dev/null
@@ -0,0 +1,5 @@
+#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@
diff --git a/flang/include/flang/CMakeLists.txt b/flang/include/flang/CMakeLists.txt
new file mode 100644 (file)
index 0000000..e5c79bc
--- /dev/null
@@ -0,0 +1,6 @@
+#!! add_subdirectory(AST)
+add_subdirectory(Basic)
+#!! add_subdirectory(Driver)
+#!! add_subdirectory(Parse)
+#!! add_subdirectory(Sema)
+
diff --git a/flang/include/flang/Config/config.h.cmake b/flang/include/flang/Config/config.h.cmake
new file mode 100644 (file)
index 0000000..6106897
--- /dev/null
@@ -0,0 +1,64 @@
+/* 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
diff --git a/flang/include/flang/Sema/Scope.h b/flang/include/flang/Sema/Scope.h
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/flang/include/flang/Sema/Sema.h b/flang/include/flang/Sema/Sema.h
new file mode 100644 (file)
index 0000000..c801de9
--- /dev/null
@@ -0,0 +1,60 @@
+//===--- 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
+
diff --git a/flang/lib/Basic/CMakeLists.txt b/flang/lib/Basic/CMakeLists.txt
new file mode 100644 (file)
index 0000000..73d05a7
--- /dev/null
@@ -0,0 +1,85 @@
+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}
+  )
+
diff --git a/flang/lib/Basic/LangOptions.cpp b/flang/lib/Basic/LangOptions.cpp
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/flang/lib/Basic/Version.cpp b/flang/lib/Basic/Version.cpp
new file mode 100644 (file)
index 0000000..dcfecf1
--- /dev/null
@@ -0,0 +1,151 @@
+//===- 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
diff --git a/flang/lib/CMakeLists.txt b/flang/lib/CMakeLists.txt
new file mode 100644 (file)
index 0000000..39e3698
--- /dev/null
@@ -0,0 +1 @@
+add_subdirectory(Basic)
diff --git a/flang/lib/Sema/CMakeLists.txt b/flang/lib/Sema/CMakeLists.txt
new file mode 100644 (file)
index 0000000..11e5b9f
--- /dev/null
@@ -0,0 +1,16 @@
+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
+  )
diff --git a/flang/lib/Sema/Scope.cpp b/flang/lib/Sema/Scope.cpp
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/flang/lib/Sema/Sema.cpp b/flang/lib/Sema/Sema.cpp
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/flang/lib/Sema/SemaExpr.cpp b/flang/lib/Sema/SemaExpr.cpp
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/flang/tools/CMakeLists.txt b/flang/tools/CMakeLists.txt
new file mode 100644 (file)
index 0000000..0520ec2
--- /dev/null
@@ -0,0 +1,11 @@
+create_subdirectory_options(FLANG TOOL)
+
+add_flang_subdirectory(flang-info)
+
+#!! add_flang_subdirectory(f18)
+
+#!! if(FLANG_ENABLE_XXXX)
+#!!  add_flang_subdirectory(xxxx)
+#!! endif()
+
+
diff --git a/flang/tools/flang-info/CMakeLists.txt b/flang/tools/flang-info/CMakeLists.txt
new file mode 100644 (file)
index 0000000..dd22236
--- /dev/null
@@ -0,0 +1,16 @@
+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)
diff --git a/flang/tools/flang-info/FlangInfo.cpp b/flang/tools/flang-info/FlangInfo.cpp
new file mode 100644 (file)
index 0000000..3dd2738
--- /dev/null
@@ -0,0 +1,41 @@
+//===--- 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 ;
+}
diff --git a/flang/utils/TableGen/CMakeLists.txt b/flang/utils/TableGen/CMakeLists.txt
new file mode 100644 (file)
index 0000000..e208de4
--- /dev/null
@@ -0,0 +1,7 @@
+set(LLVM_LINK_COMPONENTS Support)
+
+add_tablegen(flang-tblgen FLANG
+  FlangDiagnosticsEmitter.cpp
+  FlangOptionDocEmitter.cpp
+  TableGen.cpp
+  )
diff --git a/flang/utils/TableGen/FlangDiagnosticsEmitter.cpp b/flang/utils/TableGen/FlangDiagnosticsEmitter.cpp
new file mode 100644 (file)
index 0000000..0a2f101
--- /dev/null
@@ -0,0 +1,1342 @@
+//=- 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
diff --git a/flang/utils/TableGen/FlangOptionDocEmitter.cpp b/flang/utils/TableGen/FlangOptionDocEmitter.cpp
new file mode 100644 (file)
index 0000000..e57b76b
--- /dev/null
@@ -0,0 +1,392 @@
+//===- 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
diff --git a/flang/utils/TableGen/TableGen.cpp b/flang/utils/TableGen/TableGen.cpp
new file mode 100644 (file)
index 0000000..ce5aa47
--- /dev/null
@@ -0,0 +1,92 @@
+//===- 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)
diff --git a/flang/utils/TableGen/TableGenBackends.h b/flang/utils/TableGen/TableGenBackends.h
new file mode 100644 (file)
index 0000000..e7cde6c
--- /dev/null
@@ -0,0 +1,45 @@
+//===- 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