1/* Solaris support needed only by C/C++ frontends. 2 Copyright (C) 2004-2020 Free Software Foundation, Inc. 3 Contributed by CodeSourcery, LLC. 4 5This file is part of GCC. 6 7GCC is free software; you can redistribute it and/or modify 8it under the terms of the GNU General Public License as published by 9the Free Software Foundation; either version 3, or (at your option) 10any later version. 11 12GCC is distributed in the hope that it will be useful, 13but WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15GNU General Public License for more details. 16 17You should have received a copy of the GNU General Public License 18along with GCC; see the file COPYING3. If not see 19<http://www.gnu.org/licenses/>. */ 20 21#include "config.h" 22#include "system.h" 23#include "coretypes.h" 24#include "tm.h" 25#include "c-family/c-common.h" 26#include "stringpool.h" 27#include "attribs.h" 28 29#include "c-family/c-format.h" 30#include "intl.h" 31 32#include "c-family/c-pragma.h" 33 34/* cmn_err only accepts "l" and "ll". */ 35static const format_length_info cmn_err_length_specs[] = 36{ 37 { "l", FMT_LEN_l, STD_C89, "ll", FMT_LEN_ll, STD_C89, 0 }, 38 { NULL, FMT_LEN_none, STD_C89, NULL, FMT_LEN_none, STD_C89, 0 } 39}; 40 41static const format_flag_spec cmn_err_flag_specs[] = 42{ 43 { 'w', 0, 0, 0, N_("field width"), N_("field width in printf format"), STD_C89 }, 44 { 'L', 0, 0, 0, N_("length modifier"), N_("length modifier in printf format"), STD_C89 }, 45 { 0, 0, 0, 0, NULL, NULL, STD_C89 } 46}; 47 48 49static const format_flag_pair cmn_err_flag_pairs[] = 50{ 51 { 0, 0, 0, 0 } 52}; 53 54static const format_char_info bitfield_string_type = 55 { "b", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "", "cR", NULL }; 56 57static const format_char_info cmn_err_char_table[] = 58{ 59 /* C89 conversion specifiers. */ 60 { "dD", 0, STD_C89, { T89_I, BADLEN, BADLEN, T89_L, T9L_LL, BADLEN, BADLEN, BADLEN, BADLEN }, "w", "", NULL }, 61 { "oOxX",0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "w", "", NULL }, 62 { "u", 0, STD_C89, { T89_UI, BADLEN, BADLEN, T89_UL, T9L_ULL, BADLEN, BADLEN, BADLEN, BADLEN }, "w", "", NULL }, 63 { "c", 0, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "w", "", NULL }, 64 { "p", 1, STD_C89, { T89_V, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "w", "c", NULL }, 65 { "s", 1, STD_C89, { T89_C, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "w", "cR", NULL }, 66 { "b", 0, STD_C89, { T89_I, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN, BADLEN }, "w", "", &bitfield_string_type }, 67 { NULL, 0, STD_C89, NOLENGTHS, NULL, NULL, NULL } 68}; 69 70EXPORTED_CONST format_kind_info solaris_format_types[] = { 71 { "cmn_err", cmn_err_length_specs, cmn_err_char_table, "", NULL, 72 cmn_err_flag_specs, cmn_err_flag_pairs, 73 FMT_FLAG_ARG_CONVERT|FMT_FLAG_EMPTY_PREC_OK, 74 'w', 0, 0, 0, 'L', 0, 75 &integer_type_node, &integer_type_node 76 } 77}; 78 79/* Handle #pragma align ALIGNMENT (VAR [, VAR]...) */ 80 81static void 82solaris_pragma_align (cpp_reader *pfile ATTRIBUTE_UNUSED) 83{ 84 tree t, x; 85 enum cpp_ttype ttype; 86 unsigned HOST_WIDE_INT low; 87 88 if (pragma_lex (&x) != CPP_NUMBER 89 || pragma_lex (&t) != CPP_OPEN_PAREN) 90 { 91 warning (0, "malformed %<#pragma align%>, ignoring"); 92 return; 93 } 94 95 low = TREE_INT_CST_LOW (x); 96 if (!tree_fits_uhwi_p (x) 97 || (low != 1 && low != 2 && low != 4 && low != 8 && low != 16 98 && low != 32 && low != 64 && low != 128)) 99 { 100 warning (0, "invalid alignment for %<#pragma align%>, ignoring"); 101 return; 102 } 103 104 ttype = pragma_lex (&t); 105 if (ttype != CPP_NAME) 106 { 107 warning (0, "malformed %<#pragma align%>, ignoring"); 108 return; 109 } 110 111 while (1) 112 { 113 tree decl = identifier_global_value (t); 114 if (decl && DECL_P (decl)) 115 warning (0, "%<#pragma align%> must appear before the declaration of " 116 "%qD, ignoring", decl); 117 else 118 solaris_pending_aligns = tree_cons (t, build_tree_list (NULL, x), 119 solaris_pending_aligns); 120 121 ttype = pragma_lex (&t); 122 if (ttype == CPP_COMMA) 123 { 124 ttype = pragma_lex (&t); 125 if (ttype != CPP_NAME) 126 { 127 warning (0, "malformed %<#pragma align%>"); 128 return; 129 } 130 } 131 else if (ttype == CPP_CLOSE_PAREN) 132 { 133 if (pragma_lex (&t) != CPP_EOF) 134 warning (0, "junk at end of %<#pragma align%>"); 135 return; 136 } 137 else 138 { 139 warning (0, "malformed %<#pragma align%>"); 140 return; 141 } 142 } 143} 144 145/* Handle #pragma init (function [, function]...) */ 146 147static void 148solaris_pragma_init (cpp_reader *pfile ATTRIBUTE_UNUSED) 149{ 150 tree t; 151 enum cpp_ttype ttype; 152 153 if (pragma_lex (&t) != CPP_OPEN_PAREN) 154 { 155 warning (0, "malformed %<#pragma init%>, ignoring"); 156 return; 157 } 158 159 ttype = pragma_lex (&t); 160 if (ttype != CPP_NAME) 161 { 162 warning (0, "malformed %<#pragma init%>, ignoring"); 163 return; 164 } 165 166 while (1) 167 { 168 tree decl = identifier_global_value (t); 169 if (decl && DECL_P (decl)) 170 { 171 tree attrs = build_tree_list (get_identifier ("init"), 172 NULL); 173 TREE_USED (decl) = 1; 174 DECL_PRESERVE_P (decl) = 1; 175 decl_attributes (&decl, attrs, 0); 176 } 177 else 178 solaris_pending_inits = tree_cons (t, NULL, solaris_pending_inits); 179 180 ttype = pragma_lex (&t); 181 if (ttype == CPP_COMMA) 182 { 183 ttype = pragma_lex (&t); 184 if (ttype != CPP_NAME) 185 { 186 warning (0, "malformed %<#pragma init%>"); 187 return; 188 } 189 } 190 else if (ttype == CPP_CLOSE_PAREN) 191 { 192 if (pragma_lex (&t) != CPP_EOF) 193 warning (0, "junk at end of %<#pragma init%>"); 194 return; 195 } 196 else 197 { 198 warning (0, "malformed %<#pragma init%>"); 199 return; 200 } 201 } 202} 203 204/* Handle #pragma fini (function [, function]...) */ 205 206static void 207solaris_pragma_fini (cpp_reader *pfile ATTRIBUTE_UNUSED) 208{ 209 tree t; 210 enum cpp_ttype ttype; 211 212 if (pragma_lex (&t) != CPP_OPEN_PAREN) 213 { 214 warning (0, "malformed %<#pragma fini%>, ignoring"); 215 return; 216 } 217 218 ttype = pragma_lex (&t); 219 if (ttype != CPP_NAME) 220 { 221 warning (0, "malformed %<#pragma fini%>, ignoring"); 222 return; 223 } 224 225 while (1) 226 { 227 tree decl = identifier_global_value (t); 228 if (decl && DECL_P (decl)) 229 { 230 tree attrs = build_tree_list (get_identifier ("fini"), 231 NULL); 232 TREE_USED (decl) = 1; 233 DECL_PRESERVE_P (decl) = 1; 234 decl_attributes (&decl, attrs, 0); 235 } 236 else 237 solaris_pending_finis = tree_cons (t, NULL, solaris_pending_finis); 238 239 ttype = pragma_lex (&t); 240 if (ttype == CPP_COMMA) 241 { 242 ttype = pragma_lex (&t); 243 if (ttype != CPP_NAME) 244 { 245 warning (0, "malformed %<#pragma fini%>"); 246 return; 247 } 248 } 249 else if (ttype == CPP_CLOSE_PAREN) 250 { 251 if (pragma_lex (&t) != CPP_EOF) 252 warning (0, "junk at end of %<#pragma fini%>"); 253 return; 254 } 255 else 256 { 257 warning (0, "malformed %<#pragma fini%>"); 258 return; 259 } 260 } 261} 262 263/* Register Solaris-specific #pragma directives. */ 264 265void 266solaris_register_pragmas (void) 267{ 268 c_register_pragma_with_expansion (0, "align", solaris_pragma_align); 269 c_register_pragma (0, "init", solaris_pragma_init); 270 c_register_pragma (0, "fini", solaris_pragma_fini); 271} 272