]> granicus.if.org Git - clang/commitdiff
Merging r367530:
authorHans Wennborg <hans@hanshq.net>
Fri, 2 Aug 2019 13:39:28 +0000 (13:39 +0000)
committerHans Wennborg <hans@hanshq.net>
Fri, 2 Aug 2019 13:39:28 +0000 (13:39 +0000)
------------------------------------------------------------------------
r367530 | ibiryukov | 2019-08-01 11:10:37 +0200 (Thu, 01 Aug 2019) | 17 lines

[Preprocessor] Always discard body of #define if we failed to parse it

Summary:
Preivously we would only discard it if we failed to parse parameter lists.
If we do not consume the body, parser sees tokens inside directive. In
turn, this leads to spurious diagnostics and a crash in TokenBuffer, see
the added tests.

Reviewers: sammccall

Reviewed By: sammccall

Subscribers: cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D65517
------------------------------------------------------------------------

git-svn-id: https://llvm.org/svn/llvm-project/cfe/branches/release_90@367681 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Lex/PPDirectives.cpp
test/Preprocessor/stringize_skipped.c [new file with mode: 0644]
unittests/Tooling/Syntax/TokensTest.cpp

index 2756042f23eb20e0893eb72b3808de54ebaed1da..5658f46c99de93bbd08e680e7827524e1ece81dd 100644 (file)
@@ -33,6 +33,7 @@
 #include "clang/Lex/Token.h"
 #include "clang/Lex/VariadicMacroSupport.h"
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/ScopeExit.h"
 #include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/STLExtras.h"
@@ -2399,6 +2400,13 @@ MacroInfo *Preprocessor::ReadOptionalMacroParameterListAndBody(
   Token Tok;
   LexUnexpandedToken(Tok);
 
+  // Ensure we consume the rest of the macro body if errors occur.
+  auto _ = llvm::make_scope_exit([&]() {
+    // The flag indicates if we are still waiting for 'eod'.
+    if (CurLexer->ParsingPreprocessorDirective)
+      DiscardUntilEndOfDirective();
+  });
+
   // Used to un-poison and then re-poison identifiers of the __VA_ARGS__ ilk
   // within their appropriate context.
   VariadicMacroScopeGuard VariadicMacroScopeGuard(*this);
@@ -2420,12 +2428,8 @@ MacroInfo *Preprocessor::ReadOptionalMacroParameterListAndBody(
   } else if (Tok.is(tok::l_paren)) {
     // This is a function-like macro definition.  Read the argument list.
     MI->setIsFunctionLike();
-    if (ReadMacroParameterList(MI, LastTok)) {
-      // Throw away the rest of the line.
-      if (CurPPLexer->ParsingPreprocessorDirective)
-        DiscardUntilEndOfDirective();
+    if (ReadMacroParameterList(MI, LastTok))
       return nullptr;
-    }
 
     // If this is a definition of an ISO C/C++ variadic function-like macro (not
     // using the GNU named varargs extension) inform our variadic scope guard
diff --git a/test/Preprocessor/stringize_skipped.c b/test/Preprocessor/stringize_skipped.c
new file mode 100644 (file)
index 0000000..e9395fb
--- /dev/null
@@ -0,0 +1,5 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// Ensure we see the error from PP and do not see errors from the parser.
+
+// expected-error@+1{{'#' is not followed by a macro parameter}}
+#define INVALID() #B 10+10
index 24adba28a2949db0b786dfcda2631aad3ee91856..a1398bd55688fa9d9e8e62ea34d8a0c3c5e20c20 100644 (file)
@@ -298,6 +298,21 @@ file './input.cpp'
   spelled tokens:
     <empty>
   no mappings.
+)"},
+      // Should not crash on errors inside '#define' directives. Error is that
+      // stringification (#B) does not refer to a macro parameter.
+      {
+          R"cpp(
+a
+#define MACRO() A #B
+)cpp",
+          R"(expanded tokens:
+  a
+file './input.cpp'
+  spelled tokens:
+    a # define MACRO ( ) A # B
+  mappings:
+    ['#'_1, '<eof>'_9) => ['<eof>'_1, '<eof>'_1)
 )"}};
   for (auto &Test : TestCases)
     EXPECT_EQ(collectAndDump(Test.first), Test.second)