rsmith created this revision.
rsmith added a reviewer: jyknight.
Herald added a subscriber: jdoerfert.
Herald added a project: clang.
The intent is to provide similar functionality to GCC's -fpermissive.
For Clang's approach to diagnostics, this means that we remap all
extension diagnostics to no higher than a warning. As with GCC, the
warnings can then be suppressed with -w.


Repository:
  rC Clang

https://reviews.llvm.org/D58154

Files:
  docs/UsersManual.rst
  include/clang/Basic/Diagnostic.h
  include/clang/Basic/DiagnosticOptions.def
  include/clang/Basic/DiagnosticOptions.h
  include/clang/Driver/Options.td
  lib/ARCMigrate/ARCMT.cpp
  lib/Basic/DiagnosticIDs.cpp
  lib/Basic/DiagnosticOptions.cpp
  lib/Basic/Warnings.cpp
  lib/Driver/ToolChains/Clang.cpp
  lib/Frontend/CompilerInvocation.cpp
  lib/Lex/PPMacroExpansion.cpp
  lib/Serialization/ASTReader.cpp
  test/Driver/warning-options_pedantic.cpp
  test/Frontend/warning-mapping-2.c

Index: test/Frontend/warning-mapping-2.c
===================================================================
--- test/Frontend/warning-mapping-2.c
+++ test/Frontend/warning-mapping-2.c
@@ -1,7 +1,31 @@
+// Check that -pedantic-errors promotes extensions to errors
+// RUN: %clang_cc1 -verify -pedantic-errors %s -DMODE=0
+
 // Check that -w takes precedence over -pedantic-errors.
-// RUN: %clang_cc1 -verify -pedantic-errors -w %s
+// RUN: %clang_cc1 -verify -pedantic-errors -w %s -DMODE=1
 
-// Expect *not* to see a diagnostic for "implicit declaration of function"
-// expected-no-diagnostics
+// Check that -fpermissive demotes errors to warnings.
+// RUN: %clang_cc1 -verify -fpermissive %s -DMODE=2
+
+// Check that -w suppresses diagnostics demoted by -fpermissive.
+// RUN: %clang_cc1 -verify -fpermissive -w %s -DMODE=3
 
 void f0() { f1(); }
+#if MODE == 0
+  // expected-error@-2 {{implicit declaration of function}}
+#elif MODE == 1
+  // no diagnostic
+#elif MODE == 2
+  // expected-warning@-6 {{implicit declaration of function}}
+#else
+  // expected-no-diagnostics
+#endif
+
+void f2() {
+  return 123;
+#if MODE <= 1
+  // expected-error@-2 {{should not return a value}}
+#elif MODE == 2
+  // expected-warning@-4 {{should not return a value}}
+#endif
+}
Index: test/Driver/warning-options_pedantic.cpp
===================================================================
--- test/Driver/warning-options_pedantic.cpp
+++ test/Driver/warning-options_pedantic.cpp
@@ -2,12 +2,37 @@
 // Delimiters match the start of the cc1 and the start of the linker lines
 // DELIMITERS: {{^ *"}}
 
+// RUN: %clang -### -pedantic %s 2>&1 | FileCheck -check-prefix=PEDANTIC -check-prefix=DELIMITERS %s
+// RUN: %clang -### -pedantic-errors %s 2>&1 | FileCheck -check-prefix=PEDANTIC_ERRORS -check-prefix=DELIMITERS %s
+// RUN: %clang -### -Wpedantic %s 2>&1 | FileCheck -check-prefix=NO_PEDANTIC -check-prefix=DELIMITERS %s
 // RUN: %clang -### -pedantic -no-pedantic %s 2>&1 | FileCheck -check-prefix=NO_PEDANTIC -check-prefix=DELIMITERS %s
 // RUN: %clang -### -pedantic -Wno-pedantic %s 2>&1 | FileCheck -check-prefix=PEDANTIC -check-prefix=DELIMITERS %s
+// RUN: %clang -### -pedantic -no-pedantic -pedantic %s 2>&1 | FileCheck -check-prefix=PEDANTIC -check-prefix=DELIMITERS %s
+// RUN: %clang -### -pedantic -no-pedantic -pedantic-errors %s 2>&1 | FileCheck -check-prefix=PEDANTIC_ERRORS -check-prefix=DELIMITERS %s
+// RUN: %clang -### -pedantic-errors -no-pedantic -pedantic %s 2>&1 | FileCheck -check-prefix=PEDANTIC -check-prefix=DELIMITERS %s
+// RUN: %clang -### -pedantic -no-pedantic -pedantic-errors -pedantic %s 2>&1 | FileCheck -check-prefix=PEDANTIC_ERRORS -check-prefix=DELIMITERS %s
+// RUN: %clang -### -pedantic -no-pedantic -Wpedantic %s 2>&1 | FileCheck -check-prefix=NO_PEDANTIC -check-prefix=DELIMITERS %s
+// RUN: %clang -### -pedantic-errors -no-pedantic -Wpedantic %s 2>&1 | FileCheck -check-prefix=NO_PEDANTIC -check-prefix=DELIMITERS %s
+
+// RUN: %clang -### -fpermissive %s 2>&1 | FileCheck -check-prefix=PERMISSIVE -check-prefix=DELIMITERS %s
+// RUN: %clang -### -fpermissive -fno-permissive -pedantic %s 2>&1 | FileCheck -check-prefix=PEDANTIC -check-prefix=DELIMITERS %s
+// RUN: %clang -### -fpermissive -fno-permissive -pedantic-errors %s 2>&1 | FileCheck -check-prefix=PEDANTIC_ERRORS -check-prefix=DELIMITERS %s
+// RUN: %clang -### -pedantic -fpermissive -fno-permissive %s 2>&1 | FileCheck -check-prefix=PEDANTIC -check-prefix=DELIMITERS %s
+// RUN: %clang -### -pedantic-errors -fpermissive -fno-permissive %s 2>&1 | FileCheck -check-prefix=PEDANTIC_ERRORS -check-prefix=DELIMITERS %s
+// RUN: %clang -### -pedantic -no-pedantic -fpermissive %s 2>&1 | FileCheck -check-prefix=PERMISSIVE -check-prefix=DELIMITERS %s
+// RUN: %clang -### -pedantic-errors -no-pedantic -fpermissive %s 2>&1 | FileCheck -check-prefix=PERMISSIVE -check-prefix=DELIMITERS %s
+
+// RUN: %clang -### -pedantic -fpermissive %s 2>&1 | FileCheck -check-prefix=PEDANTIC_PERMISSIVE %s
+// RUN: %clang -### -pedantic-errors -fpermissive %s 2>&1 | FileCheck -check-prefix=PEDANTIC_ERRORS_PERMISSIVE %s
+// RUN: %clang -### -pedantic-errors -pedantic -fpermissive %s 2>&1 | FileCheck -check-prefix=PEDANTIC_ERRORS_PERMISSIVE %s
+
 // NO_PEDANTIC-NOT: -pedantic
-// RUN: %clang -### -pedantic -pedantic -no-pedantic -pedantic %s 2>&1 | FileCheck -check-prefix=PEDANTIC -check-prefix=DELIMITERS %s
-// RUN: %clang -### -pedantic -pedantic -no-pedantic -Wpedantic %s 2>&1 | FileCheck -check-prefix=NO_PEDANTIC -check-prefix=DELIMITERS %s
-// PEDANTIC: -pedantic
+// PEDANTIC: "-pedantic"
+// PEDANTIC_ERRORS: "-pedantic-errors"
+// PERMISSIVE: "-fpermissive"
 // REQUIRES: clang-driver
 
 // DELIMITERS: {{^ *"}}
+
+// PEDANTIC_PERMISSIVE: error: invalid argument '-pedantic' not allowed with '-fpermissive'
+// PEDANTIC_ERRORS_PERMISSIVE: error: invalid argument '-pedantic-errors' not allowed with '-fpermissive'
Index: lib/Serialization/ASTReader.cpp
===================================================================
--- lib/Serialization/ASTReader.cpp
+++ lib/Serialization/ASTReader.cpp
@@ -483,10 +483,16 @@
 }
 
 static bool isExtHandlingFromDiagsError(DiagnosticsEngine &Diags) {
-  diag::Severity Ext = Diags.getExtensionHandlingBehavior();
-  if (Ext == diag::Severity::Warning && Diags.getWarningsAsErrors())
+  switch (Diags.getExtensionHandlingBehavior()) {
+  case ExtensionDiagMode::PedanticErrors:
     return true;
-  return Ext >= diag::Severity::Error;
+  case ExtensionDiagMode::Pedantic:
+    return Diags.getWarningsAsErrors();
+  case ExtensionDiagMode::Default:
+  case ExtensionDiagMode::Permissive:
+    return false;
+  }
+  llvm_unreachable("unknown extension diagnostic mode");
 }
 
 static bool checkDiagnosticMappings(DiagnosticsEngine &StoredDiags,
@@ -5776,7 +5782,7 @@
       Initial.WarningsAsErrors = Flags & 1; Flags >>= 1;
       Initial.EnableAllWarnings = Flags & 1; Flags >>= 1;
       Initial.IgnoreAllWarnings = Flags & 1; Flags >>= 1;
-      Initial.ExtBehavior = (diag::Severity)Flags;
+      Initial.ExtBehavior = (ExtensionDiagMode)Flags;
       FirstState = ReadDiagState(Initial, SourceLocation(), true);
 
       assert(F.OriginalSourceFileID.isValid());
Index: lib/Lex/PPMacroExpansion.cpp
===================================================================
--- lib/Lex/PPMacroExpansion.cpp
+++ lib/Lex/PPMacroExpansion.cpp
@@ -1110,9 +1110,14 @@
 
   // If the use of an extension results in an error diagnostic, extensions are
   // effectively unavailable, so just return false here.
-  if (PP.getDiagnostics().getExtensionHandlingBehavior() >=
-      diag::Severity::Error)
-    return false;
+  switch (PP.getDiagnostics().getExtensionHandlingBehavior()) {
+    case ExtensionDiagMode::PedanticErrors:
+      return false;
+    case ExtensionDiagMode::Pedantic:
+    case ExtensionDiagMode::Default:
+    case ExtensionDiagMode::Permissive:
+      break;
+  }
 
   const LangOptions &LangOpts = PP.getLangOpts();
 
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -1429,8 +1429,14 @@
     Opts.DiagnosticSerializationFile = A->getValue();
   Opts.IgnoreWarnings = Args.hasArg(OPT_w);
   Opts.NoRewriteMacros = Args.hasArg(OPT_Wno_rewrite_macros);
-  Opts.Pedantic = Args.hasArg(OPT_pedantic);
-  Opts.PedanticErrors = Args.hasArg(OPT_pedantic_errors);
+
+  if (Args.hasArg(OPT_pedantic_errors))
+    Opts.setExtensionsMode(ExtensionDiagMode::PedanticErrors);
+  else if (Args.hasArg(OPT_pedantic))
+    Opts.setExtensionsMode(ExtensionDiagMode::Pedantic);
+  else if (Args.hasArg(OPT_fpermissive))
+    Opts.setExtensionsMode(ExtensionDiagMode::Permissive);
+
   Opts.ShowCarets = !Args.hasArg(OPT_fno_caret_diagnostics);
   Opts.ShowColors = parseShowColorsArgs(Args, DefaultDiagColor);
   Opts.ShowColumn = Args.hasFlag(OPT_fshow_column,
Index: lib/Driver/ToolChains/Clang.cpp
===================================================================
--- lib/Driver/ToolChains/Clang.cpp
+++ lib/Driver/ToolChains/Clang.cpp
@@ -4202,11 +4202,43 @@
   Args.AddAllArgs(CmdArgs, options::OPT_R_Group);
 
   Args.AddAllArgs(CmdArgs, options::OPT_W_Group);
-  if (Args.hasFlag(options::OPT_pedantic, options::OPT_no_pedantic, false))
-    CmdArgs.push_back("-pedantic");
-  Args.AddLastArg(CmdArgs, options::OPT_pedantic_errors);
   Args.AddLastArg(CmdArgs, options::OPT_w);
 
+  // Extensions handling: last of -pedantic / -pedantic-errors / -no-pedantic
+  // takes precedence, except that -pedantic after -pedantic-errors has no
+  // effect.
+  const Arg *PedanticArg = nullptr;
+  if (const Arg *A =
+          Args.getLastArg(options::OPT_pedantic_errors, options::OPT_pedantic,
+                          options::OPT_no_pedantic)) {
+    if (!A->getOption().matches(options::OPT_no_pedantic)) {
+      const Arg *PedErrors = Args.getLastArg(options::OPT_pedantic_errors,
+                                             options::OPT_no_pedantic);
+      if (PedErrors &&
+          PedErrors->getOption().matches(options::OPT_pedantic_errors)) {
+        CmdArgs.push_back("-pedantic-errors");
+        PedanticArg = PedErrors;
+      } else {
+        CmdArgs.push_back("-pedantic");
+        PedanticArg = A;
+      }
+    }
+  }
+  if (Args.hasFlag(options::OPT_fpermissive, options::OPT_fno_permissive,
+                   false)) {
+    // Unlike GCC, we apply -pedantic and -fpermissive to all extension
+    // diagnostics, and reject any combination of both flags.
+    //
+    // GCC allows (eg) -pedantic-errors -fpermissive, and responds by
+    // erroring on all extensions it would not error on by default, and
+    // only warning on all extensions it would error on by default. That
+    // does not seem like useful behavior, so we do not follow suit.
+    if (PedanticArg)
+      D.Diag(diag::err_drv_argument_not_allowed_with)
+          << PedanticArg->getAsString(Args) << "-fpermissive";
+    CmdArgs.push_back("-fpermissive");
+  }
+
   // Fixed point flags
   if (Args.hasFlag(options::OPT_ffixed_point, options::OPT_fno_fixed_point,
                    /*Default=*/false))
Index: lib/Basic/Warnings.cpp
===================================================================
--- lib/Basic/Warnings.cpp
+++ lib/Basic/Warnings.cpp
@@ -62,12 +62,7 @@
   // If -pedantic or -pedantic-errors was specified, then we want to map all
   // extension diagnostics onto WARNING or ERROR unless the user has futz'd
   // around with them explicitly.
-  if (Opts.PedanticErrors)
-    Diags.setExtensionHandlingBehavior(diag::Severity::Error);
-  else if (Opts.Pedantic)
-    Diags.setExtensionHandlingBehavior(diag::Severity::Warning);
-  else
-    Diags.setExtensionHandlingBehavior(diag::Severity::Ignored);
+  Diags.setExtensionHandlingBehavior(Opts.getExtensionsMode());
 
   SmallVector<diag::kind, 10> _Diags;
   const IntrusiveRefCntPtr< DiagnosticIDs > DiagIDs =
Index: lib/Basic/DiagnosticOptions.cpp
===================================================================
--- lib/Basic/DiagnosticOptions.cpp
+++ lib/Basic/DiagnosticOptions.cpp
@@ -21,4 +21,14 @@
   return Out << static_cast<UT>(M);
 }
 
+raw_ostream &operator<<(raw_ostream &Out, ExtensionDiagMode E) {
+  switch (E) {
+  case ExtensionDiagMode::PedanticErrors: return Out << "pedantic-errors";
+  case ExtensionDiagMode::Pedantic: return Out << "pedantic";
+  case ExtensionDiagMode::Default: return Out << "default";
+  case ExtensionDiagMode::Permissive: return Out << "permissive";
+  }
+  llvm_unreachable("unknown extension diagnostic mode");
+}
+
 } // namespace clang
Index: lib/Basic/DiagnosticIDs.cpp
===================================================================
--- lib/Basic/DiagnosticIDs.cpp
+++ lib/Basic/DiagnosticIDs.cpp
@@ -448,9 +448,22 @@
     return diag::Severity::Ignored;
 
   // For extension diagnostics that haven't been explicitly mapped, check if we
-  // should upgrade the diagnostic.
-  if (IsExtensionDiag && !Mapping.isUser())
-    Result = std::max(Result, State->ExtBehavior);
+  // should upgrade or downgrade the diagnostic.
+  if (IsExtensionDiag && !Mapping.isUser()) {
+    switch (State->ExtBehavior) {
+    case ExtensionDiagMode::PedanticErrors:
+      Result = std::max(Result, diag::Severity::Error);
+      break;
+    case ExtensionDiagMode::Pedantic:
+      Result = std::max(Result, diag::Severity::Warning);
+      break;
+    case ExtensionDiagMode::Default:
+      break;
+    case ExtensionDiagMode::Permissive:
+      Result = std::min(Result, diag::Severity::Warning);
+      break;
+    }
+  }
 
   // At this point, ignored errors can no longer be upgraded.
   if (Result == diag::Severity::Ignored)
@@ -460,7 +473,7 @@
   // default (disregarding attempts to upgrade severity from Warning to Error),
   // as well as disabling all messages which are currently mapped to Warning
   // (whether by default or downgraded from Error via e.g. -Wno-error or #pragma
-  // diagnostic.)
+  // diagnostic or -fpermissive.)
   if (State->IgnoreAllWarnings) {
     if (Result == diag::Severity::Warning ||
         (Result >= diag::Severity::Error &&
Index: lib/ARCMigrate/ARCMT.cpp
===================================================================
--- lib/ARCMigrate/ARCMT.cpp
+++ lib/ARCMigrate/ARCMT.cpp
@@ -195,7 +195,9 @@
   CInvok->getLangOpts()->ObjCAutoRefCount = true;
   CInvok->getLangOpts()->setGC(LangOptions::NonGC);
   CInvok->getDiagnosticOpts().ErrorLimit = 0;
-  CInvok->getDiagnosticOpts().PedanticErrors = 0;
+  if (CInvok->getDiagnosticOpts().getExtensionsMode() ==
+        ExtensionDiagMode::PedanticErrors)
+    CInvok->getDiagnosticOpts().setExtensionsMode(ExtensionDiagMode::Pedantic);
 
   // Ignore -Werror flags when migrating.
   std::vector<std::string> WarnOpts;
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -687,6 +687,9 @@
   Flags<[DriverOption, CC1Option]>,
   HelpText<"Disable GNU style inline asm">;
 
+def fpermissive : Flag<["-"], "fpermissive">, Group<f_Group>, Flags<[CC1Option]>,
+    HelpText<"Downgrade diagnostics for conforming extensions from errors to warnings">;
+def fno_permissive : Flag<["-"], "fno-permissive">, Group<f_Group>;
 def fprofile_sample_use : Flag<["-"], "fprofile-sample-use">, Group<f_Group>,
     Flags<[CoreOption]>;
 def fno_profile_sample_use : Flag<["-"], "fno-profile-sample-use">, Group<f_Group>,
@@ -3033,7 +3036,6 @@
 defm ivopts : BooleanFFlag<"ivopts">, Group<clang_ignored_gcc_optimization_f_Group>;
 defm non_call_exceptions : BooleanFFlag<"non-call-exceptions">, Group<clang_ignored_f_Group>;
 defm peel_loops : BooleanFFlag<"peel-loops">, Group<clang_ignored_gcc_optimization_f_Group>;
-defm permissive : BooleanFFlag<"permissive">, Group<clang_ignored_f_Group>;
 defm prefetch_loop_arrays : BooleanFFlag<"prefetch-loop-arrays">, Group<clang_ignored_gcc_optimization_f_Group>;
 defm printf : BooleanFFlag<"printf">, Group<clang_ignored_f_Group>;
 defm profile : BooleanFFlag<"profile">, Group<clang_ignored_f_Group>;
Index: include/clang/Basic/DiagnosticOptions.h
===================================================================
--- include/clang/Basic/DiagnosticOptions.h
+++ include/clang/Basic/DiagnosticOptions.h
@@ -59,6 +59,21 @@
 
 raw_ostream& operator<<(raw_ostream& Out, DiagnosticLevelMask M);
 
+/// An enumeration describing how extension diagnostics should be treated
+/// by default.
+enum class ExtensionDiagMode : unsigned {
+  /// Map all extension diagnostics to at most a warning.
+  Permissive,
+  /// Map all extension diagnostics as specified in the diagnostic.
+  Default,
+  /// Map all extension diagnostics to at least a warning.
+  Pedantic,
+  /// Map all extension diagnostics to at least an error.
+  PedanticErrors,
+};
+
+raw_ostream& operator<<(raw_ostream& Out, ExtensionDiagMode M);
+
 /// Options for controlling the compiler diagnostics engine.
 class DiagnosticOptions : public RefCountedBase<DiagnosticOptions>{
 public:
Index: include/clang/Basic/DiagnosticOptions.def
===================================================================
--- include/clang/Basic/DiagnosticOptions.def
+++ include/clang/Basic/DiagnosticOptions.def
@@ -45,8 +45,8 @@
 
 SEMANTIC_DIAGOPT(IgnoreWarnings, 1, 0)   /// -w
 DIAGOPT(NoRewriteMacros, 1, 0)  /// -Wno-rewrite-macros
-DIAGOPT(Pedantic, 1, 0)         /// -pedantic
-DIAGOPT(PedanticErrors, 1, 0)   /// -pedantic-errors
+ENUM_DIAGOPT(ExtensionsMode, ExtensionDiagMode, 2, ExtensionDiagMode::Default)
+                                /// -pedantic, -pedantic-errors, -fpermissive
 DIAGOPT(ShowColumn, 1, 1)       /// Show column number on diagnostics.
 DIAGOPT(ShowLocation, 1, 1)     /// Show source location information.
 DIAGOPT(AbsolutePath, 1, 0)     /// Use absolute paths.
Index: include/clang/Basic/Diagnostic.h
===================================================================
--- include/clang/Basic/Diagnostic.h
+++ include/clang/Basic/Diagnostic.h
@@ -275,12 +275,13 @@
     unsigned SuppressSystemWarnings : 1;
 
     // Map extensions to warnings or errors?
-    diag::Severity ExtBehavior = diag::Severity::Ignored;
+    ExtensionDiagMode ExtBehavior : 2;
 
     DiagState()
         : IgnoreAllWarnings(false), EnableAllWarnings(false),
           WarningsAsErrors(false), ErrorsAsFatal(false),
-          SuppressSystemWarnings(false) {}
+          SuppressSystemWarnings(false),
+          ExtBehavior(ExtensionDiagMode::Default) {}
 
     using iterator = llvm::DenseMap<unsigned, DiagnosticMapping>::iterator;
     using const_iterator =
@@ -680,11 +681,12 @@
   /// Controls whether otherwise-unmapped extension diagnostics are
   /// mapped onto ignore/warning/error.
   ///
-  /// This corresponds to the GCC -pedantic and -pedantic-errors option.
-  void setExtensionHandlingBehavior(diag::Severity H) {
-    GetCurDiagState()->ExtBehavior = H;
+  /// This corresponds to the GCC -fpermissive/-pedantic/-pedantic-errors
+  /// options.
+  void setExtensionHandlingBehavior(ExtensionDiagMode E) {
+    GetCurDiagState()->ExtBehavior = E;
   }
-  diag::Severity getExtensionHandlingBehavior() const {
+  ExtensionDiagMode getExtensionHandlingBehavior() const {
     return GetCurDiagState()->ExtBehavior;
   }
 
Index: docs/UsersManual.rst
===================================================================
--- docs/UsersManual.rst
+++ docs/UsersManual.rst
@@ -135,6 +135,17 @@
 
   Error on language extensions.
 
+.. option:: -fpermissive
+
+  Do not error on language extensions. Diagnostics for invalid code using known
+  language extensions in the current language mode are downgraded to at most a
+  warning. It is strongly recommended that ``-Wno-foo`` or ``-Wno-error=foo``
+  are used to silence or downgrade individual errors instead of using this
+  flag.
+
+  Note that this does not generally enable extensions controlled by other
+  ``-f`` flags, such as ``-fms-extensions``.
+
 .. option:: -Wsystem-headers
 
   Enable warnings from system headers.
@@ -142,13 +153,13 @@
 .. option:: -ferror-limit=123
 
   Stop emitting diagnostics after 123 errors have been produced. The default is
-  20, and the error limit can be disabled with `-ferror-limit=0`.
+  20, and the error limit can be disabled with ``-ferror-limit=0``.
 
 .. option:: -ftemplate-backtrace-limit=123
 
   Only emit up to 123 template instantiation notes within the template
   instantiation backtrace for a single warning or error. The default is 10, and
-  the limit can be disabled with `-ftemplate-backtrace-limit=0`.
+  the limit can be disabled with ``-ftemplate-backtrace-limit=0``.
 
 .. _cl_diag_formatting:
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to