2017-06-30 Nathan Sidwell <nathan@acm.org>
+ * cp-tree.h (lookup_fnfields_1, class_method_index_for_fn): Don't
+ declare.
+ (lookup_all_conversions): Declare.
+ * class.c (get_basefndecls): Use lookup_fnfields_slot.
+ * decl.c (register_dtor_fn): Use lookup_fnfields_slot.
+ * decl2.c (check_class_fn): Use lookup_fnfields_slot. Rework
+ diagnostics.
+ * pt.c (retrieve_specialization): Use lookup_fnfields_slot.
+ (check_explicit_specialization): Use lookup_fnfields_slot_nolazy,
+ lookup_all_conversions.
+ * search.c (lookup_fnfields_1): Make static.
+ (lookup_all_conversions): New.
+ (class_method_index_for_fn): Delete.
+ * semantics.c (classtype_has_nothrow_assign_or_copy_p): Use
+ lookup_fnfields_slot.
+
* call.c (build_new_method_call_1): Use constructo_name to get
ctor name. Move argument processing earlier to merge cdtor
handling blocks.
static void
get_basefndecls (tree name, tree t, vec<tree> *base_fndecls)
{
- int n_baseclasses = BINFO_N_BASE_BINFOS (TYPE_BINFO (t));
- int i;
+ bool found_decls = false;
/* Find virtual functions in T with the indicated NAME. */
- i = lookup_fnfields_1 (t, name);
- bool found_decls = false;
- if (i != -1)
- for (ovl_iterator iter ((*CLASSTYPE_METHOD_VEC (t))[i]); iter; ++iter)
- {
- tree method = *iter;
+ for (ovl_iterator iter (lookup_fnfields_slot (t, name)); iter; ++iter)
+ {
+ tree method = *iter;
- if (TREE_CODE (method) == FUNCTION_DECL
- && DECL_VINDEX (method))
- {
- base_fndecls->safe_push (method);
- found_decls = true;
- }
- }
+ if (TREE_CODE (method) == FUNCTION_DECL && DECL_VINDEX (method))
+ {
+ base_fndecls->safe_push (method);
+ found_decls = true;
+ }
+ }
if (found_decls)
return;
- for (i = 0; i < n_baseclasses; i++)
+ int n_baseclasses = BINFO_N_BASE_BINFOS (TYPE_BINFO (t));
+ for (int i = 0; i < n_baseclasses; i++)
{
tree basetype = BINFO_TYPE (BINFO_BASE_BINFO (TYPE_BINFO (t), i));
get_basefndecls (name, basetype, base_fndecls);
extern int accessible_in_template_p (tree, tree);
extern tree lookup_field_1 (tree, tree, bool);
extern tree lookup_field (tree, tree, int, bool);
-extern int lookup_fnfields_1 (tree, tree);
extern tree lookup_fnfields_slot (tree, tree);
extern tree lookup_fnfields_slot_nolazy (tree, tree);
-extern int class_method_index_for_fn (tree, tree);
+extern tree lookup_all_conversions (tree);
extern tree lookup_fnfields (tree, tree, int);
extern tree lookup_member (tree, tree, int, bool,
tsubst_flags_t,
use_dtor = ob_parm && CLASS_TYPE_P (type);
if (use_dtor)
{
- int idx;
+ cleanup = lookup_fnfields_slot (type, complete_dtor_identifier);
- /* Find the destructor. */
- idx = lookup_fnfields_1 (type, complete_dtor_identifier);
- gcc_assert (idx >= 0);
- cleanup = (*CLASSTYPE_METHOD_VEC (type))[idx];
/* Make sure it is accessible. */
perform_or_defer_access_check (TYPE_BINFO (type), cleanup, cleanup,
tf_warning_or_error);
tree
check_classfn (tree ctype, tree function, tree template_parms)
{
- int ix;
- bool is_template;
- tree pushed_scope;
-
if (DECL_USE_TEMPLATE (function)
&& !(TREE_CODE (function) == TEMPLATE_DECL
&& DECL_TEMPLATE_SPECIALIZATION (function))
}
/* OK, is this a definition of a member template? */
- is_template = (template_parms != NULL_TREE);
+ bool is_template = (template_parms != NULL_TREE);
/* [temp.mem]
/* We must enter the scope here, because conversion operators are
named by target type, and type equivalence relies on typenames
resolving within the scope of CTYPE. */
- pushed_scope = push_scope (ctype);
- ix = class_method_index_for_fn (complete_type (ctype), function);
- if (ix >= 0)
- {
- vec<tree, va_gc> *methods = CLASSTYPE_METHOD_VEC (ctype);
-
- for (ovl_iterator iter ((*methods)[ix]); iter; ++iter)
- {
- tree fndecl = *iter;
- tree p1 = TYPE_ARG_TYPES (TREE_TYPE (function));
- tree p2 = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
-
- /* We cannot simply call decls_match because this doesn't
- work for static member functions that are pretending to
- be methods, and because the name may have been changed by
- asm("new_name"). */
-
- /* Get rid of the this parameter on functions that become
- static. */
- if (DECL_STATIC_FUNCTION_P (fndecl)
- && TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
- p1 = TREE_CHAIN (p1);
-
- /* A member template definition only matches a member template
- declaration. */
- if (is_template != (TREE_CODE (fndecl) == TEMPLATE_DECL))
- continue;
-
- /* ref-qualifier or absence of same must match. */
- if (type_memfn_rqual (TREE_TYPE (function))
- != type_memfn_rqual (TREE_TYPE (fndecl)))
- continue;
-
- // Include constraints in the match.
- tree c1 = get_constraints (function);
- tree c2 = get_constraints (fndecl);
-
- /* While finding a match, same types and params are not enough
- if the function is versioned. Also check version ("target")
- attributes. */
- if (same_type_p (TREE_TYPE (TREE_TYPE (function)),
- TREE_TYPE (TREE_TYPE (fndecl)))
- && compparms (p1, p2)
- && !targetm.target_option.function_versions (function, fndecl)
- && (!is_template
- || comp_template_parms (template_parms,
- DECL_TEMPLATE_PARMS (fndecl)))
- && equivalent_constraints (c1, c2)
- && (DECL_TEMPLATE_SPECIALIZATION (function)
- == DECL_TEMPLATE_SPECIALIZATION (fndecl))
- && (!DECL_TEMPLATE_SPECIALIZATION (function)
- || (DECL_TI_TEMPLATE (function)
- == DECL_TI_TEMPLATE (fndecl))))
- {
- if (pushed_scope)
- pop_scope (pushed_scope);
- return fndecl;
- }
- }
-
- error_at (DECL_SOURCE_LOCATION (function),
- "prototype for %q#D does not match any in class %qT",
- function, ctype);
+ tree pushed_scope = push_scope (ctype);
+ tree matched = NULL_TREE;
+ tree fns = lookup_fnfields_slot (ctype, DECL_NAME (function));
+
+ for (ovl_iterator iter (fns); !matched && iter; ++iter)
+ {
+ tree fndecl = *iter;
+ tree p1 = TYPE_ARG_TYPES (TREE_TYPE (function));
+ tree p2 = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
+
+ /* We cannot simply call decls_match because this doesn't work
+ for static member functions that are pretending to be
+ methods, and because the name may have been changed by
+ asm("new_name"). */
+
+ /* Get rid of the this parameter on functions that become
+ static. */
+ if (DECL_STATIC_FUNCTION_P (fndecl)
+ && TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
+ p1 = TREE_CHAIN (p1);
+
+ /* A member template definition only matches a member template
+ declaration. */
+ if (is_template != (TREE_CODE (fndecl) == TEMPLATE_DECL))
+ continue;
- const char *format = NULL;
- tree first = OVL_FIRST ((*methods)[ix]);
- bool is_conv_op = DECL_CONV_FN_P (first);
- tree prev = NULL_TREE;
+ /* ref-qualifier or absence of same must match. */
+ if (type_memfn_rqual (TREE_TYPE (function))
+ != type_memfn_rqual (TREE_TYPE (fndecl)))
+ continue;
- if (is_conv_op)
- ix = CLASSTYPE_FIRST_CONVERSION_SLOT;
- do
- {
- ovl_iterator iter ((*methods)[ix++]);
- if (is_conv_op && !DECL_CONV_FN_P (*iter))
- break;
- for (; iter; ++iter)
- {
- if (prev)
- {
- if (!format)
- format = N_("candidates are: %+#D");
- error (format, prev);
- format = " %+#D";
- }
- prev = *iter;
- }
- }
- while (is_conv_op && size_t (ix) < methods->length ());
- if (prev)
+ // Include constraints in the match.
+ tree c1 = get_constraints (function);
+ tree c2 = get_constraints (fndecl);
+
+ /* While finding a match, same types and params are not enough
+ if the function is versioned. Also check version ("target")
+ attributes. */
+ if (same_type_p (TREE_TYPE (TREE_TYPE (function)),
+ TREE_TYPE (TREE_TYPE (fndecl)))
+ && compparms (p1, p2)
+ && !targetm.target_option.function_versions (function, fndecl)
+ && (!is_template
+ || comp_template_parms (template_parms,
+ DECL_TEMPLATE_PARMS (fndecl)))
+ && equivalent_constraints (c1, c2)
+ && (DECL_TEMPLATE_SPECIALIZATION (function)
+ == DECL_TEMPLATE_SPECIALIZATION (fndecl))
+ && (!DECL_TEMPLATE_SPECIALIZATION (function)
+ || (DECL_TI_TEMPLATE (function) == DECL_TI_TEMPLATE (fndecl))))
+ matched = fndecl;
+ }
+
+ if (!matched)
+ {
+ if (!COMPLETE_TYPE_P (ctype))
+ cxx_incomplete_type_error (function, ctype);
+ else
{
- if (!format)
- format = N_("candidate is: %+#D");
- error (format, prev);
+ if (DECL_CONV_FN_P (function))
+ fns = lookup_all_conversions (ctype);
+
+ error_at (DECL_SOURCE_LOCATION (function),
+ "no declaration matches %q#D", function);
+ if (fns)
+ print_candidates (fns);
+ else if (DECL_CONV_FN_P (function))
+ inform (DECL_SOURCE_LOCATION (function),
+ "no conversion operators declared");
+ else
+ inform (DECL_SOURCE_LOCATION (function),
+ "no functions named %qD", function);
+ inform (DECL_SOURCE_LOCATION (TYPE_NAME (ctype)),
+ "%#qT defined here", ctype);
}
+ matched = error_mark_node;
}
- else if (!COMPLETE_TYPE_P (ctype))
- cxx_incomplete_type_error (function, ctype);
- else
- error ("no %q#D member function declared in class %qT",
- function, ctype);
if (pushed_scope)
pop_scope (pushed_scope);
- return error_mark_node;
+
+ return matched;
}
/* DECL is a function with vague linkage. Remember it so that at the
= retrieve_specialization (class_template, args, 0);
if (!class_specialization)
return NULL_TREE;
- /* Now, find the appropriate entry in the CLASSTYPE_METHOD_VEC
- for the specialization. */
- int idx = class_method_index_for_fn (class_specialization, tmpl);
- if (idx == -1)
- return NULL_TREE;
- /* Iterate through the methods with the indicated name, looking
- for the one that has an instance of TMPL. */
- vec<tree, va_gc> *methods = CLASSTYPE_METHOD_VEC (class_specialization);
- for (ovl_iterator iter ((*methods)[idx]); iter; ++iter)
+
+ /* Find the instance of TMPL. */
+ tree fns = lookup_fnfields_slot (class_specialization, DECL_NAME (tmpl));
+ for (ovl_iterator iter (fns); iter; ++iter)
{
tree fn = *iter;
if (DECL_TEMPLATE_INFO (fn) && DECL_TI_TEMPLATE (fn) == tmpl
/* Find the list of functions in ctype that have the same
name as the declared function. */
tree name = TREE_OPERAND (declarator, 0);
- tree fns = NULL_TREE;
- int idx;
if (constructor_name_p (name, ctype))
{
name = DECL_NAME (decl);
}
- if (!DECL_CONV_FN_P (decl))
- {
- idx = lookup_fnfields_1 (ctype, name);
- if (idx >= 0)
- fns = (*CLASSTYPE_METHOD_VEC (ctype))[idx];
- }
+ tree fns = NULL_TREE;
+ if (DECL_CONV_FN_P (decl))
+ /* For a type-conversion operator, we cannot do a
+ name-based lookup. We might be looking for `operator
+ int' which will be a specialization of `operator T'.
+ Grab all the conversion operators, and then select from
+ them. */
+ fns = lookup_all_conversions (ctype);
else
- {
- vec<tree, va_gc> *methods;
- tree ovl;
-
- /* For a type-conversion operator, we cannot do a
- name-based lookup. We might be looking for `operator
- int' which will be a specialization of `operator T'.
- So, we find *all* the conversion operators, and then
- select from them. */
- fns = NULL_TREE;
-
- methods = CLASSTYPE_METHOD_VEC (ctype);
- if (methods)
- for (idx = CLASSTYPE_FIRST_CONVERSION_SLOT;
- methods->iterate (idx, &ovl);
- ++idx)
- {
- if (!DECL_CONV_FN_P (OVL_FIRST (ovl)))
- /* There are no more conversion functions. */
- break;
-
- /* Glue all these conversion functions together
- with those we already have. */
- fns = lookup_add (ovl, fns);
- }
- }
+ fns = lookup_fnfields_slot_nolazy (ctype, name);
if (fns == NULL_TREE)
{
/* TYPE is a class type. Return the index of the fields within
the method vector with name NAME, or -1 if no such field exists. */
-int
+static int
lookup_fnfields_1 (tree type, tree name)
{
if (!CLASS_TYPE_P (type))
return (*CLASSTYPE_METHOD_VEC (type))[ix];
}
-/* Like lookup_fnfields_1, except that the name is extracted from
- FUNCTION, which is a FUNCTION_DECL or a TEMPLATE_DECL. */
+/* Collect all the conversion operators of KLASS. */
-int
-class_method_index_for_fn (tree class_type, tree function)
+tree
+lookup_all_conversions (tree klass)
{
- gcc_assert (DECL_DECLARES_FUNCTION_P (function));
+ tree lkp = NULL_TREE;
- return lookup_fnfields_1 (class_type, DECL_NAME (function));
-}
+ if (vec<tree, va_gc> *methods = CLASSTYPE_METHOD_VEC (klass))
+ {
+ tree ovl;
+ for (int idx = CLASSTYPE_FIRST_CONVERSION_SLOT;
+ methods->iterate (idx, &ovl); ++idx)
+ {
+ if (!DECL_CONV_FN_P (OVL_FIRST (ovl)))
+ /* There are no more conversion functions. */
+ break;
+
+ lkp = lookup_add (ovl, lkp);
+ }
+ }
+ return lkp;
+}
/* DECL is the result of a qualified name lookup. QUALIFYING_SCOPE is
the class or namespace used to qualify the name. CONTEXT_CLASS is
if (assign_p)
{
- int ix;
- ix = lookup_fnfields_1 (type, cp_assignment_operator_id (NOP_EXPR));
- if (ix < 0)
+ fns = lookup_fnfields_slot (type, cp_assignment_operator_id (NOP_EXPR));
+ if (!fns)
return false;
- fns = (*CLASSTYPE_METHOD_VEC (type))[ix];
}
else if (TYPE_HAS_COPY_CTOR (type))
{
+2017-06-30 Nathan Sidwell <nathan@acm.org>
+
+ * g++.dg/concepts/memfun-err.C: Adjust diagnostics.
+ * g++.dg/cpp0x/decltype9.C: Likewise.
+ * g++.dg/cpp0x/forw_enum9.C: Likewise.
+ * g++.dg/lookup/decl1.C: Likewise.
+ * g++.dg/lookup/extern-c-redecl.C: Likewise.
+ * g++.dg/other/pr28432.C: Likewise.
+ * g++.dg/parse/crash12.C: Likewise.
+ * g++.dg/parse/enum3.C: Likewise.
+ * g++.dg/parse/operator6.C: Likewise.
+ * g++.dg/template/crash69.C: Likewise.
+ * g++.dg/template/error27.C: Likewise.
+ * g++.dg/template/error28.C: Likewise.
+ * g++.dg/template/memfriend6.C: Likewise.
+ * g++.old-deja/g++.mike/err1.C: Likewise.
+ * g++.old-deja/g++.mike/p811.C: Likewise.
+ * g++.old-deja/g++.other/crash25.C: Likewise.
+ * g++.old-deja/g++.other/dtor4.C: Likewise.
+ * g++.old-deja/g++.pt/t37.C: Likewise.
+
2017-06-30 Martin Liska <mliska@suse.cz>
PR ipa/81214
// Test constrained member definitions
template<typename T>
- struct S1 {
+ struct S1 { // { dg-message "defined here" }
void f1() requires C<T>() { }
void g1() requires C<T>() and true;
template<C U> void h1(U u) { called = 1; }
- void g2() requires C<T>(); // { dg-error "candidate" }
+ void g2() requires C<T>(); // { dg-message "candidate" }
};
template<typename T>
- void S1<T>::g2() requires D<T>() { } // { dg-error "prototype" }
+ void S1<T>::g2() requires D<T>() { } // { dg-error "no declaration matches" }
int main() {
S1<X> sx;
// PR c++/34271
// { dg-do compile { target c++11 } }
-template<int> struct A
-{
+template<int> struct A { // { dg-message "defined here" }
static int i;
};
-template<int N> int A<N>::i(decltype (A::i)); // { dg-error "member function|must be an expression" }
+template<int N> int A<N>::i(decltype (A::i)); // { dg-error "no declaration" }
+// { dg-message "no functions" "note" { target *-*-* } .-1 }
template<typename T> struct S1
{
enum E1 : int;
- enum class E2 : int;
+ enum class E2 : T;
};
template<typename T> enum S1<T>::E1 : int { e1 };
return C1<Y>();
}
-struct A
-{
- operator int (); // { dg-error "operator" }
- operator float (); // { dg-error "operator" }
- operator float () const; // { dg-error "operator" }
- template <typename T> operator T * (); // { dg-error "candidates" }
+struct A { // { dg-message "defined here" }
+ operator int (); // { dg-message "operator" }
+ operator float (); // { dg-message "operator" }
+ operator float () const; // { dg-message "operator" }
+ template <typename T> operator T * (); // { dg-message "operator" }
};
-A::operator short () { // { dg-error "prototype for" }
+A::operator short () { // { dg-error "no declaration matches" }
return 0;
}
// next line should trigger an error because
// it conflicts with previous declaration of foo_func (), due to
// different exception specifications.
-extern "C" void foo_func (); // { dg-error "C language|exception specifications" }
+extern "C" void foo_func (); // { dg-error "C language linkage|exception specifications" }
// { dg-options "" }
-struct A {};
-void A::foo(); // { dg-error "member function declared in class|outside of class is not definition" }
+struct A {}; // { dg-message "defined here" }
+
+void A::foo(); // { dg-error "no declaration matches" }
+// { dg-message "no functions named" "note" { target *-*-* } .-1 }
template <class _Tp> class auto_ptr {};
template <class _Tp>
-class counted_ptr
-{
+class counted_ptr { // { dg-message "defined here" }
public:
- counted_ptr(::auto_ptr<_Tp>& __a); // { dg-error "candidate" }
+ counted_ptr(::auto_ptr<_Tp>& __a); // { dg-message "candidate" }
::auto_ptr<_Tp> auto_ptr();
};
template <class _Tp>
-inline counted_ptr<_Tp>::counted_ptr(class auto_ptr& __a) // { dg-error "required|not match|template" }
+inline counted_ptr<_Tp>::counted_ptr(class auto_ptr& __a)
+// { dg-error "no declaration matches" "" { target *-*-* } .-1 }
+// { dg-error "template argument required" "" { target *-*-* } .-2 }
{
}
// PR c++/28261
-struct A {}; // { dg-error "A::A" }
+struct A {}; // { dg-message "A::A" }
+// { dg-message "defined here" "" { target *-*-* } .-1 }
-A::A (enum { e }) {} // { dg-error "defined|prototype" }
+A::A (enum { e }) {} // { dg-error "no declaration matches" }
+// { dg-error "in parameter types" "" { target *-*-* } .-1 }
// PR c++/25635
-struct A {};
+struct A {}; // { dg-message "defined here" }
-A::operator int(); // { dg-error "class" }
+A::operator int(); // { dg-error "no declaration matches" }
+// { dg-message "no conversion operators" "" { target *-*-* } .-1 }
template<typename T> class A
{
static int i; // { dg-message "private" }
- friend int T::foo(); // { dg-error "does not match" }
+ friend int T::foo(); // { dg-error "no declaration matches" }
};
struct B
{
- void foo() { A<B>::i; } // { dg-error "within|candidate" }
+ void foo() { A<B>::i; } // { dg-message "candidate" }
+ // { dg-error "private within" "" { target *-*-* } .-1 }
};
// PR c++/27211
-struct A {};
+struct A {}; // { dg-message "defined here" }
-template<int> void A::foo() {} // { dg-error "member function" }
+template<int> void A::foo() {} // { dg-error "no declaration matches" }
+// { dg-message "no functions named" "note" { target *-*-* } .-1 }
// PR c++/27211
-struct A {};
+struct A {}; // { dg-message "defined here" }
-template<int> void A::foo(); // { dg-error "member function" }
+template<int> void A::foo(); // { dg-error "no declaration matches" }
+// { dg-message "no functions named" "note" { target *-*-* } .-1 }
// Member function of class template as friend
// Erroneous case: mismatch during declaration
-template <class T> struct A {
- template <class U> void f(U); // { dg-error "candidate" }
- void g(); // { dg-error "candidate|with" }
- void h(); // { dg-error "candidate|with" }
- void i(int); // { dg-error "candidate" }
+template <class T> struct A { // { dg-message "defined here" }
+ template <class U> void f(U); // { dg-message "candidate" }
+ void g(); // { dg-message "candidate" }
+ void h(); // { dg-message "candidate" }
+ void i(int); // { dg-message "candidate" }
};
class C {
int ii;
- template <class U> friend void A<U>::f(U); // { dg-error "not match" }
+ template <class U>
+ friend void A<U>::f(U); // { dg-error "no declaration matches" }
template <class U> template <class V>
- friend void A<U>::g(); // { dg-error "not match|cannot be overloaded" }
- template <class U> friend int A<U>::h(); // { dg-error "not match|cannot be overloaded" }
- template <class U> friend void A<U>::i(char); // { dg-error "not match" }
+ friend void A<U>::g(); // { dg-error "no declaration matches" }
+ template <class U>
+ friend int A<U>::h(); // { dg-error "no declaration matches" }
+ template <class U>
+ friend void A<U>::i(char); // { dg-error "no declaration matches" }
};
// { dg-do assemble }
-struct gorf {
+struct gorf { // { dg-message "defined here" }
int stuff;
- void snarf(); // { dg-error "" }
+ void snarf(); // { dg-message "" }
};
-template <class T> void gorf::snarf() { return; } // { dg-error "" }
+template <class T> void gorf::snarf() { return; } // { dg-error "no declaration" }
virtual char *stringify2() const = 0; // { dg-error "overriding" }
};
-class X: public Y {
+class X: public Y { // { dg-message "defined here" }
public:
X(): Y() {}
- const char *stringify(); // { dg-error "candidate" }
- const char *stringify2() const; // { dg-error "candidate|conflicting return type" }
+ const char *stringify(); // { dg-message "candidate" }
+ const char *stringify2() const; // { dg-message "candidate" }
+ // { dg-error "conflicting return type" "" { target *-*-* } .-1 }
};
char *
-X::stringify() const // { dg-error "does not match" }
+X::stringify() const // { dg-error "no declaration matches" }
{
return "stringify";
}
const char *
-X::stringify2() // { dg-error "does not match" }
+X::stringify2() // { dg-error "no declaration matches" }
{
return "stringify2";
}
virtual ~X();
}
-X::x() // { dg-error "6:no 'X X::x\\(\\)' member function declared in class 'X'" }
+X::x() // { dg-error "1:no declaration matches" }
+// { dg-message "1:no functions named" "note" { target *-*-* } .-1 }
{
}
// { dg-do assemble }
-struct S1 {
- ~S1(); // { dg-error "" } candidate
+struct S1 { // { dg-message "defined here" }
+ ~S1(); // { dg-message "candidate" }
};
-S1::~S1() const // { dg-error "" } prototype does not match
+S1::~S1() const // { dg-error "no declaration matches" }
{
}
template <class T>
-struct S3 {
- ~S3(); // { dg-error "" } candidate
+struct S3 { // { dg-message "defined here" }
+ ~S3(); // { dg-message "candidate" }
};
template <class T>
-S3<T>::~S3() volatile // { dg-error "" } prototype does not match
+S3<T>::~S3() volatile // { dg-error "no declaration matches" }
{
}
-// { dg-do assemble }
+// { dg-do compile }
-class A { // { dg-error "" } synthesized copy ctor
+class A { // { dg-message "A::A" } synthesized copy ctor
+ // { dg-message "defined here" "note" { target *-*-* } .-1 }
public:
- A(int); // { dg-error "" } referenced below
- A(float); // { dg-error "" } referenced below
+ A(int); // { dg-message "A::A" }
+ A(float); // { dg-message "A::A" }
~A();
};