]> granicus.if.org Git - clang/commitdiff
[Preprocessor] Preserve #pragma clang assume_nonnull in preprocessed output
authorEli Friedman <efriedma@codeaurora.org>
Wed, 27 Sep 2017 23:29:37 +0000 (23:29 +0000)
committerEli Friedman <efriedma@codeaurora.org>
Wed, 27 Sep 2017 23:29:37 +0000 (23:29 +0000)
Patch by Zbigniew Sarbinowski!

Differential Revision: https://reviews.llvm.org/D37861

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

include/clang/Lex/PPCallbacks.h
lib/Frontend/PrintPreprocessedOutput.cpp
lib/Lex/Pragma.cpp
test/Preprocessor/pragma_assume_nonnull.c [new file with mode: 0644]

index 0e0a6c14067665431470b28ba5ba1d8d9402681d..8cb1656270479058d016606ac102aa1043a89b19 100644 (file)
@@ -235,6 +235,14 @@ public:
   virtual void PragmaWarningPop(SourceLocation Loc) {
   }
 
+  /// \brief Callback invoked when a \#pragma clang assume_nonnull begin directive
+  /// is read.
+  virtual void PragmaAssumeNonNullBegin(SourceLocation Loc) {}
+
+  /// \brief Callback invoked when a \#pragma clang assume_nonnull end directive
+  /// is read.
+  virtual void PragmaAssumeNonNullEnd(SourceLocation Loc) {}
+
   /// \brief Called by Preprocessor::HandleMacroExpandedIdentifier when a
   /// macro invocation is found.
   virtual void MacroExpands(const Token &MacroNameTok,
@@ -446,6 +454,16 @@ public:
     Second->PragmaWarningPop(Loc);
   }
 
+  void PragmaAssumeNonNullBegin(SourceLocation Loc) override {
+    First->PragmaAssumeNonNullBegin(Loc);
+    Second->PragmaAssumeNonNullBegin(Loc);
+  }
+
+  void PragmaAssumeNonNullEnd(SourceLocation Loc) override {
+    First->PragmaAssumeNonNullEnd(Loc);
+    Second->PragmaAssumeNonNullEnd(Loc);
+  }
+
   void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD,
                     SourceRange Range, const MacroArgs *Args) override {
     First->MacroExpands(MacroNameTok, MD, Range, Args);
index 914039ad5bb1d11a5bffd524617f5685cbad807a..8ae9038316c2c8da1a7daefcb02ca4516bf574f1 100644 (file)
@@ -143,6 +143,8 @@ public:
                      ArrayRef<int> Ids) override;
   void PragmaWarningPush(SourceLocation Loc, int Level) override;
   void PragmaWarningPop(SourceLocation Loc) override;
+  void PragmaAssumeNonNullBegin(SourceLocation Loc) override;
+  void PragmaAssumeNonNullEnd(SourceLocation Loc) override;
 
   bool HandleFirstTokOnLine(Token &Tok);
 
@@ -549,6 +551,22 @@ void PrintPPOutputPPCallbacks::PragmaWarningPop(SourceLocation Loc) {
   setEmittedDirectiveOnThisLine();
 }
 
+void PrintPPOutputPPCallbacks::
+PragmaAssumeNonNullBegin(SourceLocation Loc) {
+  startNewLineIfNeeded();
+  MoveToLine(Loc);
+  OS << "#pragma clang assume_nonnull begin";
+  setEmittedDirectiveOnThisLine();
+}
+
+void PrintPPOutputPPCallbacks::
+PragmaAssumeNonNullEnd(SourceLocation Loc) {
+  startNewLineIfNeeded();
+  MoveToLine(Loc);
+  OS << "#pragma clang assume_nonnull end";
+  setEmittedDirectiveOnThisLine();
+}
+
 /// HandleFirstTokOnLine - When emitting a preprocessed file in -E mode, this
 /// is called for the first token on each new line.  If this really is the start
 /// of a new logical line, handle it and return true, otherwise return false.
index bf2363a0a6f459a032e67897ca68aa2be76841b0..b5d0f9395499836cad9705137412c2011d460bf4 100644 (file)
@@ -1725,6 +1725,7 @@ struct PragmaAssumeNonNullHandler : public PragmaHandler {
 
     // The start location we want after processing this.
     SourceLocation NewLoc;
+    PPCallbacks *Callbacks = PP.getPPCallbacks();
 
     if (IsBegin) {
       // Complain about attempts to re-enter an audit.
@@ -1733,6 +1734,8 @@ struct PragmaAssumeNonNullHandler : public PragmaHandler {
         PP.Diag(BeginLoc, diag::note_pragma_entered_here);
       }
       NewLoc = Loc;
+      if (Callbacks)
+        Callbacks->PragmaAssumeNonNullBegin(NewLoc);
     } else {
       // Complain about attempts to leave an audit that doesn't exist.
       if (!BeginLoc.isValid()) {
@@ -1740,6 +1743,8 @@ struct PragmaAssumeNonNullHandler : public PragmaHandler {
         return;
       }
       NewLoc = SourceLocation();
+      if (Callbacks)
+        Callbacks->PragmaAssumeNonNullEnd(NewLoc);
     }
 
     PP.setPragmaAssumeNonNullLoc(NewLoc);
diff --git a/test/Preprocessor/pragma_assume_nonnull.c b/test/Preprocessor/pragma_assume_nonnull.c
new file mode 100644 (file)
index 0000000..4aa1241
--- /dev/null
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -E %s | FileCheck %s
+
+// CHECK: #pragma clang assume_nonnull begin
+#pragma clang assume_nonnull begin
+
+int bar(int * ip) { return *ip; }
+
+// CHECK: #pragma clang assume_nonnull end
+#pragma clang assume_nonnull end
+
+int foo(int * _Nonnull ip) { return *ip; }
+
+int main() {
+   return bar(0) + foo(0); // expected-warning 2 {{null passed to a callee that requires a non-null argument}}
+}