[PATCH] D122179: Serialize PragmaAssumeNonNullLoc to support preambles

Sam McCall via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Mar 22 06:43:17 PDT 2022


sammccall added inline comments.


================
Comment at: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp:748
 
+TEST(DiagnosticsTest, PreambleWithPragmaAssumeNonnull) {
+  Annotations Header(R"cpp(
----------------
This test seems to have a lot of extraneous elements.

The following seems sufficient, with no header:
```
#pragma clang assume_nonnull begin
void foo(int *x);
#pragma clang assume_nonnull end
```


================
Comment at: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp:748
 
+TEST(DiagnosticsTest, PreambleWithPragmaAssumeNonnull) {
+  Annotations Header(R"cpp(
----------------
sammccall wrote:
> This test seems to have a lot of extraneous elements.
> 
> The following seems sufficient, with no header:
> ```
> #pragma clang assume_nonnull begin
> void foo(int *x);
> #pragma clang assume_nonnull end
> ```
this should be a clang test, rather than a clangd test (or in addition)

probably under clang/PCH/, of the form
```
// RUN: %clang_cc1 -emit-pch ...
// RUN: %clang_cc1 -include-pch -fsyntax-only -verify -ast-dump ...
// and optionally without PCH:
// RUN: %clang_cc1 -fsyntax-only -verify -ast-dump ...
```

Then you can verify both the lack of diagnostics and the AST that gets generated.


================
Comment at: clang-tools-extra/clangd/unittests/DiagnosticsTests.cpp:775
+  TU.AdditionalFiles["header.h"] = std::string(Header.code());
+  EXPECT_THAT(*TU.build().getDiagnostics(), IsEmpty());
+}
----------------
you verify no diagnostics, but likely also want to verify that the parameter has the nonnull attribute.

This is probably simple enough, e.g 

```
ParsedAST AST = TU.build();
ParmVarDecl *X = cast<FunctionDecl>(findDecl(AST, "foo")).getParamDecl(0);
ASSERT_TRUE(X->hasAttr<NonnullAttr>());
```

(or by matching the AST dump)


================
Comment at: clang/include/clang/Lex/PreprocessorOptions.h:131
   /// conditional #if stack, so the ASTWriter/ASTReader can save/restore it when
-  /// processing the rest of the file.
+  /// processing the rest of the file. In addition, for preambles, we keep track
+  /// of an unterminated pragma assume nonnull.
----------------
nit: "Similarly, we track an unterminated #pragma assume_nonnull"?

Currently it's not completely clear what the connection is.


================
Comment at: clang/lib/Lex/PPLexerChange.cpp:430
 
-  // Complain about reaching a true EOF within assume_nonnull.
+  // Complain about reaching a true EOF within assume_nonnull unless we're
+  // building a preamble.
----------------
unless we're hitting _the end_ of the preamble

This is a special case though, pull it out of the one-sentence summary (as the other special case is)


================
Comment at: clang/lib/Lex/PPLexerChange.cpp:435
   // instantiation or a _Pragma.
-  if (PragmaAssumeNonNullLoc.isValid() &&
+  if (PragmaAssumeNonNullLoc.isValid() && !this->PPOpts->GeneratePreamble &&
+      !(CurLexer && CurLexer->getFileID() == PredefinesFileID) &&
----------------
It's not valid *anywhere* we exit a file when building a preamble, only when we fall off the end of the preamble region itself within the main file.


================
Comment at: clang/lib/Lex/PPLexerChange.cpp:436
+  if (PragmaAssumeNonNullLoc.isValid() && !this->PPOpts->GeneratePreamble &&
+      !(CurLexer && CurLexer->getFileID() == PredefinesFileID) &&
       !isEndOfMacro && !(CurLexer && CurLexer->Is_PragmaLexer)) {
----------------
what's the PredefinesFileID special case about?


================
Comment at: clang/lib/Serialization/ASTWriter.cpp:2303
 
+  // If we have an unterminated pragma assume non null, remember it since it
+  // might be at the end of the preamble.
----------------
nit: #pragma assume_nonnull


================
Comment at: clang/lib/Serialization/ASTWriter.cpp:2304
+  // If we have an unterminated pragma assume non null, remember it since it
+  // might be at the end of the preamble.
+  SourceLocation AssumeNonNullLoc = PP.getPragmaAssumeNonNullLoc();
----------------
this "might" is doing a lot of spooky action at a distance.

At minimum we should assert this is a preamble, right? Or move this block into the if() below?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D122179/new/

https://reviews.llvm.org/D122179



More information about the cfe-commits mailing list