[PATCH] D49091: Warn about usage of __has_include/__has_include_next in macro expansions

Alexander Richardson via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Mon Jul 9 10:53:05 PDT 2018


arichardson created this revision.
arichardson added a reviewer: rsmith.
Herald added a subscriber: cfe-commits.

The characters after '__has_include(' have special lexing rules that can't
possibly be applied when __has_include is generated by a macro. Instead of
wrapping __has_include in another macro the following should be used instead:

#ifndef __has_include
#define __has_include(...) 0
#endif

This warning should fix the underlying issue for https://llvm.org/pr37990


Repository:
  rC Clang

https://reviews.llvm.org/D49091

Files:
  include/clang/Basic/DiagnosticLexKinds.td
  lib/Lex/PPMacroExpansion.cpp
  test/Preprocessor/expr_has_include_expansion.c


Index: test/Preprocessor/expr_has_include_expansion.c
===================================================================
--- /dev/null
+++ test/Preprocessor/expr_has_include_expansion.c
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 %s -E -verify -o /dev/null
+
+#define __libcpp_has_include(x) __has_include(x)
+#if __libcpp_has_include(<chrono>) // expected-warning{{macro expansion producing '__has_include' has undefined behavior}}
+#endif
+
+#define QT_HAS_INCLUDE_NEXT(x) __has_include_next(x)
+#if QT_HAS_INCLUDE_NEXT(<sys/foo.h>) // expected-warning{{macro expansion producing '__has_include_next' has undefined behavior}} expected-warning{{#include_next in primary source file}}
+#endif
+
+#define HAS_CHRONO __has_include(<chrono>)
+#if HAS_CHRONO // expected-warning{{macro expansion producing '__has_include' has undefined behavior}}
+#endif
+
+#define HAS_QUOTED_NEXT __has_include_next("foo.h")
+#if HAS_QUOTED_NEXT // expected-warning{{macro expansion producing '__has_include_next' has undefined behavior}} expected-warning{{#include_next in primary source file}}
+#endif
+
+// check that this diagnostic doesn't warn on normal __has_include() usage
+#if __has_include("foo.h") || __has_include_next("bar.h") // expected-warning{{#include_next in primary source file}}
+#endif
Index: lib/Lex/PPMacroExpansion.cpp
===================================================================
--- lib/Lex/PPMacroExpansion.cpp
+++ lib/Lex/PPMacroExpansion.cpp
@@ -1182,6 +1182,12 @@
     }
   }
 
+  if (LParenLoc.isMacroID())
+    // The characters after '__has_include(' have special lexing rules that
+    // can't possibly be applied when __has_include is generated by a macro.
+    // Diagnose this to avoid problems such as https://llvm.org/pr37990
+    PP.Diag(LParenLoc, diag::warn_has_include_in_macro_expansion) << II;
+
   // Reserve a buffer to get the spelling.
   SmallString<128> FilenameBuffer;
   StringRef Filename;
Index: include/clang/Basic/DiagnosticLexKinds.td
===================================================================
--- include/clang/Basic/DiagnosticLexKinds.td
+++ include/clang/Basic/DiagnosticLexKinds.td
@@ -771,6 +771,11 @@
   "macro expansion producing 'defined' has undefined behavior">,
   InGroup<ExpansionToDefined>;
 
+def warn_has_include_in_macro_expansion : Warning<
+  "macro expansion producing %0 has undefined behavior">,
+InGroup<DiagGroup<"expansion-to-has-include">>;
+
+
 let CategoryName = "Nullability Issue" in {
 
 def err_pp_assume_nonnull_syntax : Error<"expected 'begin' or 'end'">;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D49091.154644.patch
Type: text/x-patch
Size: 2541 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20180709/73b63208/attachment.bin>


More information about the cfe-commits mailing list