[cfe-commits] r146765 - in /cfe/trunk: include/clang/Basic/DiagnosticLexKinds.td lib/Lex/PPDirectives.cpp test/Preprocessor/macro_arg_directive.c test/Preprocessor/macro_arg_directive.h

Richard Smith richard-llvm at metafoo.co.uk
Fri Dec 16 14:50:02 PST 2011


Author: rsmith
Date: Fri Dec 16 16:50:01 2011
New Revision: 146765

URL: http://llvm.org/viewvc/llvm-project?rev=146765&view=rev
Log:
Don't allow #include (and its friends #import, #include_next and
#__include_macros) in the arguments of a function-style macro. Directives in the
arguments of such macros have undefined behaviour, and GCC does not correctly
support these cases. In some situations, this can lead to better diagnostics.

Added:
    cfe/trunk/test/Preprocessor/macro_arg_directive.c
    cfe/trunk/test/Preprocessor/macro_arg_directive.h
Modified:
    cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
    cfe/trunk/lib/Lex/PPDirectives.cpp

Modified: cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td?rev=146765&r1=146764&r2=146765&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticLexKinds.td Fri Dec 16 16:50:01 2011
@@ -202,8 +202,10 @@
   InGroup<CXX98CompatPedantic>, DefaultIgnore;
 def ext_named_variadic_macro : Extension<
   "named variadic macros are a GNU extension">, InGroup<VariadicMacros>;
+def err_embedded_include : Error<
+  "embedding a #%0 directive within macro arguments is not supported">;
 def ext_embedded_directive : Extension<
-  "embedding a directive within macro arguments is not portable">,
+  "embedding a directive within macro arguments has undefined behavior">,
   InGroup<DiagGroup<"embedded-directive">>;
 def ext_missing_varargs_arg : Extension<
   "varargs argument missing, but tolerated as an extension">;

Modified: cfe/trunk/lib/Lex/PPDirectives.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Lex/PPDirectives.cpp?rev=146765&r1=146764&r2=146765&view=diff
==============================================================================
--- cfe/trunk/lib/Lex/PPDirectives.cpp (original)
+++ cfe/trunk/lib/Lex/PPDirectives.cpp Fri Dec 16 16:50:01 2011
@@ -577,9 +577,25 @@
   //   A(abc
   //     #warning blah
   //   def)
-  // If so, the user is relying on non-portable behavior, emit a diagnostic.
-  if (InMacroArgs)
+  // If so, the user is relying on undefined behavior, emit a diagnostic. Do
+  // not support this for #include-like directives, since that can result in
+  // terrible diagnostics, and does not work in GCC.
+  if (InMacroArgs) {
+    if (IdentifierInfo *II = Result.getIdentifierInfo()) {
+      switch (II->getPPKeywordID()) {
+      case tok::pp_include:
+      case tok::pp_import:
+      case tok::pp_include_next:
+      case tok::pp___include_macros:
+        Diag(Result, diag::err_embedded_include) << II->getName();
+        DiscardUntilEndOfDirective();
+        return;
+      default:
+        break;
+      }
+    }
     Diag(Result, diag::ext_embedded_directive);
+  }
 
 TryAgain:
   switch (Result.getKind()) {

Added: cfe/trunk/test/Preprocessor/macro_arg_directive.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/macro_arg_directive.c?rev=146765&view=auto
==============================================================================
--- cfe/trunk/test/Preprocessor/macro_arg_directive.c (added)
+++ cfe/trunk/test/Preprocessor/macro_arg_directive.c Fri Dec 16 16:50:01 2011
@@ -0,0 +1,20 @@
+// RUN: %clang_cc1 %s -fsyntax-only -verify
+
+// header1.h
+void fail(const char *);
+#define MUNCH(...) \
+ ({ int result = 0; __VA_ARGS__; if (!result) { fail(#__VA_ARGS__); }; result })
+
+static inline int f(int k) {
+  return MUNCH( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{returning 'void'}}
+    if (k < 3)
+      result = 24;
+    else if (k > 4)
+      result = k - 4;
+}
+
+#include "macro_arg_directive.h" // expected-error {{embedding a #include directive within macro arguments is not supported}}
+
+int g(int k) {
+  return f(k) + f(k-1));
+}

Added: cfe/trunk/test/Preprocessor/macro_arg_directive.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Preprocessor/macro_arg_directive.h?rev=146765&view=auto
==============================================================================
--- cfe/trunk/test/Preprocessor/macro_arg_directive.h (added)
+++ cfe/trunk/test/Preprocessor/macro_arg_directive.h Fri Dec 16 16:50:01 2011
@@ -0,0 +1,9 @@
+// Support header for macro_arg_directive.c
+
+int n;
+
+struct S {
+  int k;
+};
+
+void g(int);





More information about the cfe-commits mailing list