1e8d8bef9SDimitry Andric //===--- MacroExpander.h - Format C++ code ----------------------*- C++ -*-===// 2e8d8bef9SDimitry Andric // 3*349cc55cSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*349cc55cSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 5*349cc55cSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6e8d8bef9SDimitry Andric // 7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 8e8d8bef9SDimitry Andric /// 9e8d8bef9SDimitry Andric /// \file 10e8d8bef9SDimitry Andric /// This file contains the main building blocks of macro support in 11e8d8bef9SDimitry Andric /// clang-format. 12e8d8bef9SDimitry Andric /// 13e8d8bef9SDimitry Andric /// In order to not violate the requirement that clang-format can format files 14e8d8bef9SDimitry Andric /// in isolation, clang-format's macro support uses expansions users provide 15e8d8bef9SDimitry Andric /// as part of clang-format's style configuration. 16e8d8bef9SDimitry Andric /// 17e8d8bef9SDimitry Andric /// Macro definitions are of the form "MACRO(p1, p2)=p1 + p2", but only support 18e8d8bef9SDimitry Andric /// one level of expansion (\see MacroExpander for a full description of what 19e8d8bef9SDimitry Andric /// is supported). 20e8d8bef9SDimitry Andric /// 21e8d8bef9SDimitry Andric /// As part of parsing, clang-format uses the MacroExpander to expand the 22e8d8bef9SDimitry Andric /// spelled token streams into expanded token streams when it encounters a 23e8d8bef9SDimitry Andric /// macro call. The UnwrappedLineParser continues to parse UnwrappedLines 24e8d8bef9SDimitry Andric /// from the expanded token stream. 25e8d8bef9SDimitry Andric /// After the expanded unwrapped lines are parsed, the MacroUnexpander matches 26e8d8bef9SDimitry Andric /// the spelled token stream into unwrapped lines that best resemble the 27e8d8bef9SDimitry Andric /// structure of the expanded unwrapped lines. 28e8d8bef9SDimitry Andric /// 29e8d8bef9SDimitry Andric /// When formatting, clang-format formats the expanded unwrapped lines first, 30e8d8bef9SDimitry Andric /// determining the token types. Next, it formats the spelled unwrapped lines, 31e8d8bef9SDimitry Andric /// keeping the token types fixed, while allowing other formatting decisions 32e8d8bef9SDimitry Andric /// to change. 33e8d8bef9SDimitry Andric /// 34e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===// 35e8d8bef9SDimitry Andric 36e8d8bef9SDimitry Andric #ifndef CLANG_LIB_FORMAT_MACROS_H 37e8d8bef9SDimitry Andric #define CLANG_LIB_FORMAT_MACROS_H 38e8d8bef9SDimitry Andric 39e8d8bef9SDimitry Andric #include <string> 40e8d8bef9SDimitry Andric #include <unordered_map> 41e8d8bef9SDimitry Andric #include <vector> 42e8d8bef9SDimitry Andric 43e8d8bef9SDimitry Andric #include "Encoding.h" 44e8d8bef9SDimitry Andric #include "FormatToken.h" 45e8d8bef9SDimitry Andric #include "llvm/ADT/ArrayRef.h" 46e8d8bef9SDimitry Andric #include "llvm/ADT/SmallVector.h" 47e8d8bef9SDimitry Andric #include "llvm/ADT/StringRef.h" 48e8d8bef9SDimitry Andric 49e8d8bef9SDimitry Andric namespace llvm { 50e8d8bef9SDimitry Andric class MemoryBuffer; 51e8d8bef9SDimitry Andric } // namespace llvm 52e8d8bef9SDimitry Andric 53e8d8bef9SDimitry Andric namespace clang { 54e8d8bef9SDimitry Andric class IdentifierTable; 55e8d8bef9SDimitry Andric class SourceManager; 56e8d8bef9SDimitry Andric 57e8d8bef9SDimitry Andric namespace format { 58e8d8bef9SDimitry Andric struct FormatStyle; 59e8d8bef9SDimitry Andric 60e8d8bef9SDimitry Andric /// Takes a set of macro definitions as strings and allows expanding calls to 61e8d8bef9SDimitry Andric /// those macros. 62e8d8bef9SDimitry Andric /// 63e8d8bef9SDimitry Andric /// For example: 64e8d8bef9SDimitry Andric /// Definition: A(x, y)=x + y 65e8d8bef9SDimitry Andric /// Call : A(int a = 1, 2) 66e8d8bef9SDimitry Andric /// Expansion : int a = 1 + 2 67e8d8bef9SDimitry Andric /// 68e8d8bef9SDimitry Andric /// Expansion does not check arity of the definition. 69e8d8bef9SDimitry Andric /// If fewer arguments than expected are provided, the remaining parameters 70e8d8bef9SDimitry Andric /// are considered empty: 71e8d8bef9SDimitry Andric /// Call : A(a) 72e8d8bef9SDimitry Andric /// Expansion: a + 73e8d8bef9SDimitry Andric /// If more arguments than expected are provided, they will be discarded. 74e8d8bef9SDimitry Andric /// 75e8d8bef9SDimitry Andric /// The expander does not support: 76e8d8bef9SDimitry Andric /// - recursive expansion 77e8d8bef9SDimitry Andric /// - stringification 78e8d8bef9SDimitry Andric /// - concatenation 79e8d8bef9SDimitry Andric /// - variadic macros 80e8d8bef9SDimitry Andric /// 81e8d8bef9SDimitry Andric /// Furthermore, only a single expansion of each macro argument is supported, 82e8d8bef9SDimitry Andric /// so that we cannot get conflicting formatting decisions from different 83e8d8bef9SDimitry Andric /// expansions. 84e8d8bef9SDimitry Andric /// Definition: A(x)=x+x 85e8d8bef9SDimitry Andric /// Call : A(id) 86e8d8bef9SDimitry Andric /// Expansion : id+x 87e8d8bef9SDimitry Andric /// 88e8d8bef9SDimitry Andric class MacroExpander { 89e8d8bef9SDimitry Andric public: 90e8d8bef9SDimitry Andric using ArgsList = llvm::ArrayRef<llvm::SmallVector<FormatToken *, 8>>; 91e8d8bef9SDimitry Andric 92e8d8bef9SDimitry Andric /// Construct a macro expander from a set of macro definitions. 93e8d8bef9SDimitry Andric /// Macro definitions must be encoded as UTF-8. 94e8d8bef9SDimitry Andric /// 95e8d8bef9SDimitry Andric /// Each entry in \p Macros must conform to the following simple 96e8d8bef9SDimitry Andric /// macro-definition language: 97e8d8bef9SDimitry Andric /// <definition> ::= <id> <expansion> | <id> "(" <params> ")" <expansion> 98e8d8bef9SDimitry Andric /// <params> ::= <id-list> | "" 99e8d8bef9SDimitry Andric /// <id-list> ::= <id> | <id> "," <params> 100e8d8bef9SDimitry Andric /// <expansion> ::= "=" <tail> | <eof> 101e8d8bef9SDimitry Andric /// <tail> ::= <tok> <tail> | <eof> 102e8d8bef9SDimitry Andric /// 103e8d8bef9SDimitry Andric /// Macros that cannot be parsed will be silently discarded. 104e8d8bef9SDimitry Andric /// 105e8d8bef9SDimitry Andric MacroExpander(const std::vector<std::string> &Macros, 106e8d8bef9SDimitry Andric clang::SourceManager &SourceMgr, const FormatStyle &Style, 107e8d8bef9SDimitry Andric llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator, 108e8d8bef9SDimitry Andric IdentifierTable &IdentTable); 109e8d8bef9SDimitry Andric ~MacroExpander(); 110e8d8bef9SDimitry Andric 111e8d8bef9SDimitry Andric /// Returns whether a macro \p Name is defined. 112e8d8bef9SDimitry Andric bool defined(llvm::StringRef Name) const; 113e8d8bef9SDimitry Andric 114e8d8bef9SDimitry Andric /// Returns whether the macro has no arguments and should not consume 115e8d8bef9SDimitry Andric /// subsequent parentheses. 116e8d8bef9SDimitry Andric bool objectLike(llvm::StringRef Name) const; 117e8d8bef9SDimitry Andric 118e8d8bef9SDimitry Andric /// Returns the expanded stream of format tokens for \p ID, where 119e8d8bef9SDimitry Andric /// each element in \p Args is a positional argument to the macro call. 120e8d8bef9SDimitry Andric llvm::SmallVector<FormatToken *, 8> expand(FormatToken *ID, 121e8d8bef9SDimitry Andric ArgsList Args) const; 122e8d8bef9SDimitry Andric 123e8d8bef9SDimitry Andric private: 124e8d8bef9SDimitry Andric struct Definition; 125e8d8bef9SDimitry Andric class DefinitionParser; 126e8d8bef9SDimitry Andric 127e8d8bef9SDimitry Andric void parseDefinition(const std::string &Macro); 128e8d8bef9SDimitry Andric 129e8d8bef9SDimitry Andric clang::SourceManager &SourceMgr; 130e8d8bef9SDimitry Andric const FormatStyle &Style; 131e8d8bef9SDimitry Andric llvm::SpecificBumpPtrAllocator<FormatToken> &Allocator; 132e8d8bef9SDimitry Andric IdentifierTable &IdentTable; 133e8d8bef9SDimitry Andric std::vector<std::unique_ptr<llvm::MemoryBuffer>> Buffers; 134e8d8bef9SDimitry Andric llvm::StringMap<Definition> Definitions; 135e8d8bef9SDimitry Andric }; 136e8d8bef9SDimitry Andric 137e8d8bef9SDimitry Andric } // namespace format 138e8d8bef9SDimitry Andric } // namespace clang 139e8d8bef9SDimitry Andric 140e8d8bef9SDimitry Andric #endif 141