parser.c (cp_parser_elaborated_type_specifier): Added a warning for inner-style nested forward declarations that don't declare...

2007-07-02  Simon Baldwin  <simonb@google.com>

        * parser.c (cp_parser_elaborated_type_specifier): Added a warning
        for inner-style nested forward declarations that don't declare
        anything useful.

From-SVN: r126219
This commit is contained in:
Simon Baldwin 2007-07-02 17:57:57 +00:00 committed by Simon Baldwin
parent d49343266b
commit 2a7b8343cb
3 changed files with 104 additions and 0 deletions

View file

@ -1,3 +1,9 @@
2007-07-02 Simon Baldwin <simonb@google.com>
* parser.c (cp_parser_elaborated_type_specifier): Added a warning
for inner-style nested forward declarations that don't declare
anything useful.
2007-07-02 Jakub Jelinek <jakub@redhat.com>
PR c++/31748

View file

@ -10913,6 +10913,23 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
return error_mark_node;
}
/* Forward declarations of nested types, such as
class C1::C2;
class C1::C2::C3;
are invalid unless all components preceding the final '::'
are complete. If all enclosing types are complete, these
declarations become merely pointless.
Invalid forward declarations of nested types are errors
caught elsewhere in parsing. Those that are pointless arrive
here. */
if (cp_parser_declares_only_class_p (parser)
&& !is_friend && !processing_explicit_instantiation)
warning (0, "declaration %qD does not declare anything", decl);
type = TREE_TYPE (decl);
}
else

View file

@ -0,0 +1,81 @@
// Check that the compiler warns about inner-style forward declarations in
// contexts where they're not actually illegal, but merely useless.
// Verify warnings for and within classes, and by extension, struct and union.
class C1;
class C1::C2; // { dg-error "does not name a type" }
class C1::C2::C3; // { dg-error "has not been declared" }
class C1 {
public:
class C2;
class C2::C3; // { dg-error "does not name a type" }
class C2 {
public:
class C3;
class C3 { };
class C3;
};
class C2;
class C2::C3; // { dg-warning "declaration 'class C1::C2::C3' does not declare anything" }
};
class C1;
class C1::C2; // { dg-warning "declaration 'class C1::C2' does not declare anything" }
class C1::C2::C3; // { dg-warning "declaration 'class C1::C2::C3' does not declare anything" }
// Verify warnings for namespace scopes.
class N1::C4; // { dg-error "has not been declared" }
class N1::N2::C5; // { dg-error "has not been declared" }
namespace N1 {
class C4;
class C4 { };
class C4;
class N2::C5; // { dg-error "has not been declared" }
namespace N2 {
class C5;
class C5 { };
class C5;
}
class N2::C5; // { dg-warning "declaration 'class N1::N2::C5' does not declare anything" }
}
class N1::C4; // { dg-warning "declaration 'class N1::C4' does not declare anything" }
class N1::N2::C5; // { dg-warning "declaration 'class N1::N2::C5' does not declare anything" }
// Verify that using declarations related to namespaces don't generate a
// warning.
using namespace N1;
using namespace N1::N2;
namespace N3 {
using N1::C4; // Valid using declaration, no warning
using N1::N2::C5; // Valid using declaration, no warning
}
// Verify that explicit template instantiations, easy to confuse with
// forward declarations, don't generate a warning.
template<class C>
class TC6 {
public:
class TC7 { };
};
template class TC6<int>::TC7; // Valid explicit instantiation, no warning
// Verify that friend declarations, also easy to confuse with forward
// declrations, are similarly not warned about.
class C8 {
public:
class C9 { };
};
class C10 {
public:
friend class C8::C9; // Valid friend declaration, no warning
};