Add -Wunused-local-typedef, a warning that finds unused local typedefs.
The warning warns on TypedefNameDecls -- typedefs and C++11 using aliases --
that are !isReferenced(). Since the isReferenced() bit on TypedefNameDecls
wasn't used for anything before this warning it wasn't always set correctly,
so this patch also adds a few missing MarkAnyDeclReferenced() calls in
various places for TypedefNameDecls.
This is made a bit complicated due to local typedefs possibly being used only
after their local scope has closed. Consider:
template <class T>
void template_fun(T t) {
typename T::Foo s3foo; // YYY
(void)s3foo;
}
void template_fun_user() {
struct Local {
typedef int Foo; // XXX
} p;
template_fun(p);
}
Here the typedef in XXX is only used at end-of-translation unit, when YYY in
template_fun() gets instantiated. To handle this, typedefs that are unused when
their scope exits are added to a set of potentially unused typedefs, and that
set gets checked at end-of-TU. Typedefs that are still unused at that point then
get warned on. There's also serialization code for this set, so that the
warning works with precompiled headers and modules. For modules, the warning
is emitted when the module is built, for precompiled headers each time the
header gets used.
Finally, consider a function using C++14 auto return types to return a local
type defined in a header:
auto f() {
struct S { typedef int a; };
return S();
}
Here, the typedef escapes its local scope and could be used by only some
translation units including the header. To not warn on this, add a
RecursiveASTVisitor that marks all delcs on local types returned from auto
functions as referenced. (Except if it's a function with internal linkage, or
the decls are private and the local type has no friends -- in these cases, it
_is_ safe to warn.)
Several of the included testcases (most of the interesting ones) were provided
by Richard Smith.
(gcc's spelling -Wunused-local-typedefs is supported as an alias for this
warning.)
llvm-svn: 217298
2014-09-06 09:25:55 +08:00
// RUN: %clang_cc1 -fsyntax-only -fcxx-exceptions -verify -std=c++11 -Wall -Wno-unused-local-typedefs %s
2011-06-12 01:19:42 +08:00
template < bool b > struct ExceptionIf { static int f ( ) ; } ;
template < > struct ExceptionIf < false > { typedef int f ; } ;
// The exception specification of a defaulted default constructor depends on
// the contents of in-class member initializers. However, the in-class member
// initializers can depend on the exception specification of the constructor,
// since the class is considered complete within them. We reject any such cases.
namespace InClassInitializers {
// Noexcept::Noexcept() is implicitly declared as noexcept(false), because it
// directly invokes ThrowSomething(). However...
//
// If noexcept(Noexcept()) is false, then Noexcept() is a constant expression,
// so noexcept(Noexcept()) is true. But if noexcept(Noexcept()) is true, then
// Noexcept::Noexcept is not declared constexpr, therefore noexcept(Noexcept())
// is false.
bool ThrowSomething ( ) noexcept ( false ) ;
struct ConstExpr {
2014-11-18 07:36:45 +08:00
bool b = noexcept ( ConstExpr ( ) ) & & ThrowSomething ( ) ; // expected-error {{cannot use defaulted default constructor of 'ConstExpr' within the class outside of member functions}}
// expected-note@-1 {{implicit default constructor for 'InClassInitializers::ConstExpr' first required here}}
2011-06-12 01:19:42 +08:00
} ;
// Much more obviously broken: we can't parse the initializer without already
// knowing whether it produces a noexcept expression.
struct TemplateArg {
2014-11-18 07:36:45 +08:00
int n = ExceptionIf < noexcept ( TemplateArg ( ) ) > : : f ( ) ; // expected-error {{cannot use defaulted default constructor of 'TemplateArg' within the class outside of member functions}}
// expected-note@-1 {{implicit default constructor for 'InClassInitializers::TemplateArg' first required here}}
2011-06-12 01:19:42 +08:00
} ;
// And within a nested class.
2014-11-18 07:36:45 +08:00
struct Nested { // expected-note {{implicit default constructor for 'InClassInitializers::Nested::Inner' first required here}}
2011-06-12 01:19:42 +08:00
struct Inner {
2014-11-18 07:36:45 +08:00
// expected-error@+1 {{cannot use defaulted default constructor of 'Inner' within 'Nested' outside of member functions}}
2012-11-07 09:14:25 +08:00
int n = ExceptionIf < noexcept ( Nested ( ) ) > : : f ( ) ; // expected-note {{implicit default constructor for 'InClassInitializers::Nested' first required here}}
} inner ;
2011-06-12 01:19:42 +08:00
} ;
Final piece of core issue 1330: delay computing the exception specification of
a defaulted special member function until the exception specification is needed
(using the same criteria used for the delayed instantiation of exception
specifications for function temploids).
EST_Delayed is now EST_Unevaluated (using 1330's terminology), and, like
EST_Uninstantiated, carries a pointer to the FunctionDecl which will be used to
resolve the exception specification.
This is enabled for all C++ modes: it's a little faster in the case where the
exception specification isn't used, allows our C++11-in-C++98 extensions to
work, and is still correct for C++98, since in that mode the computation of the
exception specification can't fail.
The diagnostics here aren't great (in particular, we should include implicit
evaluation of exception specifications for defaulted special members in the
template instantiation backtraces), but they're not much worse than before.
Our approach to the problem of cycles between in-class initializers and the
exception specification for a defaulted default constructor is modified a
little by this change -- we now reject any odr-use of a defaulted default
constructor if that constructor uses an in-class initializer and the use is in
an in-class initialzer which is declared lexically earlier. This is a closer
approximation to the current draft solution in core issue 1351, but isn't an
exact match (but the current draft wording isn't reasonable, so that's to be
expected).
llvm-svn: 160847
2012-07-27 12:22:15 +08:00
2014-11-18 07:36:45 +08:00
struct Nested2 { // expected-error {{implicit default constructor for 'InClassInitializers::Nested2' must explicitly initialize the member 'inner' which does not have a default constructor}}
Final piece of core issue 1330: delay computing the exception specification of
a defaulted special member function until the exception specification is needed
(using the same criteria used for the delayed instantiation of exception
specifications for function temploids).
EST_Delayed is now EST_Unevaluated (using 1330's terminology), and, like
EST_Uninstantiated, carries a pointer to the FunctionDecl which will be used to
resolve the exception specification.
This is enabled for all C++ modes: it's a little faster in the case where the
exception specification isn't used, allows our C++11-in-C++98 extensions to
work, and is still correct for C++98, since in that mode the computation of the
exception specification can't fail.
The diagnostics here aren't great (in particular, we should include implicit
evaluation of exception specifications for defaulted special members in the
template instantiation backtraces), but they're not much worse than before.
Our approach to the problem of cycles between in-class initializers and the
exception specification for a defaulted default constructor is modified a
little by this change -- we now reject any odr-use of a defaulted default
constructor if that constructor uses an in-class initializer and the use is in
an in-class initialzer which is declared lexically earlier. This is a closer
approximation to the current draft solution in core issue 1351, but isn't an
exact match (but the current draft wording isn't reasonable, so that's to be
expected).
llvm-svn: 160847
2012-07-27 12:22:15 +08:00
struct Inner ;
2014-11-18 07:36:45 +08:00
int n = Inner ( ) . n ; // expected-note {{implicit default constructor for 'InClassInitializers::Nested2::Inner' first required here}}
struct Inner { // expected-note {{declared here}}
// expected-error@+1 {{cannot use defaulted default constructor of 'Inner' within 'Nested2' outside of member functions}}
2012-11-07 09:14:25 +08:00
int n = ExceptionIf < noexcept ( Nested2 ( ) ) > : : f ( ) ;
2014-11-18 07:36:45 +08:00
// expected-note@-1 {{implicit default constructor for 'InClassInitializers::Nested2' first required here}}
} inner ; // expected-note {{member is declared here}}
Final piece of core issue 1330: delay computing the exception specification of
a defaulted special member function until the exception specification is needed
(using the same criteria used for the delayed instantiation of exception
specifications for function temploids).
EST_Delayed is now EST_Unevaluated (using 1330's terminology), and, like
EST_Uninstantiated, carries a pointer to the FunctionDecl which will be used to
resolve the exception specification.
This is enabled for all C++ modes: it's a little faster in the case where the
exception specification isn't used, allows our C++11-in-C++98 extensions to
work, and is still correct for C++98, since in that mode the computation of the
exception specification can't fail.
The diagnostics here aren't great (in particular, we should include implicit
evaluation of exception specifications for defaulted special members in the
template instantiation backtraces), but they're not much worse than before.
Our approach to the problem of cycles between in-class initializers and the
exception specification for a defaulted default constructor is modified a
little by this change -- we now reject any odr-use of a defaulted default
constructor if that constructor uses an in-class initializer and the use is in
an in-class initialzer which is declared lexically earlier. This is a closer
approximation to the current draft solution in core issue 1351, but isn't an
exact match (but the current draft wording isn't reasonable, so that's to be
expected).
llvm-svn: 160847
2012-07-27 12:22:15 +08:00
} ;
2011-06-12 01:19:42 +08:00
}
namespace ExceptionSpecification {
2014-11-14 04:01:57 +08:00
// FIXME: This diagnostic is quite useless; we should indicate whose
// exception specification we were looking for and why.
struct Nested {
2011-06-12 01:19:42 +08:00
struct T {
2014-11-14 04:01:57 +08:00
T ( ) noexcept ( ! noexcept ( Nested ( ) ) ) ;
} t ; // expected-error{{exception specification is not available until end of class definition}}
2011-06-12 01:19:42 +08:00
} ;
}
namespace DefaultArgument {
2012-03-31 04:53:28 +08:00
struct Default {
2011-06-12 01:19:42 +08:00
struct T {
2012-02-16 03:33:52 +08:00
T ( int = ExceptionIf < noexcept ( Default ( ) ) : : f ( ) ) ; // expected-error {{call to implicitly-deleted default constructor}}
2012-03-31 04:53:28 +08:00
} t ; // expected-note {{has no default constructor}}
2011-06-12 01:19:42 +08:00
} ;
}
2012-04-22 02:42:51 +08:00
namespace ImplicitDtorExceptionSpec {
struct A {
virtual ~ A ( ) ;
struct Inner {
~ Inner ( ) throw ( ) ;
} ;
Inner inner ;
} ;
struct B {
virtual ~ B ( ) { } // expected-note {{here}}
} ;
struct C : B {
virtual ~ C ( ) { }
A a ;
} ;
struct D : B {
~ D ( ) ; // expected-error {{more lax than base}}
struct E {
~ E ( ) ;
struct F {
~ F ( ) throw ( A ) ;
} f ;
} e ;
} ;
}