diff mbox

[C++] Coding rule enforcement

Message ID 55F816F2.5010209@acm.org
State New
Headers show

Commit Message

Nathan Sidwell Sept. 15, 2015, 1:02 p.m. UTC
Jason,
somme of our customers have 'interesting' C++ coding rules, they'd like to have 
the compiler enforced.  They want to disable:

1) namespace definitions
2) template declarations
3) multiple inheritance
4) virtual inheritance

But they want to use the STL.  This patch implements 4 new flags, intended to be 
use in the -fno-FOO form.  They're only active outside of system header files.

1) -fno-namespaces disables namespace definitions, but not using directives or 
qualified names.

2) -fno-templates disables primary template declarations, but not template 
instantiations or specializations (partial or otherwise).

3) -fno-multiple-inheritance disables direct multiple inheritance, but not 
indirect multiple inheritance

4) -fno-virtual-inheritance disables direct virtual inheritance, but not 
indirect virtual inheritance.

Thus you can't use any of these features directly, but one can use the STL and 
have it behave as intended.

WDYT?

nathan

Comments

Richard Biener Sept. 15, 2015, 1:26 p.m. UTC | #1
On Tue, Sep 15, 2015 at 3:02 PM, Nathan Sidwell <nathan@acm.org> wrote:
> Jason,
> somme of our customers have 'interesting' C++ coding rules, they'd like to
> have the compiler enforced.  They want to disable:
>
> 1) namespace definitions
> 2) template declarations
> 3) multiple inheritance
> 4) virtual inheritance
>
> But they want to use the STL.  This patch implements 4 new flags, intended
> to be use in the -fno-FOO form.  They're only active outside of system
> header files.
>
> 1) -fno-namespaces disables namespace definitions, but not using directives
> or qualified names.
>
> 2) -fno-templates disables primary template declarations, but not template
> instantiations or specializations (partial or otherwise).
>
> 3) -fno-multiple-inheritance disables direct multiple inheritance, but not
> indirect multiple inheritance
>
> 4) -fno-virtual-inheritance disables direct virtual inheritance, but not
> indirect virtual inheritance.

Wouldn't warning flags be better so you can decide whether it's an error
or a warning via -Werror=virtual-inheritance vs. -Wvirtual-inheritance?

> Thus you can't use any of these features directly, but one can use the STL
> and have it behave as intended.
>
> WDYT?
>
> nathan
Nathan Sidwell Sept. 15, 2015, 1:28 p.m. UTC | #2
On 09/15/15 09:26, Richard Biener wrote:

> Wouldn't warning flags be better so you can decide whether it's an error
> or a warning via -Werror=virtual-inheritance vs. -Wvirtual-inheritance?

I agree.  I didn't know of the -Werror=FOO trick to make them individually errors.

nathan
Jason Merrill Sept. 15, 2015, 1:33 p.m. UTC | #3
On 09/15/2015 09:26 AM, Richard Biener wrote:
> Wouldn't warning flags be better so you can decide whether it's an error
> or a warning via -Werror=virtual-inheritance vs. -Wvirtual-inheritance?

Yep.  That also handles the system header exemption (unless 
-Wsystem-headers).

Jason
Manuel López-Ibáñez Sept. 15, 2015, 5:20 p.m. UTC | #4
On 15/09/15 15:26, Richard Biener wrote:
> On Tue, Sep 15, 2015 at 3:02 PM, Nathan Sidwell <nathan@acm.org> wrote:
>> Jason,
>> somme of our customers have 'interesting' C++ coding rules, they'd like to
>> have the compiler enforced.  They want to disable:
>>
>> 1) namespace definitions
>> 2) template declarations
>> 3) multiple inheritance
>> 4) virtual inheritance
>>
>> But they want to use the STL.  This patch implements 4 new flags, intended
>> to be use in the -fno-FOO form.  They're only active outside of system
>> header files.

If these are quite specific coding rules, wouldn't this be something ideal for 
a plugin rather than implemented in the compiler proper?

One can implement warnings with plugins (in python if desired!)

http://gcc-python-plugin.readthedocs.org/en/latest/basics.html#generating-custom-errors-and-warnings

Compiler plugins that implement specific coding rules are quite common, alas, 
using clang not GCC: https://wiki.documentfoundation.org/Development/Clang_plugins

It would be more generally useful to extend GCC to fully support this type of 
plugins.

Cheers,

Manuel.
Jason Merrill Sept. 15, 2015, 6:31 p.m. UTC | #5
On 09/15/2015 01:20 PM, Manuel López-Ibáñez wrote:
> On 15/09/15 15:26, Richard Biener wrote:
>> On Tue, Sep 15, 2015 at 3:02 PM, Nathan Sidwell <nathan@acm.org> wrote:
>>> Jason,
>>> somme of our customers have 'interesting' C++ coding rules, they'd
>>> like to
>>> have the compiler enforced.  They want to disable:
>>>
>>> 1) namespace definitions
>>> 2) template declarations
>>> 3) multiple inheritance
>>> 4) virtual inheritance
>>>
>>> But they want to use the STL.  This patch implements 4 new flags,
>>> intended
>>> to be use in the -fno-FOO form.  They're only active outside of system
>>> header files.
>
> If these are quite specific coding rules, wouldn't this be something
> ideal for a plugin rather than implemented in the compiler proper?
>
> One can implement warnings with plugins (in python if desired!)
>
> http://gcc-python-plugin.readthedocs.org/en/latest/basics.html#generating-custom-errors-and-warnings
>
>
> Compiler plugins that implement specific coding rules are quite common,
> alas, using clang not GCC:
> https://wiki.documentfoundation.org/Development/Clang_plugins
>
> It would be more generally useful to extend GCC to fully support this
> type of plugins.

Good point.

Jason
Daniel Gutson Sept. 21, 2015, 1:46 p.m. UTC | #6
On Tue, Sep 15, 2015 at 3:31 PM, Jason Merrill <jason@redhat.com> wrote:
> On 09/15/2015 01:20 PM, Manuel López-Ibáñez wrote:
>>
>> On 15/09/15 15:26, Richard Biener wrote:
>>>
>>> On Tue, Sep 15, 2015 at 3:02 PM, Nathan Sidwell <nathan@acm.org> wrote:
>>>>
>>>> Jason,
>>>> somme of our customers have 'interesting' C++ coding rules, they'd
>>>> like to
>>>> have the compiler enforced.  They want to disable:
>>>>
>>>> 1) namespace definitions
>>>> 2) template declarations
>>>> 3) multiple inheritance
>>>> 4) virtual inheritance
>>>>
>>>> But they want to use the STL.  This patch implements 4 new flags,
>>>> intended
>>>> to be use in the -fno-FOO form.  They're only active outside of system
>>>> header files.
>>
>>
>> If these are quite specific coding rules, wouldn't this be something
>> ideal for a plugin rather than implemented in the compiler proper?
>>
>> One can implement warnings with plugins (in python if desired!)
>>
>>
>> http://gcc-python-plugin.readthedocs.org/en/latest/basics.html#generating-custom-errors-and-warnings
>>
>>
>> Compiler plugins that implement specific coding rules are quite common,
>> alas, using clang not GCC:
>> https://wiki.documentfoundation.org/Development/Clang_plugins
>>
>> It would be more generally useful to extend GCC to fully support this
>> type of plugins.
>
>
> Good point.

FWIW, we could make this plugin in 2 weeks (w already have static
checkers as plugins for our customers). I understand Nathan that you
may have some deadlines, but if we could have the opportunity to
implement it, we could accomplish a clean isolation of a particular
business needs (despite I acknowledge that a warning about virtual
inheritance may be useful for a broader audience). OTOH, a plugin can
receive arguments, such as a configuration file which could point to
specific sources or hints about where to apply the warning, or a
suppression file, both things useful for large legacy code. IMVHO I
think this is a superior solution.
Please let me know if we could collaborate to get both a better gcc
and a better static checker.


>
> Jason
>
>
Manuel López-Ibáñez Sept. 21, 2015, 2:01 p.m. UTC | #7
On 21 September 2015 at 15:46, Daniel Gutson
<daniel.gutson@tallertechnologies.com> wrote:
>
> FWIW, we could make this plugin in 2 weeks (w already have static
> checkers as plugins for our customers). I understand Nathan that you
> may have some deadlines, but if we could have the opportunity to
> implement it, we could accomplish a clean isolation of a particular
> business needs (despite I acknowledge that a warning about virtual
> inheritance may be useful for a broader audience). OTOH, a plugin can
> receive arguments, such as a configuration file which could point to
> specific sources or hints about where to apply the warning, or a
> suppression file, both things useful for large legacy code. IMVHO I
> think this is a superior solution.
> Please let me know if we could collaborate to get both a better gcc
> and a better static checker.

My opinion is that if people want to "donate" their plugins to the
FSF, they are willing to maintain them, and they are not overtly
complex or require any third-party software, they should be added to
the GCC repository and build/tested. They could serve as examples and
extra testing for the plugin framework, with the expectation that they
may get removed if they become unmaintained.

Cheers,

Manuel.
Jason Merrill Sept. 21, 2015, 4:23 p.m. UTC | #8
On 09/21/2015 10:01 AM, Manuel López-Ibáñez wrote:
> On 21 September 2015 at 15:46, Daniel Gutson
> <daniel.gutson@tallertechnologies.com> wrote:
>>
>> FWIW, we could make this plugin in 2 weeks (w already have static
>> checkers as plugins for our customers). I understand Nathan that you
>> may have some deadlines, but if we could have the opportunity to
>> implement it, we could accomplish a clean isolation of a particular
>> business needs (despite I acknowledge that a warning about virtual
>> inheritance may be useful for a broader audience). OTOH, a plugin can
>> receive arguments, such as a configuration file which could point to
>> specific sources or hints about where to apply the warning, or a
>> suppression file, both things useful for large legacy code. IMVHO I
>> think this is a superior solution.
>> Please let me know if we could collaborate to get both a better gcc
>> and a better static checker.
>
> My opinion is that if people want to "donate" their plugins to the
> FSF, they are willing to maintain them, and they are not overtly
> complex or require any third-party software, they should be added to
> the GCC repository and build/tested. They could serve as examples and
> extra testing for the plugin framework, with the expectation that they
> may get removed if they become unmaintained.

Absolutely.

Jason
Daniel Gutson Sept. 21, 2015, 4:31 p.m. UTC | #9
On Mon, Sep 21, 2015 at 1:23 PM, Jason Merrill <jason@redhat.com> wrote:
> On 09/21/2015 10:01 AM, Manuel López-Ibáñez wrote:
>>
>> On 21 September 2015 at 15:46, Daniel Gutson
>> <daniel.gutson@tallertechnologies.com> wrote:
>>>
>>>
>>> FWIW, we could make this plugin in 2 weeks (w already have static
>>> checkers as plugins for our customers). I understand Nathan that you
>>> may have some deadlines, but if we could have the opportunity to
>>> implement it, we could accomplish a clean isolation of a particular
>>> business needs (despite I acknowledge that a warning about virtual
>>> inheritance may be useful for a broader audience). OTOH, a plugin can
>>> receive arguments, such as a configuration file which could point to
>>> specific sources or hints about where to apply the warning, or a
>>> suppression file, both things useful for large legacy code. IMVHO I
>>> think this is a superior solution.
>>> Please let me know if we could collaborate to get both a better gcc
>>> and a better static checker.
>>
>>
>> My opinion is that if people want to "donate" their plugins to the
>> FSF, they are willing to maintain them, and they are not overtly
>> complex or require any third-party software, they should be added to
>> the GCC repository and build/tested. They could serve as examples and
>> extra testing for the plugin framework, with the expectation that they
>> may get removed if they become unmaintained.
>
>
> Absolutely.

Three of those plugins are already available in bitbucket. Maybe we
should move them to the official plugins page.
The fourth plugin is under development but I asked for volunteers to
test it in ths C++' std-proposals forum,
since it enhances the semantic of constexpr in order to allocate
memory during constexpr construction and
therefore having associative containers in ROM, so this is a special
case where the main intent is a proof of
concept for a C++ proposal.

>
> Jason
>
>
Nathan Sidwell Sept. 21, 2015, 4:39 p.m. UTC | #10
On 09/21/15 12:23, Jason Merrill wrote:
> On 09/21/2015 10:01 AM, Manuel López-Ibáñez wrote:
>> On 21 September 2015 at 15:46, Daniel Gutson
>> <daniel.gutson@tallertechnologies.com> wrote:
>>>
>>> FWIW, we could make this plugin in 2 weeks (w already have static
>>> checkers as plugins for our customers). I understand Nathan that you
>>> may have some deadlines, but if we could have the opportunity to
>>> implement it, we could accomplish a clean isolation of a particular
>>> business needs (despite I acknowledge that a warning about virtual
>>> inheritance may be useful for a broader audience). OTOH, a plugin can
>>> receive arguments, such as a configuration file which could point to
>>> specific sources or hints about where to apply the warning, or a
>>> suppression file, both things useful for large legacy code. IMVHO I
>>> think this is a superior solution.
>>> Please let me know if we could collaborate to get both a better gcc
>>> and a better static checker.
>>
>> My opinion is that if people want to "donate" their plugins to the
>> FSF, they are willing to maintain them, and they are not overtly
>> complex or require any third-party software, they should be added to
>> the GCC repository and build/tested. They could serve as examples and
>> extra testing for the plugin framework, with the expectation that they
>> may get removed if they become unmaintained.
>
> Absolutely.

I've no objection to going the plugin way, but I'm extremely unlikely to be able 
to devote time to doing that in the foreseeable future.

nathan
Jason Merrill Sept. 21, 2015, 5:12 p.m. UTC | #11
On 09/21/2015 12:39 PM, Nathan Sidwell wrote:
> On 09/21/15 12:23, Jason Merrill wrote:
>> On 09/21/2015 10:01 AM, Manuel López-Ibáñez wrote:
>>> On 21 September 2015 at 15:46, Daniel Gutson
>>> <daniel.gutson@tallertechnologies.com> wrote:
>>>>
>>>> FWIW, we could make this plugin in 2 weeks (w already have static
>>>> checkers as plugins for our customers). I understand Nathan that you
>>>> may have some deadlines, but if we could have the opportunity to
>>>> implement it, we could accomplish a clean isolation of a particular
>>>> business needs (despite I acknowledge that a warning about virtual
>>>> inheritance may be useful for a broader audience). OTOH, a plugin can
>>>> receive arguments, such as a configuration file which could point to
>>>> specific sources or hints about where to apply the warning, or a
>>>> suppression file, both things useful for large legacy code. IMVHO I
>>>> think this is a superior solution.
>>>> Please let me know if we could collaborate to get both a better gcc
>>>> and a better static checker.
>>>
>>> My opinion is that if people want to "donate" their plugins to the
>>> FSF, they are willing to maintain them, and they are not overtly
>>> complex or require any third-party software, they should be added to
>>> the GCC repository and build/tested. They could serve as examples and
>>> extra testing for the plugin framework, with the expectation that they
>>> may get removed if they become unmaintained.
>>
>> Absolutely.
>
> I've no objection to going the plugin way, but I'm extremely unlikely to
> be able to devote time to doing that in the foreseeable future.

I like the idea of the plugin, but your patch is very clean, so I think 
let's go ahead and put it in.

Jason
diff mbox

Patch

2015-09-15  Nathan Sidwell  <nathan@codesourcery.com>

	c-family/
	* c.opt (fmultiple-inheritance, fvirtual-inheritance, ftemplates,
	fnamespaces): New C++ options.

	cp/
	* decl.c (xref_basetypes): Check virtual and/or multiple
	inheritance not disabled.
	* parser.c (cp_parser_namespace_definition): Check namespaces
	not disabled.
	* pt.c (push_template_decl_real): Check templates not disabled.

	* doc/invoke.texi  (-fmultiple-inheritance, -fvirtual-inheritance,
	-ftemplates, -namespaces): Document.

	testsuite/
	* g++.dg/diagostic/disable.C: New.

Index: c-family/c.opt
===================================================================
--- c-family/c.opt	(revision 227761)
+++ c-family/c.opt	(working copy)
@@ -1257,9 +1257,17 @@  C ObjC C++ ObjC++ Ignore Warn(switch %qs
 fmudflapir
 C ObjC C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
 
+fmultiple-inheritance
+C++ ObjC++ Var(flag_multiple_inheritance) Init(1)
+Enable multiple inheritance
+
 fname-mangling-version-
 C++ ObjC++ Joined Ignore Warn(switch %qs is no longer supported)
 
+fnamespaces
+C++ ObjC++ Var(flag_namespaces) Init(1)
+Enable namespaces
+
 fnew-abi
 C++ ObjC++ Ignore Warn(switch %qs is no longer supported)
 
@@ -1446,6 +1454,10 @@  ftabstop=
 C ObjC C++ ObjC++ Joined RejectNegative UInteger
 -ftabstop=<number>	Distance between tab stops for column reporting
 
+ftemplates
+C++ ObjC++ Var(flag_templates) Init(1)
+Enable templates
+
 ftemplate-backtrace-limit=
 C++ ObjC++ Joined RejectNegative UInteger Var(template_backtrace_limit) Init(10)
 Set the maximum number of template instantiation notes for a single warning or error
@@ -1480,6 +1492,10 @@  fuse-cxa-get-exception-ptr
 C++ ObjC++ Var(flag_use_cxa_get_exception_ptr) Init(2)
 Use __cxa_get_exception_ptr in exception handling
 
+fvirtual-inheritance
+C++ ObjC++ Var(flag_virtual_inheritance) Init(1)
+Enable virtual inheritance
+
 fvisibility-inlines-hidden
 C++ ObjC++
 Marks all inlined functions and methods as having hidden visibility
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 227761)
+++ cp/decl.c	(working copy)
@@ -12814,6 +12814,9 @@  xref_basetypes (tree ref, tree base_list
 	  error ("Java class %qT cannot have multiple bases", ref);
           return false;
         }
+      else if (!flag_multiple_inheritance
+	       && !in_system_header_at (input_location))
+	error ("%qT defined with multiple bases", ref);
     }
 
   if (max_vbases)
@@ -12825,6 +12828,9 @@  xref_basetypes (tree ref, tree base_list
 	  error ("Java class %qT cannot have virtual bases", ref);
           return false;
         }
+      else if (!flag_virtual_inheritance
+	       && !in_system_header_at (input_location))
+	error ("%qT defined with virtual base", ref);
     }
 
   for (igo_prev = binfo; base_list; base_list = TREE_CHAIN (base_list))
Index: cp/parser.c
===================================================================
--- cp/parser.c	(revision 227761)
+++ cp/parser.c	(working copy)
@@ -16798,6 +16798,9 @@  cp_parser_namespace_definition (cp_parse
 
   has_visibility = handle_namespace_attrs (current_namespace, attribs);
 
+  if (!flag_namespaces && !in_system_header_at (input_location))
+    error  ("namepace %qD entered", current_namespace);
+
   /* Parse the body of the namespace.  */
   cp_parser_namespace_body (parser);
 
Index: cp/pt.c
===================================================================
--- cp/pt.c	(revision 227761)
+++ cp/pt.c	(working copy)
@@ -5088,6 +5088,9 @@  push_template_decl_real (tree decl, bool
 
   if (is_primary)
     {
+      if (!flag_templates && !in_system_header_at (input_location))
+	error ("template %qD declared", decl);
+
       if (DECL_CLASS_SCOPE_P (decl))
 	member_template_p = true;
       if (TREE_CODE (decl) == TYPE_DECL
Index: doc/invoke.texi
===================================================================
--- doc/invoke.texi	(revision 227761)
+++ doc/invoke.texi	(working copy)
@@ -183,19 +183,19 @@  in the following sections.
 -ffor-scope  -fno-for-scope  -fno-gnu-keywords @gol
 -fno-implicit-templates @gol
 -fno-implicit-inline-templates @gol
--fno-implement-inlines  -fms-extensions @gol
--fno-nonansi-builtins  -fnothrow-opt  -fno-operator-names @gol
+-fno-implement-inlines  -fms-extensions -fno-multiple-inheritance &gol
+-fno-namespaces -fno-nonansi-builtins  -fnothrow-opt  -fno-operator-names @gol
 -fno-optional-diags  -fpermissive @gol
 -fno-pretty-templates @gol
 -frepo  -fno-rtti -fsized-deallocation @gol
 -fstats  -ftemplate-backtrace-limit=@var{n} @gol
--ftemplate-depth=@var{n} @gol
+-ftemplate-depth=@var{n} -fno-templates @gol
 -fno-threadsafe-statics  -fuse-cxa-atexit @gol
 -fno-weak  -nostdinc++ @gol
 -fvisibility-inlines-hidden @gol
 -fvtable-verify=@r{[}std@r{|}preinit@r{|}none@r{]} @gol
 -fvtv-counts -fvtv-debug @gol
--fvisibility-ms-compat @gol
+-fno-virtual-inheritance -fvisibility-ms-compat @gol
 -fext-numeric-literals @gol
 -Wabi=@var{n}  -Wabi-tag  -Wconversion-null  -Wctor-dtor-privacy @gol
 -Wdelete-non-virtual-dtor -Wliteral-suffix -Wnarrowing @gol
@@ -2292,6 +2292,14 @@  errors if these functions are not inline
 Disable Wpedantic warnings about constructs used in MFC, such as implicit
 int and getting a pointer to member function via non-standard syntax.
 
+@item -fno-multiple-inheritance
+@opindex fno-multiple-inheritance
+Do not permit multiple inheritance, except in system header files.
+
+@item -fno-namespaces
+@opindex fno-namespacess
+Do not permit namespace definitions, except in system header files.
+
 @item -fno-nonansi-builtins
 @opindex fno-nonansi-builtins
 Disable built-in declarations of functions that are not mandated by
@@ -2399,6 +2407,10 @@  conforming programs must not rely on a m
 (changed to 1024 in C++11).  The default value is 900, as the compiler
 can run out of stack space before hitting 1024 in some situations.
 
+@item -fno-templates
+@opindex fno-templates
+Do not permit primary template declarations, except in system header files.
+
 @item -fno-threadsafe-statics
 @opindex fno-threadsafe-statics
 Do not emit the extra code to use the routines specified in the C++
@@ -2420,6 +2432,10 @@  Don't use the @code{__cxa_get_exception_
 causes @code{std::uncaught_exception} to be incorrect, but is necessary
 if the runtime routine is not available.
 
+@item -fno-virtual-inheritance
+@opindex fno-virtual-inheritance
+Do not permit virtual inheritance, except in system header files.
+
 @item -fvisibility-inlines-hidden
 @opindex fvisibility-inlines-hidden
 This switch declares that the user does not attempt to compare
Index: testsuite/g++.dg/diagnostic/disable.C
===================================================================
--- testsuite/g++.dg/diagnostic/disable.C	(revision 0)
+++ testsuite/g++.dg/diagnostic/disable.C	(working copy)
@@ -0,0 +1,23 @@ 
+// { dg-options "-fno-templates -fno-multiple-inheritance -fno-virtual-inheritance -fno-namespaces" }
+
+#include <iostream>
+#include <algorithm>
+
+namespace foo { } // { dg-error "namepace" }
+
+template <typename X> X Foo (); // { dg-error "template" }
+
+struct B1 {};
+struct B2 {};
+struct V {};
+
+struct D :  B1, B2 {}; //  { dg-error "multiple" }
+
+struct E : virtual V {};  // { dg-error "virtual" }
+
+void Baz (int a, int b)
+{
+  std::swap (a, b);
+}
+
+