This is an archive of the discontinued LLVM Phabricator instance.

[clangd] Add tests covering existing header-guard behavior. NFC
ClosedPublic

Authored by sammccall on Jul 16 2021, 5:10 PM.

Details

Summary

A few different mechanisms here that will need some work to untangle:

  • self-include in a preamble being an error even if the file is ifdef-guarded
  • the is-include-guarded flag not being propagated from preamble to main ast
  • preambles containing the first half on an include guard discard that info

For now just record current behavior.

Relevant to:

Diff Detail

Event Timeline

sammccall created this revision.Jul 16 2021, 5:10 PM
sammccall requested review of this revision.Jul 16 2021, 5:10 PM

i mostly agree with the desired behaviours laid out by the tests, mentioned a coupe extra cases and wrinkly looking parts in comments.

clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
724

i think we want the same behaviour for

;
#pragma once
#include "self.h"
725
#include "self.h"
#pragma once

might also be an interesting case (with preamble/main file split variations). I think all of these should raise a warning for sure, I don't think we should mark these as pragma guarded. (interestingly clangd actually somewhat works on this case today, but it feels like an accident and this code won't actually compile, so I don't think preserving clangd's current behviour would be beneficial to anyone).

733

what about

#include "self.h"
#ifndef GUARD
#define GUARD
;
#endif

I suppose this shouldn't be header guarded and raise diags

745

similar to above might be nice checking following isn't guarded and doesn't raise diags (as we won't include main file infinitely many times).

;
#ifndef GUARD
#define GUARD
#include "self.h"
#endif
759

s/There/These

804

but this is actually wrong from compiler's perspective, right ? if user wanted to compile implementation file they would hit redefinition errors. i think we should expect a header guard/pragma once on the implementation file on the common case.

sammccall updated this revision to Diff 359771.Jul 19 2021, 6:33 AM
sammccall marked 5 inline comments as done.

Added cases to address comments, and added comments about semicolons.

clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
725

Done, but only with a couple of splits, as I don't think we can cover all these edge cases exhaustively and the main behavior (diagnostic) is kinda obvious.

I don't think we should mark these as pragma guarded

I can't see any principled reason (or way) to make them not pragma guarded.
#pragma once at the end of a file is a perfectly valid header guard and not observably different from having it at the top unless the file transitively includes itself.

804

The compiler doesn't really have a perspective on this code, nobody ever tries to compile impl.h (and we probably don't have a real non-inferred compile command for it).

The include guard isn't required for the compiler/build system, as long as impl.h is only ever included from iface.h and the latter is guarded. And including impl.h directly usually won't compile (guarded or not) so there's no great reason to include-guard impl.h apart from tools.

This is common I think, and seems principled:

// impl.h
#ifndef IFACE_H // include guard from another file!
#error Do not include this directly!
#endif
// no include guard
// actual impl follows
kadircet accepted this revision.Jul 19 2021, 10:05 AM

thanks!

clang-tools-extra/clangd/unittests/ParsedASTTests.cpp
725

sorry i was thinking about the header guards appearing after the self-include not the pragma case, when talking about not marking them as pragma guarded. so it all makes sense, thanks!

This revision is now accepted and ready to land.Jul 19 2021, 10:05 AM