forked from OSchip/llvm-project
[docs] Add TableGen-based generator for command line argument documentation,
and generate documentation for all (non-hidden) options supported by the 'clang' driver. llvm-svn: 292968
This commit is contained in:
parent
1ee7bf6313
commit
081ad4d3e5
File diff suppressed because it is too large
Load Diff
|
@ -19,6 +19,7 @@ Using Clang as a Compiler
|
|||
UsersManual
|
||||
Toolchain
|
||||
LanguageExtensions
|
||||
ClangCommandLineReference
|
||||
AttributeReference
|
||||
DiagnosticsReference
|
||||
CrossCompilation
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
def cl_Group : OptionGroup<"<clang-cl options>">,
|
||||
def cl_Group : OptionGroup<"<clang-cl options>">, Flags<[CLOption]>,
|
||||
HelpText<"CL.EXE COMPATIBILITY OPTIONS">;
|
||||
|
||||
def cl_compile_Group : OptionGroup<"<clang-cl compile-only options>">,
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
//==--- ClangOptionDocs.td - Option 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-opt-docs. Do not edit this file by hand!!
|
||||
-------------------------------------------------------------------
|
||||
|
||||
=====================================
|
||||
Clang command line argument reference
|
||||
=====================================
|
||||
.. contents::
|
||||
:local:
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
This page lists the command line arguments currently supported by the
|
||||
GCC-compatible ``clang`` and ``clang++`` drivers.
|
||||
|
||||
}];
|
||||
|
||||
string Program = "clang";
|
||||
list<string> ExcludedFlags = ["HelpHidden", "NoDriverOption",
|
||||
"CLOption", "Unsupported", "Ignored"];
|
||||
}
|
||||
|
||||
include "Options.td"
|
|
@ -33,7 +33,8 @@ enum ClangFlags {
|
|||
CLOption = (1 << 9),
|
||||
CC1Option = (1 << 10),
|
||||
CC1AsOption = (1 << 11),
|
||||
NoDriverOption = (1 << 12)
|
||||
NoDriverOption = (1 << 12),
|
||||
Ignored = (1 << 13)
|
||||
};
|
||||
|
||||
enum ID {
|
||||
|
|
|
@ -33,6 +33,9 @@ def NoArgumentUnused : OptionFlag;
|
|||
// lines that use it.
|
||||
def Unsupported : OptionFlag;
|
||||
|
||||
// Ignored - The option is unsupported, and the driver will silently ignore it.
|
||||
def Ignored : OptionFlag;
|
||||
|
||||
// CoreOption - This is considered a "core" Clang option, available in both
|
||||
// clang and clang-cl modes.
|
||||
def CoreOption : OptionFlag;
|
||||
|
@ -50,72 +53,130 @@ def CC1AsOption : OptionFlag;
|
|||
// NoDriverOption - This option should not be accepted by the driver.
|
||||
def NoDriverOption : OptionFlag;
|
||||
|
||||
// A short name to show in documentation. The name will be interpreted as rST.
|
||||
class DocName<string name> { string DocName = name; }
|
||||
|
||||
// A brief description to show in documentation, interpreted as rST.
|
||||
class DocBrief<code descr> { code DocBrief = descr; }
|
||||
|
||||
// Indicates that this group should be flattened into its parent when generating
|
||||
// documentation.
|
||||
class DocFlatten { bit DocFlatten = 1; }
|
||||
|
||||
/////////
|
||||
// Groups
|
||||
|
||||
def Action_Group : OptionGroup<"<action group>">, DocName<"Actions">,
|
||||
DocBrief<[{The action to perform on the input.}]>;
|
||||
|
||||
// Meta-group for options which are only used for compilation,
|
||||
// and not linking etc.
|
||||
def CompileOnly_Group : OptionGroup<"<CompileOnly group>">;
|
||||
def CompileOnly_Group : OptionGroup<"<CompileOnly group>">,
|
||||
DocName<"Compilation flags">, DocBrief<[{
|
||||
Flags controlling the behavior of Clang during compilation. These flags have
|
||||
no effect during actions that do not perform compilation.}]>;
|
||||
|
||||
def Action_Group : OptionGroup<"<action group>">;
|
||||
def IncludePath_Group : OptionGroup<"<I/i group>">, Group<CompileOnly_Group>,
|
||||
DocName<"Include path management">,
|
||||
DocBrief<[{
|
||||
Flags controlling how ``#include``\s are resolved to files.}]>;
|
||||
|
||||
def I_Group : OptionGroup<"<I group>">, Group<CompileOnly_Group>;
|
||||
def M_Group : OptionGroup<"<M group>">, Group<CompileOnly_Group>;
|
||||
def T_Group : OptionGroup<"<T group>">;
|
||||
def O_Group : OptionGroup<"<O group>">, Group<CompileOnly_Group>;
|
||||
def R_Group : OptionGroup<"<R group>">, Group<CompileOnly_Group>;
|
||||
def R_value_Group : OptionGroup<"<R (with value) group>">, Group<R_Group>;
|
||||
def W_Group : OptionGroup<"<W group>">, Group<CompileOnly_Group>;
|
||||
def W_value_Group : OptionGroup<"<W (with value) group>">, Group<W_Group>;
|
||||
def d_Group : OptionGroup<"<d group>">;
|
||||
def f_Group : OptionGroup<"<f group>">, Group<CompileOnly_Group>;
|
||||
def f_clang_Group : OptionGroup<"<f (clang-only) group>">, Group<CompileOnly_Group>;
|
||||
def g_Group : OptionGroup<"<g group>">;
|
||||
def gN_Group : OptionGroup<"<gN group>">, Group<g_Group>;
|
||||
def ggdbN_Group : OptionGroup<"<ggdbN group>">, Group<gN_Group>;
|
||||
def gTune_Group : OptionGroup<"<gTune group>">, Group<g_Group>;
|
||||
def g_flags_Group : OptionGroup<"<g flags group>">;
|
||||
def i_Group : OptionGroup<"<i group>">, Group<CompileOnly_Group>;
|
||||
def clang_i_Group : OptionGroup<"<clang i group>">, Group<i_Group>;
|
||||
def m_Group : OptionGroup<"<m group>">, Group<CompileOnly_Group>;
|
||||
def opencl_Group : OptionGroup<"<opencl group>">, Group<CompileOnly_Group>;
|
||||
def I_Group : OptionGroup<"<I group>">, Group<IncludePath_Group>, DocFlatten;
|
||||
def i_Group : OptionGroup<"<i group>">, Group<IncludePath_Group>, DocFlatten;
|
||||
def clang_i_Group : OptionGroup<"<clang i group>">, Group<i_Group>, DocFlatten;
|
||||
|
||||
def M_Group : OptionGroup<"<M group>">, Group<CompileOnly_Group>,
|
||||
DocName<"Dependency file generation">, DocBrief<[{
|
||||
Flags controlling generation of a dependency file for ``make``-like build
|
||||
systems.}]>;
|
||||
|
||||
def d_Group : OptionGroup<"<d group>">, Group<CompileOnly_Group>,
|
||||
DocName<"Dumping preprocessor state">, DocBrief<[{
|
||||
Flags allowing the state of the preprocessor to be dumped in various ways.}]>;
|
||||
|
||||
def Diag_Group : OptionGroup<"<W/R group>">, Group<CompileOnly_Group>,
|
||||
DocName<"Diagnostic flags">, DocBrief<[{
|
||||
Flags controlling which warnings, errors, and remarks Clang will generate.
|
||||
See the :doc:`full list of warning and remark flags <DiagnosticsReference>`.}]>;
|
||||
|
||||
def R_Group : OptionGroup<"<R group>">, Group<Diag_Group>, DocFlatten;
|
||||
def R_value_Group : OptionGroup<"<R (with value) group>">, Group<R_Group>,
|
||||
DocFlatten;
|
||||
def W_Group : OptionGroup<"<W group>">, Group<Diag_Group>, DocFlatten;
|
||||
def W_value_Group : OptionGroup<"<W (with value) group>">, Group<W_Group>,
|
||||
DocFlatten;
|
||||
|
||||
def f_Group : OptionGroup<"<f group>">, Group<CompileOnly_Group>,
|
||||
DocName<"Target-independent compilation options">;
|
||||
|
||||
def f_clang_Group : OptionGroup<"<f (clang-only) group>">,
|
||||
Group<CompileOnly_Group>, DocFlatten;
|
||||
def pedantic_Group : OptionGroup<"<pedantic group>">, Group<f_Group>,
|
||||
DocFlatten;
|
||||
def opencl_Group : OptionGroup<"<opencl group>">, Group<f_Group>,
|
||||
DocName<"OpenCL flags">;
|
||||
|
||||
def m_Group : OptionGroup<"<m group>">, Group<CompileOnly_Group>,
|
||||
DocName<"Target-dependent compilation options">;
|
||||
|
||||
// Feature groups - these take command line options that correspond directly to
|
||||
// target specific features and can be translated directly from command line
|
||||
// options.
|
||||
def m_x86_Features_Group : OptionGroup<"<x86 features group>">,
|
||||
Group<m_Group>,
|
||||
Flags<[CoreOption]>;
|
||||
def m_hexagon_Features_Group : OptionGroup<"<hexagon features group>">,
|
||||
Group<m_Group>;
|
||||
def m_arm_Features_Group : OptionGroup<"<arm features group>">,
|
||||
Group<m_Group>;
|
||||
def m_aarch64_Features_Group : OptionGroup<"<aarch64 features group>">,
|
||||
Group<m_Group>;
|
||||
def m_ppc_Features_Group : OptionGroup<"<ppc features group>">,
|
||||
Group<m_Group>;
|
||||
def m_wasm_Features_Group : OptionGroup<"<wasm features group>">,
|
||||
Group<m_Group>;
|
||||
Group<m_Group>, DocName<"AARCH64">;
|
||||
def m_amdgpu_Features_Group : OptionGroup<"<amdgpu features group>">,
|
||||
Group<m_Group>;
|
||||
Group<m_Group>, DocName<"AMDGPU">;
|
||||
def m_arm_Features_Group : OptionGroup<"<arm features group>">,
|
||||
Group<m_Group>, DocName<"ARM">;
|
||||
def m_hexagon_Features_Group : OptionGroup<"<hexagon features group>">,
|
||||
Group<m_Group>, DocName<"Hexagon">;
|
||||
def m_ppc_Features_Group : OptionGroup<"<ppc features group>">,
|
||||
Group<m_Group>, DocName<"PowerPC">;
|
||||
def m_wasm_Features_Group : OptionGroup<"<wasm features group>">,
|
||||
Group<m_Group>, DocName<"WebAssembly">;
|
||||
def m_x86_Features_Group : OptionGroup<"<x86 features group>">,
|
||||
Group<m_Group>, Flags<[CoreOption]>, DocName<"X86">;
|
||||
|
||||
def m_libc_Group : OptionGroup<"<m libc group>">, Group<m_Group>;
|
||||
def u_Group : OptionGroup<"<u group>">;
|
||||
def m_libc_Group : OptionGroup<"<m libc group>">, Group<m_Group>,
|
||||
Flags<[HelpHidden]>;
|
||||
|
||||
def pedantic_Group : OptionGroup<"<pedantic group>">,
|
||||
Group<CompileOnly_Group>;
|
||||
def reserved_lib_Group : OptionGroup<"<reserved libs group>">;
|
||||
def O_Group : OptionGroup<"<O group>">, Group<CompileOnly_Group>,
|
||||
DocName<"Optimization level">, DocBrief<[{
|
||||
Flags controlling how much optimization should be performed.}]>;
|
||||
|
||||
def DebugInfo_Group : OptionGroup<"<g group>">, Group<CompileOnly_Group>,
|
||||
DocName<"Debug information generation">, DocBrief<[{
|
||||
Flags controlling how much and what kind of debug information should be
|
||||
generated.}]>;
|
||||
|
||||
def g_Group : OptionGroup<"<g group>">, Group<DebugInfo_Group>,
|
||||
DocName<"Kind and level of debug information">;
|
||||
def gN_Group : OptionGroup<"<gN group>">, Group<g_Group>,
|
||||
DocName<"Debug level">;
|
||||
def ggdbN_Group : OptionGroup<"<ggdbN group>">, Group<gN_Group>, DocFlatten;
|
||||
def gTune_Group : OptionGroup<"<gTune group>">, Group<g_Group>,
|
||||
DocName<"Debugger to tune debug information for">;
|
||||
def g_flags_Group : OptionGroup<"<g flags group>">, Group<DebugInfo_Group>,
|
||||
DocName<"Debug information flags">;
|
||||
|
||||
def Link_Group : OptionGroup<"<T/e/s/t/u group>">, DocName<"Linker flags">,
|
||||
DocBrief<[{Flags that are passed on to the linker}]>;
|
||||
def T_Group : OptionGroup<"<T group>">, Group<Link_Group>, DocFlatten;
|
||||
def u_Group : OptionGroup<"<u group>">, Group<Link_Group>, DocFlatten;
|
||||
|
||||
def reserved_lib_Group : OptionGroup<"<reserved libs group>">,
|
||||
Flags<[Unsupported]>;
|
||||
|
||||
// Temporary groups for clang options which we know we don't support,
|
||||
// but don't want to verbosely warn the user about.
|
||||
def clang_ignored_f_Group : OptionGroup<"<clang ignored f group>">,
|
||||
Group<f_Group>;
|
||||
Group<f_Group>, Flags<[Ignored]>;
|
||||
def clang_ignored_m_Group : OptionGroup<"<clang ignored m group>">,
|
||||
Group<m_Group>;
|
||||
Group<m_Group>, Flags<[Ignored]>;
|
||||
|
||||
// Group that ignores all gcc optimizations that won't be implemented
|
||||
def clang_ignored_gcc_optimization_f_Group : OptionGroup<
|
||||
"<clang_ignored_gcc_optimization_f_Group>">, Group<f_Group>;
|
||||
"<clang_ignored_gcc_optimization_f_Group>">, Group<f_Group>, Flags<[Ignored]>;
|
||||
|
||||
/////////
|
||||
// Options
|
||||
|
@ -141,7 +202,7 @@ def clang_ignored_gcc_optimization_f_Group : OptionGroup<
|
|||
|
||||
// Developer Driver Options
|
||||
|
||||
def internal_Group : OptionGroup<"<clang internal options>">;
|
||||
def internal_Group : OptionGroup<"<clang internal options>">, Flags<[HelpHidden]>;
|
||||
def internal_driver_Group : OptionGroup<"<clang driver internal options>">,
|
||||
Group<internal_Group>, HelpText<"DRIVER OPTIONS">;
|
||||
def internal_debug_Group :
|
||||
|
@ -252,7 +313,7 @@ def H : Flag<["-"], "H">, Flags<[CC1Option]>,
|
|||
def I_ : Flag<["-"], "I-">, Group<I_Group>;
|
||||
def I : JoinedOrSeparate<["-"], "I">, Group<I_Group>, Flags<[CC1Option,CC1AsOption]>,
|
||||
HelpText<"Add directory to include search path">;
|
||||
def L : JoinedOrSeparate<["-"], "L">, Flags<[RenderJoined]>;
|
||||
def L : JoinedOrSeparate<["-"], "L">, Flags<[RenderJoined]>, Group<Link_Group>;
|
||||
def MD : Flag<["-"], "MD">, Group<M_Group>,
|
||||
HelpText<"Write a depfile containing user and system headers">;
|
||||
def MMD : Flag<["-"], "MMD">, Group<M_Group>,
|
||||
|
@ -323,7 +384,7 @@ def Wno_deprecated : Flag<["-"], "Wno-deprecated">, Group<W_Group>, Flags<[CC1Op
|
|||
def Wextra : Flag<["-"], "Wextra">, Group<W_Group>, Flags<[CC1Option]>;
|
||||
def Wl_COMMA : CommaJoined<["-"], "Wl,">, Flags<[LinkerInput, RenderAsInput]>,
|
||||
HelpText<"Pass the comma separated arguments in <arg> to the linker">,
|
||||
MetaVarName<"<arg>">;
|
||||
MetaVarName<"<arg>">, Group<Link_Group>;
|
||||
// FIXME: This is broken; these should not be Joined arguments.
|
||||
def Wno_nonportable_cfstrings : Joined<["-"], "Wno-nonportable-cfstrings">, Group<W_Group>,
|
||||
Flags<[CC1Option]>;
|
||||
|
@ -349,14 +410,16 @@ def Xcuda_fatbinary : Separate<["-"], "Xcuda-fatbinary">,
|
|||
def Xcuda_ptxas : Separate<["-"], "Xcuda-ptxas">,
|
||||
HelpText<"Pass <arg> to the ptxas assembler">, MetaVarName<"<arg>">;
|
||||
def z : Separate<["-"], "z">, Flags<[LinkerInput, RenderAsInput]>,
|
||||
HelpText<"Pass -z <arg> to the linker">, MetaVarName<"<arg>">;
|
||||
HelpText<"Pass -z <arg> to the linker">, MetaVarName<"<arg>">,
|
||||
Group<Link_Group>;
|
||||
def Xlinker : Separate<["-"], "Xlinker">, Flags<[LinkerInput, RenderAsInput]>,
|
||||
HelpText<"Pass <arg> to the linker">, MetaVarName<"<arg>">;
|
||||
HelpText<"Pass <arg> to the linker">, MetaVarName<"<arg>">,
|
||||
Group<Link_Group>;
|
||||
def Xpreprocessor : Separate<["-"], "Xpreprocessor">,
|
||||
HelpText<"Pass <arg> to the preprocessor">, MetaVarName<"<arg>">;
|
||||
def X_Flag : Flag<["-"], "X">;
|
||||
def X_Joined : Joined<["-"], "X">;
|
||||
def Z_Flag : Flag<["-"], "Z">;
|
||||
def Z_Flag : Flag<["-"], "Z">, Group<Link_Group>;
|
||||
def Z_Joined : Joined<["-"], "Z">;
|
||||
def all__load : Flag<["-"], "all_load">;
|
||||
def allowable__client : Separate<["-"], "allowable_client">;
|
||||
|
@ -462,7 +525,7 @@ def emit_ast : Flag<["-"], "emit-ast">,
|
|||
def emit_llvm : Flag<["-"], "emit-llvm">, Flags<[CC1Option]>, Group<Action_Group>,
|
||||
HelpText<"Use the LLVM representation for assembler and object files">;
|
||||
def exported__symbols__list : Separate<["-"], "exported_symbols_list">;
|
||||
def e : JoinedOrSeparate<["-"], "e">;
|
||||
def e : JoinedOrSeparate<["-"], "e">, Group<Link_Group>;
|
||||
def fPIC : Flag<["-"], "fPIC">, Group<f_Group>;
|
||||
def fno_PIC : Flag<["-"], "fno-PIC">, Group<f_Group>;
|
||||
def fPIE : Flag<["-"], "fPIE">, Group<f_Group>;
|
||||
|
@ -822,7 +885,8 @@ def fno_gnu89_inline : Flag<["-"], "fno-gnu89-inline">, Group<f_Group>;
|
|||
def fgnu_runtime : Flag<["-"], "fgnu-runtime">, Group<f_Group>,
|
||||
HelpText<"Generate output compatible with the standard GNU Objective-C runtime">;
|
||||
def fheinous_gnu_extensions : Flag<["-"], "fheinous-gnu-extensions">, Flags<[CC1Option]>;
|
||||
def filelist : Separate<["-"], "filelist">, Flags<[LinkerInput]>;
|
||||
def filelist : Separate<["-"], "filelist">, Flags<[LinkerInput]>,
|
||||
Group<Link_Group>;
|
||||
def : Flag<["-"], "findirect-virtual-calls">, Alias<fapple_kext>;
|
||||
def finline_functions : Flag<["-"], "finline-functions">, Group<f_clang_Group>, Flags<[CC1Option]>,
|
||||
HelpText<"Inline suitable functions">;
|
||||
|
@ -1455,7 +1519,8 @@ def ivfsoverlay : JoinedOrSeparate<["-"], "ivfsoverlay">, Group<clang_i_Group>,
|
|||
HelpText<"Overlay the virtual filesystem described by file over the real file system">;
|
||||
def i : Joined<["-"], "i">, Group<i_Group>;
|
||||
def keep__private__externs : Flag<["-"], "keep_private_externs">;
|
||||
def l : JoinedOrSeparate<["-"], "l">, Flags<[LinkerInput, RenderJoined]>;
|
||||
def l : JoinedOrSeparate<["-"], "l">, Flags<[LinkerInput, RenderJoined]>,
|
||||
Group<Link_Group>;
|
||||
def lazy__framework : Separate<["-"], "lazy_framework">, Flags<[LinkerInput]>;
|
||||
def lazy__library : Separate<["-"], "lazy_library">, Flags<[LinkerInput]>;
|
||||
def mlittle_endian : Flag<["-"], "mlittle-endian">, Flags<[DriverOption]>;
|
||||
|
@ -1965,10 +2030,11 @@ def resource_dir : Separate<["-"], "resource-dir">,
|
|||
HelpText<"The directory which holds the compiler resource files">;
|
||||
def resource_dir_EQ : Joined<["-"], "resource-dir=">, Flags<[DriverOption, CoreOption]>,
|
||||
Alias<resource_dir>;
|
||||
def rpath : Separate<["-"], "rpath">, Flags<[LinkerInput]>;
|
||||
def rpath : Separate<["-"], "rpath">, Flags<[LinkerInput]>, Group<Link_Group>;
|
||||
def rtlib_EQ : Joined<["-", "--"], "rtlib=">,
|
||||
HelpText<"Compiler runtime library to use">;
|
||||
def r : Flag<["-"], "r">, Flags<[LinkerInput,NoArgumentUnused]>;
|
||||
def r : Flag<["-"], "r">, Flags<[LinkerInput,NoArgumentUnused]>,
|
||||
Group<Link_Group>;
|
||||
def save_temps_EQ : Joined<["-", "--"], "save-temps=">, Flags<[DriverOption]>,
|
||||
HelpText<"Save intermediate compilation results.">;
|
||||
def save_temps : Flag<["-", "--"], "save-temps">, Flags<[DriverOption]>,
|
||||
|
@ -2020,7 +2086,7 @@ def no_system_header_prefix : Joined<["--"], "no-system-header-prefix=">,
|
|||
HelpText<"Treat all #include paths starting with <prefix> as not including a "
|
||||
"system header.">;
|
||||
def : Separate<["--"], "no-system-header-prefix">, Alias<no_system_header_prefix>;
|
||||
def s : Flag<["-"], "s">;
|
||||
def s : Flag<["-"], "s">, Group<Link_Group>;
|
||||
def target : Joined<["--"], "target=">, Flags<[DriverOption, CoreOption]>,
|
||||
HelpText<"Generate code for the given target">;
|
||||
def gcc_toolchain : Joined<["--"], "gcc-toolchain=">, Flags<[DriverOption]>,
|
||||
|
@ -2034,7 +2100,7 @@ def trigraphs : Flag<["-", "--"], "trigraphs">, Alias<ftrigraphs>,
|
|||
HelpText<"Process trigraph sequences">;
|
||||
def twolevel__namespace__hints : Flag<["-"], "twolevel_namespace_hints">;
|
||||
def twolevel__namespace : Flag<["-"], "twolevel_namespace">;
|
||||
def t : Flag<["-"], "t">;
|
||||
def t : Flag<["-"], "t">, Group<Link_Group>;
|
||||
def umbrella : Separate<["-"], "umbrella">;
|
||||
def undefined : JoinedOrSeparate<["-"], "undefined">, Group<u_Group>;
|
||||
def undef : Flag<["-"], "undef">, Group<u_Group>, Flags<[CC1Option]>,
|
||||
|
@ -2330,7 +2396,10 @@ defm devirtualize_speculatively : BooleanFFlag<"devirtualize-speculatively">,
|
|||
|
||||
// gfortran options that we recognize in the driver and pass along when
|
||||
// invoking GCC to compile Fortran code.
|
||||
def gfortran_Group : OptionGroup<"gfortran Group">;
|
||||
def gfortran_Group : OptionGroup<"<gfortran group>">,
|
||||
DocName<"Fortran compilation flags">, DocBrief<[{
|
||||
Flags that will be passed onto the ``gfortran`` compiler when Clang is given
|
||||
a Fortran input.}]>;
|
||||
|
||||
// Generic gfortran options.
|
||||
def A_DASH : Joined<["-"], "A-">, Group<gfortran_Group>;
|
||||
|
|
|
@ -7,6 +7,7 @@ add_tablegen(clang-tblgen CLANG
|
|||
ClangCommentHTMLNamedCharacterReferenceEmitter.cpp
|
||||
ClangCommentHTMLTagsEmitter.cpp
|
||||
ClangDiagnosticsEmitter.cpp
|
||||
ClangOptionDocEmitter.cpp
|
||||
ClangSACheckersEmitter.cpp
|
||||
NeonEmitter.cpp
|
||||
TableGen.cpp
|
||||
|
|
|
@ -0,0 +1,358 @@
|
|||
//===- ClangOptionDocEmitter.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 clang {
|
||||
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.
|
||||
auto 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(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, 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;
|
||||
}
|
||||
|
||||
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, Record *Option,
|
||||
ArrayRef<std::string> 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, 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, Args, OS);
|
||||
|
||||
auto AliasArgs = Option->getValueAsListOfStrings("AliasArgs");
|
||||
if (!AliasArgs.empty()) {
|
||||
Record *Alias = Option->getValueAsDef("Alias");
|
||||
OS << " (equivalent to ";
|
||||
emitOptionWithArgs(Alias->getValueAsListOfStrings("Prefixes").front(),
|
||||
Alias, Option->getValueAsListOfStrings("AliasArgs"), OS);
|
||||
OS << ")";
|
||||
}
|
||||
}
|
||||
|
||||
bool emitOptionNames(Record *Option, raw_ostream &OS, bool EmittedAny) {
|
||||
for (auto &Prefix : Option->getValueAsListOfStrings("Prefixes")) {
|
||||
if (EmittedAny)
|
||||
OS << ", ";
|
||||
emitOptionName(Prefix, Option, OS);
|
||||
EmittedAny = true;
|
||||
}
|
||||
return EmittedAny;
|
||||
}
|
||||
|
||||
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=).
|
||||
static int Emitted = 0;
|
||||
OS << ".. program:: " << DocInfo->getValueAsString("Program") << Emitted++
|
||||
<< "\n";
|
||||
|
||||
// Emit the names of the option.
|
||||
OS << ".. option:: ";
|
||||
bool EmittedAny = emitOptionNames(Option.Option, OS, false);
|
||||
for (auto *Alias : Option.Aliases)
|
||||
if (!isExcluded(Alias, DocInfo) && canSphinxCopeWithOption(Option.Option))
|
||||
EmittedAny = emitOptionNames(Alias, OS, EmittedAny);
|
||||
assert(EmittedAny && "no flags for option");
|
||||
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 EmitClangOptDocs(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 clang
|
|
@ -53,7 +53,8 @@ enum ActionType {
|
|||
GenArmNeonSema,
|
||||
GenArmNeonTest,
|
||||
GenAttrDocs,
|
||||
GenDiagDocs
|
||||
GenDiagDocs,
|
||||
GenOptDocs
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
@ -135,7 +136,9 @@ cl::opt<ActionType> Action(
|
|||
clEnumValN(GenAttrDocs, "gen-attr-docs",
|
||||
"Generate attribute documentation"),
|
||||
clEnumValN(GenDiagDocs, "gen-diag-docs",
|
||||
"Generate attribute documentation")));
|
||||
"Generate diagnostic documentation"),
|
||||
clEnumValN(GenOptDocs, "gen-opt-docs",
|
||||
"Generate option documentation")));
|
||||
|
||||
cl::opt<std::string>
|
||||
ClangComponent("clang-component",
|
||||
|
@ -238,6 +241,9 @@ bool ClangTableGenMain(raw_ostream &OS, RecordKeeper &Records) {
|
|||
case GenDiagDocs:
|
||||
EmitClangDiagDocs(Records, OS);
|
||||
break;
|
||||
case GenOptDocs:
|
||||
EmitClangOptDocs(Records, OS);
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -70,6 +70,7 @@ void EmitNeonTest2(RecordKeeper &Records, raw_ostream &OS);
|
|||
|
||||
void EmitClangAttrDocs(RecordKeeper &Records, raw_ostream &OS);
|
||||
void EmitClangDiagDocs(RecordKeeper &Records, raw_ostream &OS);
|
||||
void EmitClangOptDocs(RecordKeeper &Records, raw_ostream &OS);
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
|
|
Loading…
Reference in New Issue