aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2007-10-16 21:00:47 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2007-10-16 21:00:47 +0000
commit15896502058d04821f1f2b4f09615a87babdd0ce (patch)
treec9fd19db215ed38eb9c7b7d407f8e60c5817857c
parent9eb061d7411734dac29533d4c8a6aba17ced2b76 (diff)
downloadgcc-15896502058d04821f1f2b4f09615a87babdd0ce.zip
gcc-15896502058d04821f1f2b4f09615a87babdd0ce.tar.gz
gcc-15896502058d04821f1f2b4f09615a87babdd0ce.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/decl.c128
-rw-r--r--gcc/cp/typeck.c13
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/g++.dg/opt/const5.C13
5 files changed, 106 insertions, 60 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index b81f0e8..559226b 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@
+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>
PR c++/30303
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 5553ec1..0a42b69 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -3914,20 +3914,20 @@ groktypename (cp_decl_specifier_seq *type_specifiers,
return type;
}
-/* Decode a declarator in an ordinary declaration or data definition.
- This is called as soon as the type information and variable name
- have been parsed, before parsing the initializer if any.
- Here we create the ..._DECL node, fill in its type,
- and put it on the list of decls for the current context.
- The ..._DECL node is returned as the value.
-
- Exception: for arrays where the length is not specified,
- the type is left null, to be filled in by `cp_finish_decl'.
-
- Function definitions do not come here; they go to start_function
- instead. However, external and forward declarations of functions
- do go through here. Structure field declarations are done by
- grokfield and not through here. */
+/* Process a DECLARATOR for a function-scope variable declaration,
+ namespace-scope variable declaration, or function declaration.
+ (Function definitions go through start_function; class member
+ declarations appearing in the body of the class go through
+ grokfield.) The DECL corresponding to the DECLARATOR is returned.
+ If an error occurs, the error_mark_node is returned instead.
+
+ DECLSPECS are the decl-specifiers for the declaration. INITIALIZED
+ is true if an explicit initializer is present, but false if this is
+ a variable implicitly initialized via a default constructor.
+ ATTRIBUTES and PREFIX_ATTRIBUTES are GNU attributes associated with
+ this declaration. *PUSHED_SCOPE_P is set to the scope entered in
+ this function, if any; if set, the caller is responsible for
+ calling pop_scope. */
tree
start_decl (const cp_declarator *declarator,
@@ -3938,7 +3938,7 @@ start_decl (const cp_declarator *declarator,
tree *pushed_scope_p)
{
tree decl;
- tree type, tem;
+ tree type;
tree context;
bool was_public;
@@ -4099,11 +4099,11 @@ start_decl (const cp_declarator *declarator,
was_public = TREE_PUBLIC (decl);
/* Enter this declaration into the symbol table. */
- tem = maybe_push_decl (decl);
+ decl = maybe_push_decl (decl);
if (processing_template_decl)
- tem = push_template_decl (tem);
- if (tem == error_mark_node)
+ decl = push_template_decl (decl);
+ if (decl == error_mark_node)
return error_mark_node;
/* 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,
produce errors about redefs; to do this we force variables into the
data segment. */
if (flag_conserve_space
- && TREE_CODE (tem) == VAR_DECL
- && TREE_PUBLIC (tem)
- && !DECL_THREAD_LOCAL_P (tem)
+ && TREE_CODE (decl) == VAR_DECL
+ && TREE_PUBLIC (decl)
+ && !DECL_THREAD_LOCAL_P (decl)
&& !have_global_bss_p ())
- DECL_COMMON (tem) = 1;
+ DECL_COMMON (decl) = 1;
- if (TREE_CODE (tem) == VAR_DECL
- && DECL_NAMESPACE_SCOPE_P (tem) && !TREE_PUBLIC (tem) && !was_public
- && !DECL_THIS_STATIC (tem) && !DECL_ARTIFICIAL (tem))
+ if (TREE_CODE (decl) == VAR_DECL
+ && DECL_NAMESPACE_SCOPE_P (decl) && !TREE_PUBLIC (decl) && !was_public
+ && !DECL_THIS_STATIC (decl) && !DECL_ARTIFICIAL (decl))
{
/* This is a const variable with implicit 'static'. Set
DECL_THIS_STATIC so we can tell it from variables that are
!TREE_PUBLIC because of the anonymous namespace. */
- gcc_assert (cp_type_readonly (TREE_TYPE (tem)));
- DECL_THIS_STATIC (tem) = 1;
+ gcc_assert (cp_type_readonly (TREE_TYPE (decl)));
+ DECL_THIS_STATIC (decl) = 1;
}
- if (!processing_template_decl && TREE_CODE (tem) == VAR_DECL)
- start_decl_1 (tem, initialized);
+ if (!processing_template_decl && TREE_CODE (decl) == VAR_DECL)
+ 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
start_decl_1 (tree decl, bool initialized)
{
tree type;
+ bool complete_p;
+ bool aggregate_definition_p;
gcc_assert (!processing_template_decl);
@@ -4146,21 +4155,37 @@ start_decl_1 (tree decl, bool initialized)
return;
gcc_assert (TREE_CODE (decl) == VAR_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)
- /* 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. */
+ /* Is it valid for this decl to have an initializer at all? */
{
/* Don't allow initializations for incomplete types except for
arrays which might be completed by the initialization. */
- if (COMPLETE_TYPE_P (complete_type (type)))
+ if (complete_p)
; /* A complete type is ok. */
else if (TREE_CODE (type) != ARRAY_TYPE)
{
error ("variable %q#D has initializer but incomplete type", decl);
- initialized = 0;
type = TREE_TYPE (decl) = error_mark_node;
}
else if (!COMPLETE_TYPE_P (complete_type (TREE_TYPE (type))))
@@ -4168,30 +4193,15 @@ start_decl_1 (tree decl, bool initialized)
if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
error ("elements of array %q#D have incomplete type", decl);
/* else we already gave an error in start_decl. */
- initialized = 0;
}
}
- else if (IS_AGGR_TYPE (type)
- && ! DECL_EXTERNAL (decl))
+ else if (aggregate_definition_p && !complete_p)
{
- if (!COMPLETE_TYPE_P (complete_type (type)))
- {
- error ("aggregate %q#D has incomplete type and cannot be defined",
- decl);
- /* Change the type so that assemble_variable will give
- 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);
- }
+ error ("aggregate %q#D has incomplete type and cannot be defined",
+ decl);
+ /* Change the type so that assemble_variable will give
+ DECL an rtl we can live with: (mem (const_int 0)). */
+ type = TREE_TYPE (decl) = error_mark_node;
}
/* Create a new scope to hold this declaration if necessary.
@@ -9113,9 +9123,9 @@ grokdeclarator (const cp_declarator *declarator,
else if (storage_class == sc_static)
DECL_THIS_STATIC (decl) = 1;
- /* Record constancy and volatility. There's no need to do this
- when processing a template; we'll do this for the instantiated
- declaration based on the type of DECL. */
+ /* Record constancy and volatility on the DECL itself . There's
+ no need to do this when processing a template; we'll do this
+ for the instantiated declaration based on the type of DECL. */
if (!processing_template_decl)
cp_apply_type_quals_to_decl (type_quals, decl);
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 45988db..cfad878 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -6976,7 +6976,18 @@ cp_has_mutable_p (const_tree 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
cp_apply_type_quals_to_decl (int type_quals, tree decl)
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a9157ca..586e53f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2007-10-16 Mark Mitchell <mark@codesourcery.com>
+
+ * g++.dg/opt/const-5.C: New test.
+
2007-10-15 Paolo Bonzini <bonzini@gnu.org>
Maxim Kuvyrkov <maxim@codesourcery.com>
diff --git a/gcc/testsuite/g++.dg/opt/const5.C b/gcc/testsuite/g++.dg/opt/const5.C
new file mode 100644
index 0000000..3785271
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/const5.C
@@ -0,0 +1,13 @@
+// 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 };