aboutsummaryrefslogtreecommitdiff
path: root/libcpp
diff options
context:
space:
mode:
authorEdward Smith-Rowland <3dw4rd@verizon.net>2014-11-10 15:53:12 +0000
committerEdward Smith-Rowland <emsr@gcc.gnu.org>2014-11-10 15:53:12 +0000
commit42fd12b1e7fc50183bcf62861aae81301a9efbcf (patch)
treecdf2ab35de7a1da1bcda63af97f127dea644c2ce /libcpp
parent6d64f20c8d50ce563f7b709593ac1229f2146c61 (diff)
cpplib.h (cpp_callbacks): Add has_attribute.
libcpp: 2014-11-10 Edward Smith-Rowland <3dw4rd@verizon.net> * include/cpplib.h (cpp_callbacks): Add has_attribute. * internal.h (lexer_state): Add in__has_attribute__. * directives.c (lex_macro_node): Prevent use of __has_attribute__ as a macro. * expr.c (parse_has_attribute): New function; (eval_token): Look for __has_attribute__ and route to parse_has_attribute. * identifiers.c (_cpp_init_hashtable): Initialize n__has_attribute__. * pch.c (cpp_read_state): Initialize n__has_attribute__. * traditional.c (enum ls): Add ls_has_attribute, ls_has_attribute_close; (_cpp_scan_out_logical_line): Attend to __has_attribute__. gcc/c-family: 2014-11-10 Edward Smith-Rowland <3dw4rd@verizon.net> * c-cppbuiltin.c (__has_attribute, __has_cpp_attribute): New macros; (__cpp_rtti, __cpp_exceptions): New macros for C++98; (__cpp_range_based_for, __cpp_initializer_lists, __cpp_delegating_constructors, __cpp_nsdmi, __cpp_inheriting_constructors, __cpp_ref_qualifiers): New macros for C++11; (__cpp_attribute_deprecated): Remove in favor of __has_cpp_attribute. * c-lex.c (cb_has_attribute): New callback CPP function; (init_c_lex): Set has_attribute callback. gcc/testsuite: 2014-11-10 Edward Smith-Rowland <3dw4rd@verizon.net> * g++.dg/cpp1y/feat-cxx11.C: Test new feature macros for C++98 and C++11; Test existence of __has_cpp_attribute; Test C++11 attributes. * g++.dg/cpp1y/feat-cxx11-neg.C: Ditto. * g++.dg/cpp1y/feat-cxx14.C: Ditto and test for C++14 attributes. * g++.dg/cpp1y/feat-cxx98.C: Test new feature macros for C++98. * g++.dg/cpp1y/feat-cxx98-neg.C: Ditto. * g++.dg/cpp1y/feat-neg.C: Test that __cpp_rtti, _cpp_exceptions will be undefined for -fno-rtti -fno-exceptions. From-SVN: r217292
Diffstat (limited to 'libcpp')
-rw-r--r--libcpp/ChangeLog13
-rw-r--r--libcpp/directives.c4
-rw-r--r--libcpp/expr.c21
-rw-r--r--libcpp/identifiers.c1
-rw-r--r--libcpp/include/cpplib.h3
-rw-r--r--libcpp/internal.h4
-rw-r--r--libcpp/pch.c1
-rw-r--r--libcpp/traditional.c18
8 files changed, 62 insertions, 3 deletions
diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog
index c29fe87e219..331a82dcd63 100644
--- a/libcpp/ChangeLog
+++ b/libcpp/ChangeLog
@@ -1,3 +1,16 @@
+2014-11-10 Edward Smith-Rowland <3dw4rd@verizon.net>
+
+ * include/cpplib.h (cpp_callbacks): Add has_attribute.
+ * internal.h (lexer_state): Add in__has_attribute__.
+ * directives.c (lex_macro_node): Prevent use of __has_attribute__
+ as a macro.
+ * expr.c (parse_has_attribute): New function; (eval_token): Look for
+ __has_attribute__ and route to parse_has_attribute.
+ * identifiers.c (_cpp_init_hashtable): Initialize n__has_attribute__.
+ * pch.c (cpp_read_state): Initialize n__has_attribute__.
+ * traditional.c (enum ls): Add ls_has_attribute, ls_has_attribute_close;
+ (_cpp_scan_out_logical_line): Attend to __has_attribute__.
+
2014-11-06 Joseph Myers <joseph@codesourcery.com>
* include/cpp-id-data.h (struct cpp_macro): Update comment
diff --git a/libcpp/directives.c b/libcpp/directives.c
index 0a8569aeebf..ba92ec2a6e4 100644
--- a/libcpp/directives.c
+++ b/libcpp/directives.c
@@ -571,6 +571,10 @@ lex_macro_node (cpp_reader *pfile, bool is_def_or_undef)
|| node == pfile->spec_nodes.n__has_include_next__))
cpp_error (pfile, CPP_DL_ERROR,
"\"__has_include__\" cannot be used as a macro name");
+ else if (is_def_or_undef
+ && node == pfile->spec_nodes.n__has_attribute__)
+ cpp_error (pfile, CPP_DL_ERROR,
+ "\"__has_attribute__\" cannot be used as a macro name");
else if (! (node->flags & NODE_POISONED))
return node;
}
diff --git a/libcpp/expr.c b/libcpp/expr.c
index c24b640ba16..529709c8560 100644
--- a/libcpp/expr.c
+++ b/libcpp/expr.c
@@ -65,6 +65,7 @@ static unsigned int interpret_int_suffix (cpp_reader *, const uchar *, size_t);
static void check_promotion (cpp_reader *, const struct op *);
static cpp_num parse_has_include (cpp_reader *, enum include_type);
+static cpp_num parse_has_attribute (cpp_reader *);
/* Token type abuse to create unary plus and minus operators. */
#define CPP_UPLUS ((enum cpp_ttype) (CPP_LAST_CPP_OP + 1))
@@ -1054,6 +1055,8 @@ eval_token (cpp_reader *pfile, const cpp_token *token,
return parse_has_include (pfile, IT_INCLUDE);
else if (token->val.node.node == pfile->spec_nodes.n__has_include_next__)
return parse_has_include (pfile, IT_INCLUDE_NEXT);
+ else if (token->val.node.node == pfile->spec_nodes.n__has_attribute__)
+ return parse_has_attribute (pfile);
else if (CPP_OPTION (pfile, cplusplus)
&& (token->val.node.node == pfile->spec_nodes.n_true
|| token->val.node.node == pfile->spec_nodes.n_false))
@@ -2147,3 +2150,21 @@ parse_has_include (cpp_reader *pfile, enum include_type type)
return result;
}
+
+/* Handle meeting "__has_attribute__" in a preprocessor expression. */
+static cpp_num
+parse_has_attribute (cpp_reader *pfile)
+{
+ pfile->state.in__has_attribute__++;
+
+ cpp_num result;
+ result.unsignedp = false;
+ result.high = 0;
+ result.overflow = false;
+
+ result.low = pfile->cb.has_attribute (pfile);
+
+ pfile->state.in__has_attribute__--;
+
+ return result;
+}
diff --git a/libcpp/identifiers.c b/libcpp/identifiers.c
index 35d19067495..108939a65b2 100644
--- a/libcpp/identifiers.c
+++ b/libcpp/identifiers.c
@@ -72,6 +72,7 @@ _cpp_init_hashtable (cpp_reader *pfile, cpp_hash_table *table)
s->n__VA_ARGS__->flags |= NODE_DIAGNOSTIC;
s->n__has_include__ = cpp_lookup (pfile, DSC("__has_include__"));
s->n__has_include_next__ = cpp_lookup (pfile, DSC("__has_include_next__"));
+ s->n__has_attribute__ = cpp_lookup (pfile, DSC("__has_attribute__"));
}
/* Tear down the identifier hash table. */
diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h
index 7f8e719ef8e..406200a2805 100644
--- a/libcpp/include/cpplib.h
+++ b/libcpp/include/cpplib.h
@@ -580,6 +580,9 @@ struct cpp_callbacks
Second argument is the location of the start of the current expansion. */
void (*used) (cpp_reader *, source_location, cpp_hashnode *);
+ /* Callback to identify whether an attribute exists. */
+ int (*has_attribute) (cpp_reader *);
+
/* Callback that can change a user builtin into normal macro. */
bool (*user_builtin_macro) (cpp_reader *, cpp_hashnode *);
};
diff --git a/libcpp/internal.h b/libcpp/internal.h
index 427f4c6def6..3a111c0144c 100644
--- a/libcpp/internal.h
+++ b/libcpp/internal.h
@@ -261,6 +261,9 @@ struct lexer_state
/* Nonzero if in a __has_include__ or __has_include_next__ statement. */
unsigned char in__has_include__;
+ /* Nonzero if in a __has_attribute__ statement. */
+ unsigned char in__has_attribute__;
+
/* Nonzero if prevent_expansion is true only because output is
being discarded. */
unsigned char discarding_output;
@@ -284,6 +287,7 @@ struct spec_nodes
cpp_hashnode *n__VA_ARGS__; /* C99 vararg macros */
cpp_hashnode *n__has_include__; /* __has_include__ operator */
cpp_hashnode *n__has_include_next__; /* __has_include_next__ operator */
+ cpp_hashnode *n__has_attribute__; /* __has_attribute__ operator */
};
typedef struct _cpp_line_note _cpp_line_note;
diff --git a/libcpp/pch.c b/libcpp/pch.c
index 3ff39d7ef09..d7a2dac347f 100644
--- a/libcpp/pch.c
+++ b/libcpp/pch.c
@@ -835,6 +835,7 @@ cpp_read_state (cpp_reader *r, const char *name, FILE *f,
s->n__VA_ARGS__ = cpp_lookup (r, DSC("__VA_ARGS__"));
s->n__has_include__ = cpp_lookup (r, DSC("__has_include__"));
s->n__has_include_next__ = cpp_lookup (r, DSC("__has_include_next__"));
+ s->n__has_attribute__ = cpp_lookup (r, DSC("__has_attribute__"));
}
old_state = r->state;
diff --git a/libcpp/traditional.c b/libcpp/traditional.c
index 3d40c2f2122..664bf054a03 100644
--- a/libcpp/traditional.c
+++ b/libcpp/traditional.c
@@ -76,7 +76,9 @@ enum ls {ls_none = 0, /* Normal state. */
ls_predicate, /* After the predicate, maybe paren? */
ls_answer, /* In answer to predicate. */
ls_has_include, /* After __has_include__. */
- ls_has_include_close}; /* Looking for ')' of __has_include__. */
+ ls_has_include_close, /* Looking for ')' of __has_include__. */
+ ls_has_attribute, /* After __has_attribute__. */
+ ls_has_attribute_close}; /* Looking for ')' of __has_attribute__. */
/* Lexing TODO: Maybe handle space in escaped newlines. Stop lex.c
from recognizing comments and directives during its lexing pass. */
@@ -533,6 +535,12 @@ _cpp_scan_out_logical_line (cpp_reader *pfile, cpp_macro *macro)
lex_state = ls_has_include;
continue;
}
+ else if (pfile->state.in_expression
+ && node == pfile->spec_nodes.n__has_attribute__)
+ {
+ lex_state = ls_has_attribute;
+ continue;
+ }
}
break;
@@ -558,6 +566,8 @@ _cpp_scan_out_logical_line (cpp_reader *pfile, cpp_macro *macro)
lex_state = ls_defined_close;
else if (lex_state == ls_has_include)
lex_state = ls_has_include_close;
+ else if (lex_state == ls_has_attribute)
+ lex_state = ls_has_attribute_close;
}
break;
@@ -596,7 +606,8 @@ _cpp_scan_out_logical_line (cpp_reader *pfile, cpp_macro *macro)
}
}
else if (lex_state == ls_answer || lex_state == ls_defined_close
- || lex_state == ls_has_include_close)
+ || lex_state == ls_has_include_close
+ || lex_state == ls_has_attribute_close)
lex_state = ls_none;
}
break;
@@ -678,7 +689,8 @@ _cpp_scan_out_logical_line (cpp_reader *pfile, cpp_macro *macro)
else if (lex_state == ls_hash
|| lex_state == ls_predicate
|| lex_state == ls_defined
- || lex_state == ls_has_include)
+ || lex_state == ls_has_include
+ || lex_state == ls_has_attribute)
lex_state = ls_none;
/* ls_answer and ls_defined_close keep going until ')'. */