diff options
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 72 | ||||
-rw-r--r-- | gcc/cp/cxx-pretty-print.c | 9 | ||||
-rw-r--r-- | gcc/cp/decl.c | 90 | ||||
-rw-r--r-- | gcc/cp/error.c | 3 | ||||
-rw-r--r-- | gcc/cp/method.c | 10 | ||||
-rw-r--r-- | gcc/cp/name-lookup.c | 28 | ||||
-rw-r--r-- | gcc/cp/name-lookup.h | 1 | ||||
-rw-r--r-- | gcc/cp/parser.c | 176 | ||||
-rw-r--r-- | gcc/cp/pt.c | 8 | ||||
-rw-r--r-- | gcc/cp/typeck.c | 20 |
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); |