aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog72
-rw-r--r--gcc/cp/cxx-pretty-print.c9
-rw-r--r--gcc/cp/decl.c90
-rw-r--r--gcc/cp/error.c3
-rw-r--r--gcc/cp/method.c10
-rw-r--r--gcc/cp/name-lookup.c28
-rw-r--r--gcc/cp/name-lookup.h1
-rw-r--r--gcc/cp/parser.c176
-rw-r--r--gcc/cp/pt.c8
-rw-r--r--gcc/cp/typeck.c20
10 files changed, 302 insertions, 115 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 6edab04fe2b..378c324909b 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,75 @@
+2005-11-15 Jason Merrill <jason@redhat.com>
+
+ PR c++/24580
+ * method.c (locate_copy): Also use skip_artificial_parms here.
+ (synthesize_exception_spec): Use CLASS_TYPE_P rather than checking
+ for RECORD_TYPE.
+ (locate_ctor): Abort if we fail to find a default constructor.
+
+2005-11-15 Mike Stump <mrs@apple.com>
+
+ * name-lookup.c (lookup_name_two): Add.
+ * name-lookup.h: Likewise.
+
+2005-11-15 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/24667
+ * typeck.c (check_for_casting_away_constness): Use the diag_fn.
+ (build_const_cast_1): Call it, for C-style casts.
+
+2005-11-14 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/24687
+ * pt.c (check_explicit_specialization): Don't check for C linkage.
+ (push_template_decl_real): Likewise.
+ * parser.c (cp_parser_explicit_specialization): Check here.
+ (cp_parser_template_declaration_after_export): And here.
+
+ * parser.c (cp_lexer_get_preprocessor_token): Initialize keyword
+ field.
+
+2005-11-14 Jason Merrill <jason@redhat.com>
+
+ PR c++/24580
+ * method.c (locate_ctor): Skip all artificial parms, not just
+ 'this'.
+
+2005-11-14 Mark Mitchell <mark@codesourcery.com>
+
+ * parser.c (eof_token): Add initializer for ambiguous_p.
+
+2005-11-13 Mark Mitchell <mark@codesourcery.com>
+
+ PR c++/24817
+ * decl.c (check_redeclaration_exception_specification): New
+ function.
+ (duplicate_decls): Use it.
+ * error.c (fndecl_to_string): Print the template parameter list.
+
+ PR c++/20293
+ * cxx-pretty-print.c (pp_cxx_statement): Print qualifying scopes
+ for namespaces.
+ (pp_cxx_original_namespace_definition): Likewise.
+ * name-lookup.c (ambiguous_decl): Don't issue error messages;
+ instead return lists of ambiguous candidates.
+ (select_decl): Handle ambiguous namespace lookups.
+ * parser.c (cp_token): Add ambiguous_p.
+ (cp_lexer_get_preprocessor_token): Set it.
+ (cp_parser_diagnose_invalid_type_name): Avoid duplicate messages
+ when a qualified name uses an invalid scope.
+ (cp_parser_primary_expression): Print ambiguous candidates.
+ (cp_parser_type_parameter): Adjust comment to reflect new
+ parameter name for cp_parser_lookup_name.
+ (cp_parser_template_argument): Likewise.
+ (cp_parser_elaborated_type_specifier): Likewise.
+ (cp_parser_namespace_name): Likewise.
+ (cp_parser_class_name): Print ambiguous candidates.
+ (cp_parser_lookup_name): Rename ambiguous_p parameter to
+ ambiguous_decls. Use it to return a list of ambiguous candiates
+ when a lookup is ambiguous.
+ (cp_parser_lookup_name_simple): Adjust comment to reflect new
+ parameter name for cp_parser_lookup_name.
+
2005-11-12 Jakub Jelinek <jakub@redhat.com>
PR c++/24780
diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index f4f8819d1ed..cdaf470ce26 100644
--- a/gcc/cp/cxx-pretty-print.c
+++ b/gcc/cp/cxx-pretty-print.c
@@ -1514,6 +1514,8 @@ pp_cxx_statement (cxx_pretty_printer *pp, tree t)
case USING_STMT:
pp_cxx_identifier (pp, "using");
pp_cxx_identifier (pp, "namespace");
+ if (DECL_CONTEXT (t))
+ pp_cxx_nested_name_specifier (pp, DECL_CONTEXT (t));
pp_cxx_qualified_id (pp, USING_STMT_NAMESPACE (t));
break;
@@ -1701,6 +1703,8 @@ static void
pp_cxx_original_namespace_definition (cxx_pretty_printer *pp, tree t)
{
pp_cxx_identifier (pp, "namespace");
+ if (DECL_CONTEXT (t))
+ pp_cxx_nested_name_specifier (pp, DECL_CONTEXT (t));
if (DECL_NAME (t))
pp_cxx_unqualified_id (pp, t);
pp_cxx_whitespace (pp);
@@ -1723,10 +1727,15 @@ static void
pp_cxx_namespace_alias_definition (cxx_pretty_printer *pp, tree t)
{
pp_cxx_identifier (pp, "namespace");
+ if (DECL_CONTEXT (t))
+ pp_cxx_nested_name_specifier (pp, DECL_CONTEXT (t));
pp_cxx_unqualified_id (pp, t);
pp_cxx_whitespace (pp);
pp_equal (pp);
pp_cxx_whitespace (pp);
+ if (DECL_CONTEXT (DECL_NAMESPACE_ALIAS (t)))
+ pp_cxx_nested_name_specifier (pp,
+ DECL_CONTEXT (DECL_NAMESPACE_ALIAS (t)));
pp_cxx_qualified_id (pp, DECL_NAMESPACE_ALIAS (t));
pp_cxx_semicolon (pp);
}
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index c6ee7cb3b92..6e0c5dca02d 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -1064,6 +1064,41 @@ warn_extern_redeclared_static (tree newdecl, tree olddecl)
pedwarn ("previous declaration of %q+D", olddecl);
}
+/* NEW_DECL is a redeclaration of OLD_DECL; both are functions or
+ function templates. If their exception specifications do not
+ match, issue an a diagnostic. */
+
+static void
+check_redeclaration_exception_specification (tree new_decl,
+ tree old_decl)
+{
+ tree new_type;
+ tree old_type;
+ tree new_exceptions;
+ tree old_exceptions;
+
+ new_type = TREE_TYPE (new_decl);
+ new_exceptions = TYPE_RAISES_EXCEPTIONS (new_type);
+ old_type = TREE_TYPE (old_decl);
+ old_exceptions = TYPE_RAISES_EXCEPTIONS (old_type);
+
+ /* [except.spec]
+
+ If any declaration of a function has an exception-specification,
+ all declarations, including the definition and an explicit
+ specialization, of that function shall have an
+ exception-specification with the same set of type-ids. */
+ if ((pedantic || ! DECL_IN_SYSTEM_HEADER (old_decl))
+ && ! DECL_IS_BUILTIN (old_decl)
+ && flag_exceptions
+ && !comp_except_specs (new_exceptions, old_exceptions,
+ /*exact=*/true))
+ {
+ error ("declaration of %qF throws different exceptions", new_decl);
+ error ("from previous declaration %q+F", old_decl);
+ }
+}
+
/* If NEWDECL is a redeclaration of OLDDECL, merge the declarations.
If the redeclaration is invalid, a diagnostic is issued, and the
error_mark_node is returned. Otherwise, OLDDECL is returned.
@@ -1555,30 +1590,35 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
- TREE_TYPE (olddecl) = TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl));
+ tree old_result;
+ tree new_result;
+ old_result = DECL_TEMPLATE_RESULT (olddecl);
+ new_result = DECL_TEMPLATE_RESULT (newdecl);
+ TREE_TYPE (olddecl) = TREE_TYPE (old_result);
DECL_TEMPLATE_SPECIALIZATIONS (olddecl)
= chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
+ if (DECL_FUNCTION_TEMPLATE_P (newdecl))
+ {
+ DECL_INLINE (old_result)
+ |= DECL_INLINE (new_result);
+ DECL_DECLARED_INLINE_P (old_result)
+ |= DECL_DECLARED_INLINE_P (new_result);
+ check_redeclaration_exception_specification (newdecl, olddecl);
+ }
+
/* If the new declaration is a definition, update the file and
line information on the declaration. */
- if (DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl)) == NULL_TREE
- && DECL_INITIAL (DECL_TEMPLATE_RESULT (newdecl)) != NULL_TREE)
+ if (DECL_INITIAL (old_result) == NULL_TREE
+ && DECL_INITIAL (new_result) != NULL_TREE)
{
DECL_SOURCE_LOCATION (olddecl)
- = DECL_SOURCE_LOCATION (DECL_TEMPLATE_RESULT (olddecl))
+ = DECL_SOURCE_LOCATION (old_result)
= DECL_SOURCE_LOCATION (newdecl);
if (DECL_FUNCTION_TEMPLATE_P (newdecl))
- DECL_ARGUMENTS (DECL_TEMPLATE_RESULT (olddecl))
- = DECL_ARGUMENTS (DECL_TEMPLATE_RESULT (newdecl));
- }
-
- if (DECL_FUNCTION_TEMPLATE_P (newdecl))
- {
- DECL_INLINE (DECL_TEMPLATE_RESULT (olddecl))
- |= DECL_INLINE (DECL_TEMPLATE_RESULT (newdecl));
- DECL_DECLARED_INLINE_P (DECL_TEMPLATE_RESULT (olddecl))
- |= DECL_DECLARED_INLINE_P (DECL_TEMPLATE_RESULT (newdecl));
+ DECL_ARGUMENTS (old_result)
+ = DECL_ARGUMENTS (new_result);
}
return olddecl;
@@ -1622,26 +1662,8 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
/* Do this after calling `merge_types' so that default
parameters don't confuse us. */
- else if (TREE_CODE (newdecl) == FUNCTION_DECL
- && (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl))
- != TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl))))
- {
- TREE_TYPE (newdecl) = build_exception_variant (newtype,
- TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)));
- TREE_TYPE (olddecl) = build_exception_variant (newtype,
- TYPE_RAISES_EXCEPTIONS (oldtype));
-
- if ((pedantic || ! DECL_IN_SYSTEM_HEADER (olddecl))
- && ! DECL_IS_BUILTIN (olddecl)
- && flag_exceptions
- && !comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)),
- TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl)), 1))
- {
- error ("declaration of %qF throws different exceptions",
- newdecl);
- error ("than previous declaration %q+F", olddecl);
- }
- }
+ else if (TREE_CODE (newdecl) == FUNCTION_DECL)
+ check_redeclaration_exception_specification (newdecl, olddecl);
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
/* Lay the type out, unless already done. */
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 22c2d304d88..674e407055f 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -2008,7 +2008,8 @@ fndecl_to_string (tree fndecl, int verbose)
{
int flags;
- flags = TFF_EXCEPTION_SPECIFICATION | TFF_DECL_SPECIFIERS;
+ flags = TFF_EXCEPTION_SPECIFICATION | TFF_DECL_SPECIFIERS
+ | TFF_TEMPLATE_HEADER;
if (verbose)
flags |= TFF_FUNCTION_DEFAULT_ARGUMENTS;
reinit_cxx_pp ();
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 67e42ea1e0e..f3c86d3178d 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -847,7 +847,7 @@ synthesize_exception_spec (tree type, tree (*extractor) (tree, void*),
continue;
while (TREE_CODE (type) == ARRAY_TYPE)
type = TREE_TYPE (type);
- if (TREE_CODE (type) != RECORD_TYPE)
+ if (!CLASS_TYPE_P (type))
continue;
fn = (*extractor) (type, client);
@@ -889,10 +889,12 @@ locate_ctor (tree type, void *client ATTRIBUTE_UNUSED)
tree fn = OVL_CURRENT (fns);
tree parms = TYPE_ARG_TYPES (TREE_TYPE (fn));
- if (sufficient_parms_p (TREE_CHAIN (parms)))
+ parms = skip_artificial_parms_for (fn, parms);
+
+ if (sufficient_parms_p (parms))
return fn;
}
- return NULL_TREE;
+ gcc_unreachable ();
}
struct copy_data
@@ -939,7 +941,7 @@ locate_copy (tree type, void *client_)
int excess;
int quals;
- parms = TREE_CHAIN (parms);
+ parms = skip_artificial_parms_for (fn, parms);
if (!parms)
continue;
src_type = non_reference (TREE_VALUE (parms));
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 70c764956be..f61f521a401 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -3401,20 +3401,9 @@ ambiguous_decl (tree name, struct scope_binding *old, cxx_binding *new,
old->value = merge_functions (old->value, val);
else
{
- /* Some declarations are functions, some are not. */
- if (flags & LOOKUP_COMPLAIN)
- {
- /* If we've already given this error for this lookup,
- old->value is error_mark_node, so let's not
- repeat ourselves. */
- if (old->value != error_mark_node)
- {
- error ("use of %qD is ambiguous", name);
- error (" first declared as %q+#D here", old->value);
- }
- error (" also declared as %q+#D here", val);
- }
- old->value = error_mark_node;
+ old->value = tree_cons (NULL_TREE, old->value,
+ build_tree_list (NULL_TREE, new->value));
+ TREE_TYPE (old->value) = error_mark_node;
}
}
/* ... and copy the type. */
@@ -3610,7 +3599,8 @@ select_decl (const struct scope_binding *binding, int flags)
if (LOOKUP_NAMESPACES_ONLY (flags))
{
/* We are not interested in types. */
- if (val && TREE_CODE (val) == NAMESPACE_DECL)
+ if (val && (TREE_CODE (val) == NAMESPACE_DECL
+ || TREE_CODE (val) == TREE_LIST))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
@@ -4017,6 +4007,14 @@ lookup_name_prefer_type (tree name, int prefer_type)
0, LOOKUP_COMPLAIN);
}
+/* Similar to `lookup_name' for the benefit of common code. */
+
+tree
+lookup_name_two (tree name, int prefer_type)
+{
+ return lookup_name_prefer_type (name, prefer_type);
+}
+
/* Look up NAME for type used in elaborated name specifier in
the scopes given by SCOPE. SCOPE can be either TS_CURRENT or
TS_WITHIN_ENCLOSING_NON_CLASS. Although not implied by the
diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h
index b3b8289a2f2..7bb8cffcab7 100644
--- a/gcc/cp/name-lookup.h
+++ b/gcc/cp/name-lookup.h
@@ -314,6 +314,7 @@ extern void pushlevel_class (void);
extern void poplevel_class (void);
extern tree pushdecl_with_scope (tree, cxx_scope *, bool);
extern tree lookup_name_prefer_type (tree, int);
+extern tree lookup_name_two (tree, int);
extern tree lookup_name_real (tree, int, int, bool, int, int);
extern tree lookup_type_scope (tree, tag_scope);
extern tree namespace_binding (tree, tree);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index cecbcb356a6..9cad919e700 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -61,6 +61,10 @@ typedef struct cp_token GTY (())
BOOL_BITFIELD in_system_header : 1;
/* True if this token is from a context where it is implicitly extern "C" */
BOOL_BITFIELD implicit_extern_c : 1;
+ /* True for a CPP_NAME token that is not a keyword (i.e., for which
+ KEYWORD is RID_MAX) iff this name was looked up and found to be
+ ambiguous. An error has already been reported. */
+ BOOL_BITFIELD ambiguous_p : 1;
/* The value associated with this token, if any. */
tree value;
/* The location at which this token was found. */
@@ -74,7 +78,7 @@ DEF_VEC_ALLOC_P (cp_token_position,heap);
static const cp_token eof_token =
{
- CPP_EOF, RID_MAX, 0, PRAGMA_NONE, 0, 0, NULL_TREE,
+ CPP_EOF, RID_MAX, 0, PRAGMA_NONE, 0, 0, false, NULL_TREE,
#if USE_MAPPED_LOCATION
0
#else
@@ -399,10 +403,9 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
pending_lang_change = 0;
token->implicit_extern_c = is_extern_c > 0;
- switch (token->type)
+ /* Check to see if this token is a keyword. */
+ if (token->type == CPP_NAME)
{
- case CPP_NAME:
- /* Check to see if this token is a keyword. */
if (C_IS_RESERVED_WORD (token->value))
{
/* Mark this token as a keyword. */
@@ -415,10 +418,15 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
mapped to `const'. */
token->value = ridpointers[token->keyword];
}
- break;
-
- case CPP_AT_NAME:
- /* Handle Objective-C++ keywords. */
+ else
+ {
+ token->ambiguous_p = false;
+ token->keyword = RID_MAX;
+ }
+ }
+ /* Handle Objective-C++ keywords. */
+ else if (token->type == CPP_AT_NAME)
+ {
token->type = CPP_KEYWORD;
switch (C_RID_CODE (token->value))
{
@@ -432,16 +440,12 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
case RID_CATCH: token->keyword = RID_AT_CATCH; break;
default: token->keyword = C_RID_CODE (token->value);
}
- break;
-
- case CPP_PRAGMA:
+ }
+ else if (token->type == CPP_PRAGMA)
+ {
/* We smuggled the cpp_token->u.pragma value in an INTEGER_CST. */
token->pragma_kind = TREE_INT_CST_LOW (token->value);
token->value = NULL;
- break;
-
- default:
- break;
}
}
@@ -1700,7 +1704,7 @@ static tree cp_parser_objc_statement
/* Utility Routines */
static tree cp_parser_lookup_name
- (cp_parser *, tree, enum tag_types, bool, bool, bool, bool *);
+ (cp_parser *, tree, enum tag_types, bool, bool, bool, tree *);
static tree cp_parser_lookup_name_simple
(cp_parser *, tree);
static tree cp_parser_maybe_treat_template_as_class
@@ -2057,7 +2061,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
if (TREE_CODE (decl) == TEMPLATE_DECL)
error ("invalid use of template-name %qE without an argument list",
decl);
- else if (!parser->scope || parser->scope == error_mark_node)
+ else if (!parser->scope)
{
/* Issue an error message. */
error ("%qE does not name a type", id);
@@ -2104,7 +2108,7 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
}
/* Here we diagnose qualified-ids where the scope is actually correct,
but the identifier does not resolve to a valid type name. */
- else
+ else if (parser->scope != error_mark_node)
{
if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
error ("%qE in namespace %qE does not name a type",
@@ -3032,17 +3036,17 @@ cp_parser_primary_expression (cp_parser *parser,
/* Look up the name. */
else
{
- bool ambiguous_p;
+ tree ambiguous_decls;
decl = cp_parser_lookup_name (parser, id_expression,
none_type,
template_p,
/*is_namespace=*/false,
/*check_dependency=*/true,
- &ambiguous_p);
+ &ambiguous_decls);
/* If the lookup was ambiguous, an error will already have
been issued. */
- if (ambiguous_p)
+ if (ambiguous_decls)
return error_mark_node;
/* In Objective-C++, an instance variable (ivar) may be preferred
@@ -3648,16 +3652,32 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
token = cp_lexer_consume_token (parser->lexer);
if (!error_p)
{
- tree decl;
-
- decl = cp_parser_lookup_name_simple (parser, token->value);
- if (TREE_CODE (decl) == TEMPLATE_DECL)
- error ("%qD used without template parameters", decl);
- else
- cp_parser_name_lookup_error
- (parser, token->value, decl,
- "is not a class or namespace");
- parser->scope = NULL_TREE;
+ if (!token->ambiguous_p)
+ {
+ tree decl;
+ tree ambiguous_decls;
+
+ decl = cp_parser_lookup_name (parser, token->value,
+ none_type,
+ /*is_template=*/false,
+ /*is_namespace=*/false,
+ /*check_dependency=*/true,
+ &ambiguous_decls);
+ if (TREE_CODE (decl) == TEMPLATE_DECL)
+ error ("%qD used without template parameters", decl);
+ else if (ambiguous_decls)
+ {
+ error ("reference to %qD is ambiguous",
+ token->value);
+ print_candidates (ambiguous_decls);
+ decl = error_mark_node;
+ }
+ else
+ cp_parser_name_lookup_error
+ (parser, token->value, decl,
+ "is not a class or namespace");
+ }
+ parser->scope = error_mark_node;
error_p = true;
/* Treat this as a successful nested-name-specifier
due to:
@@ -8532,7 +8552,7 @@ cp_parser_type_parameter (cp_parser* parser)
/*is_template=*/is_template,
/*is_namespace=*/false,
/*check_dependency=*/true,
- /*ambiguous_p=*/NULL);
+ /*ambiguous_decls=*/NULL);
/* See if the default argument is valid. */
default_argument
= check_template_template_default_arg (default_argument);
@@ -8888,7 +8908,7 @@ cp_parser_template_name (cp_parser* parser,
/*is_template=*/false,
/*is_namespace=*/false,
check_dependency_p,
- /*ambiguous_p=*/NULL);
+ /*ambiguous_decls=*/NULL);
decl = maybe_get_template_decl_from_type_decl (decl);
/* If DECL is a template, then the name was a template-name. */
@@ -9089,7 +9109,7 @@ cp_parser_template_argument (cp_parser* parser)
/*is_template=*/template_p,
/*is_namespace=*/false,
/*check_dependency=*/true,
- /*ambiguous_p=*/NULL);
+ /*ambiguous_decls=*/NULL);
if (TREE_CODE (argument) != TEMPLATE_DECL
&& TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
cp_parser_error (parser, "expected template-name");
@@ -9343,6 +9363,7 @@ cp_parser_explicit_instantiation (cp_parser* parser)
static void
cp_parser_explicit_specialization (cp_parser* parser)
{
+ bool need_lang_pop;
/* Look for the `template' keyword. */
cp_parser_require_keyword (parser, RID_TEMPLATE, "`template'");
/* Look for the `<'. */
@@ -9351,9 +9372,22 @@ cp_parser_explicit_specialization (cp_parser* parser)
cp_parser_require (parser, CPP_GREATER, "`>'");
/* We have processed another parameter list. */
++parser->num_template_parameter_lists;
+ /* [temp]
+
+ A template ... explicit specialization ... shall not have C
+ linkage. */
+ if (current_lang_name == lang_name_c)
+ {
+ error ("template specialization with C linkage");
+ /* Give it C++ linkage to avoid confusing other parts of the
+ front end. */
+ push_lang_context (lang_name_cplusplus);
+ need_lang_pop = true;
+ }
+ else
+ need_lang_pop = false;
/* Let the front end know that we are beginning a specialization. */
begin_specialization ();
-
/* If the next keyword is `template', we need to figure out whether
or not we're looking a template-declaration. */
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TEMPLATE))
@@ -9370,9 +9404,12 @@ cp_parser_explicit_specialization (cp_parser* parser)
cp_parser_single_declaration (parser,
/*member_p=*/false,
/*friend_p=*/NULL);
-
/* We're done with the specialization. */
end_specialization ();
+ /* For the erroneous case of a template with C linkage, we pushed an
+ implicit C++ linkage scope; exit that scope now. */
+ if (need_lang_pop)
+ pop_lang_context ();
/* We're done with this parameter list. */
--parser->num_template_parameter_lists;
}
@@ -10012,7 +10049,7 @@ cp_parser_elaborated_type_specifier (cp_parser* parser,
/*is_template=*/false,
/*is_namespace=*/false,
/*check_dependency=*/true,
- /*ambiguous_p=*/NULL);
+ /*ambiguous_decls=*/NULL);
/* If we are parsing friend declaration, DECL may be a
TEMPLATE_DECL tree node here. However, we need to check
@@ -10308,7 +10345,7 @@ cp_parser_namespace_name (cp_parser* parser)
/*is_template=*/false,
/*is_namespace=*/true,
/*check_dependency=*/true,
- /*ambiguous_p=*/NULL);
+ /*ambiguous_decls=*/NULL);
/* If it's not a namespace, issue an error. */
if (namespace_decl == error_mark_node
|| TREE_CODE (namespace_decl) != NAMESPACE_DECL)
@@ -12545,9 +12582,13 @@ cp_parser_class_name (cp_parser *parser,
if (token->type == CPP_NAME
&& !cp_parser_nth_token_starts_template_argument_list_p (parser, 2))
{
+ cp_token *identifier_token;
tree identifier;
+ bool ambiguous_p;
/* Look for the identifier. */
+ identifier_token = cp_lexer_peek_token (parser->lexer);
+ ambiguous_p = identifier_token->ambiguous_p;
identifier = cp_parser_identifier (parser);
/* If the next token isn't an identifier, we are certainly not
looking at a class-name. */
@@ -12559,6 +12600,15 @@ cp_parser_class_name (cp_parser *parser,
decl = identifier;
else
{
+ tree ambiguous_decls;
+ /* If we already know that this lookup is ambiguous, then
+ we've already issued an error message; there's no reason
+ to check again. */
+ if (ambiguous_p)
+ {
+ cp_parser_simulate_error (parser);
+ return error_mark_node;
+ }
/* If the next token is a `::', then the name must be a type
name.
@@ -12575,7 +12625,18 @@ cp_parser_class_name (cp_parser *parser,
/*is_template=*/false,
/*is_namespace=*/false,
check_dependency_p,
- /*ambiguous_p=*/NULL);
+ &ambiguous_decls);
+ if (ambiguous_decls)
+ {
+ error ("reference to %qD is ambiguous", identifier);
+ print_candidates (ambiguous_decls);
+ if (cp_parser_parsing_tentatively (parser))
+ {
+ identifier_token->ambiguous_p = true;
+ cp_parser_simulate_error (parser);
+ }
+ return error_mark_node;
+ }
}
}
else
@@ -14516,8 +14577,9 @@ cp_parser_label_declaration (cp_parser* parser)
If CHECK_DEPENDENCY is TRUE, names are not looked up in dependent
types.
- If AMBIGUOUS_P is non-NULL, it is set to true if name-lookup
- results in an ambiguity, and false otherwise. */
+ If AMBIGUOUS_DECLS is non-NULL, *AMBIGUOUS_DECLS is set to a
+ TREE_LIST of candiates if name-lookup results in an ambiguity, and
+ NULL_TREE otherwise. */
static tree
cp_parser_lookup_name (cp_parser *parser, tree name,
@@ -14525,7 +14587,7 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
bool is_template,
bool is_namespace,
bool check_dependency,
- bool *ambiguous_p)
+ tree *ambiguous_decls)
{
int flags = 0;
tree decl;
@@ -14535,8 +14597,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
flags |= LOOKUP_COMPLAIN;
/* Assume that the lookup will be unambiguous. */
- if (ambiguous_p)
- *ambiguous_p = false;
+ if (ambiguous_decls)
+ *ambiguous_decls = NULL_TREE;
/* Now that we have looked up the name, the OBJECT_TYPE (if any) is
no longer valid. Note that if we are parsing tentatively, and
@@ -14693,8 +14755,8 @@ cp_parser_lookup_name (cp_parser *parser, tree name,
/* If it's a TREE_LIST, the result of the lookup was ambiguous. */
if (TREE_CODE (decl) == TREE_LIST)
{
- if (ambiguous_p)
- *ambiguous_p = true;
+ if (ambiguous_decls)
+ *ambiguous_decls = decl;
/* The error message we have to print is too complicated for
cp_parser_error, so we incorporate its actions directly. */
if (!cp_parser_simulate_error (parser))
@@ -14736,7 +14798,7 @@ cp_parser_lookup_name_simple (cp_parser* parser, tree name)
/*is_template=*/false,
/*is_namespace=*/false,
/*check_dependency=*/true,
- /*ambiguous_p=*/NULL);
+ /*ambiguous_decls=*/NULL);
}
/* If DECL is a TEMPLATE_DECL that can be treated like a TYPE_DECL in
@@ -15200,6 +15262,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
tree decl = NULL_TREE;
tree parameter_list;
bool friend_p = false;
+ bool need_lang_pop;
/* Look for the `template' keyword. */
if (!cp_parser_require_keyword (parser, RID_TEMPLATE, "`template'"))
@@ -15208,7 +15271,19 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
/* And the `<'. */
if (!cp_parser_require (parser, CPP_LESS, "`<'"))
return;
-
+ /* [temp]
+
+ A template ... shall not have C linkage. */
+ if (current_lang_name == lang_name_c)
+ {
+ error ("template with C linkage");
+ /* Give it C++ linkage to avoid confusing other parts of the
+ front end. */
+ push_lang_context (lang_name_cplusplus);
+ need_lang_pop = true;
+ }
+ else
+ need_lang_pop = false;
/* If the next token is `>', then we have an invalid
specialization. Rather than complain about an invalid template
parameter, issue an error message here. */
@@ -15269,7 +15344,10 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
/* Register member declarations. */
if (member_p && !friend_p && decl && !DECL_CLASS_TEMPLATE_P (decl))
finish_member_declaration (decl);
-
+ /* For the erroneous case of a template with C linkage, we pushed an
+ implicit C++ linkage scope; exit that scope now. */
+ if (need_lang_pop)
+ pop_lang_context ();
/* If DECL is a function template, we must return to parse it later.
(Even though there is no definition, there might be default
arguments that need handling.) */
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 9fac8c90fd1..a741fa855a1 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -1895,8 +1895,6 @@ check_explicit_specialization (tree declarator,
("default argument specified in explicit specialization");
break;
}
- if (current_lang_name == lang_name_c)
- error ("template specialization with C linkage");
}
if (specialization || member_specialization || explicit_instantiation)
@@ -2985,10 +2983,8 @@ push_template_decl_real (tree decl, bool is_friend)
{
if (DECL_CLASS_SCOPE_P (decl))
member_template_p = true;
- if (current_lang_name == lang_name_c)
- error ("template with C linkage");
- else if (TREE_CODE (decl) == TYPE_DECL
- && ANON_AGGRNAME_P (DECL_NAME (decl)))
+ if (TREE_CODE (decl) == TYPE_DECL
+ && ANON_AGGRNAME_P (DECL_NAME (decl)))
error ("template class without a name");
else if (TREE_CODE (decl) == FUNCTION_DECL)
{
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 31e2d6f58fc..a86ee6a516e 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -4559,8 +4559,8 @@ check_for_casting_away_constness (tree src_type, tree dest_type,
const char *description)
{
if (diag_fn && casts_away_constness (src_type, dest_type))
- error ("%s from type %qT to type %qT casts away constness",
- description, src_type, dest_type);
+ diag_fn ("%s from type %qT to type %qT casts away constness",
+ description, src_type, dest_type);
}
/* Convert EXPR (an expression with pointer-to-member type) to TYPE
@@ -5085,9 +5085,9 @@ build_reinterpret_cast (tree type, tree expr)
/* Perform a const_cast from EXPR to TYPE. If the cast is valid,
return an appropriate expression. Otherwise, return
error_mark_node. If the cast is not valid, and COMPLAIN is true,
- then a diagnostic will be issued. If VALID_P is non-NULL, its
- value upon return will indicate whether or not the conversion
- succeeded. */
+ then a diagnostic will be issued. If VALID_P is non-NULL, we are
+ performing a C-style cast, its value upon return will indicate
+ whether or not the conversion succeeded. */
static tree
build_const_cast_1 (tree dst_type, tree expr, bool complain,
@@ -5163,7 +5163,15 @@ build_const_cast_1 (tree dst_type, tree expr, bool complain,
&& comp_ptr_ttypes_const (dst_type, src_type))
{
if (valid_p)
- *valid_p = true;
+ {
+ *valid_p = true;
+ /* This cast is actually a C-style cast. Issue a warning if
+ the user is making a potentially unsafe cast. */
+ if (warn_cast_qual)
+ check_for_casting_away_constness (src_type, dst_type,
+ warning0,
+ "cast");
+ }
if (reference_type)
{
expr = build_unary_op (ADDR_EXPR, expr, 0);