@@ -2404,6 +2404,63 @@ static void simplifySizeof(simplecpp::TokenList &expr, const std::map<std::strin
24042404 }
24052405}
24062406
2407+ /* * Evaluate __has_include(file) */
2408+ static std::string openHeader (std::ifstream &f, const simplecpp::DUI &dui, const std::string &sourcefile, const std::string &header, bool systemheader);
2409+ static void simplifyHasInclude (simplecpp::TokenList &expr, const simplecpp::DUI &dui)
2410+ {
2411+ for (simplecpp::Token *tok = expr.front (); tok; tok = tok->next ) {
2412+ if (tok->str () != " __has_include" )
2413+ continue ;
2414+ simplecpp::Token *tok1 = tok->next ;
2415+ if (!tok1) {
2416+ throw std::runtime_error (" missing __has_include argument" );
2417+ }
2418+ simplecpp::Token *tok2 = tok1->next ;
2419+ if (!tok2) {
2420+ throw std::runtime_error (" missing __has_include argument" );
2421+ }
2422+ if (tok1->op == ' (' ) {
2423+ tok1 = tok1->next ;
2424+ while (tok2->op != ' )' ) {
2425+ tok2 = tok2->next ;
2426+ if (!tok2) {
2427+ throw std::runtime_error (" invalid __has_include expression" );
2428+ }
2429+ }
2430+ }
2431+
2432+ const std::string &sourcefile = tok->location .file ();
2433+ const bool systemheader = (tok1 && tok1->op == ' <' );
2434+ std::string header;
2435+ if (systemheader) {
2436+ simplecpp::Token *tok3 = tok1->next ;
2437+ if (!tok3) {
2438+ throw std::runtime_error (" missing __has_include closing angular bracket" );
2439+ }
2440+ while (tok3->op != ' >' ) {
2441+ tok3 = tok3->next ;
2442+ if (!tok3) {
2443+ throw std::runtime_error (" invalid __has_include expression" );
2444+ }
2445+ }
2446+
2447+ for (simplecpp::Token *headerToken = tok1->next ; headerToken != tok3; headerToken = headerToken->next )
2448+ header += headerToken->str ();
2449+ header = realFilename (header);
2450+ }
2451+ else {
2452+ header = realFilename (tok1->str ().substr (1U , tok1->str ().size () - 2U ));
2453+ }
2454+ std::ifstream f;
2455+ const std::string header2 = openHeader (f,dui,sourcefile,header,systemheader);
2456+ tok->setstr (header2.empty () ? " 0" : " 1" );
2457+
2458+ tok2 = tok2->next ;
2459+ while (tok->next != tok2)
2460+ expr.deleteToken (tok->next );
2461+ }
2462+ }
2463+
24072464static const char * const altopData[] = {" and" ," or" ," bitand" ," bitor" ," compl" ," not" ," not_eq" ," xor" };
24082465static const std::set<std::string> altop (&altopData[0 ], &altopData[8 ]);
24092466static void simplifyName (simplecpp::TokenList &expr)
@@ -2694,10 +2751,11 @@ static void simplifyComments(simplecpp::TokenList &expr)
26942751 }
26952752}
26962753
2697- static long long evaluate (simplecpp::TokenList &expr, const std::map<std::string, std::size_t > &sizeOfType)
2754+ static long long evaluate (simplecpp::TokenList &expr, const simplecpp::DUI &dui, const std::map<std::string, std::size_t > &sizeOfType)
26982755{
26992756 simplifyComments (expr);
27002757 simplifySizeof (expr, sizeOfType);
2758+ simplifyHasInclude (expr, dui);
27012759 simplifyName (expr);
27022760 simplifyNumbers (expr);
27032761 expr.constFold ();
@@ -3258,17 +3316,30 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
32583316 const bool par = (tok && tok->op == ' (' );
32593317 if (par)
32603318 tok = tok->next ;
3319+ bool closingAngularBracket = false ;
32613320 if (tok) {
32623321 const std::string &sourcefile = rawtok->location .file ();
3263- const bool systemheader = (tok->str ()[0 ] == ' <' );
3264- const std::string header (realFilename (tok->str ().substr (1U , tok->str ().size () - 2U )));
3322+ const bool systemheader = (tok && tok->op == ' <' );
3323+ std::string header;
3324+
3325+ if (systemheader) {
3326+ while ((tok = tok->next ) && tok->op != ' >' )
3327+ header += tok->str ();
3328+ header = realFilename (header);
3329+ if (tok && tok->op == ' >' )
3330+ closingAngularBracket = true ;
3331+ }
3332+ else {
3333+ header = realFilename (tok->str ().substr (1U , tok->str ().size () - 2U ));
3334+ closingAngularBracket = true ;
3335+ }
32653336 std::ifstream f;
32663337 const std::string header2 = openHeader (f,dui,sourcefile,header,systemheader);
32673338 expr.push_back (new Token (header2.empty () ? " 0" : " 1" , tok->location ));
32683339 }
32693340 if (par)
32703341 tok = tok ? tok->next : nullptr ;
3271- if (!tok || !sameline (rawtok,tok) || (par && tok->op != ' )' )) {
3342+ if (!tok || !sameline (rawtok,tok) || (par && tok->op != ' )' ) || (!closingAngularBracket) ) {
32723343 if (outputList) {
32733344 Output out (rawtok->location .files );
32743345 out.type = Output::SYNTAX_ERROR;
@@ -3298,11 +3369,11 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL
32983369 std::string E;
32993370 for (const simplecpp::Token *tok = expr.cfront (); tok; tok = tok->next )
33003371 E += (E.empty () ? " " : " " ) + tok->str ();
3301- const long long result = evaluate (expr, sizeOfType);
3372+ const long long result = evaluate (expr, dui, sizeOfType);
33023373 conditionIsTrue = (result != 0 );
33033374 ifCond->push_back (IfCond (rawtok->location , E, result));
33043375 } else {
3305- const long long result = evaluate (expr, sizeOfType);
3376+ const long long result = evaluate (expr, dui, sizeOfType);
33063377 conditionIsTrue = (result != 0 );
33073378 }
33083379 } catch (const std::exception &e) {
0 commit comments