Commit 15896502 by Mark Mitchell Committed by Mark Mitchell

typeck.c (cp_apply_type_quals_to_decl): Expand documentation.

	* typeck.c (cp_apply_type_quals_to_decl): Expand documentation.
	* decl.c (start_decl): Tidy.
	(start_decl_1): Call cp_apply_type_quals_to_decl after completing
	the type.
	(grokdeclarator): Clarify comment.
	* g++.dg/opt/const-5.C: New test.

From-SVN: r129386
parent 9eb061d7
2007-10-16 Mark Mitchell <mark@codesourcery.com>
* typeck.c (cp_apply_type_quals_to_decl): Expand documentation.
* decl.c (start_decl): Tidy.
(start_decl_1): Call cp_apply_type_quals_to_decl after completing
the type.
(grokdeclarator): Clarify comment.
2007-10-14 Andrew Pinski <pinskia@gmail.com> 2007-10-14 Andrew Pinski <pinskia@gmail.com>
PR c++/30303 PR c++/30303
......
...@@ -3914,20 +3914,20 @@ groktypename (cp_decl_specifier_seq *type_specifiers, ...@@ -3914,20 +3914,20 @@ groktypename (cp_decl_specifier_seq *type_specifiers,
return type; return type;
} }
/* Decode a declarator in an ordinary declaration or data definition. /* Process a DECLARATOR for a function-scope variable declaration,
This is called as soon as the type information and variable name namespace-scope variable declaration, or function declaration.
have been parsed, before parsing the initializer if any. (Function definitions go through start_function; class member
Here we create the ..._DECL node, fill in its type, declarations appearing in the body of the class go through
and put it on the list of decls for the current context. grokfield.) The DECL corresponding to the DECLARATOR is returned.
The ..._DECL node is returned as the value. If an error occurs, the error_mark_node is returned instead.
Exception: for arrays where the length is not specified, DECLSPECS are the decl-specifiers for the declaration. INITIALIZED
the type is left null, to be filled in by `cp_finish_decl'. is true if an explicit initializer is present, but false if this is
a variable implicitly initialized via a default constructor.
Function definitions do not come here; they go to start_function ATTRIBUTES and PREFIX_ATTRIBUTES are GNU attributes associated with
instead. However, external and forward declarations of functions this declaration. *PUSHED_SCOPE_P is set to the scope entered in
do go through here. Structure field declarations are done by this function, if any; if set, the caller is responsible for
grokfield and not through here. */ calling pop_scope. */
tree tree
start_decl (const cp_declarator *declarator, start_decl (const cp_declarator *declarator,
...@@ -3938,7 +3938,7 @@ start_decl (const cp_declarator *declarator, ...@@ -3938,7 +3938,7 @@ start_decl (const cp_declarator *declarator,
tree *pushed_scope_p) tree *pushed_scope_p)
{ {
tree decl; tree decl;
tree type, tem; tree type;
tree context; tree context;
bool was_public; bool was_public;
...@@ -4099,11 +4099,11 @@ start_decl (const cp_declarator *declarator, ...@@ -4099,11 +4099,11 @@ start_decl (const cp_declarator *declarator,
was_public = TREE_PUBLIC (decl); was_public = TREE_PUBLIC (decl);
/* Enter this declaration into the symbol table. */ /* Enter this declaration into the symbol table. */
tem = maybe_push_decl (decl); decl = maybe_push_decl (decl);
if (processing_template_decl) if (processing_template_decl)
tem = push_template_decl (tem); decl = push_template_decl (decl);
if (tem == error_mark_node) if (decl == error_mark_node)
return error_mark_node; return error_mark_node;
/* Tell the back end to use or not use .common as appropriate. If we say /* Tell the back end to use or not use .common as appropriate. If we say
...@@ -4112,33 +4112,42 @@ start_decl (const cp_declarator *declarator, ...@@ -4112,33 +4112,42 @@ start_decl (const cp_declarator *declarator,
produce errors about redefs; to do this we force variables into the produce errors about redefs; to do this we force variables into the
data segment. */ data segment. */
if (flag_conserve_space if (flag_conserve_space
&& TREE_CODE (tem) == VAR_DECL && TREE_CODE (decl) == VAR_DECL
&& TREE_PUBLIC (tem) && TREE_PUBLIC (decl)
&& !DECL_THREAD_LOCAL_P (tem) && !DECL_THREAD_LOCAL_P (decl)
&& !have_global_bss_p ()) && !have_global_bss_p ())
DECL_COMMON (tem) = 1; DECL_COMMON (decl) = 1;
if (TREE_CODE (tem) == VAR_DECL if (TREE_CODE (decl) == VAR_DECL
&& DECL_NAMESPACE_SCOPE_P (tem) && !TREE_PUBLIC (tem) && !was_public && DECL_NAMESPACE_SCOPE_P (decl) && !TREE_PUBLIC (decl) && !was_public
&& !DECL_THIS_STATIC (tem) && !DECL_ARTIFICIAL (tem)) && !DECL_THIS_STATIC (decl) && !DECL_ARTIFICIAL (decl))
{ {
/* This is a const variable with implicit 'static'. Set /* This is a const variable with implicit 'static'. Set
DECL_THIS_STATIC so we can tell it from variables that are DECL_THIS_STATIC so we can tell it from variables that are
!TREE_PUBLIC because of the anonymous namespace. */ !TREE_PUBLIC because of the anonymous namespace. */
gcc_assert (cp_type_readonly (TREE_TYPE (tem))); gcc_assert (cp_type_readonly (TREE_TYPE (decl)));
DECL_THIS_STATIC (tem) = 1; DECL_THIS_STATIC (decl) = 1;
} }
if (!processing_template_decl && TREE_CODE (tem) == VAR_DECL) if (!processing_template_decl && TREE_CODE (decl) == VAR_DECL)
start_decl_1 (tem, initialized); start_decl_1 (decl, initialized);
return tem; return decl;
} }
/* Process the declaration of a variable DECL. INITIALIZED is true
iff DECL is explicitly initialized. (INITIALIZED is false if the
variable is initialized via an implicitly-called constructor.)
This function must be called for ordinary variables (including, for
example, implicit instantiations of templates), but must not be
called for template declarations. */
void void
start_decl_1 (tree decl, bool initialized) start_decl_1 (tree decl, bool initialized)
{ {
tree type; tree type;
bool complete_p;
bool aggregate_definition_p;
gcc_assert (!processing_template_decl); gcc_assert (!processing_template_decl);
...@@ -4146,21 +4155,37 @@ start_decl_1 (tree decl, bool initialized) ...@@ -4146,21 +4155,37 @@ start_decl_1 (tree decl, bool initialized)
return; return;
gcc_assert (TREE_CODE (decl) == VAR_DECL); gcc_assert (TREE_CODE (decl) == VAR_DECL);
type = TREE_TYPE (decl); type = TREE_TYPE (decl);
complete_p = COMPLETE_TYPE_P (type);
aggregate_definition_p = IS_AGGR_TYPE (type) && !DECL_EXTERNAL (decl);
/* If an explicit initializer is present, or if this is a definition
of an aggregate, then we need a complete type at this point.
(Scalars are always complete types, so there is nothing to
check.) This code just sets COMPLETE_P; errors (if necessary)
are issued below. */
if ((initialized || aggregate_definition_p)
&& !complete_p
&& COMPLETE_TYPE_P (complete_type (type)))
{
complete_p = true;
/* We will not yet have set TREE_READONLY on DECL if the type
was "const", but incomplete, before this point. But, now, we
have a complete type, so we can try again. */
cp_apply_type_quals_to_decl (cp_type_quals (type), decl);
}
if (initialized) if (initialized)
/* Is it valid for this decl to have an initializer at all? /* Is it valid for this decl to have an initializer at all? */
If not, set INITIALIZED to zero, which will indirectly
tell `cp_finish_decl' to ignore the initializer once it is parsed. */
{ {
/* Don't allow initializations for incomplete types except for /* Don't allow initializations for incomplete types except for
arrays which might be completed by the initialization. */ arrays which might be completed by the initialization. */
if (COMPLETE_TYPE_P (complete_type (type))) if (complete_p)
; /* A complete type is ok. */ ; /* A complete type is ok. */
else if (TREE_CODE (type) != ARRAY_TYPE) else if (TREE_CODE (type) != ARRAY_TYPE)
{ {
error ("variable %q#D has initializer but incomplete type", decl); error ("variable %q#D has initializer but incomplete type", decl);
initialized = 0;
type = TREE_TYPE (decl) = error_mark_node; type = TREE_TYPE (decl) = error_mark_node;
} }
else if (!COMPLETE_TYPE_P (complete_type (TREE_TYPE (type)))) else if (!COMPLETE_TYPE_P (complete_type (TREE_TYPE (type))))
...@@ -4168,30 +4193,15 @@ start_decl_1 (tree decl, bool initialized) ...@@ -4168,30 +4193,15 @@ start_decl_1 (tree decl, bool initialized)
if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)) if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
error ("elements of array %q#D have incomplete type", decl); error ("elements of array %q#D have incomplete type", decl);
/* else we already gave an error in start_decl. */ /* else we already gave an error in start_decl. */
initialized = 0;
} }
} }
else if (IS_AGGR_TYPE (type) else if (aggregate_definition_p && !complete_p)
&& ! DECL_EXTERNAL (decl))
{ {
if (!COMPLETE_TYPE_P (complete_type (type))) error ("aggregate %q#D has incomplete type and cannot be defined",
{ decl);
error ("aggregate %q#D has incomplete type and cannot be defined", /* Change the type so that assemble_variable will give
decl); DECL an rtl we can live with: (mem (const_int 0)). */
/* Change the type so that assemble_variable will give type = TREE_TYPE (decl) = error_mark_node;
DECL an rtl we can live with: (mem (const_int 0)). */
type = TREE_TYPE (decl) = error_mark_node;
}
else
{
/* If any base type in the hierarchy of TYPE needs a constructor,
then we set initialized to 1. This way any nodes which are
created for the purposes of initializing this aggregate
will live as long as it does. This is necessary for global
aggregates which do not have their initializers processed until
the end of the file. */
initialized = TYPE_NEEDS_CONSTRUCTING (type);
}
} }
/* Create a new scope to hold this declaration if necessary. /* Create a new scope to hold this declaration if necessary.
...@@ -9113,9 +9123,9 @@ grokdeclarator (const cp_declarator *declarator, ...@@ -9113,9 +9123,9 @@ grokdeclarator (const cp_declarator *declarator,
else if (storage_class == sc_static) else if (storage_class == sc_static)
DECL_THIS_STATIC (decl) = 1; DECL_THIS_STATIC (decl) = 1;
/* Record constancy and volatility. There's no need to do this /* Record constancy and volatility on the DECL itself . There's
when processing a template; we'll do this for the instantiated no need to do this when processing a template; we'll do this
declaration based on the type of DECL. */ for the instantiated declaration based on the type of DECL. */
if (!processing_template_decl) if (!processing_template_decl)
cp_apply_type_quals_to_decl (type_quals, decl); cp_apply_type_quals_to_decl (type_quals, decl);
......
...@@ -6976,7 +6976,18 @@ cp_has_mutable_p (const_tree type) ...@@ -6976,7 +6976,18 @@ cp_has_mutable_p (const_tree type)
return CLASS_TYPE_P (type) && CLASSTYPE_HAS_MUTABLE (type); return CLASS_TYPE_P (type) && CLASSTYPE_HAS_MUTABLE (type);
} }
/* Apply the TYPE_QUALS to the new DECL. */ /* Set TREE_READONLY and TREE_VOLATILE on DECL as indicated by the
TYPE_QUALS. For a VAR_DECL, this may be an optimistic
approximation. In particular, consider:
int f();
struct S { int i; };
const S s = { f(); }
Here, we will make "s" as TREE_READONLY (because it is declared
"const") -- only to reverse ourselves upon seeing that the
initializer is non-constant. */
void void
cp_apply_type_quals_to_decl (int type_quals, tree decl) cp_apply_type_quals_to_decl (int type_quals, tree decl)
{ {
......
2007-10-16 Mark Mitchell <mark@codesourcery.com>
* g++.dg/opt/const-5.C: New test.
2007-10-15 Paolo Bonzini <bonzini@gnu.org> 2007-10-15 Paolo Bonzini <bonzini@gnu.org>
Maxim Kuvyrkov <maxim@codesourcery.com> Maxim Kuvyrkov <maxim@codesourcery.com>
// We don't have a good way of determining how ".rodata" is spelled on
// all targets, so we limit this test to a few common targets where we
// do know the spelling.
// { dg-do compile { target i?86-*-linux* x86_64-*-linux* } }
// { dg-final { scan-assembler "\\.rodata" } }
template <typename T>
struct B {
int i;
};
// This declaration should be placed in .rodata.
const B<int> const_B __attribute__((used)) = { 3 };
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment