From 16fee0841002b532890c03b35c69438dd755602b Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Wed, 27 Sep 2017 23:29:37 +0000 Subject: [PATCH] [Preprocessor] Preserve #pragma clang assume_nonnull in preprocessed output Patch by Zbigniew Sarbinowski! Differential Revision: https://reviews.llvm.org/D37861 llvm-svn: 314364 --- clang/include/clang/Lex/PPCallbacks.h | 18 ++++++++++++++++++ clang/lib/Frontend/PrintPreprocessedOutput.cpp | 18 ++++++++++++++++++ clang/lib/Lex/Pragma.cpp | 5 +++++ clang/test/Preprocessor/pragma_assume_nonnull.c | 16 ++++++++++++++++ 4 files changed, 57 insertions(+) create mode 100644 clang/test/Preprocessor/pragma_assume_nonnull.c diff --git a/clang/include/clang/Lex/PPCallbacks.h b/clang/include/clang/Lex/PPCallbacks.h index 0e0a6c1..8cb1656 100644 --- a/clang/include/clang/Lex/PPCallbacks.h +++ b/clang/include/clang/Lex/PPCallbacks.h @@ -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); diff --git a/clang/lib/Frontend/PrintPreprocessedOutput.cpp b/clang/lib/Frontend/PrintPreprocessedOutput.cpp index 914039a..8ae9038 100644 --- a/clang/lib/Frontend/PrintPreprocessedOutput.cpp +++ b/clang/lib/Frontend/PrintPreprocessedOutput.cpp @@ -143,6 +143,8 @@ public: ArrayRef 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. diff --git a/clang/lib/Lex/Pragma.cpp b/clang/lib/Lex/Pragma.cpp index bf2363a..b5d0f93 100644 --- a/clang/lib/Lex/Pragma.cpp +++ b/clang/lib/Lex/Pragma.cpp @@ -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/clang/test/Preprocessor/pragma_assume_nonnull.c b/clang/test/Preprocessor/pragma_assume_nonnull.c new file mode 100644 index 0000000..4aa1241 --- /dev/null +++ b/clang/test/Preprocessor/pragma_assume_nonnull.c @@ -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}} +} -- 2.7.4