//===--- PPExpressions.cpp - Preprocessor Expression Evaluation -----------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file implements the Preprocessor::EvaluateDirectiveExpression method, // which parses and evaluates integer constant expressions for #if directives. // //===----------------------------------------------------------------------===// // // FIXME: implement testing for #assert's. // //===----------------------------------------------------------------------===// #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/TokenKinds.h" #include "clang/Lex/CodeCompletionHandler.h" #include "clang/Lex/LexDiagnostic.h" #include "clang/Lex/LiteralSupport.h" #include "clang/Lex/MacroInfo.h" #include "clang/Lex/PPCallbacks.h" #include "clang/Lex/Preprocessor.h" #include "clang/Lex/Token.h" #include "llvm/ADT/APSInt.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/SaveAndRestore.h" #include <cassert> usingnamespaceclang; namespace { /// PPValue - Represents the value of a subexpression of a preprocessor /// conditional and the source range covered by it. class PPValue { … }; } // end anonymous namespace static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec, Token &PeekTok, bool ValueLive, bool &IncludedUndefinedIds, Preprocessor &PP); /// DefinedTracker - This struct is used while parsing expressions to keep track /// of whether !defined(X) has been seen. /// /// With this simple scheme, we handle the basic forms: /// !defined(X) and !defined X /// but we also trivially handle (silly) stuff like: /// !!!defined(X) and +!defined(X) and !+!+!defined(X) and !(defined(X)). struct DefinedTracker { … }; /// EvaluateDefined - Process a 'defined(sym)' expression. static bool EvaluateDefined(PPValue &Result, Token &PeekTok, DefinedTracker &DT, bool ValueLive, Preprocessor &PP) { … } /// EvaluateValue - Evaluate the token PeekTok (and any others needed) and /// return the computed value in Result. Return true if there was an error /// parsing. This function also returns information about the form of the /// expression in DT. See above for information on what DT means. /// /// If ValueLive is false, then this value is being evaluated in a context where /// the result is not used. As such, avoid diagnostics that relate to /// evaluation. static bool EvaluateValue(PPValue &Result, Token &PeekTok, DefinedTracker &DT, bool ValueLive, Preprocessor &PP) { … } /// getPrecedence - Return the precedence of the specified binary operator /// token. This returns: /// ~0 - Invalid token. /// 14 -> 3 - various operators. /// 0 - 'eod' or ')' static unsigned getPrecedence(tok::TokenKind Kind) { … } static void diagnoseUnexpectedOperator(Preprocessor &PP, PPValue &LHS, Token &Tok) { … } /// EvaluateDirectiveSubExpr - Evaluate the subexpression whose first token is /// PeekTok, and whose precedence is PeekPrec. This returns the result in LHS. /// /// If ValueLive is false, then this value is being evaluated in a context where /// the result is not used. As such, avoid diagnostics that relate to /// evaluation, such as division by zero warnings. static bool EvaluateDirectiveSubExpr(PPValue &LHS, unsigned MinPrec, Token &PeekTok, bool ValueLive, bool &IncludedUndefinedIds, Preprocessor &PP) { … } /// EvaluateDirectiveExpression - Evaluate an integer constant expression that /// may occur after a #if or #elif directive. If the expression is equivalent /// to "!defined(X)" return X in IfNDefMacro. Preprocessor::DirectiveEvalResult Preprocessor::EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro, Token &Tok, bool &EvaluatedDefined, bool CheckForEoD) { … } Preprocessor::DirectiveEvalResult Preprocessor::EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro, bool CheckForEoD) { … }