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