[Preprocessor] Preserve #pragma clang assume_nonnull in preprocessed output

Patch by Zbigniew Sarbinowski!

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

llvm-svn: 314364
This commit is contained in:
Eli Friedman 2017-09-27 23:29:37 +00:00
parent fa57bd0ced
commit 16fee08410
4 changed files with 57 additions and 0 deletions

View 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);

View 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.

View 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);

View File

@ -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}}
}