Index: clang/include/clang/Lex/MultipleIncludeOpt.h =================================================================== --- clang/include/clang/Lex/MultipleIncludeOpt.h +++ clang/include/clang/Lex/MultipleIncludeOpt.h @@ -108,6 +108,12 @@ ImmediatelyAfterTopLevelIfndef = false; } + /// ResetReadToken - reset whether we have read any tokens. Called when + /// encountering tokens outside of the include guard that have no effect if + /// the file in question is is included multiple times (e.g. the null + /// directive). + void ResetReadToken() { ReadAnyTokens = false; } + /// ExpandedMacro - When a macro is expanded with this lexer as the current /// buffer, this method is called to disable the MIOpt if needed. void ExpandedMacro() { DidMacroExpansion = true; } Index: clang/lib/Lex/PPDirectives.cpp =================================================================== --- clang/lib/Lex/PPDirectives.cpp +++ clang/lib/Lex/PPDirectives.cpp @@ -1177,6 +1177,12 @@ switch (Result.getKind()) { case tok::eod: + // Allow the null directive to appear outside of the include guard and still + // keep multiple-include optimization. So if we haven't recorded any tokens + // yet we can reset MIOpt to forget about the null directive. + if (!ReadAnyTokensBeforeDirective) { + CurPPLexer->MIOpt.ResetReadToken(); + } return; // null directive. case tok::code_completion: setCodeCompletionReached(); Index: clang/test/Preprocessor/multiple-inclusion-opt.h =================================================================== --- /dev/null +++ clang/test/Preprocessor/multiple-inclusion-opt.h @@ -0,0 +1,18 @@ +# // null directive and comments before include guard + +#ifndef MULTIPLE_INCLUSION_OPT + +int foo(); + +// The position of the define should not matter +#define MULTIPLE_INCLUSION_OPT + +int bar(); + +#endif + +# +# +/* Two null directives + and a multiline comment + after the #endif */ Index: clang/test/Preprocessor/multiple-inclusion-opt.cpp =================================================================== --- /dev/null +++ clang/test/Preprocessor/multiple-inclusion-opt.cpp @@ -0,0 +1,7 @@ +// RUN: %clang_cc1 -E -P -H %s 2>&1 | grep "multiple-inclusion-opt.h" | count 1 + +#include "multiple-inclusion-opt.h" +#include "multiple-inclusion-opt.h" +#include "multiple-inclusion-opt.h" +#include "multiple-inclusion-opt.h" +#include "multiple-inclusion-opt.h"