diff options
author | Aaron Ballman <aaron@aaronballman.com> | 2013-01-16 19:32:21 +0000 |
---|---|---|
committer | Aaron Ballman <aaron@aaronballman.com> | 2013-01-16 19:32:21 +0000 |
commit | 31672b1745195d709b641f1c0f44e203742fa73b (patch) | |
tree | 12fbebdd3494a696805c698f0b60668fd5038e2c | |
parent | f0e00046711280d494f3ef2d85ae67a442b97406 (diff) |
No longer crashing with an assert when __has_include or __has_include_next is used outside of a preprocessor directive. This fixes PR14837.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@172639 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/Basic/DiagnosticLexKinds.td | 2 | ||||
-rw-r--r-- | include/clang/Lex/Preprocessor.h | 8 | ||||
-rw-r--r-- | lib/Lex/PPDirectives.cpp | 3 | ||||
-rw-r--r-- | lib/Lex/PPMacroExpansion.cpp | 6 | ||||
-rw-r--r-- | lib/Lex/Preprocessor.cpp | 3 | ||||
-rw-r--r-- | test/Preprocessor/has_include.c | 24 |
6 files changed, 44 insertions, 2 deletions
diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index b9dbaf2e9e..59c6ce77fd 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -285,6 +285,8 @@ def warn_cxx98_compat_empty_fnmacro_arg : Warning< def note_macro_here : Note<"macro %0 defined here">; def err_pp_invalid_directive : Error<"invalid preprocessing directive">; +def err_pp_directive_required : Error< + "%0 must be used within a preprocessing directive">; def err_pp_file_not_found : Error<"'%0' file not found">, DefaultFatal; def err_pp_file_not_found_not_fatal : Error< "'%0' file not found with <angled> include; use \"quotes\" instead">; diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index e7bd0dfeec..faaec3517d 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -160,6 +160,9 @@ class Preprocessor : public RefCountedBase<Preprocessor> { /// \brief True if pragmas are enabled. bool PragmasEnabled : 1; + /// \brief True if we are currently preprocessing a #if or #elif directive + bool ParsingIfOrElifDirective; + /// \brief True if we are pre-expanding macro arguments. bool InMacroArgPreExpansion; @@ -446,6 +449,11 @@ public: /// \brief Retrieve the module loader associated with this preprocessor. ModuleLoader &getModuleLoader() const { return TheModuleLoader; } + /// \brief True if we are currently preprocessing a #if or #elif directive + bool isParsingIfOrElifDirective() const { + return ParsingIfOrElifDirective; + } + /// SetCommentRetentionState - Control whether or not the preprocessor retains /// comments in output. void SetCommentRetentionState(bool KeepComments, bool KeepMacroComments) { diff --git a/lib/Lex/PPDirectives.cpp b/lib/Lex/PPDirectives.cpp index bdca03637d..7e46a9cc28 100644 --- a/lib/Lex/PPDirectives.cpp +++ b/lib/Lex/PPDirectives.cpp @@ -24,6 +24,7 @@ #include "clang/Lex/Pragma.h" #include "llvm/ADT/APInt.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/SaveAndRestore.h" using namespace clang; //===----------------------------------------------------------------------===// @@ -2071,6 +2072,7 @@ void Preprocessor::HandleIfdefDirective(Token &Result, bool isIfndef, /// void Preprocessor::HandleIfDirective(Token &IfToken, bool ReadAnyTokensBeforeDirective) { + SaveAndRestore<bool> PPDir(ParsingIfOrElifDirective, true); ++NumIf; // Parse and evaluate the conditional expression. @@ -2162,6 +2164,7 @@ void Preprocessor::HandleElseDirective(Token &Result) { /// HandleElifDirective - Implements the \#elif directive. /// void Preprocessor::HandleElifDirective(Token &ElifToken) { + SaveAndRestore<bool> PPDir(ParsingIfOrElifDirective, true); ++NumElse; // #elif directive in a non-skipping conditional... start skipping. diff --git a/lib/Lex/PPMacroExpansion.cpp b/lib/Lex/PPMacroExpansion.cpp index 7b8871576a..20e5dd986f 100644 --- a/lib/Lex/PPMacroExpansion.cpp +++ b/lib/Lex/PPMacroExpansion.cpp @@ -964,6 +964,12 @@ static bool EvaluateHasIncludeCommon(Token &Tok, // that location. If not, use the end of this location instead. SourceLocation LParenLoc = Tok.getLocation(); + // These expressions are only allowed within a preprocessor directive. + if (!PP.isParsingIfOrElifDirective()) { + PP.Diag(LParenLoc, diag::err_pp_directive_required) << II->getName(); + return false; + } + // Get '('. PP.LexNonComment(Tok); diff --git a/lib/Lex/Preprocessor.cpp b/lib/Lex/Preprocessor.cpp index 9ce4874f63..ccb2df0602 100644 --- a/lib/Lex/Preprocessor.cpp +++ b/lib/Lex/Preprocessor.cpp @@ -69,7 +69,8 @@ Preprocessor::Preprocessor(IntrusiveRefCntPtr<PreprocessorOptions> PPOpts, CodeCompletionFile(0), CodeCompletionOffset(0), CodeCompletionReached(0), SkipMainFilePreamble(0, true), CurPPLexer(0), CurDirLookup(0), CurLexerKind(CLK_Lexer), Callbacks(0), Listener(0), - MacroArgCache(0), Record(0), MIChainHead(0), MICache(0) + MacroArgCache(0), Record(0), MIChainHead(0), MICache(0), + ParsingIfOrElifDirective(false) { OwnsHeaderSearch = OwnsHeaders; diff --git a/test/Preprocessor/has_include.c b/test/Preprocessor/has_include.c index 985501a215..4e71a36974 100644 --- a/test/Preprocessor/has_include.c +++ b/test/Preprocessor/has_include.c @@ -91,6 +91,28 @@ #error "__has_include with macro failed (2)." #endif +// Try as non-preprocessor directives +void foo( void ) { + __has_include_next("stdint.h") // expected-warning {{#include_next in primary source file}} expected-error {{__has_include_next must be used within a preprocessing directive}} + __has_include("stdint.h") // expected-error {{__has_include must be used within a preprocessing directive}} +} + +MACRO1 // expected-error {{__has_include must be used within a preprocessing directive}} + +#if 1 +MACRO1 // expected-error {{__has_include must be used within a preprocessing directive}} +#endif + +#if 0 +#elif 1 +MACRO1 // expected-error {{__has_include must be used within a preprocessing directive}} +#endif + +#if 0 +MACRO1 // This should be fine because it is never actually reached +#endif + + // Try badly formed expressions. // FIXME: We can recover better in almost all of these cases. (PR13335) @@ -126,7 +148,7 @@ #if __has_include(stdint.h>) #endif -// expected-error@+1 {{missing '(' after '__has_include'}} +// expected-error@+1 {{__has_include must be used within a preprocessing directive}} __has_include // expected-error@+1 {{missing ')' after '__has_include'}} // expected-error@+1 {{expected value in expression}} // expected-note@+1 {{to match this '('}} |