aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/pt.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/pt.c')
-rw-r--r--gcc/cp/pt.c123
1 files changed, 107 insertions, 16 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index b3b8106..2429f7f 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -171,8 +171,11 @@ static void copy_default_args_to_explicit_spec PARAMS ((tree));
static int invalid_nontype_parm_type_p PARAMS ((tree, tsubst_flags_t));
static int eq_local_specializations (const void *, const void *);
static tree template_for_substitution (tree);
-static bool value_dependent_expression_p (tree);
static bool dependent_template_id_p (tree, tree);
+static tree tsubst (tree, tree, tsubst_flags_t, tree);
+static tree tsubst_expr (tree, tree, tsubst_flags_t, tree);
+static tree tsubst_copy (tree, tree, tsubst_flags_t, tree);
+static tree tsubst_copy_and_build (tree, tree, tsubst_flags_t, tree);
/* Make the current scope suitable for access checking when we are
processing T. T can be FUNCTION_DECL for instantiated function
@@ -215,7 +218,7 @@ push_access_scope_real (t, args, context)
if (!context)
context = DECL_CONTEXT (t);
if (context && TYPE_P (context))
- push_nested_class (context, 2);
+ push_nested_class (context);
else
push_to_top_level ();
@@ -5043,7 +5046,7 @@ tsubst_friend_class (friend_tmpl, args)
if (TREE_CODE (context) == NAMESPACE_DECL)
push_nested_namespace (context);
else
- push_nested_class (tsubst (context, args, tf_none, NULL_TREE), 2);
+ push_nested_class (tsubst (context, args, tf_none, NULL_TREE));
}
/* First, we look for a class template. */
@@ -5328,7 +5331,7 @@ instantiate_class_template (type)
correctly. This is precisely analogous to what we do in
begin_class_definition when defining an ordinary non-template
class. */
- pushclass (type, 1);
+ pushclass (type, true);
/* Now members are processed in the order of declaration. */
for (member = CLASSTYPE_DECL_LIST (pattern); member; member = TREE_CHAIN (member))
@@ -6467,7 +6470,7 @@ tsubst_call_declarator_parms (parms, args, complain, in_decl)
This function is used for dealing with types, decls and the like;
for expressions, use tsubst_expr or tsubst_copy. */
-tree
+static tree
tsubst (t, args, complain, in_decl)
tree t, args;
tsubst_flags_t complain;
@@ -7103,7 +7106,7 @@ tsubst (t, args, complain, in_decl)
template parms; to finish processing the resultant expression, use
tsubst_expr. */
-tree
+static tree
tsubst_copy (t, args, complain, in_decl)
tree t, args;
tsubst_flags_t complain;
@@ -7505,7 +7508,7 @@ tsubst_copy (t, args, complain, in_decl)
/* Like tsubst_copy for expressions, etc. but also does semantic
processing. */
-tree
+static tree
tsubst_expr (t, args, complain, in_decl)
tree t, args;
tsubst_flags_t complain;
@@ -7832,7 +7835,7 @@ tsubst_expr (t, args, complain, in_decl)
/* Like tsubst but deals with expressions and performs semantic
analysis. */
-tree
+static tree
tsubst_copy_and_build (t, args, complain, in_decl)
tree t, args;
tsubst_flags_t complain;
@@ -11314,15 +11317,16 @@ dependent_type_p (type)
/* Returns TRUE if the EXPRESSION is value-dependent. */
-static bool
+bool
value_dependent_expression_p (tree expression)
{
if (!processing_template_decl)
return false;
/* A name declared with a dependent type. */
- if (DECL_P (expression)
- && dependent_type_p (TREE_TYPE (expression)))
+ if (TREE_CODE (expression) == LOOKUP_EXPR
+ || (DECL_P (expression)
+ && dependent_type_p (TREE_TYPE (expression))))
return true;
/* A non-type template parameter. */
if ((TREE_CODE (expression) == CONST_DECL
@@ -11370,11 +11374,14 @@ value_dependent_expression_p (tree expression)
case 'e':
{
int i;
- for (i = 0;
- i < TREE_CODE_LENGTH (TREE_CODE (expression));
- ++i)
- if (value_dependent_expression_p
- (TREE_OPERAND (expression, i)))
+ for (i = 0; i < first_rtl_op (TREE_CODE (expression)); ++i)
+ /* In some cases, some of the operands may be missing.
+ (For example, in the case of PREDECREMENT_EXPR, the
+ amount to increment by may be missing.) That doesn't
+ make the expression dependent. */
+ if (TREE_OPERAND (expression, i)
+ && (value_dependent_expression_p
+ (TREE_OPERAND (expression, i))))
return true;
return false;
}
@@ -11478,4 +11485,88 @@ dependent_template_p (tree tmpl)
return false;
}
+/* TYPE is a TYPENAME_TYPE. Returns the ordinary TYPE to which the
+ TYPENAME_TYPE corresponds. Returns ERROR_MARK_NODE if no such TYPE
+ can be found. Note that this function peers inside uninstantiated
+ templates and therefore should be used only in extremely limited
+ situations. */
+
+tree
+resolve_typename_type (tree type, bool only_current_p)
+{
+ tree scope;
+ tree name;
+ tree decl;
+ int quals;
+
+ my_friendly_assert (TREE_CODE (type) == TYPENAME_TYPE,
+ 20010702);
+
+ scope = TYPE_CONTEXT (type);
+ name = TYPE_IDENTIFIER (type);
+
+ /* If the SCOPE is itself a TYPENAME_TYPE, then we need to resolve
+ it first before we can figure out what NAME refers to. */
+ if (TREE_CODE (scope) == TYPENAME_TYPE)
+ scope = resolve_typename_type (scope, only_current_p);
+ /* If we don't know what SCOPE refers to, then we cannot resolve the
+ TYPENAME_TYPE. */
+ if (scope == error_mark_node || TREE_CODE (scope) == TYPENAME_TYPE)
+ return error_mark_node;
+ /* If the SCOPE is a template type parameter, we have no way of
+ resolving the name. */
+ if (TREE_CODE (scope) == TEMPLATE_TYPE_PARM)
+ return type;
+ /* If the SCOPE is not the current instantiation, there's no reason
+ to look inside it. */
+ if (only_current_p && !currently_open_class (scope))
+ return error_mark_node;
+ /* Enter the SCOPE so that name lookup will be resolved as if we
+ were in the class definition. In particular, SCOPE will no
+ longer be considered a dependent type. */
+ push_scope (scope);
+ /* Look up the declaration. */
+ decl = lookup_member (scope, name, /*protect=*/0, /*want_type=*/1);
+ /* Obtain the set of qualifiers applied to the TYPE. */
+ quals = cp_type_quals (type);
+ /* For a TYPENAME_TYPE like "typename X::template Y<T>", we want to
+ find a TEMPLATE_DECL. Otherwise, we want to find a TYPE_DECL. */
+ if (!decl)
+ type = error_mark_node;
+ else if (TREE_CODE (TYPENAME_TYPE_FULLNAME (type)) == IDENTIFIER_NODE
+ && TREE_CODE (decl) == TYPE_DECL)
+ type = TREE_TYPE (decl);
+ else if (TREE_CODE (TYPENAME_TYPE_FULLNAME (type)) == TEMPLATE_ID_EXPR
+ && DECL_CLASS_TEMPLATE_P (decl))
+ {
+ tree tmpl;
+ tree args;
+ /* Obtain the template and the arguments. */
+ tmpl = TREE_OPERAND (TYPENAME_TYPE_FULLNAME (type), 0);
+ args = TREE_OPERAND (TYPENAME_TYPE_FULLNAME (type), 1);
+ /* Instantiate the template. */
+ type = lookup_template_class (tmpl, args, NULL_TREE, NULL_TREE,
+ /*entering_scope=*/0,
+ tf_error);
+ }
+ else
+ type = error_mark_node;
+ /* Qualify the resulting type. */
+ if (type != error_mark_node && quals)
+ type = cp_build_qualified_type (type, quals);
+ /* Leave the SCOPE. */
+ pop_scope (scope);
+
+ return type;
+}
+
+tree
+resolve_typename_type_in_current_instantiation (tree type)
+{
+ tree t;
+
+ t = resolve_typename_type (type, /*only_current_p=*/true);
+ return (t != error_mark_node) ? t : type;
+}
+
#include "gt-cp-pt.h"