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