//===- MacroExpansionContext.h - Macro expansion information ----*- C++ -*-===// // // 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 // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_ANALYSIS_MACROEXPANSIONCONTEXT_H #define LLVM_CLANG_ANALYSIS_MACROEXPANSIONCONTEXT_H #include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceLocation.h" #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include <optional> namespace clang { namespace detail { class MacroExpansionRangeRecorder; } // namespace detail /// MacroExpansionContext tracks the macro expansions processed by the /// Preprocessor. It means that it can track source locations from a single /// translation unit. For every macro expansion it can tell you what text will /// be substituted. /// /// It was designed to deal with: /// - regular macros /// - macro functions /// - variadic macros /// - transitive macro expansions /// - macro redefinition /// - unbalanced parenthesis /// /// \code{.c} /// void bar(); /// #define retArg(x) x /// #define retArgUnclosed retArg(bar() /// #define BB CC /// #define applyInt BB(int) /// #define CC(x) retArgUnclosed /// /// void unbalancedMacros() { /// applyInt ); /// //^~~~~~~~~~^ is the substituted range /// // Substituted text is "applyInt )" /// // Expanded text is "bar()" /// } /// /// #define expandArgUnclosedCommaExpr(x) (x, bar(), 1 /// #define f expandArgUnclosedCommaExpr /// /// void unbalancedMacros2() { /// int x = f(f(1)) )); // Look at the parenthesis! /// // ^~~~~~^ is the substituted range /// // Substituted text is "f(f(1))" /// // Expanded text is "((1,bar(),1,bar(),1" /// } /// \endcode /// \remark Currently we don't respect the whitespaces between expanded tokens, /// so the output for this example might differ from the -E compiler /// invocation. /// \remark All whitespaces are consumed while constructing the expansion. /// After all identifier a single space inserted to produce a valid C /// code even if identifier follows an other identifiers such as /// variable declarations. /// \remark MacroExpansionContext object must outlive the Preprocessor /// parameter. class MacroExpansionContext { … }; } // end namespace clang #endif // LLVM_CLANG_ANALYSIS_MACROEXPANSIONCONTEXT_H