xref: /freebsd/contrib/llvm-project/clang/lib/Format/Macros.h (revision 0d8fe2373503aeac48492f28073049a8bfa4feb5)
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 
50 namespace llvm {
51 class MemoryBuffer;
52 } // namespace llvm
53 
54 namespace clang {
55 class IdentifierTable;
56 class SourceManager;
57 
58 namespace format {
59 struct 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 ///
89 class MacroExpander {
90 public:
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 
124 private:
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