File: | tools/clang/lib/Format/FormatToken.cpp |
Location: | line 153, column 12 |
Description: | Access to field 'HasUnescapedNewline' results in a dereference of a null pointer (loaded from variable 'ItemBegin') |
1 | //===--- FormatToken.cpp - Format C++ code --------------------------------===// | |||
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 | /// \brief This file implements specific functions of \c FormatTokens and their | |||
12 | /// roles. | |||
13 | /// | |||
14 | //===----------------------------------------------------------------------===// | |||
15 | ||||
16 | #include "FormatToken.h" | |||
17 | #include "ContinuationIndenter.h" | |||
18 | #include "clang/Format/Format.h" | |||
19 | #include "llvm/ADT/SmallVector.h" | |||
20 | #include "llvm/Support/Debug.h" | |||
21 | ||||
22 | namespace clang { | |||
23 | namespace format { | |||
24 | ||||
25 | // FIXME: This is copy&pasted from Sema. Put it in a common place and remove | |||
26 | // duplication. | |||
27 | bool FormatToken::isSimpleTypeSpecifier() const { | |||
28 | switch (Tok.getKind()) { | |||
29 | case tok::kw_short: | |||
30 | case tok::kw_long: | |||
31 | case tok::kw___int64: | |||
32 | case tok::kw___int128: | |||
33 | case tok::kw_signed: | |||
34 | case tok::kw_unsigned: | |||
35 | case tok::kw_void: | |||
36 | case tok::kw_char: | |||
37 | case tok::kw_int: | |||
38 | case tok::kw_half: | |||
39 | case tok::kw_float: | |||
40 | case tok::kw_double: | |||
41 | case tok::kw_wchar_t: | |||
42 | case tok::kw_bool: | |||
43 | case tok::kw___underlying_type: | |||
44 | case tok::annot_typename: | |||
45 | case tok::kw_char16_t: | |||
46 | case tok::kw_char32_t: | |||
47 | case tok::kw_typeof: | |||
48 | case tok::kw_decltype: | |||
49 | return true; | |||
50 | default: | |||
51 | return false; | |||
52 | } | |||
53 | } | |||
54 | ||||
55 | TokenRole::~TokenRole() {} | |||
56 | ||||
57 | void TokenRole::precomputeFormattingInfos(const FormatToken *Token) {} | |||
58 | ||||
59 | unsigned CommaSeparatedList::formatAfterToken(LineState &State, | |||
60 | ContinuationIndenter *Indenter, | |||
61 | bool DryRun) { | |||
62 | if (!State.NextToken->Previous || !State.NextToken->Previous->Previous) | |||
63 | return 0; | |||
64 | ||||
65 | // Ensure that we start on the opening brace. | |||
66 | const FormatToken *LBrace = State.NextToken->Previous->Previous; | |||
67 | if (LBrace->isNot(tok::l_brace) || LBrace->BlockKind == BK_Block || | |||
68 | LBrace->Type == TT_DictLiteral || | |||
69 | LBrace->Next->Type == TT_DesignatedInitializerPeriod) | |||
70 | return 0; | |||
71 | ||||
72 | // Calculate the number of code points we have to format this list. As the | |||
73 | // first token is already placed, we have to subtract it. | |||
74 | unsigned RemainingCodePoints = | |||
75 | Style.ColumnLimit - State.Column + State.NextToken->Previous->ColumnWidth; | |||
76 | ||||
77 | // Find the best ColumnFormat, i.e. the best number of columns to use. | |||
78 | const ColumnFormat *Format = getColumnFormat(RemainingCodePoints); | |||
79 | // If no ColumnFormat can be used, the braced list would generally be | |||
80 | // bin-packed. Add a severe penalty to this so that column layouts are | |||
81 | // preferred if possible. | |||
82 | if (!Format) | |||
83 | return 10000; | |||
84 | ||||
85 | // Format the entire list. | |||
86 | unsigned Penalty = 0; | |||
87 | unsigned Column = 0; | |||
88 | unsigned Item = 0; | |||
89 | while (State.NextToken != LBrace->MatchingParen) { | |||
90 | bool NewLine = false; | |||
91 | unsigned ExtraSpaces = 0; | |||
92 | ||||
93 | // If the previous token was one of our commas, we are now on the next item. | |||
94 | if (Item < Commas.size() && State.NextToken->Previous == Commas[Item]) { | |||
95 | if (!State.NextToken->isTrailingComment()) { | |||
96 | ExtraSpaces += Format->ColumnSizes[Column] - ItemLengths[Item]; | |||
97 | ++Column; | |||
98 | } | |||
99 | ++Item; | |||
100 | } | |||
101 | ||||
102 | if (Column == Format->Columns || State.NextToken->MustBreakBefore) { | |||
103 | Column = 0; | |||
104 | NewLine = true; | |||
105 | } | |||
106 | ||||
107 | // Place token using the continuation indenter and store the penalty. | |||
108 | Penalty += Indenter->addTokenToState(State, NewLine, DryRun, ExtraSpaces); | |||
109 | } | |||
110 | return Penalty; | |||
111 | } | |||
112 | ||||
113 | unsigned CommaSeparatedList::formatFromToken(LineState &State, | |||
114 | ContinuationIndenter *Indenter, | |||
115 | bool DryRun) { | |||
116 | if (HasNestedBracedList) | |||
117 | State.Stack.back().AvoidBinPacking = true; | |||
118 | return 0; | |||
119 | } | |||
120 | ||||
121 | // Returns the lengths in code points between Begin and End (both included), | |||
122 | // assuming that the entire sequence is put on a single line. | |||
123 | static unsigned CodePointsBetween(const FormatToken *Begin, | |||
124 | const FormatToken *End) { | |||
125 | assert(End->TotalLength >= Begin->TotalLength)((End->TotalLength >= Begin->TotalLength) ? static_cast <void> (0) : __assert_fail ("End->TotalLength >= Begin->TotalLength" , "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn222849/tools/clang/lib/Format/FormatToken.cpp" , 125, __PRETTY_FUNCTION__)); | |||
126 | return End->TotalLength - Begin->TotalLength + Begin->ColumnWidth; | |||
127 | } | |||
128 | ||||
129 | void CommaSeparatedList::precomputeFormattingInfos(const FormatToken *Token) { | |||
130 | // FIXME: At some point we might want to do this for other lists, too. | |||
131 | if (!Token->MatchingParen || Token->isNot(tok::l_brace)) | |||
| ||||
132 | return; | |||
133 | ||||
134 | // In C++11 braced list style, we should not format in columns unless they | |||
135 | // have many items (20 or more) or we allow bin-packing of function | |||
136 | // parameters. | |||
137 | if (Style.Cpp11BracedListStyle && !Style.BinPackParameters && | |||
138 | Commas.size() < 19) | |||
139 | return; | |||
140 | ||||
141 | FormatToken *ItemBegin = Token->Next; | |||
142 | SmallVector<bool, 8> MustBreakBeforeItem; | |||
143 | ||||
144 | // The lengths of an item if it is put at the end of the line. This includes | |||
145 | // trailing comments which are otherwise ignored for column alignment. | |||
146 | SmallVector<unsigned, 8> EndOfLineItemLength; | |||
147 | ||||
148 | unsigned MinItemLength = Style.ColumnLimit; | |||
149 | unsigned MaxItemLength = 0; | |||
150 | ||||
151 | for (unsigned i = 0, e = Commas.size() + 1; i != e; ++i) { | |||
152 | // Skip comments on their own line. | |||
153 | while (ItemBegin->HasUnescapedNewline && ItemBegin->isTrailingComment()) | |||
| ||||
154 | ItemBegin = ItemBegin->Next; | |||
155 | ||||
156 | MustBreakBeforeItem.push_back(ItemBegin->MustBreakBefore); | |||
157 | if (ItemBegin->is(tok::l_brace)) | |||
158 | HasNestedBracedList = true; | |||
159 | const FormatToken *ItemEnd = nullptr; | |||
160 | if (i == Commas.size()) { | |||
161 | ItemEnd = Token->MatchingParen; | |||
162 | const FormatToken *NonCommentEnd = ItemEnd->getPreviousNonComment(); | |||
163 | ItemLengths.push_back(CodePointsBetween(ItemBegin, NonCommentEnd)); | |||
164 | if (Style.Cpp11BracedListStyle) { | |||
165 | // In Cpp11 braced list style, the } and possibly other subsequent | |||
166 | // tokens will need to stay on a line with the last element. | |||
167 | while (ItemEnd->Next && !ItemEnd->Next->CanBreakBefore) | |||
168 | ItemEnd = ItemEnd->Next; | |||
169 | } else { | |||
170 | // In other braced lists styles, the "}" can be wrapped to the new line. | |||
171 | ItemEnd = Token->MatchingParen->Previous; | |||
172 | } | |||
173 | } else { | |||
174 | ItemEnd = Commas[i]; | |||
175 | // The comma is counted as part of the item when calculating the length. | |||
176 | ItemLengths.push_back(CodePointsBetween(ItemBegin, ItemEnd)); | |||
177 | MinItemLength = std::min(MinItemLength, ItemLengths.back()); | |||
178 | MaxItemLength = std::max(MaxItemLength, ItemLengths.back()); | |||
179 | ||||
180 | // Consume trailing comments so the are included in EndOfLineItemLength. | |||
181 | if (ItemEnd->Next && !ItemEnd->Next->HasUnescapedNewline && | |||
182 | ItemEnd->Next->isTrailingComment()) | |||
183 | ItemEnd = ItemEnd->Next; | |||
184 | } | |||
185 | EndOfLineItemLength.push_back(CodePointsBetween(ItemBegin, ItemEnd)); | |||
186 | // If there is a trailing comma in the list, the next item will start at the | |||
187 | // closing brace. Don't create an extra item for this. | |||
188 | if (ItemEnd->getNextNonComment() == Token->MatchingParen) | |||
189 | break; | |||
190 | ItemBegin = ItemEnd->Next; | |||
191 | } | |||
192 | ||||
193 | // If this doesn't have a nested list, we require at least 6 elements in order | |||
194 | // create a column layout. If it has a nested list, column layout ensures one | |||
195 | // list element per line. If the difference between the shortest and longest | |||
196 | // element is too large, column layout would create too much whitespace. | |||
197 | if (HasNestedBracedList || Commas.size() < 5 || Token->NestingLevel != 0 || | |||
198 | MaxItemLength - MinItemLength > 10) | |||
199 | return; | |||
200 | ||||
201 | // We can never place more than ColumnLimit / 3 items in a row (because of the | |||
202 | // spaces and the comma). | |||
203 | for (unsigned Columns = 1; Columns <= Style.ColumnLimit / 3; ++Columns) { | |||
204 | ColumnFormat Format; | |||
205 | Format.Columns = Columns; | |||
206 | Format.ColumnSizes.resize(Columns); | |||
207 | Format.LineCount = 1; | |||
208 | bool HasRowWithSufficientColumns = false; | |||
209 | unsigned Column = 0; | |||
210 | for (unsigned i = 0, e = ItemLengths.size(); i != e; ++i) { | |||
211 | assert(i < MustBreakBeforeItem.size())((i < MustBreakBeforeItem.size()) ? static_cast<void> (0) : __assert_fail ("i < MustBreakBeforeItem.size()", "/tmp/buildd/llvm-toolchain-snapshot-3.6~svn222849/tools/clang/lib/Format/FormatToken.cpp" , 211, __PRETTY_FUNCTION__)); | |||
212 | if (MustBreakBeforeItem[i] || Column == Columns) { | |||
213 | ++Format.LineCount; | |||
214 | Column = 0; | |||
215 | } | |||
216 | if (Column == Columns - 1) | |||
217 | HasRowWithSufficientColumns = true; | |||
218 | unsigned length = | |||
219 | (Column == Columns - 1) ? EndOfLineItemLength[i] : ItemLengths[i]; | |||
220 | Format.ColumnSizes[Column] = std::max(Format.ColumnSizes[Column], length); | |||
221 | ++Column; | |||
222 | } | |||
223 | // If all rows are terminated early (e.g. by trailing comments), we don't | |||
224 | // need to look further. | |||
225 | if (!HasRowWithSufficientColumns) | |||
226 | break; | |||
227 | Format.TotalWidth = Columns - 1; // Width of the N-1 spaces. | |||
228 | for (unsigned i = 0; i < Columns; ++i) { | |||
229 | Format.TotalWidth += Format.ColumnSizes[i]; | |||
230 | } | |||
231 | ||||
232 | // Ignore layouts that are bound to violate the column limit. | |||
233 | if (Format.TotalWidth > Style.ColumnLimit) | |||
234 | continue; | |||
235 | ||||
236 | Formats.push_back(Format); | |||
237 | } | |||
238 | } | |||
239 | ||||
240 | const CommaSeparatedList::ColumnFormat * | |||
241 | CommaSeparatedList::getColumnFormat(unsigned RemainingCharacters) const { | |||
242 | const ColumnFormat *BestFormat = nullptr; | |||
243 | for (SmallVector<ColumnFormat, 4>::const_reverse_iterator | |||
244 | I = Formats.rbegin(), | |||
245 | E = Formats.rend(); | |||
246 | I != E; ++I) { | |||
247 | if (I->TotalWidth <= RemainingCharacters) { | |||
248 | if (BestFormat && I->LineCount > BestFormat->LineCount) | |||
249 | break; | |||
250 | BestFormat = &*I; | |||
251 | } | |||
252 | } | |||
253 | return BestFormat; | |||
254 | } | |||
255 | ||||
256 | } // namespace format | |||
257 | } // namespace clang |