mirror of
https://github.com/intel/llvm.git
synced 2026-01-27 06:06:34 +08:00
No longer crashing with an assert when __has_include or __has_include_next is used outside of a preprocessor directive. This fixes PR14837.
llvm-svn: 172639
This commit is contained in:
@@ -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">;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 '('}}
|
||||
|
||||
Reference in New Issue
Block a user