+2009-08-10 Jason Merrill <jason@redhat.com>
+
+ Implement DR 757: It's OK for a decl to use a type without linkage
+ so long as the decl is defined in the current translation unit.
+ * decl2.c (no_linkage_decls): New vector.
+ (mark_used): Add decls that use types with no linkage.
+ (cp_write_global_declarations): Check that they are defined.
+ (decl_defined_p, no_linkage_error): New fns.
+ * cp-tree.h (DECL_NO_LINKAGE_CHECKED): New macro.
+ (struct lang_decl_base): Add flag.
+ * decl.c (grokfndecl): Don't check type linkage.
+ (grokvardecl): If the type has no linkage, just make sure
+ DECL_LANG_SPECIFIC is set.
+ * pt.c (check_instantiated_arg): Don't check type linkage.
+ * name-lookup.c (is_local_extern): New fn.
+ * name-lookup.h: Declare it.
+
2009-08-05 Jason Merrill <jason@redhat.com>
PR c++/40948
unsigned anticipated_p : 1; /* fn or type */
unsigned friend_attr : 1; /* fn or type */
unsigned template_conv_p : 1; /* template only? */
+ unsigned no_linkage_checked : 1; /* var or fn */
unsigned u2sel : 1;
- /* 2 spare bits */
+ /* 1 spare bit */
};
/* True for DECL codes which have template info and access. */
(DECL_LANG_SPECIFIC (VAR_OR_FUNCTION_DECL_CHECK (DECL)) \
->u.base.initialized_in_class)
+/* Nonzero if we've checked whether DECL uses types without linkage in a
+ potentially invalid way.
+ ??? Instead, should fix mark_used to only set TREE_USED when we're
+ really using something, and just return if it's already set. */
+#define DECL_NO_LINKAGE_CHECKED(DECL) \
+ (DECL_LANG_SPECIFIC (VAR_OR_FUNCTION_DECL_CHECK (DECL)) \
+ ->u.base.no_linkage_checked)
+
/* Nonzero for DECL means that this decl is just a friend declaration,
and should not be added to the list of members for this class. */
#define DECL_FRIEND_P(NODE) (DECL_LANG_SPECIFIC (NODE)->u.base.friend_attr)
|| decl_function_context (TYPE_MAIN_DECL (ctype))))
publicp = 0;
- if (publicp)
- {
- /* [basic.link]: A name with no linkage (notably, the name of a class
- or enumeration declared in a local scope) shall not be used to
- declare an entity with linkage.
-
- Only check this for public decls for now. See core 319, 389. */
- t = no_linkage_check (TREE_TYPE (decl),
- /*relaxed_p=*/false);
- if (t)
- {
- if (TYPE_ANONYMOUS_P (t))
- {
- if (DECL_EXTERN_C_P (decl))
- /* Allow this; it's pretty common in C. */;
- else
- {
- permerror (input_location, "non-local function %q#D uses anonymous type",
- decl);
- if (DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
- permerror (input_location, "%q+#D does not refer to the unqualified "
- "type, so it is not used for linkage",
- TYPE_NAME (t));
- }
- }
- else
- permerror (input_location, "non-local function %q#D uses local type %qT", decl, t);
- }
- }
-
TREE_PUBLIC (decl) = publicp;
if (! publicp)
{
if (TREE_PUBLIC (decl))
{
- /* [basic.link]: A name with no linkage (notably, the name of a class
- or enumeration declared in a local scope) shall not be used to
- declare an entity with linkage.
-
- Only check this for public decls for now. */
- tree t = no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false);
- if (t)
- {
- if (TYPE_ANONYMOUS_P (t))
- {
- if (DECL_EXTERN_C_P (decl))
- /* Allow this; it's pretty common in C. */
- ;
- else
- {
- /* DRs 132, 319 and 389 seem to indicate types with
- no linkage can only be used to declare extern "C"
- entities. Since it's not always an error in the
- ISO C++ 90 Standard, we only issue a warning. */
- warning (0, "non-local variable %q#D uses anonymous type",
- decl);
- if (DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
- warning (0, "%q+#D does not refer to the unqualified "
- "type, so it is not used for linkage",
- TYPE_NAME (t));
- }
- }
- else
- warning (0, "non-local variable %q#D uses local type %qT", decl, t);
- }
+ /* If the type of the decl has no linkage, make sure that we'll
+ notice that in mark_used. */
+ if (DECL_LANG_SPECIFIC (decl) == NULL
+ && TREE_PUBLIC (decl)
+ && !DECL_EXTERN_C_P (decl)
+ && no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false))
+ retrofit_lang_decl (decl);
}
else
DECL_INTERFACE_KNOWN (decl) = 1;
static void import_export_class (tree);
static tree get_guard_bits (tree);
static void determine_visibility_from_class (tree, tree);
+static bool decl_defined_p (tree);
/* A list of static class variables. This is needed, because a
static class variable can be declared inside the class without
may need to emit outline anyway. */
static GTY(()) VEC(tree,gc) *deferred_fns;
+/* A list of decls that use types with no linkage, which we need to make
+ sure are defined. */
+static GTY(()) VEC(tree,gc) *no_linkage_decls;
+
/* Nonzero if we're done parsing and into end-of-file activities. */
int at_eof;
}
}
+/* Returns true iff there is a definition available for variable or
+ function DECL. */
+
+static bool
+decl_defined_p (tree decl)
+{
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ return (DECL_INITIAL (decl) != NULL_TREE);
+ else
+ {
+ gcc_assert (TREE_CODE (decl) == VAR_DECL);
+ return !DECL_EXTERNAL (decl);
+ }
+}
+
+/* Complain that DECL uses a type with no linkage but is never defined. */
+
+static void
+no_linkage_error (tree decl)
+{
+ tree t = no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false);
+ if (TYPE_ANONYMOUS_P (t))
+ {
+ permerror (0, "%q+#D, declared using anonymous type, "
+ "is used but never defined", decl);
+ if (is_typedef_decl (TYPE_NAME (t)))
+ permerror (0, "%q+#D does not refer to the unqualified type, "
+ "so it is not used for linkage", TYPE_NAME (t));
+ }
+ else
+ permerror (0, "%q+#D, declared using local type %qT, "
+ "is used but never defined", decl, t);
+}
+
/* This routine is called at the end of compilation.
Its job is to create all the code needed to initialize and
destroy the global aggregates. We do the destruction
}
}
+ /* So must decls that use a type with no linkage. */
+ for (i = 0; VEC_iterate (tree, no_linkage_decls, i, decl); ++i)
+ if (!decl_defined_p (decl))
+ no_linkage_error (decl);
+
/* We give C linkage to static constructors and destructors. */
push_lang_context (lang_name_c);
if (processing_template_decl)
return;
+ /* DR 757: A type without linkage shall not be used as the type of a
+ variable or function with linkage, unless
+ o the variable or function has extern "C" linkage (7.5 [dcl.link]), or
+ o the variable or function is not used (3.2 [basic.def.odr]) or is
+ defined in the same translation unit. */
+ if (TREE_PUBLIC (decl)
+ && (TREE_CODE (decl) == FUNCTION_DECL
+ || TREE_CODE (decl) == VAR_DECL)
+ && DECL_LANG_SPECIFIC (decl)
+ && !DECL_NO_LINKAGE_CHECKED (decl))
+ {
+ DECL_NO_LINKAGE_CHECKED (decl) = true;
+ if (!DECL_EXTERN_C_P (decl)
+ && !DECL_ARTIFICIAL (decl)
+ && !decl_defined_p (decl)
+ && no_linkage_check (TREE_TYPE (decl), /*relaxed_p=*/false))
+ {
+ if (is_local_extern (decl))
+ /* There's no way to define a local extern, and adding it to
+ the vector interferes with GC, so give an error now. */
+ no_linkage_error (decl);
+ else
+ VEC_safe_push (tree, gc, no_linkage_decls, decl);
+ }
+ }
+
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl)
&& !TREE_ASM_WRITTEN (decl))
/* Remember it, so we can check it was defined. */
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
+/* Returns true iff DECL is a block-scope extern declaration of a function
+ or variable. */
+
+bool
+is_local_extern (tree decl)
+{
+ cxx_binding *binding;
+
+ /* For functions, this is easy. */
+ if (TREE_CODE (decl) == FUNCTION_DECL)
+ return DECL_LOCAL_FUNCTION_P (decl);
+
+ if (TREE_CODE (decl) != VAR_DECL)
+ return false;
+ if (!current_function_decl)
+ return false;
+
+ /* For variables, this is not easy. We need to look at the binding stack
+ for the identifier to see whether the decl we have is a local. */
+ for (binding = IDENTIFIER_BINDING (DECL_NAME (decl));
+ binding && binding->scope->kind != sk_namespace;
+ binding = binding->previous)
+ if (binding->value == decl)
+ return LOCAL_BINDING_P (binding);
+
+ return false;
+}
+
/* Like lookup_name_innermost_nonclass_level, but for types. */
static tree
extern tree lookup_qualified_name (tree, tree, bool, bool);
extern tree lookup_name_nonclass (tree);
extern tree lookup_name_innermost_nonclass_level (tree);
+extern bool is_local_extern (tree);
extern tree lookup_function_nonclass (tree, VEC(tree,gc) *, bool);
extern void push_local_binding (tree, tree, int);
extern bool pushdecl_class_level (tree);
}
/* Verify that the instantiated ARGS are valid. For type arguments,
- make sure that the type's linkage is ok. For non-type arguments,
+ make sure that the type is not variably modified. For non-type arguments,
make sure they are constants if they are integral or enumerations.
Emit an error under control of COMPLAIN, and return TRUE on error. */
}
else if (TYPE_P (t))
{
- /* [basic.link]: A name with no linkage (notably, the name
- of a class or enumeration declared in a local scope)
- shall not be used to declare an entity with linkage.
- This implies that names with no linkage cannot be used as
- template arguments. */
- tree nt = no_linkage_check (t, /*relaxed_p=*/false);
-
- if (nt)
- {
- /* DR 488 makes use of a type with no linkage cause
- type deduction to fail. */
- if (complain & tf_error)
- {
- if (TYPE_ANONYMOUS_P (nt))
- error ("%qT is/uses anonymous type", t);
- else
- error ("template argument for %qD uses local type %qT",
- tmpl, t);
- }
- return true;
- }
- /* In order to avoid all sorts of complications, we do not
- allow variably-modified types as template arguments. */
- else if (variably_modified_type_p (t, NULL_TREE))
+ if (variably_modified_type_p (t, NULL_TREE))
{
if (complain & tf_error)
error ("%qT is a variably modified type", t);
+2009-08-10 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/other/linkage2.C: New test for types-without-linkage
+ handling.
+ * g++.dg/ext/anon-struct4.C: No error about anonymous type.
+ * g++.dg/lookup/anon2.C: Likewise.
+ * g++.dg/other/anon3.C: Likewise.
+ * g++.dg/template/arg2.C: Likewise.
+ * g++.dg/template/local4.C: Likewise.
+ * g++.old-deja/g++.law/operators32.C: Likewise.
+ * g++.old-deja/g++.other/linkage2.C: Likewise.
+ * g++.old-deja/g++.pt/enum6.C: Likewise.
+ * g++.old-deja/g++.other/anon9.C: Use the undefined decls.
+ * g++.old-deja/g++.other/linkage1.C: Likewise.
+
2009-08-10 Manuel López-Ibáñez <manu@gcc.gnu.org>
* gcc.dg/dg.exp: Test also c-c++-common dir.
// PR c++/14401
struct { struct { int& i ; } bar ; } foo ; // { dg-error "uninitialized" "uninit" }
-// { dg-warning "anonymous" "anon" { target *-*-* } 3 }
// { dg-do compile }
// { dg-options "" }
-// Make sure we issue a diagnostic if a type with no linkage is used
-// to declare a a variable that has linkage.
+// Make sure we don't issue a diagnostic if a type with no linkage is used
+// to declare a a variable that has linkage if that variable is defined.
-struct { int i; } a; // { dg-warning "anonymous type" }
+struct { int i; } a;
void foo() { a.i; }
// { dg-do compile }
-enum { a = 3 } x; // { dg-warning "anonymous type" }
+enum { a = 3 } x;
--- /dev/null
+// DR 743: A type without linkage shall not be used as the type of a
+// variable or function with linkage, unless
+// o the variable or function has extern "C" linkage (7.5 [dcl.link]), or
+// o the variable or function is not used (3.2 [basic.def.odr]) or is
+// defined in the same translation unit.
+
+template <typename T> struct B {
+ void g(T){}
+ void h(T); // { dg-error "never defined" }
+ friend void i(B, T){}
+ static T t1; // { dg-error "never defined" }
+ static T t2;
+};
+
+template <typename T> T B<T>::t2 = { };
+
+enum {} e1; // OK, defined
+extern enum {} e2; // { dg-error "never defined" }
+extern "C" enum {} e3; // OK, extern "C"
+
+void f() {
+ struct A { int x; }; // no linkage
+ A a = {1};
+ B<A> ba; // declares B<A>::g(A) and B<A>::h(A)
+ ba.t1 = a; // error, B<T>::t never defined
+ ba.t2 = a; // OK
+ ba.g(a); // OK
+ ba.h(a); // error, B<T>::h never defined
+ i(ba, a); // OK
+ e1+e2+e3;
+}
void fn ()
{
class L {};
- X<L> f; // { dg-error "uses local type|trying to instantiate|no type|invalid type" "" }
+ X<L> f;
}
int main () {
struct S {};
- foo<S> (); // { dg-error "match" }
+ foo<S> ();
}
};
foo **f2;
-allocate2d(d1, d2, f2);// { dg-error "" } type.*// ERROR - trying to.*
-ffree(d1, f2);// { dg-error "" } type.*// ERROR - trying to.*
+allocate2d(d1, d2, f2);
+ffree(d1, f2);
}
typedef const struct { int i; } T; // { dg-error "" } referenced below
void f (T* t); // { dg-error "" } uses unnamed type
+
+int main()
+{
+ f(0);
+}
int i;
} *p;
-void f (p) { } // { dg-error "uses anonymous type" }
-p q; // { dg-warning "uses anonymous type" }
+void f (p) { }
+p q;
int main()
{
- extern p j; // { dg-warning "uses anonymous type" }
+ extern p j; // { dg-error "anonymous type" }
+ j+1;
struct A { int j; };
- extern A a; // { dg-warning "uses local type" }
- extern void f (A); // { dg-error "uses local type" }
+ extern A a; // { dg-error "local type" }
+ a.j+1;
+ extern void f (A); // { dg-error "local type" }
+ f(a);
}
}
typedef struct { int dummy[10]; } *FAIL_FILE;
-extern FAIL_FILE fail_open(); // { dg-error "" } non-local function
+extern FAIL_FILE fail_open(); // OK because it's never used
typedef struct { int dummy[10]; } *SUCCESS_FILE, S;
extern SUCCESS_FILE success_open();
{
enum tern { H, L, X, U };
- vector<tern> ternvec; // { dg-error "" } composed from a local type
+ vector<tern> ternvec;
}
template void fn(int);