llunak created this revision.
llunak added reviewers: vsapsai, bkramer.
llunak added a project: clang.
Herald added subscribers: cfe-commits, dexonsmith.

Qt5 has a wrapper macro that makes __has_include simpler to use:
 #ifdef __has_include

1. define QT_HAS_INCLUDE(x)             __has_include(x) #else
2. define QT_HAS_INCLUDE(x)             0 #endif #if QT_HAS_INCLUDE(<chrono>)
3. include <chrono> #endif

The code handling this so far ignores macros entirely. This patch
handles this specific case in a crude way by checking if an identifier
in #if is a macro whose first token is the checked for macro.


Repository:
  rC Clang

https://reviews.llvm.org/D63508

Files:
  clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
  clang/test/Frontend/rewrite-includes-has-include-macro.c


Index: clang/test/Frontend/rewrite-includes-has-include-macro.c
===================================================================
--- /dev/null
+++ clang/test/Frontend/rewrite-includes-has-include-macro.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -verify -E -frewrite-includes %s -o - | FileCheck 
-strict-whitespace %s
+// expected-no-diagnostics
+
+#define MACRO_HAS_INCLUDE(x) __has_include(x)
+#if MACRO_HAS_INCLUDE(<this_header_does_not_exist.h>)
+#endif
+
+// CHECK: #define MACRO_HAS_INCLUDE(x) __has_include(x)
+// CHECK-NEXT: #if (0)/*MACRO_HAS_INCLUDE(<this_header_does_not_exist.h>)*/
+// CHECK-NEXT: #endif
Index: clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
===================================================================
--- clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
+++ clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
@@ -527,16 +527,28 @@
                 PP.LookUpIdentifierInfo(RawToken);
 
               if (RawToken.is(tok::identifier)) {
+                // Try to handle macros in the form of
+                // '#define QT_HAS_INCLUDE(x) __has_include(x)'.
+                const Token *ExpandedToken = &RawToken;
+                if (const MacroInfo *macroInfo =
+                        PP.getMacroInfo(RawToken.getIdentifierInfo())) {
+                  if (macroInfo->getNumTokens() > 0 &&
+                      macroInfo->getReplacementToken(0).is(tok::identifier)) {
+                    ExpandedToken = &macroInfo->getReplacementToken(0);
+                  }
+                }
+
                 bool HasFile;
                 SourceLocation Loc = RawToken.getLocation();
 
                 // Rewrite __has_include(x)
-                if (RawToken.getIdentifierInfo()->isStr("__has_include")) {
+                if (ExpandedToken->getIdentifierInfo()->isStr(
+                        "__has_include")) {
                   if (!HandleHasInclude(FileId, RawLex, nullptr, RawToken,
                                         HasFile))
                     continue;
                   // Rewrite __has_include_next(x)
-                } else if (RawToken.getIdentifierInfo()->isStr(
+                } else if (ExpandedToken->getIdentifierInfo()->isStr(
                                "__has_include_next")) {
                   if (DirLookup)
                     ++DirLookup;


Index: clang/test/Frontend/rewrite-includes-has-include-macro.c
===================================================================
--- /dev/null
+++ clang/test/Frontend/rewrite-includes-has-include-macro.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -verify -E -frewrite-includes %s -o - | FileCheck -strict-whitespace %s
+// expected-no-diagnostics
+
+#define MACRO_HAS_INCLUDE(x) __has_include(x)
+#if MACRO_HAS_INCLUDE(<this_header_does_not_exist.h>)
+#endif
+
+// CHECK: #define MACRO_HAS_INCLUDE(x) __has_include(x)
+// CHECK-NEXT: #if (0)/*MACRO_HAS_INCLUDE(<this_header_does_not_exist.h>)*/
+// CHECK-NEXT: #endif
Index: clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
===================================================================
--- clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
+++ clang/lib/Frontend/Rewrite/InclusionRewriter.cpp
@@ -527,16 +527,28 @@
                 PP.LookUpIdentifierInfo(RawToken);
 
               if (RawToken.is(tok::identifier)) {
+                // Try to handle macros in the form of
+                // '#define QT_HAS_INCLUDE(x) __has_include(x)'.
+                const Token *ExpandedToken = &RawToken;
+                if (const MacroInfo *macroInfo =
+                        PP.getMacroInfo(RawToken.getIdentifierInfo())) {
+                  if (macroInfo->getNumTokens() > 0 &&
+                      macroInfo->getReplacementToken(0).is(tok::identifier)) {
+                    ExpandedToken = &macroInfo->getReplacementToken(0);
+                  }
+                }
+
                 bool HasFile;
                 SourceLocation Loc = RawToken.getLocation();
 
                 // Rewrite __has_include(x)
-                if (RawToken.getIdentifierInfo()->isStr("__has_include")) {
+                if (ExpandedToken->getIdentifierInfo()->isStr(
+                        "__has_include")) {
                   if (!HandleHasInclude(FileId, RawLex, nullptr, RawToken,
                                         HasFile))
                     continue;
                   // Rewrite __has_include_next(x)
-                } else if (RawToken.getIdentifierInfo()->isStr(
+                } else if (ExpandedToken->getIdentifierInfo()->isStr(
                                "__has_include_next")) {
                   if (DirLookup)
                     ++DirLookup;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to