/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/Sema/SemaAttr.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- SemaAttr.cpp - Semantic Analysis for Attributes ------------------===// |
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 | | // This file implements semantic analysis for non-trivial attributes and |
10 | | // pragmas. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "clang/AST/ASTConsumer.h" |
15 | | #include "clang/AST/Attr.h" |
16 | | #include "clang/AST/Expr.h" |
17 | | #include "clang/Basic/TargetInfo.h" |
18 | | #include "clang/Lex/Preprocessor.h" |
19 | | #include "clang/Sema/Lookup.h" |
20 | | #include "clang/Sema/SemaInternal.h" |
21 | | using namespace clang; |
22 | | |
23 | | //===----------------------------------------------------------------------===// |
24 | | // Pragma 'pack' and 'options align' |
25 | | //===----------------------------------------------------------------------===// |
26 | | |
27 | | Sema::PragmaStackSentinelRAII::PragmaStackSentinelRAII(Sema &S, |
28 | | StringRef SlotLabel, |
29 | | bool ShouldAct) |
30 | 3.86M | : S(S), SlotLabel(SlotLabel), ShouldAct(ShouldAct) { |
31 | 3.86M | if (ShouldAct) { |
32 | 876k | S.VtorDispStack.SentinelAction(PSK_Push, SlotLabel); |
33 | 876k | S.DataSegStack.SentinelAction(PSK_Push, SlotLabel); |
34 | 876k | S.BSSSegStack.SentinelAction(PSK_Push, SlotLabel); |
35 | 876k | S.ConstSegStack.SentinelAction(PSK_Push, SlotLabel); |
36 | 876k | S.CodeSegStack.SentinelAction(PSK_Push, SlotLabel); |
37 | 876k | } |
38 | 3.86M | } |
39 | | |
40 | 3.86M | Sema::PragmaStackSentinelRAII::~PragmaStackSentinelRAII() { |
41 | 3.86M | if (ShouldAct) { |
42 | 876k | S.VtorDispStack.SentinelAction(PSK_Pop, SlotLabel); |
43 | 876k | S.DataSegStack.SentinelAction(PSK_Pop, SlotLabel); |
44 | 876k | S.BSSSegStack.SentinelAction(PSK_Pop, SlotLabel); |
45 | 876k | S.ConstSegStack.SentinelAction(PSK_Pop, SlotLabel); |
46 | 876k | S.CodeSegStack.SentinelAction(PSK_Pop, SlotLabel); |
47 | 876k | } |
48 | 3.86M | } |
49 | | |
50 | 1.19M | void Sema::AddAlignmentAttributesForRecord(RecordDecl *RD) { |
51 | 1.19M | AlignPackInfo InfoVal = AlignPackStack.CurrentValue; |
52 | 1.19M | AlignPackInfo::Mode M = InfoVal.getAlignMode(); |
53 | 1.19M | bool IsPackSet = InfoVal.IsPackSet(); |
54 | 1.19M | bool IsXLPragma = getLangOpts().XLPragmaPack; |
55 | | |
56 | | // If we are not under mac68k/natural alignment mode and also there is no pack |
57 | | // value, we don't need any attributes. |
58 | 1.19M | if (!IsPackSet && M != AlignPackInfo::Mac68k954k && M != AlignPackInfo::Natural954k ) |
59 | 954k | return; |
60 | | |
61 | 239k | if (M == AlignPackInfo::Mac68k && (14 IsXLPragma14 || InfoVal.IsAlignAttr()14 )) { |
62 | 14 | RD->addAttr(AlignMac68kAttr::CreateImplicit(Context)); |
63 | 239k | } else if (IsPackSet) { |
64 | | // Check to see if we need a max field alignment attribute. |
65 | 239k | RD->addAttr(MaxFieldAlignmentAttr::CreateImplicit( |
66 | 239k | Context, InfoVal.getPackNumber() * 8)); |
67 | 239k | } |
68 | | |
69 | 239k | if (IsXLPragma && M == AlignPackInfo::Natural78 ) |
70 | 26 | RD->addAttr(AlignNaturalAttr::CreateImplicit(Context)); |
71 | | |
72 | 239k | if (AlignPackIncludeStack.empty()) |
73 | 470 | return; |
74 | | // The #pragma align/pack affected a record in an included file, so Clang |
75 | | // should warn when that pragma was written in a file that included the |
76 | | // included file. |
77 | 238k | for (auto &AlignPackedInclude : llvm::reverse(AlignPackIncludeStack))238k { |
78 | 238k | if (AlignPackedInclude.CurrentPragmaLocation != |
79 | 238k | AlignPackStack.CurrentPragmaLocation) |
80 | 238k | break; |
81 | 18 | if (AlignPackedInclude.HasNonDefaultValue) |
82 | 14 | AlignPackedInclude.ShouldWarnOnInclude = true; |
83 | 18 | } |
84 | 238k | } |
85 | | |
86 | 1.19M | void Sema::AddMsStructLayoutForRecord(RecordDecl *RD) { |
87 | 1.19M | if (MSStructPragmaOn) |
88 | 21 | RD->addAttr(MSStructAttr::CreateImplicit(Context)); |
89 | | |
90 | | // FIXME: We should merge AddAlignmentAttributesForRecord with |
91 | | // AddMsStructLayoutForRecord into AddPragmaAttributesForRecord, which takes |
92 | | // all active pragmas and applies them as attributes to class definitions. |
93 | 1.19M | if (VtorDispStack.CurrentValue != getLangOpts().getVtorDispMode()) |
94 | 29 | RD->addAttr(MSVtorDispAttr::CreateImplicit( |
95 | 29 | Context, unsigned(VtorDispStack.CurrentValue))); |
96 | 1.19M | } |
97 | | |
98 | | template <typename Attribute> |
99 | | static void addGslOwnerPointerAttributeIfNotExisting(ASTContext &Context, |
100 | 19.1k | CXXRecordDecl *Record) { |
101 | 19.1k | if (Record->hasAttr<OwnerAttr>() || Record->hasAttr<PointerAttr>()) |
102 | 6.48k | return; |
103 | | |
104 | 12.6k | for (Decl *Redecl : Record->redecls()) |
105 | 14.2k | Redecl->addAttr(Attribute::CreateImplicit(Context, /*DerefType=*/nullptr)); |
106 | 12.6k | } SemaAttr.cpp:void addGslOwnerPointerAttributeIfNotExisting<clang::PointerAttr>(clang::ASTContext&, clang::CXXRecordDecl*) Line | Count | Source | 100 | 10.9k | CXXRecordDecl *Record) { | 101 | 10.9k | if (Record->hasAttr<OwnerAttr>() || Record->hasAttr<PointerAttr>()) | 102 | 6.48k | return; | 103 | | | 104 | 4.48k | for (Decl *Redecl : Record->redecls()) | 105 | 6.11k | Redecl->addAttr(Attribute::CreateImplicit(Context, /*DerefType=*/nullptr)); | 106 | 4.48k | } |
SemaAttr.cpp:void addGslOwnerPointerAttributeIfNotExisting<clang::OwnerAttr>(clang::ASTContext&, clang::CXXRecordDecl*) Line | Count | Source | 100 | 8.14k | CXXRecordDecl *Record) { | 101 | 8.14k | if (Record->hasAttr<OwnerAttr>() || Record->hasAttr<PointerAttr>()) | 102 | 0 | return; | 103 | | | 104 | 8.14k | for (Decl *Redecl : Record->redecls()) | 105 | 8.14k | Redecl->addAttr(Attribute::CreateImplicit(Context, /*DerefType=*/nullptr)); | 106 | 8.14k | } |
|
107 | | |
108 | | void Sema::inferGslPointerAttribute(NamedDecl *ND, |
109 | 2.80M | CXXRecordDecl *UnderlyingRecord) { |
110 | 2.80M | if (!UnderlyingRecord) |
111 | 2.16M | return; |
112 | | |
113 | 642k | const auto *Parent = dyn_cast<CXXRecordDecl>(ND->getDeclContext()); |
114 | 642k | if (!Parent) |
115 | 409k | return; |
116 | | |
117 | 232k | static llvm::StringSet<> Containers{ |
118 | 232k | "array", |
119 | 232k | "basic_string", |
120 | 232k | "deque", |
121 | 232k | "forward_list", |
122 | 232k | "vector", |
123 | 232k | "list", |
124 | 232k | "map", |
125 | 232k | "multiset", |
126 | 232k | "multimap", |
127 | 232k | "priority_queue", |
128 | 232k | "queue", |
129 | 232k | "set", |
130 | 232k | "stack", |
131 | 232k | "unordered_set", |
132 | 232k | "unordered_map", |
133 | 232k | "unordered_multiset", |
134 | 232k | "unordered_multimap", |
135 | 232k | }; |
136 | | |
137 | 232k | static llvm::StringSet<> Iterators{"iterator", "const_iterator", |
138 | 232k | "reverse_iterator", |
139 | 232k | "const_reverse_iterator"}; |
140 | | |
141 | 232k | if (Parent->isInStdNamespace() && Iterators.count(ND->getName())209k && |
142 | 232k | Containers.count(Parent->getName())12.2k ) |
143 | 10.1k | addGslOwnerPointerAttributeIfNotExisting<PointerAttr>(Context, |
144 | 10.1k | UnderlyingRecord); |
145 | 232k | } |
146 | | |
147 | 2.52M | void Sema::inferGslPointerAttribute(TypedefNameDecl *TD) { |
148 | | |
149 | 2.52M | QualType Canonical = TD->getUnderlyingType().getCanonicalType(); |
150 | | |
151 | 2.52M | CXXRecordDecl *RD = Canonical->getAsCXXRecordDecl(); |
152 | 2.52M | if (!RD) { |
153 | 2.26M | if (auto *TST = |
154 | 2.26M | dyn_cast<TemplateSpecializationType>(Canonical.getTypePtr())) { |
155 | | |
156 | 102k | RD = dyn_cast_or_null<CXXRecordDecl>( |
157 | 102k | TST->getTemplateName().getAsTemplateDecl()->getTemplatedDecl()); |
158 | 102k | } |
159 | 2.26M | } |
160 | | |
161 | 2.52M | inferGslPointerAttribute(TD, RD); |
162 | 2.52M | } |
163 | | |
164 | 647k | void Sema::inferGslOwnerPointerAttribute(CXXRecordDecl *Record) { |
165 | 647k | static llvm::StringSet<> StdOwners{ |
166 | 647k | "any", |
167 | 647k | "array", |
168 | 647k | "basic_regex", |
169 | 647k | "basic_string", |
170 | 647k | "deque", |
171 | 647k | "forward_list", |
172 | 647k | "vector", |
173 | 647k | "list", |
174 | 647k | "map", |
175 | 647k | "multiset", |
176 | 647k | "multimap", |
177 | 647k | "optional", |
178 | 647k | "priority_queue", |
179 | 647k | "queue", |
180 | 647k | "set", |
181 | 647k | "stack", |
182 | 647k | "unique_ptr", |
183 | 647k | "unordered_set", |
184 | 647k | "unordered_map", |
185 | 647k | "unordered_multiset", |
186 | 647k | "unordered_multimap", |
187 | 647k | "variant", |
188 | 647k | }; |
189 | 647k | static llvm::StringSet<> StdPointers{ |
190 | 647k | "basic_string_view", |
191 | 647k | "reference_wrapper", |
192 | 647k | "regex_iterator", |
193 | 647k | }; |
194 | | |
195 | 647k | if (!Record->getIdentifier()) |
196 | 43.7k | return; |
197 | | |
198 | | // Handle classes that directly appear in std namespace. |
199 | 603k | if (Record->isInStdNamespace()) { |
200 | 325k | if (Record->hasAttr<OwnerAttr>() || Record->hasAttr<PointerAttr>()320k ) |
201 | 6.59k | return; |
202 | | |
203 | 319k | if (StdOwners.count(Record->getName())) |
204 | 8.14k | addGslOwnerPointerAttributeIfNotExisting<OwnerAttr>(Context, Record); |
205 | 311k | else if (StdPointers.count(Record->getName())) |
206 | 845 | addGslOwnerPointerAttributeIfNotExisting<PointerAttr>(Context, Record); |
207 | | |
208 | 319k | return; |
209 | 325k | } |
210 | | |
211 | | // Handle nested classes that could be a gsl::Pointer. |
212 | 277k | inferGslPointerAttribute(Record, Record); |
213 | 277k | } |
214 | | |
215 | | void Sema::ActOnPragmaOptionsAlign(PragmaOptionsAlignKind Kind, |
216 | 2.81k | SourceLocation PragmaLoc) { |
217 | 2.81k | PragmaMsStackAction Action = Sema::PSK_Reset; |
218 | 2.81k | AlignPackInfo::Mode ModeVal = AlignPackInfo::Native; |
219 | | |
220 | 2.81k | switch (Kind) { |
221 | | // For most of the platforms we support, native and natural are the same. |
222 | | // With XL, native is the same as power, natural means something else. |
223 | | // |
224 | | // FIXME: This is not true on Darwin/PPC. |
225 | 1 | case POAK_Native: |
226 | 1.34k | case POAK_Power: |
227 | 1.34k | Action = Sema::PSK_Push_Set; |
228 | 1.34k | break; |
229 | 29 | case POAK_Natural: |
230 | 29 | Action = Sema::PSK_Push_Set; |
231 | 29 | ModeVal = AlignPackInfo::Natural; |
232 | 29 | break; |
233 | | |
234 | | // Note that '#pragma options align=packed' is not equivalent to attribute |
235 | | // packed, it has a different precedence relative to attribute aligned. |
236 | 25 | case POAK_Packed: |
237 | 25 | Action = Sema::PSK_Push_Set; |
238 | 25 | ModeVal = AlignPackInfo::Packed; |
239 | 25 | break; |
240 | | |
241 | 9 | case POAK_Mac68k: |
242 | | // Check if the target supports this. |
243 | 9 | if (!this->Context.getTargetInfo().hasAlignMac68kSupport()) { |
244 | 2 | Diag(PragmaLoc, diag::err_pragma_options_align_mac68k_target_unsupported); |
245 | 2 | return; |
246 | 2 | } |
247 | 7 | Action = Sema::PSK_Push_Set; |
248 | 7 | ModeVal = AlignPackInfo::Mac68k; |
249 | 7 | break; |
250 | 1.40k | case POAK_Reset: |
251 | | // Reset just pops the top of the stack, or resets the current alignment to |
252 | | // default. |
253 | 1.40k | Action = Sema::PSK_Pop; |
254 | 1.40k | if (AlignPackStack.Stack.empty()) { |
255 | 10 | if (AlignPackStack.CurrentValue.getAlignMode() != AlignPackInfo::Native || |
256 | 10 | AlignPackStack.CurrentValue.IsPackAttr()) { |
257 | 7 | Action = Sema::PSK_Reset; |
258 | 7 | } else { |
259 | 3 | Diag(PragmaLoc, diag::warn_pragma_options_align_reset_failed) |
260 | 3 | << "stack empty"; |
261 | 3 | return; |
262 | 3 | } |
263 | 10 | } |
264 | 1.39k | break; |
265 | 2.81k | } |
266 | | |
267 | 2.80k | AlignPackInfo Info(ModeVal, getLangOpts().XLPragmaPack); |
268 | | |
269 | 2.80k | AlignPackStack.Act(PragmaLoc, Action, StringRef(), Info); |
270 | 2.80k | } |
271 | | |
272 | | void Sema::ActOnPragmaClangSection(SourceLocation PragmaLoc, |
273 | | PragmaClangSectionAction Action, |
274 | | PragmaClangSectionKind SecKind, |
275 | 91 | StringRef SecName) { |
276 | 91 | PragmaClangSection *CSec; |
277 | 91 | int SectionFlags = ASTContext::PSF_Read; |
278 | 91 | switch (SecKind) { |
279 | 24 | case PragmaClangSectionKind::PCSK_BSS: |
280 | 24 | CSec = &PragmaClangBSSSection; |
281 | 24 | SectionFlags |= ASTContext::PSF_Write | ASTContext::PSF_ZeroInit; |
282 | 24 | break; |
283 | 21 | case PragmaClangSectionKind::PCSK_Data: |
284 | 21 | CSec = &PragmaClangDataSection; |
285 | 21 | SectionFlags |= ASTContext::PSF_Write; |
286 | 21 | break; |
287 | 22 | case PragmaClangSectionKind::PCSK_Rodata: |
288 | 22 | CSec = &PragmaClangRodataSection; |
289 | 22 | break; |
290 | 2 | case PragmaClangSectionKind::PCSK_Relro: |
291 | 2 | CSec = &PragmaClangRelroSection; |
292 | 2 | break; |
293 | 22 | case PragmaClangSectionKind::PCSK_Text: |
294 | 22 | CSec = &PragmaClangTextSection; |
295 | 22 | SectionFlags |= ASTContext::PSF_Execute; |
296 | 22 | break; |
297 | 0 | default: |
298 | 0 | llvm_unreachable("invalid clang section kind"); |
299 | 91 | } |
300 | | |
301 | 91 | if (Action == PragmaClangSectionAction::PCSA_Clear) { |
302 | 45 | CSec->Valid = false; |
303 | 45 | return; |
304 | 45 | } |
305 | | |
306 | 46 | if (llvm::Error E = isValidSectionSpecifier(SecName)) { |
307 | 2 | Diag(PragmaLoc, diag::err_pragma_section_invalid_for_target) |
308 | 2 | << toString(std::move(E)); |
309 | 2 | CSec->Valid = false; |
310 | 2 | return; |
311 | 2 | } |
312 | | |
313 | 44 | if (UnifySection(SecName, SectionFlags, PragmaLoc)) |
314 | 5 | return; |
315 | | |
316 | 39 | CSec->Valid = true; |
317 | 39 | CSec->SectionName = std::string(SecName); |
318 | 39 | CSec->PragmaLocation = PragmaLoc; |
319 | 39 | } |
320 | | |
321 | | void Sema::ActOnPragmaPack(SourceLocation PragmaLoc, PragmaMsStackAction Action, |
322 | 259k | StringRef SlotLabel, Expr *alignment) { |
323 | 259k | bool IsXLPragma = getLangOpts().XLPragmaPack; |
324 | | // XL pragma pack does not support identifier syntax. |
325 | 259k | if (IsXLPragma && !SlotLabel.empty()188 ) { |
326 | 2 | Diag(PragmaLoc, diag::err_pragma_pack_identifer_not_supported); |
327 | 2 | return; |
328 | 2 | } |
329 | | |
330 | 259k | const AlignPackInfo CurVal = AlignPackStack.CurrentValue; |
331 | 259k | Expr *Alignment = static_cast<Expr *>(alignment); |
332 | | |
333 | | // If specified then alignment must be a "small" power of two. |
334 | 259k | unsigned AlignmentVal = 0; |
335 | 259k | AlignPackInfo::Mode ModeVal = CurVal.getAlignMode(); |
336 | | |
337 | 259k | if (Alignment) { |
338 | 129k | Optional<llvm::APSInt> Val; |
339 | 129k | Val = Alignment->getIntegerConstantExpr(Context); |
340 | | |
341 | | // pack(0) is like pack(), which just works out since that is what |
342 | | // we use 0 for in PackAttr. |
343 | 129k | if (Alignment->isTypeDependent() || !Val || |
344 | 129k | !(*Val == 0 || Val->isPowerOf2()129k ) || Val->getZExtValue() > 16129k ) { |
345 | 1 | Diag(PragmaLoc, diag::warn_pragma_pack_invalid_alignment); |
346 | 1 | return; // Ignore |
347 | 1 | } |
348 | | |
349 | 129k | if (IsXLPragma && *Val == 072 ) { |
350 | | // pack(0) does not work out with XL. |
351 | 2 | Diag(PragmaLoc, diag::err_pragma_pack_invalid_alignment); |
352 | 2 | return; // Ignore |
353 | 2 | } |
354 | | |
355 | 129k | AlignmentVal = (unsigned)Val->getZExtValue(); |
356 | 129k | } |
357 | | |
358 | 259k | if (Action == Sema::PSK_Show) { |
359 | | // Show the current alignment, making sure to show the right value |
360 | | // for the default. |
361 | | // FIXME: This should come from the target. |
362 | 80 | AlignmentVal = CurVal.IsPackSet() ? CurVal.getPackNumber()40 : 840 ; |
363 | 80 | if (ModeVal == AlignPackInfo::Mac68k && |
364 | 80 | (0 IsXLPragma0 || CurVal.IsAlignAttr()0 )) |
365 | 0 | Diag(PragmaLoc, diag::warn_pragma_pack_show) << "mac68k"; |
366 | 80 | else |
367 | 80 | Diag(PragmaLoc, diag::warn_pragma_pack_show) << AlignmentVal; |
368 | 80 | } |
369 | | |
370 | | // MSDN, C/C++ Preprocessor Reference > Pragma Directives > pack: |
371 | | // "#pragma pack(pop, identifier, n) is undefined" |
372 | 259k | if (Action & Sema::PSK_Pop) { |
373 | 127k | if (Alignment && !SlotLabel.empty()1 ) |
374 | 0 | Diag(PragmaLoc, diag::warn_pragma_pack_pop_identifier_and_alignment); |
375 | 127k | if (AlignPackStack.Stack.empty()) { |
376 | 22 | assert(CurVal.getAlignMode() == AlignPackInfo::Native && |
377 | 22 | "Empty pack stack can only be at Native alignment mode."); |
378 | 0 | Diag(PragmaLoc, diag::warn_pragma_pop_failed) << "pack" << "stack empty"; |
379 | 22 | } |
380 | 127k | } |
381 | | |
382 | 0 | AlignPackInfo Info(ModeVal, AlignmentVal, IsXLPragma); |
383 | | |
384 | 259k | AlignPackStack.Act(PragmaLoc, Action, SlotLabel, Info); |
385 | 259k | } |
386 | | |
387 | | bool Sema::ConstantFoldAttrArgs(const AttributeCommonInfo &CI, |
388 | 467 | MutableArrayRef<Expr *> Args) { |
389 | 467 | llvm::SmallVector<PartialDiagnosticAt, 8> Notes; |
390 | 618 | for (unsigned Idx = 0; Idx < Args.size(); Idx++151 ) { |
391 | 160 | Expr *&E = Args.begin()[Idx]; |
392 | 160 | assert(E && "error are handled before"); |
393 | 160 | if (E->isValueDependent() || E->isTypeDependent()118 ) |
394 | 42 | continue; |
395 | | |
396 | | // FIXME: Use DefaultFunctionArrayLValueConversion() in place of the logic |
397 | | // that adds implicit casts here. |
398 | 118 | if (E->getType()->isArrayType()) |
399 | 3 | E = ImpCastExprToType(E, Context.getPointerType(E->getType()), |
400 | 3 | clang::CK_ArrayToPointerDecay) |
401 | 3 | .get(); |
402 | 118 | if (E->getType()->isFunctionType()) |
403 | 2 | E = ImplicitCastExpr::Create(Context, |
404 | 2 | Context.getPointerType(E->getType()), |
405 | 2 | clang::CK_FunctionToPointerDecay, E, nullptr, |
406 | 2 | VK_PRValue, FPOptionsOverride()); |
407 | 118 | if (E->isLValue()) |
408 | 9 | E = ImplicitCastExpr::Create(Context, E->getType().getNonReferenceType(), |
409 | 9 | clang::CK_LValueToRValue, E, nullptr, |
410 | 9 | VK_PRValue, FPOptionsOverride()); |
411 | | |
412 | 118 | Expr::EvalResult Eval; |
413 | 118 | Notes.clear(); |
414 | 118 | Eval.Diag = &Notes; |
415 | | |
416 | 118 | bool Result = E->EvaluateAsConstantExpr(Eval, Context); |
417 | | |
418 | | /// Result means the expression can be folded to a constant. |
419 | | /// Note.empty() means the expression is a valid constant expression in the |
420 | | /// current language mode. |
421 | 118 | if (!Result || !Notes.empty()110 ) { |
422 | 9 | Diag(E->getBeginLoc(), diag::err_attribute_argument_n_type) |
423 | 9 | << CI << (Idx + 1) << AANT_ArgumentConstantExpr; |
424 | 9 | for (auto &Note : Notes) |
425 | 13 | Diag(Note.first, Note.second); |
426 | 9 | return false; |
427 | 9 | } |
428 | 109 | assert(Eval.Val.hasValue()); |
429 | 0 | E = ConstantExpr::Create(Context, E, Eval.Val); |
430 | 109 | } |
431 | | |
432 | 458 | return true; |
433 | 467 | } |
434 | | |
435 | | void Sema::DiagnoseNonDefaultPragmaAlignPack(PragmaAlignPackDiagnoseKind Kind, |
436 | 1.45M | SourceLocation IncludeLoc) { |
437 | 1.45M | if (Kind == PragmaAlignPackDiagnoseKind::NonDefaultStateAtInclude) { |
438 | 727k | SourceLocation PrevLocation = AlignPackStack.CurrentPragmaLocation; |
439 | | // Warn about non-default alignment at #includes (without redundant |
440 | | // warnings for the same directive in nested includes). |
441 | | // The warning is delayed until the end of the file to avoid warnings |
442 | | // for files that don't have any records that are affected by the modified |
443 | | // alignment. |
444 | 727k | bool HasNonDefaultValue = |
445 | 727k | AlignPackStack.hasValue() && |
446 | 727k | (21 AlignPackIncludeStack.empty()21 || |
447 | 21 | AlignPackIncludeStack.back().CurrentPragmaLocation != PrevLocation9 ); |
448 | 727k | AlignPackIncludeStack.push_back( |
449 | 727k | {AlignPackStack.CurrentValue, |
450 | 727k | AlignPackStack.hasValue() ? PrevLocation21 : SourceLocation()727k , |
451 | 727k | HasNonDefaultValue, /*ShouldWarnOnInclude*/ false}); |
452 | 727k | return; |
453 | 727k | } |
454 | | |
455 | 727k | assert(Kind == PragmaAlignPackDiagnoseKind::ChangedStateAtExit && |
456 | 727k | "invalid kind"); |
457 | 0 | AlignPackIncludeState PrevAlignPackState = |
458 | 727k | AlignPackIncludeStack.pop_back_val(); |
459 | | // FIXME: AlignPackStack may contain both #pragma align and #pragma pack |
460 | | // information, diagnostics below might not be accurate if we have mixed |
461 | | // pragmas. |
462 | 727k | if (PrevAlignPackState.ShouldWarnOnInclude) { |
463 | | // Emit the delayed non-default alignment at #include warning. |
464 | 12 | Diag(IncludeLoc, diag::warn_pragma_pack_non_default_at_include); |
465 | 12 | Diag(PrevAlignPackState.CurrentPragmaLocation, diag::note_pragma_pack_here); |
466 | 12 | } |
467 | | // Warn about modified alignment after #includes. |
468 | 727k | if (PrevAlignPackState.CurrentValue != AlignPackStack.CurrentValue) { |
469 | 22 | Diag(IncludeLoc, diag::warn_pragma_pack_modified_after_include); |
470 | 22 | Diag(AlignPackStack.CurrentPragmaLocation, diag::note_pragma_pack_here); |
471 | 22 | } |
472 | 727k | } |
473 | | |
474 | 85.3k | void Sema::DiagnoseUnterminatedPragmaAlignPack() { |
475 | 85.3k | if (AlignPackStack.Stack.empty()) |
476 | 85.3k | return; |
477 | 37 | bool IsInnermost = true; |
478 | | |
479 | | // FIXME: AlignPackStack may contain both #pragma align and #pragma pack |
480 | | // information, diagnostics below might not be accurate if we have mixed |
481 | | // pragmas. |
482 | 48 | for (const auto &StackSlot : llvm::reverse(AlignPackStack.Stack)) { |
483 | 48 | Diag(StackSlot.PragmaPushLocation, diag::warn_pragma_pack_no_pop_eof); |
484 | | // The user might have already reset the alignment, so suggest replacing |
485 | | // the reset with a pop. |
486 | 48 | if (IsInnermost && |
487 | 48 | AlignPackStack.CurrentValue == AlignPackStack.DefaultValue37 ) { |
488 | 4 | auto DB = Diag(AlignPackStack.CurrentPragmaLocation, |
489 | 4 | diag::note_pragma_pack_pop_instead_reset); |
490 | 4 | SourceLocation FixItLoc = |
491 | 4 | Lexer::findLocationAfterToken(AlignPackStack.CurrentPragmaLocation, |
492 | 4 | tok::l_paren, SourceMgr, LangOpts, |
493 | 4 | /*SkipTrailing=*/false); |
494 | 4 | if (FixItLoc.isValid()) |
495 | 4 | DB << FixItHint::CreateInsertion(FixItLoc, "pop"); |
496 | 4 | } |
497 | 48 | IsInnermost = false; |
498 | 48 | } |
499 | 37 | } |
500 | | |
501 | 3.99k | void Sema::ActOnPragmaMSStruct(PragmaMSStructKind Kind) { |
502 | 3.99k | MSStructPragmaOn = (Kind == PMSST_ON); |
503 | 3.99k | } |
504 | | |
505 | | void Sema::ActOnPragmaMSComment(SourceLocation CommentLoc, |
506 | 66 | PragmaMSCommentKind Kind, StringRef Arg) { |
507 | 66 | auto *PCD = PragmaCommentDecl::Create( |
508 | 66 | Context, Context.getTranslationUnitDecl(), CommentLoc, Kind, Arg); |
509 | 66 | Context.getTranslationUnitDecl()->addDecl(PCD); |
510 | 66 | Consumer.HandleTopLevelDecl(DeclGroupRef(PCD)); |
511 | 66 | } |
512 | | |
513 | | void Sema::ActOnPragmaDetectMismatch(SourceLocation Loc, StringRef Name, |
514 | 16 | StringRef Value) { |
515 | 16 | auto *PDMD = PragmaDetectMismatchDecl::Create( |
516 | 16 | Context, Context.getTranslationUnitDecl(), Loc, Name, Value); |
517 | 16 | Context.getTranslationUnitDecl()->addDecl(PDMD); |
518 | 16 | Consumer.HandleTopLevelDecl(DeclGroupRef(PDMD)); |
519 | 16 | } |
520 | | |
521 | | void Sema::ActOnPragmaFPEvalMethod(SourceLocation Loc, |
522 | 101 | LangOptions::FPEvalMethodKind Value) { |
523 | 101 | FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); |
524 | 101 | switch (Value) { |
525 | 0 | default: |
526 | 0 | llvm_unreachable("invalid pragma eval_method kind"); |
527 | 35 | case LangOptions::FEM_Source: |
528 | 35 | NewFPFeatures.setFPEvalMethodOverride(LangOptions::FEM_Source); |
529 | 35 | break; |
530 | 41 | case LangOptions::FEM_Double: |
531 | 41 | NewFPFeatures.setFPEvalMethodOverride(LangOptions::FEM_Double); |
532 | 41 | break; |
533 | 25 | case LangOptions::FEM_Extended: |
534 | 25 | NewFPFeatures.setFPEvalMethodOverride(LangOptions::FEM_Extended); |
535 | 25 | break; |
536 | 101 | } |
537 | 101 | if (getLangOpts().ApproxFunc) |
538 | 2 | Diag(Loc, diag::err_setting_eval_method_used_in_unsafe_context) << 0 << 0; |
539 | 101 | if (getLangOpts().AllowFPReassoc) |
540 | 3 | Diag(Loc, diag::err_setting_eval_method_used_in_unsafe_context) << 0 << 1; |
541 | 101 | if (getLangOpts().AllowRecip) |
542 | 3 | Diag(Loc, diag::err_setting_eval_method_used_in_unsafe_context) << 0 << 2; |
543 | 101 | FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures); |
544 | 101 | CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); |
545 | 101 | PP.setCurrentFPEvalMethod(Loc, Value); |
546 | 101 | } |
547 | | |
548 | | void Sema::ActOnPragmaFloatControl(SourceLocation Loc, |
549 | | PragmaMsStackAction Action, |
550 | 476 | PragmaFloatControlKind Value) { |
551 | 476 | FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); |
552 | 476 | if ((Action == PSK_Push_Set || Action == PSK_Push465 || Action == PSK_Pop402 ) && |
553 | 476 | !CurContext->getRedeclContext()->isFileContext()165 ) { |
554 | | // Push and pop can only occur at file or namespace scope, or within a |
555 | | // language linkage declaration. |
556 | 4 | Diag(Loc, diag::err_pragma_fc_pp_scope); |
557 | 4 | return; |
558 | 4 | } |
559 | 472 | switch (Value) { |
560 | 0 | default: |
561 | 0 | llvm_unreachable("invalid pragma float_control kind"); |
562 | 75 | case PFC_Precise: |
563 | 75 | NewFPFeatures.setFPPreciseEnabled(true); |
564 | 75 | FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures); |
565 | 75 | if (PP.getCurrentFPEvalMethod() == |
566 | 75 | LangOptions::FPEvalMethodKind::FEM_Indeterminable && |
567 | 75 | PP.getLastFPEvalPragmaLocation().isValid()23 ) |
568 | | // A preceding `pragma float_control(precise,off)` has changed |
569 | | // the value of the evaluation method. |
570 | | // Set it back to its old value. |
571 | 16 | PP.setCurrentFPEvalMethod(SourceLocation(), PP.getLastFPEvalMethod()); |
572 | 75 | break; |
573 | 118 | case PFC_NoPrecise: |
574 | 118 | if (CurFPFeatures.getExceptionMode() == LangOptions::FPE_Strict) |
575 | 13 | Diag(Loc, diag::err_pragma_fc_noprecise_requires_noexcept); |
576 | 105 | else if (CurFPFeatures.getAllowFEnvAccess()) |
577 | 0 | Diag(Loc, diag::err_pragma_fc_noprecise_requires_nofenv); |
578 | 105 | else |
579 | 105 | NewFPFeatures.setFPPreciseEnabled(false); |
580 | 118 | FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures); |
581 | 118 | PP.setLastFPEvalMethod(PP.getCurrentFPEvalMethod()); |
582 | | // `AllowFPReassoc` or `AllowReciprocal` option is enabled. |
583 | 118 | PP.setCurrentFPEvalMethod( |
584 | 118 | Loc, LangOptions::FPEvalMethodKind::FEM_Indeterminable); |
585 | 118 | break; |
586 | 98 | case PFC_Except: |
587 | 98 | if (!isPreciseFPEnabled()) |
588 | 0 | Diag(Loc, diag::err_pragma_fc_except_requires_precise); |
589 | 98 | else |
590 | 98 | NewFPFeatures.setSpecifiedExceptionModeOverride(LangOptions::FPE_Strict); |
591 | 98 | FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures); |
592 | 98 | break; |
593 | 29 | case PFC_NoExcept: |
594 | 29 | NewFPFeatures.setSpecifiedExceptionModeOverride(LangOptions::FPE_Ignore); |
595 | 29 | FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures); |
596 | 29 | break; |
597 | 62 | case PFC_Push: |
598 | 62 | FpPragmaStack.Act(Loc, Sema::PSK_Push_Set, StringRef(), NewFPFeatures); |
599 | 62 | break; |
600 | 90 | case PFC_Pop: |
601 | 90 | if (FpPragmaStack.Stack.empty()) { |
602 | 20 | Diag(Loc, diag::warn_pragma_pop_failed) << "float_control" |
603 | 20 | << "stack empty"; |
604 | 20 | return; |
605 | 20 | } |
606 | 70 | FpPragmaStack.Act(Loc, Action, StringRef(), NewFPFeatures); |
607 | 70 | NewFPFeatures = FpPragmaStack.CurrentValue; |
608 | 70 | if (CurFPFeatures.getAllowFPReassociate() || |
609 | 70 | CurFPFeatures.getAllowReciprocal()45 ) |
610 | | // Since we are popping the pragma, we don't want to be passing |
611 | | // a location here. |
612 | 25 | PP.setCurrentFPEvalMethod(SourceLocation(), |
613 | 25 | CurFPFeatures.getFPEvalMethod()); |
614 | 70 | break; |
615 | 472 | } |
616 | 452 | CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); |
617 | 452 | } |
618 | | |
619 | | void Sema::ActOnPragmaMSPointersToMembers( |
620 | | LangOptions::PragmaMSPointersToMembersKind RepresentationMethod, |
621 | 26 | SourceLocation PragmaLoc) { |
622 | 26 | MSPointerToMemberRepresentationMethod = RepresentationMethod; |
623 | 26 | ImplicitMSInheritanceAttrLoc = PragmaLoc; |
624 | 26 | } |
625 | | |
626 | | void Sema::ActOnPragmaMSVtorDisp(PragmaMsStackAction Action, |
627 | | SourceLocation PragmaLoc, |
628 | 45 | MSVtorDispMode Mode) { |
629 | 45 | if (Action & PSK_Pop && VtorDispStack.Stack.empty()20 ) |
630 | 4 | Diag(PragmaLoc, diag::warn_pragma_pop_failed) << "vtordisp" |
631 | 4 | << "stack empty"; |
632 | 45 | VtorDispStack.Act(PragmaLoc, Action, StringRef(), Mode); |
633 | 45 | } |
634 | | |
635 | | template <> |
636 | | void Sema::PragmaStack<Sema::AlignPackInfo>::Act(SourceLocation PragmaLocation, |
637 | | PragmaMsStackAction Action, |
638 | | llvm::StringRef StackSlotLabel, |
639 | 262k | AlignPackInfo Value) { |
640 | 262k | if (Action == PSK_Reset) { |
641 | 1.87k | CurrentValue = DefaultValue; |
642 | 1.87k | CurrentPragmaLocation = PragmaLocation; |
643 | 1.87k | return; |
644 | 1.87k | } |
645 | 260k | if (Action & PSK_Push) |
646 | 129k | Stack.emplace_back(Slot(StackSlotLabel, CurrentValue, CurrentPragmaLocation, |
647 | 129k | PragmaLocation)); |
648 | 131k | else if (Action & PSK_Pop) { |
649 | 129k | if (!StackSlotLabel.empty()) { |
650 | | // If we've got a label, try to find it and jump there. |
651 | 10 | auto I = llvm::find_if(llvm::reverse(Stack), [&](const Slot &x) { |
652 | 10 | return x.StackSlotLabel == StackSlotLabel; |
653 | 10 | }); |
654 | | // We found the label, so pop from there. |
655 | 9 | if (I != Stack.rend()) { |
656 | 5 | CurrentValue = I->Value; |
657 | 5 | CurrentPragmaLocation = I->PragmaLocation; |
658 | 5 | Stack.erase(std::prev(I.base()), Stack.end()); |
659 | 5 | } |
660 | 129k | } else if (Value.IsXLStack() && Value.IsAlignAttr()114 && |
661 | 129k | CurrentValue.IsPackAttr()40 ) { |
662 | | // XL '#pragma align(reset)' would pop the stack until |
663 | | // a current in effect pragma align is popped. |
664 | 8 | auto I = llvm::find_if(llvm::reverse(Stack), [&](const Slot &x) { |
665 | 8 | return x.Value.IsAlignAttr(); |
666 | 8 | }); |
667 | | // If we found pragma align so pop from there. |
668 | 8 | if (I != Stack.rend()) { |
669 | 8 | Stack.erase(std::prev(I.base()), Stack.end()); |
670 | 8 | if (Stack.empty()) { |
671 | 2 | CurrentValue = DefaultValue; |
672 | 2 | CurrentPragmaLocation = PragmaLocation; |
673 | 6 | } else { |
674 | 6 | CurrentValue = Stack.back().Value; |
675 | 6 | CurrentPragmaLocation = Stack.back().PragmaLocation; |
676 | 6 | Stack.pop_back(); |
677 | 6 | } |
678 | 8 | } |
679 | 129k | } else if (!Stack.empty()) { |
680 | | // xl '#pragma align' sets the baseline, and `#pragma pack` cannot pop |
681 | | // over the baseline. |
682 | 128k | if (Value.IsXLStack() && Value.IsPackAttr()96 && CurrentValue.IsAlignAttr()64 ) |
683 | 2 | return; |
684 | | |
685 | | // We don't have a label, just pop the last entry. |
686 | 128k | CurrentValue = Stack.back().Value; |
687 | 128k | CurrentPragmaLocation = Stack.back().PragmaLocation; |
688 | 128k | Stack.pop_back(); |
689 | 128k | } |
690 | 129k | } |
691 | 260k | if (Action & PSK_Set) { |
692 | 131k | CurrentValue = Value; |
693 | 131k | CurrentPragmaLocation = PragmaLocation; |
694 | 131k | } |
695 | 260k | } |
696 | | |
697 | | bool Sema::UnifySection(StringRef SectionName, int SectionFlags, |
698 | 1.30k | NamedDecl *Decl) { |
699 | 1.30k | SourceLocation PragmaLocation; |
700 | 1.30k | if (auto A = Decl->getAttr<SectionAttr>()) |
701 | 1.30k | if (A->isImplicit()) |
702 | 68 | PragmaLocation = A->getLocation(); |
703 | 1.30k | auto SectionIt = Context.SectionInfos.find(SectionName); |
704 | 1.30k | if (SectionIt == Context.SectionInfos.end()) { |
705 | 100 | Context.SectionInfos[SectionName] = |
706 | 100 | ASTContext::SectionInfo(Decl, PragmaLocation, SectionFlags); |
707 | 100 | return false; |
708 | 100 | } |
709 | | // A pre-declared section takes precedence w/o diagnostic. |
710 | 1.20k | const auto &Section = SectionIt->second; |
711 | 1.20k | if (Section.SectionFlags == SectionFlags || |
712 | 1.20k | (26 (SectionFlags & ASTContext::PSF_Implicit)26 && |
713 | 26 | !(Section.SectionFlags & ASTContext::PSF_Implicit)13 )) |
714 | 1.18k | return false; |
715 | 16 | Diag(Decl->getLocation(), diag::err_section_conflict) << Decl << Section; |
716 | 16 | if (Section.Decl) |
717 | 15 | Diag(Section.Decl->getLocation(), diag::note_declared_at) |
718 | 15 | << Section.Decl->getName(); |
719 | 16 | if (PragmaLocation.isValid()) |
720 | 2 | Diag(PragmaLocation, diag::note_pragma_entered_here); |
721 | 16 | if (Section.PragmaSectionLocation.isValid()) |
722 | 3 | Diag(Section.PragmaSectionLocation, diag::note_pragma_entered_here); |
723 | 16 | return true; |
724 | 1.20k | } |
725 | | |
726 | | bool Sema::UnifySection(StringRef SectionName, |
727 | | int SectionFlags, |
728 | 66 | SourceLocation PragmaSectionLocation) { |
729 | 66 | auto SectionIt = Context.SectionInfos.find(SectionName); |
730 | 66 | if (SectionIt != Context.SectionInfos.end()) { |
731 | 7 | const auto &Section = SectionIt->second; |
732 | 7 | if (Section.SectionFlags == SectionFlags) |
733 | 0 | return false; |
734 | 7 | if (!(Section.SectionFlags & ASTContext::PSF_Implicit)) { |
735 | 7 | Diag(PragmaSectionLocation, diag::err_section_conflict) |
736 | 7 | << "this" << Section; |
737 | 7 | if (Section.Decl) |
738 | 1 | Diag(Section.Decl->getLocation(), diag::note_declared_at) |
739 | 1 | << Section.Decl->getName(); |
740 | 7 | if (Section.PragmaSectionLocation.isValid()) |
741 | 6 | Diag(Section.PragmaSectionLocation, diag::note_pragma_entered_here); |
742 | 7 | return true; |
743 | 7 | } |
744 | 7 | } |
745 | 59 | Context.SectionInfos[SectionName] = |
746 | 59 | ASTContext::SectionInfo(nullptr, PragmaSectionLocation, SectionFlags); |
747 | 59 | return false; |
748 | 66 | } |
749 | | |
750 | | /// Called on well formed \#pragma bss_seg(). |
751 | | void Sema::ActOnPragmaMSSeg(SourceLocation PragmaLocation, |
752 | | PragmaMsStackAction Action, |
753 | | llvm::StringRef StackSlotLabel, |
754 | | StringLiteral *SegmentName, |
755 | 57 | llvm::StringRef PragmaName) { |
756 | 57 | PragmaStack<StringLiteral *> *Stack = |
757 | 57 | llvm::StringSwitch<PragmaStack<StringLiteral *> *>(PragmaName) |
758 | 57 | .Case("data_seg", &DataSegStack) |
759 | 57 | .Case("bss_seg", &BSSSegStack) |
760 | 57 | .Case("const_seg", &ConstSegStack) |
761 | 57 | .Case("code_seg", &CodeSegStack); |
762 | 57 | if (Action & PSK_Pop && Stack->Stack.empty()7 ) |
763 | 0 | Diag(PragmaLocation, diag::warn_pragma_pop_failed) << PragmaName |
764 | 0 | << "stack empty"; |
765 | 57 | if (SegmentName) { |
766 | 45 | if (!checkSectionName(SegmentName->getBeginLoc(), SegmentName->getString())) |
767 | 1 | return; |
768 | | |
769 | 44 | if (SegmentName->getString() == ".drectve" && |
770 | 44 | Context.getTargetInfo().getCXXABI().isMicrosoft()4 ) |
771 | 4 | Diag(PragmaLocation, diag::warn_attribute_section_drectve) << PragmaName; |
772 | 44 | } |
773 | | |
774 | 56 | Stack->Act(PragmaLocation, Action, StackSlotLabel, SegmentName); |
775 | 56 | } |
776 | | |
777 | | /// Called on well formed \#pragma bss_seg(). |
778 | | void Sema::ActOnPragmaMSSection(SourceLocation PragmaLocation, |
779 | 22 | int SectionFlags, StringLiteral *SegmentName) { |
780 | 22 | UnifySection(SegmentName->getString(), SectionFlags, PragmaLocation); |
781 | 22 | } |
782 | | |
783 | | void Sema::ActOnPragmaMSInitSeg(SourceLocation PragmaLocation, |
784 | 24 | StringLiteral *SegmentName) { |
785 | | // There's no stack to maintain, so we just have a current section. When we |
786 | | // see the default section, reset our current section back to null so we stop |
787 | | // tacking on unnecessary attributes. |
788 | 24 | CurInitSeg = SegmentName->getString() == ".CRT$XCU" ? nullptr1 : SegmentName23 ; |
789 | 24 | CurInitSegLoc = PragmaLocation; |
790 | 24 | } |
791 | | |
792 | | void Sema::ActOnPragmaMSAllocText( |
793 | | SourceLocation PragmaLocation, StringRef Section, |
794 | | const SmallVector<std::tuple<IdentifierInfo *, SourceLocation>> |
795 | 18 | &Functions) { |
796 | 18 | if (!CurContext->getRedeclContext()->isFileContext()) { |
797 | 1 | Diag(PragmaLocation, diag::err_pragma_expected_file_scope) << "alloc_text"; |
798 | 1 | return; |
799 | 1 | } |
800 | | |
801 | 18 | for (auto &Function : Functions)17 { |
802 | 18 | IdentifierInfo *II; |
803 | 18 | SourceLocation Loc; |
804 | 18 | std::tie(II, Loc) = Function; |
805 | | |
806 | 18 | DeclarationName DN(II); |
807 | 18 | NamedDecl *ND = LookupSingleName(TUScope, DN, Loc, LookupOrdinaryName); |
808 | 18 | if (!ND) { |
809 | 1 | Diag(Loc, diag::err_undeclared_use) << II->getName(); |
810 | 1 | return; |
811 | 1 | } |
812 | | |
813 | 17 | auto *FD = dyn_cast<FunctionDecl>(ND->getCanonicalDecl()); |
814 | 17 | if (!FD) { |
815 | 2 | Diag(Loc, diag::err_pragma_alloc_text_not_function); |
816 | 2 | return; |
817 | 2 | } |
818 | | |
819 | 15 | if (getLangOpts().CPlusPlus && !FD->isInExternCContext()13 ) { |
820 | 3 | Diag(Loc, diag::err_pragma_alloc_text_c_linkage); |
821 | 3 | return; |
822 | 3 | } |
823 | | |
824 | 12 | FunctionToSectionMap[II->getName()] = std::make_tuple(Section, Loc); |
825 | 12 | } |
826 | 17 | } |
827 | | |
828 | | void Sema::ActOnPragmaUnused(const Token &IdTok, Scope *curScope, |
829 | 25 | SourceLocation PragmaLoc) { |
830 | | |
831 | 25 | IdentifierInfo *Name = IdTok.getIdentifierInfo(); |
832 | 25 | LookupResult Lookup(*this, Name, IdTok.getLocation(), LookupOrdinaryName); |
833 | 25 | LookupParsedName(Lookup, curScope, nullptr, true); |
834 | | |
835 | 25 | if (Lookup.empty()) { |
836 | 3 | Diag(PragmaLoc, diag::warn_pragma_unused_undeclared_var) |
837 | 3 | << Name << SourceRange(IdTok.getLocation()); |
838 | 3 | return; |
839 | 3 | } |
840 | | |
841 | 22 | VarDecl *VD = Lookup.getAsSingle<VarDecl>(); |
842 | 22 | if (!VD) { |
843 | 0 | Diag(PragmaLoc, diag::warn_pragma_unused_expected_var_arg) |
844 | 0 | << Name << SourceRange(IdTok.getLocation()); |
845 | 0 | return; |
846 | 0 | } |
847 | | |
848 | | // Warn if this was used before being marked unused. |
849 | 22 | if (VD->isUsed()) |
850 | 1 | Diag(PragmaLoc, diag::warn_used_but_marked_unused) << Name; |
851 | | |
852 | 22 | VD->addAttr(UnusedAttr::CreateImplicit(Context, IdTok.getLocation(), |
853 | 22 | AttributeCommonInfo::AS_Pragma, |
854 | 22 | UnusedAttr::GNU_unused)); |
855 | 22 | } |
856 | | |
857 | 24.9M | void Sema::AddCFAuditedAttribute(Decl *D) { |
858 | 24.9M | IdentifierInfo *Ident; |
859 | 24.9M | SourceLocation Loc; |
860 | 24.9M | std::tie(Ident, Loc) = PP.getPragmaARCCFCodeAuditedInfo(); |
861 | 24.9M | if (!Loc.isValid()) return24.5M ; |
862 | | |
863 | | // Don't add a redundant or conflicting attribute. |
864 | 476k | if (D->hasAttr<CFAuditedTransferAttr>() || |
865 | 476k | D->hasAttr<CFUnknownTransferAttr>()475k ) |
866 | 888 | return; |
867 | | |
868 | 475k | AttributeCommonInfo Info(Ident, SourceRange(Loc), |
869 | 475k | AttributeCommonInfo::AS_Pragma); |
870 | 475k | D->addAttr(CFAuditedTransferAttr::CreateImplicit(Context, Info)); |
871 | 475k | } |
872 | | |
873 | | namespace { |
874 | | |
875 | | Optional<attr::SubjectMatchRule> |
876 | 342 | getParentAttrMatcherRule(attr::SubjectMatchRule Rule) { |
877 | 342 | using namespace attr; |
878 | 342 | switch (Rule) { |
879 | 233 | default: |
880 | 233 | return None; |
881 | 0 | #define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) |
882 | 0 | #define ATTR_MATCH_SUB_RULE(Value, Spelling, IsAbstract, Parent, IsNegated) \ |
883 | 109 | case Value: \ |
884 | 109 | return Parent; |
885 | 342 | #include "clang/Basic/AttrSubMatchRulesList.inc"233 |
886 | 342 | } |
887 | 342 | } |
888 | | |
889 | 59 | bool isNegatedAttrMatcherSubRule(attr::SubjectMatchRule Rule) { |
890 | 59 | using namespace attr; |
891 | 59 | switch (Rule) { |
892 | 4 | default: |
893 | 4 | return false; |
894 | 0 | #define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) |
895 | 0 | #define ATTR_MATCH_SUB_RULE(Value, Spelling, IsAbstract, Parent, IsNegated) \ |
896 | 55 | case Value: \ |
897 | 55 | return IsNegated; |
898 | 59 | #include "clang/Basic/AttrSubMatchRulesList.inc"4 |
899 | 59 | } |
900 | 59 | } |
901 | | |
902 | | CharSourceRange replacementRangeForListElement(const Sema &S, |
903 | 44 | SourceRange Range) { |
904 | | // Make sure that the ',' is removed as well. |
905 | 44 | SourceLocation AfterCommaLoc = Lexer::findLocationAfterToken( |
906 | 44 | Range.getEnd(), tok::comma, S.getSourceManager(), S.getLangOpts(), |
907 | 44 | /*SkipTrailingWhitespaceAndNewLine=*/false); |
908 | 44 | if (AfterCommaLoc.isValid()) |
909 | 16 | return CharSourceRange::getCharRange(Range.getBegin(), AfterCommaLoc); |
910 | 28 | else |
911 | 28 | return CharSourceRange::getTokenRange(Range); |
912 | 44 | } |
913 | | |
914 | | std::string |
915 | 22 | attrMatcherRuleListToString(ArrayRef<attr::SubjectMatchRule> Rules) { |
916 | 22 | std::string Result; |
917 | 22 | llvm::raw_string_ostream OS(Result); |
918 | 27 | for (const auto &I : llvm::enumerate(Rules)) { |
919 | 27 | if (I.index()) |
920 | 5 | OS << (I.index() == Rules.size() - 1 ? ", and " : ", "0 ); |
921 | 27 | OS << "'" << attr::getSubjectMatchRuleSpelling(I.value()) << "'"; |
922 | 27 | } |
923 | 22 | return Result; |
924 | 22 | } |
925 | | |
926 | | } // end anonymous namespace |
927 | | |
928 | | void Sema::ActOnPragmaAttributeAttribute( |
929 | | ParsedAttr &Attribute, SourceLocation PragmaLoc, |
930 | 1.07k | attr::ParsedSubjectMatchRuleSet Rules) { |
931 | 1.07k | Attribute.setIsPragmaClangAttribute(); |
932 | 1.07k | SmallVector<attr::SubjectMatchRule, 4> SubjectMatchRules; |
933 | | // Gather the subject match rules that are supported by the attribute. |
934 | 1.07k | SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> |
935 | 1.07k | StrictSubjectMatchRuleSet; |
936 | 1.07k | Attribute.getMatchRules(LangOpts, StrictSubjectMatchRuleSet); |
937 | | |
938 | | // Figure out which subject matching rules are valid. |
939 | 1.07k | if (StrictSubjectMatchRuleSet.empty()) { |
940 | | // Check for contradicting match rules. Contradicting match rules are |
941 | | // either: |
942 | | // - a top-level rule and one of its sub-rules. E.g. variable and |
943 | | // variable(is_parameter). |
944 | | // - a sub-rule and a sibling that's negated. E.g. |
945 | | // variable(is_thread_local) and variable(unless(is_parameter)) |
946 | 86 | llvm::SmallDenseMap<int, std::pair<int, SourceRange>, 2> |
947 | 86 | RulesToFirstSpecifiedNegatedSubRule; |
948 | 155 | for (const auto &Rule : Rules) { |
949 | 155 | attr::SubjectMatchRule MatchRule = attr::SubjectMatchRule(Rule.first); |
950 | 155 | Optional<attr::SubjectMatchRule> ParentRule = |
951 | 155 | getParentAttrMatcherRule(MatchRule); |
952 | 155 | if (!ParentRule) |
953 | 105 | continue; |
954 | 50 | auto It = Rules.find(*ParentRule); |
955 | 50 | if (It != Rules.end()) { |
956 | | // A sub-rule contradicts a parent rule. |
957 | 11 | Diag(Rule.second.getBegin(), |
958 | 11 | diag::err_pragma_attribute_matcher_subrule_contradicts_rule) |
959 | 11 | << attr::getSubjectMatchRuleSpelling(MatchRule) |
960 | 11 | << attr::getSubjectMatchRuleSpelling(*ParentRule) << It->second |
961 | 11 | << FixItHint::CreateRemoval( |
962 | 11 | replacementRangeForListElement(*this, Rule.second)); |
963 | | // Keep going without removing this rule as it won't change the set of |
964 | | // declarations that receive the attribute. |
965 | 11 | continue; |
966 | 11 | } |
967 | 39 | if (isNegatedAttrMatcherSubRule(MatchRule)) |
968 | 12 | RulesToFirstSpecifiedNegatedSubRule.insert( |
969 | 12 | std::make_pair(*ParentRule, Rule)); |
970 | 39 | } |
971 | 86 | bool IgnoreNegatedSubRules = false; |
972 | 155 | for (const auto &Rule : Rules) { |
973 | 155 | attr::SubjectMatchRule MatchRule = attr::SubjectMatchRule(Rule.first); |
974 | 155 | Optional<attr::SubjectMatchRule> ParentRule = |
975 | 155 | getParentAttrMatcherRule(MatchRule); |
976 | 155 | if (!ParentRule) |
977 | 105 | continue; |
978 | 50 | auto It = RulesToFirstSpecifiedNegatedSubRule.find(*ParentRule); |
979 | 50 | if (It != RulesToFirstSpecifiedNegatedSubRule.end() && |
980 | 50 | It->second != Rule12 ) { |
981 | | // Negated sub-rule contradicts another sub-rule. |
982 | 6 | Diag( |
983 | 6 | It->second.second.getBegin(), |
984 | 6 | diag:: |
985 | 6 | err_pragma_attribute_matcher_negated_subrule_contradicts_subrule) |
986 | 6 | << attr::getSubjectMatchRuleSpelling( |
987 | 6 | attr::SubjectMatchRule(It->second.first)) |
988 | 6 | << attr::getSubjectMatchRuleSpelling(MatchRule) << Rule.second |
989 | 6 | << FixItHint::CreateRemoval( |
990 | 6 | replacementRangeForListElement(*this, It->second.second)); |
991 | | // Keep going but ignore all of the negated sub-rules. |
992 | 6 | IgnoreNegatedSubRules = true; |
993 | 6 | RulesToFirstSpecifiedNegatedSubRule.erase(It); |
994 | 6 | } |
995 | 50 | } |
996 | | |
997 | 86 | if (!IgnoreNegatedSubRules) { |
998 | 80 | for (const auto &Rule : Rules) |
999 | 135 | SubjectMatchRules.push_back(attr::SubjectMatchRule(Rule.first)); |
1000 | 80 | } else { |
1001 | 20 | for (const auto &Rule : Rules) { |
1002 | 20 | if (!isNegatedAttrMatcherSubRule(attr::SubjectMatchRule(Rule.first))) |
1003 | 14 | SubjectMatchRules.push_back(attr::SubjectMatchRule(Rule.first)); |
1004 | 20 | } |
1005 | 6 | } |
1006 | 86 | Rules.clear(); |
1007 | 991 | } else { |
1008 | | // Each rule in Rules must be a strict subset of the attribute's |
1009 | | // SubjectMatch rules. I.e. we're allowed to use |
1010 | | // `apply_to=variables(is_global)` on an attrubute with SubjectList<[Var]>, |
1011 | | // but should not allow `apply_to=variables` on an attribute which has |
1012 | | // `SubjectList<[GlobalVar]>`. |
1013 | 13.7k | for (const auto &StrictRule : StrictSubjectMatchRuleSet) { |
1014 | | // First, check for exact match. |
1015 | 13.7k | if (Rules.erase(StrictRule.first)) { |
1016 | | // Add the rule to the set of attribute receivers only if it's supported |
1017 | | // in the current language mode. |
1018 | 10.7k | if (StrictRule.second) |
1019 | 10.7k | SubjectMatchRules.push_back(StrictRule.first); |
1020 | 10.7k | } |
1021 | 13.7k | } |
1022 | | // Check remaining rules for subset matches. |
1023 | 991 | auto RulesToCheck = Rules; |
1024 | 991 | for (const auto &Rule : RulesToCheck) { |
1025 | 32 | attr::SubjectMatchRule MatchRule = attr::SubjectMatchRule(Rule.first); |
1026 | 32 | if (auto ParentRule = getParentAttrMatcherRule(MatchRule)) { |
1027 | 9 | if (llvm::any_of(StrictSubjectMatchRuleSet, |
1028 | 10 | [ParentRule](const auto &StrictRule) { |
1029 | 10 | return StrictRule.first == *ParentRule && |
1030 | 10 | StrictRule.second5 ; // IsEnabled |
1031 | 10 | })) { |
1032 | 5 | SubjectMatchRules.push_back(MatchRule); |
1033 | 5 | Rules.erase(MatchRule); |
1034 | 5 | } |
1035 | 9 | } |
1036 | 32 | } |
1037 | 991 | } |
1038 | | |
1039 | 1.07k | if (!Rules.empty()) { |
1040 | 22 | auto Diagnostic = |
1041 | 22 | Diag(PragmaLoc, diag::err_pragma_attribute_invalid_matchers) |
1042 | 22 | << Attribute; |
1043 | 22 | SmallVector<attr::SubjectMatchRule, 2> ExtraRules; |
1044 | 27 | for (const auto &Rule : Rules) { |
1045 | 27 | ExtraRules.push_back(attr::SubjectMatchRule(Rule.first)); |
1046 | 27 | Diagnostic << FixItHint::CreateRemoval( |
1047 | 27 | replacementRangeForListElement(*this, Rule.second)); |
1048 | 27 | } |
1049 | 22 | Diagnostic << attrMatcherRuleListToString(ExtraRules); |
1050 | 22 | } |
1051 | | |
1052 | 1.07k | if (PragmaAttributeStack.empty()) { |
1053 | 1 | Diag(PragmaLoc, diag::err_pragma_attr_attr_no_push); |
1054 | 1 | return; |
1055 | 1 | } |
1056 | | |
1057 | 1.07k | PragmaAttributeStack.back().Entries.push_back( |
1058 | 1.07k | {PragmaLoc, &Attribute, std::move(SubjectMatchRules), /*IsUsed=*/false}); |
1059 | 1.07k | } |
1060 | | |
1061 | | void Sema::ActOnPragmaAttributeEmptyPush(SourceLocation PragmaLoc, |
1062 | 1.07k | const IdentifierInfo *Namespace) { |
1063 | 1.07k | PragmaAttributeStack.emplace_back(); |
1064 | 1.07k | PragmaAttributeStack.back().Loc = PragmaLoc; |
1065 | 1.07k | PragmaAttributeStack.back().Namespace = Namespace; |
1066 | 1.07k | } |
1067 | | |
1068 | | void Sema::ActOnPragmaAttributePop(SourceLocation PragmaLoc, |
1069 | 1.06k | const IdentifierInfo *Namespace) { |
1070 | 1.06k | if (PragmaAttributeStack.empty()) { |
1071 | 4 | Diag(PragmaLoc, diag::err_pragma_attribute_stack_mismatch) << 1; |
1072 | 4 | return; |
1073 | 4 | } |
1074 | | |
1075 | | // Dig back through the stack trying to find the most recently pushed group |
1076 | | // that in Namespace. Note that this works fine if no namespace is present, |
1077 | | // think of push/pops without namespaces as having an implicit "nullptr" |
1078 | | // namespace. |
1079 | 1.06k | for (size_t Index = PragmaAttributeStack.size(); 1.05k Index;) { |
1080 | 1.06k | --Index; |
1081 | 1.06k | if (PragmaAttributeStack[Index].Namespace == Namespace) { |
1082 | 1.05k | for (const PragmaAttributeEntry &Entry : |
1083 | 1.06k | PragmaAttributeStack[Index].Entries) { |
1084 | 1.06k | if (!Entry.IsUsed) { |
1085 | 69 | assert(Entry.Attribute && "Expected an attribute"); |
1086 | 0 | Diag(Entry.Attribute->getLoc(), diag::warn_pragma_attribute_unused) |
1087 | 69 | << *Entry.Attribute; |
1088 | 69 | Diag(PragmaLoc, diag::note_pragma_attribute_region_ends_here); |
1089 | 69 | } |
1090 | 1.06k | } |
1091 | 1.05k | PragmaAttributeStack.erase(PragmaAttributeStack.begin() + Index); |
1092 | 1.05k | return; |
1093 | 1.05k | } |
1094 | 1.06k | } |
1095 | | |
1096 | 2 | if (Namespace) |
1097 | 1 | Diag(PragmaLoc, diag::err_pragma_attribute_stack_mismatch) |
1098 | 1 | << 0 << Namespace->getName(); |
1099 | 1 | else |
1100 | 1 | Diag(PragmaLoc, diag::err_pragma_attribute_stack_mismatch) << 1; |
1101 | 2 | } |
1102 | | |
1103 | 106M | void Sema::AddPragmaAttributes(Scope *S, Decl *D) { |
1104 | 106M | if (PragmaAttributeStack.empty()) |
1105 | 106M | return; |
1106 | 64.7k | for (auto &Group : PragmaAttributeStack)64.6k { |
1107 | 64.7k | for (auto &Entry : Group.Entries) { |
1108 | 64.7k | ParsedAttr *Attribute = Entry.Attribute; |
1109 | 64.7k | assert(Attribute && "Expected an attribute"); |
1110 | 0 | assert(Attribute->isPragmaClangAttribute() && |
1111 | 64.7k | "expected #pragma clang attribute"); |
1112 | | |
1113 | | // Ensure that the attribute can be applied to the given declaration. |
1114 | 0 | bool Applies = false; |
1115 | 598k | for (const auto &Rule : Entry.MatchRules) { |
1116 | 598k | if (Attribute->appliesToDecl(D, Rule)) { |
1117 | 64.1k | Applies = true; |
1118 | 64.1k | break; |
1119 | 64.1k | } |
1120 | 598k | } |
1121 | 64.7k | if (!Applies) |
1122 | 640 | continue; |
1123 | 64.1k | Entry.IsUsed = true; |
1124 | 64.1k | PragmaAttributeCurrentTargetDecl = D; |
1125 | 64.1k | ParsedAttributesView Attrs; |
1126 | 64.1k | Attrs.addAtEnd(Attribute); |
1127 | 64.1k | ProcessDeclAttributeList(S, D, Attrs); |
1128 | 64.1k | PragmaAttributeCurrentTargetDecl = nullptr; |
1129 | 64.1k | } |
1130 | 64.7k | } |
1131 | 64.6k | } |
1132 | | |
1133 | 21 | void Sema::PrintPragmaAttributeInstantiationPoint() { |
1134 | 21 | assert(PragmaAttributeCurrentTargetDecl && "Expected an active declaration"); |
1135 | 0 | Diags.Report(PragmaAttributeCurrentTargetDecl->getBeginLoc(), |
1136 | 21 | diag::note_pragma_attribute_applied_decl_here); |
1137 | 21 | } |
1138 | | |
1139 | 85.3k | void Sema::DiagnoseUnterminatedPragmaAttribute() { |
1140 | 85.3k | if (PragmaAttributeStack.empty()) |
1141 | 85.3k | return; |
1142 | 3 | Diag(PragmaAttributeStack.back().Loc, diag::err_pragma_attribute_no_pop_eof); |
1143 | 3 | } |
1144 | | |
1145 | 31 | void Sema::ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc) { |
1146 | 31 | if(On) |
1147 | 14 | OptimizeOffPragmaLocation = SourceLocation(); |
1148 | 17 | else |
1149 | 17 | OptimizeOffPragmaLocation = PragmaLoc; |
1150 | 31 | } |
1151 | | |
1152 | 4 | void Sema::ActOnPragmaMSOptimize(SourceLocation Loc, bool IsOn) { |
1153 | 4 | if (!CurContext->getRedeclContext()->isFileContext()) { |
1154 | 1 | Diag(Loc, diag::err_pragma_expected_file_scope) << "optimize"; |
1155 | 1 | return; |
1156 | 1 | } |
1157 | | |
1158 | 3 | MSPragmaOptimizeIsOn = IsOn; |
1159 | 3 | } |
1160 | | |
1161 | | void Sema::ActOnPragmaMSFunction( |
1162 | 12 | SourceLocation Loc, const llvm::SmallVectorImpl<StringRef> &NoBuiltins) { |
1163 | 12 | if (!CurContext->getRedeclContext()->isFileContext()) { |
1164 | 1 | Diag(Loc, diag::err_pragma_expected_file_scope) << "function"; |
1165 | 1 | return; |
1166 | 1 | } |
1167 | | |
1168 | 11 | MSFunctionNoBuiltins.insert(NoBuiltins.begin(), NoBuiltins.end()); |
1169 | 11 | } |
1170 | | |
1171 | 3.92M | void Sema::AddRangeBasedOptnone(FunctionDecl *FD) { |
1172 | | // In the future, check other pragmas if they're implemented (e.g. pragma |
1173 | | // optimize 0 will probably map to this functionality too). |
1174 | 3.92M | if(OptimizeOffPragmaLocation.isValid()) |
1175 | 29 | AddOptnoneAttributeIfNoConflicts(FD, OptimizeOffPragmaLocation); |
1176 | 3.92M | } |
1177 | | |
1178 | 3.91M | void Sema::AddSectionMSAllocText(FunctionDecl *FD) { |
1179 | 3.91M | if (!FD->getIdentifier()) |
1180 | 639k | return; |
1181 | | |
1182 | 3.27M | StringRef Name = FD->getName(); |
1183 | 3.27M | auto It = FunctionToSectionMap.find(Name); |
1184 | 3.27M | if (It != FunctionToSectionMap.end()) { |
1185 | 9 | StringRef Section; |
1186 | 9 | SourceLocation Loc; |
1187 | 9 | std::tie(Section, Loc) = It->second; |
1188 | | |
1189 | 9 | if (!FD->hasAttr<SectionAttr>()) |
1190 | 9 | FD->addAttr(SectionAttr::CreateImplicit(Context, Section)); |
1191 | 9 | } |
1192 | 3.27M | } |
1193 | | |
1194 | 3.91M | void Sema::ModifyFnAttributesMSPragmaOptimize(FunctionDecl *FD) { |
1195 | | // Don't modify the function attributes if it's "on". "on" resets the |
1196 | | // optimizations to the ones listed on the command line |
1197 | 3.91M | if (!MSPragmaOptimizeIsOn) |
1198 | 2 | AddOptnoneAttributeIfNoConflicts(FD, FD->getBeginLoc()); |
1199 | 3.91M | } |
1200 | | |
1201 | | void Sema::AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD, |
1202 | 31 | SourceLocation Loc) { |
1203 | | // Don't add a conflicting attribute. No diagnostic is needed. |
1204 | 31 | if (FD->hasAttr<MinSizeAttr>() || FD->hasAttr<AlwaysInlineAttr>()28 ) |
1205 | 6 | return; |
1206 | | |
1207 | | // Add attributes only if required. Optnone requires noinline as well, but if |
1208 | | // either is already present then don't bother adding them. |
1209 | 25 | if (!FD->hasAttr<OptimizeNoneAttr>()) |
1210 | 25 | FD->addAttr(OptimizeNoneAttr::CreateImplicit(Context, Loc)); |
1211 | 25 | if (!FD->hasAttr<NoInlineAttr>()) |
1212 | 25 | FD->addAttr(NoInlineAttr::CreateImplicit(Context, Loc)); |
1213 | 25 | } |
1214 | | |
1215 | 3.91M | void Sema::AddImplicitMSFunctionNoBuiltinAttr(FunctionDecl *FD) { |
1216 | 3.91M | SmallVector<StringRef> V(MSFunctionNoBuiltins.begin(), |
1217 | 3.91M | MSFunctionNoBuiltins.end()); |
1218 | 3.91M | if (!MSFunctionNoBuiltins.empty()) |
1219 | 4 | FD->addAttr(NoBuiltinAttr::CreateImplicit(Context, V.data(), V.size())); |
1220 | 3.91M | } |
1221 | | |
1222 | | typedef std::vector<std::pair<unsigned, SourceLocation> > VisStack; |
1223 | | enum : unsigned { NoVisibility = ~0U }; |
1224 | | |
1225 | 7.54M | void Sema::AddPushedVisibilityAttribute(Decl *D) { |
1226 | 7.54M | if (!VisContext) |
1227 | 7.54M | return; |
1228 | | |
1229 | 443 | NamedDecl *ND = dyn_cast<NamedDecl>(D); |
1230 | 443 | if (ND && ND->getExplicitVisibility(NamedDecl::VisibilityForValue)) |
1231 | 96 | return; |
1232 | | |
1233 | 347 | VisStack *Stack = static_cast<VisStack*>(VisContext); |
1234 | 347 | unsigned rawType = Stack->back().first; |
1235 | 347 | if (rawType == NoVisibility) return30 ; |
1236 | | |
1237 | 317 | VisibilityAttr::VisibilityType type |
1238 | 317 | = (VisibilityAttr::VisibilityType) rawType; |
1239 | 317 | SourceLocation loc = Stack->back().second; |
1240 | | |
1241 | 317 | D->addAttr(VisibilityAttr::CreateImplicit(Context, type, loc)); |
1242 | 317 | } |
1243 | | |
1244 | | /// FreeVisContext - Deallocate and null out VisContext. |
1245 | 81 | void Sema::FreeVisContext() { |
1246 | 81 | delete static_cast<VisStack*>(VisContext); |
1247 | 81 | VisContext = nullptr; |
1248 | 81 | } |
1249 | | |
1250 | 85 | static void PushPragmaVisibility(Sema &S, unsigned type, SourceLocation loc) { |
1251 | | // Put visibility on stack. |
1252 | 85 | if (!S.VisContext) |
1253 | 81 | S.VisContext = new VisStack; |
1254 | | |
1255 | 85 | VisStack *Stack = static_cast<VisStack*>(S.VisContext); |
1256 | 85 | Stack->push_back(std::make_pair(type, loc)); |
1257 | 85 | } |
1258 | | |
1259 | | void Sema::ActOnPragmaVisibility(const IdentifierInfo* VisType, |
1260 | 125 | SourceLocation PragmaLoc) { |
1261 | 125 | if (VisType) { |
1262 | | // Compute visibility to use. |
1263 | 64 | VisibilityAttr::VisibilityType T; |
1264 | 64 | if (!VisibilityAttr::ConvertStrToVisibilityType(VisType->getName(), T)) { |
1265 | 1 | Diag(PragmaLoc, diag::warn_attribute_unknown_visibility) << VisType; |
1266 | 1 | return; |
1267 | 1 | } |
1268 | 63 | PushPragmaVisibility(*this, T, PragmaLoc); |
1269 | 63 | } else { |
1270 | 61 | PopPragmaVisibility(false, PragmaLoc); |
1271 | 61 | } |
1272 | 125 | } |
1273 | | |
1274 | | void Sema::ActOnPragmaFPContract(SourceLocation Loc, |
1275 | 51 | LangOptions::FPModeKind FPC) { |
1276 | 51 | FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); |
1277 | 51 | switch (FPC) { |
1278 | 31 | case LangOptions::FPM_On: |
1279 | 31 | NewFPFeatures.setAllowFPContractWithinStatement(); |
1280 | 31 | break; |
1281 | 10 | case LangOptions::FPM_Fast: |
1282 | 10 | NewFPFeatures.setAllowFPContractAcrossStatement(); |
1283 | 10 | break; |
1284 | 10 | case LangOptions::FPM_Off: |
1285 | 10 | NewFPFeatures.setDisallowFPContract(); |
1286 | 10 | break; |
1287 | 0 | case LangOptions::FPM_FastHonorPragmas: |
1288 | 0 | llvm_unreachable("Should not happen"); |
1289 | 51 | } |
1290 | 51 | FpPragmaStack.Act(Loc, Sema::PSK_Set, StringRef(), NewFPFeatures); |
1291 | 51 | CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); |
1292 | 51 | } |
1293 | | |
1294 | 39 | void Sema::ActOnPragmaFPReassociate(SourceLocation Loc, bool IsEnabled) { |
1295 | 39 | if (IsEnabled) { |
1296 | | // For value unsafe context, combining this pragma with eval method |
1297 | | // setting is not recommended. See comment in function FixupInvocation#506. |
1298 | 29 | int Reason = -1; |
1299 | 29 | if (getLangOpts().getFPEvalMethod() != LangOptions::FEM_UnsetOnCommandLine) |
1300 | | // Eval method set using the option 'ffp-eval-method'. |
1301 | 2 | Reason = 1; |
1302 | 29 | if (PP.getLastFPEvalPragmaLocation().isValid()) |
1303 | | // Eval method set using the '#pragma clang fp eval_method'. |
1304 | | // We could have both an option and a pragma used to the set the eval |
1305 | | // method. The pragma overrides the option in the command line. The Reason |
1306 | | // of the diagnostic is overriden too. |
1307 | 7 | Reason = 0; |
1308 | 29 | if (Reason != -1) |
1309 | 8 | Diag(Loc, diag::err_setting_eval_method_used_in_unsafe_context) |
1310 | 8 | << Reason << 4; |
1311 | 29 | } |
1312 | 39 | FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); |
1313 | 39 | NewFPFeatures.setAllowFPReassociateOverride(IsEnabled); |
1314 | 39 | FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures); |
1315 | 39 | CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); |
1316 | 39 | } |
1317 | | |
1318 | 76 | void Sema::ActOnPragmaFEnvRound(SourceLocation Loc, llvm::RoundingMode FPR) { |
1319 | 76 | FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); |
1320 | 76 | NewFPFeatures.setConstRoundingModeOverride(FPR); |
1321 | 76 | FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures); |
1322 | 76 | CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); |
1323 | 76 | } |
1324 | | |
1325 | | void Sema::setExceptionMode(SourceLocation Loc, |
1326 | 16 | LangOptions::FPExceptionModeKind FPE) { |
1327 | 16 | FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); |
1328 | 16 | NewFPFeatures.setSpecifiedExceptionModeOverride(FPE); |
1329 | 16 | FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures); |
1330 | 16 | CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); |
1331 | 16 | } |
1332 | | |
1333 | 74 | void Sema::ActOnPragmaFEnvAccess(SourceLocation Loc, bool IsEnabled) { |
1334 | 74 | FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); |
1335 | 74 | if (IsEnabled) { |
1336 | | // Verify Microsoft restriction: |
1337 | | // You can't enable fenv_access unless precise semantics are enabled. |
1338 | | // Precise semantics can be enabled either by the float_control |
1339 | | // pragma, or by using the /fp:precise or /fp:strict compiler options |
1340 | 50 | if (!isPreciseFPEnabled()) |
1341 | 0 | Diag(Loc, diag::err_pragma_fenv_requires_precise); |
1342 | 50 | } |
1343 | 74 | NewFPFeatures.setAllowFEnvAccessOverride(IsEnabled); |
1344 | 74 | FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures); |
1345 | 74 | CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); |
1346 | 74 | } |
1347 | | |
1348 | | void Sema::ActOnPragmaFPExceptions(SourceLocation Loc, |
1349 | 16 | LangOptions::FPExceptionModeKind FPE) { |
1350 | 16 | setExceptionMode(Loc, FPE); |
1351 | 16 | } |
1352 | | |
1353 | | void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr, |
1354 | 22 | SourceLocation Loc) { |
1355 | | // Visibility calculations will consider the namespace's visibility. |
1356 | | // Here we just want to note that we're in a visibility context |
1357 | | // which overrides any enclosing #pragma context, but doesn't itself |
1358 | | // contribute visibility. |
1359 | 22 | PushPragmaVisibility(*this, NoVisibility, Loc); |
1360 | 22 | } |
1361 | | |
1362 | 83 | void Sema::PopPragmaVisibility(bool IsNamespaceEnd, SourceLocation EndLoc) { |
1363 | 83 | if (!VisContext) { |
1364 | 2 | Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch); |
1365 | 2 | return; |
1366 | 2 | } |
1367 | | |
1368 | | // Pop visibility from stack |
1369 | 81 | VisStack *Stack = static_cast<VisStack*>(VisContext); |
1370 | | |
1371 | 81 | const std::pair<unsigned, SourceLocation> *Back = &Stack->back(); |
1372 | 81 | bool StartsWithPragma = Back->first != NoVisibility; |
1373 | 81 | if (StartsWithPragma && IsNamespaceEnd59 ) { |
1374 | 1 | Diag(Back->second, diag::err_pragma_push_visibility_mismatch); |
1375 | 1 | Diag(EndLoc, diag::note_surrounding_namespace_ends_here); |
1376 | | |
1377 | | // For better error recovery, eat all pushes inside the namespace. |
1378 | 1 | do { |
1379 | 1 | Stack->pop_back(); |
1380 | 1 | Back = &Stack->back(); |
1381 | 1 | StartsWithPragma = Back->first != NoVisibility; |
1382 | 1 | } while (StartsWithPragma); |
1383 | 80 | } else if (!StartsWithPragma && !IsNamespaceEnd22 ) { |
1384 | 1 | Diag(EndLoc, diag::err_pragma_pop_visibility_mismatch); |
1385 | 1 | Diag(Back->second, diag::note_surrounding_namespace_starts_here); |
1386 | 1 | return; |
1387 | 1 | } |
1388 | | |
1389 | 80 | Stack->pop_back(); |
1390 | | // To simplify the implementation, never keep around an empty stack. |
1391 | 80 | if (Stack->empty()) |
1392 | 77 | FreeVisContext(); |
1393 | 80 | } |
1394 | | |
1395 | | template <typename Ty> |
1396 | | static bool checkCommonAttributeFeatures(Sema &S, const Ty *Node, |
1397 | | const ParsedAttr &A, |
1398 | 81.6M | bool SkipArgCountCheck) { |
1399 | | // Several attributes carry different semantics than the parsing requires, so |
1400 | | // those are opted out of the common argument checks. |
1401 | | // |
1402 | | // We also bail on unknown and ignored attributes because those are handled |
1403 | | // as part of the target-specific handling logic. |
1404 | 81.6M | if (A.getKind() == ParsedAttr::UnknownAttribute) |
1405 | 0 | return false; |
1406 | | // Check whether the attribute requires specific language extensions to be |
1407 | | // enabled. |
1408 | 81.6M | if (!A.diagnoseLangOpts(S)) |
1409 | 35 | return true; |
1410 | | // Check whether the attribute appertains to the given subject. |
1411 | 81.6M | if (!A.diagnoseAppertainsTo(S, Node)) |
1412 | 1.07k | return true; |
1413 | | // Check whether the attribute is mutually exclusive with other attributes |
1414 | | // that have already been applied to the declaration. |
1415 | 81.6M | if (!A.diagnoseMutualExclusion(S, Node)) |
1416 | 69 | return true; |
1417 | | // Check whether the attribute exists in the target architecture. |
1418 | 81.6M | if (S.CheckAttrTarget(A)) |
1419 | 0 | return true; |
1420 | | |
1421 | 81.6M | if (A.hasCustomParsing()) |
1422 | 6.04M | return false; |
1423 | | |
1424 | 75.6M | if (!SkipArgCountCheck) { |
1425 | 75.6M | if (A.getMinArgs() == A.getMaxArgs()) { |
1426 | | // If there are no optional arguments, then checking for the argument |
1427 | | // count is trivial. |
1428 | 74.4M | if (!A.checkExactlyNumArgs(S, A.getMinArgs())) |
1429 | 259 | return true; |
1430 | 74.4M | } else { |
1431 | | // There are optional arguments, so checking is slightly more involved. |
1432 | 1.17M | if (A.getMinArgs() && !A.checkAtLeastNumArgs(S, A.getMinArgs())6.31k ) |
1433 | 42 | return true; |
1434 | 1.17M | else if (!A.hasVariadicArg() && A.getMaxArgs()110k && |
1435 | 1.17M | !A.checkAtMostNumArgs(S, A.getMaxArgs())110k ) |
1436 | 14 | return true; |
1437 | 1.17M | } |
1438 | 75.6M | } |
1439 | | |
1440 | 75.6M | return false; |
1441 | 75.6M | } SemaAttr.cpp:bool checkCommonAttributeFeatures<clang::Decl>(clang::Sema&, clang::Decl const*, clang::ParsedAttr const&, bool) Line | Count | Source | 1398 | 81.6M | bool SkipArgCountCheck) { | 1399 | | // Several attributes carry different semantics than the parsing requires, so | 1400 | | // those are opted out of the common argument checks. | 1401 | | // | 1402 | | // We also bail on unknown and ignored attributes because those are handled | 1403 | | // as part of the target-specific handling logic. | 1404 | 81.6M | if (A.getKind() == ParsedAttr::UnknownAttribute) | 1405 | 0 | return false; | 1406 | | // Check whether the attribute requires specific language extensions to be | 1407 | | // enabled. | 1408 | 81.6M | if (!A.diagnoseLangOpts(S)) | 1409 | 35 | return true; | 1410 | | // Check whether the attribute appertains to the given subject. | 1411 | 81.6M | if (!A.diagnoseAppertainsTo(S, Node)) | 1412 | 1.03k | return true; | 1413 | | // Check whether the attribute is mutually exclusive with other attributes | 1414 | | // that have already been applied to the declaration. | 1415 | 81.6M | if (!A.diagnoseMutualExclusion(S, Node)) | 1416 | 69 | return true; | 1417 | | // Check whether the attribute exists in the target architecture. | 1418 | 81.6M | if (S.CheckAttrTarget(A)) | 1419 | 0 | return true; | 1420 | | | 1421 | 81.6M | if (A.hasCustomParsing()) | 1422 | 6.04M | return false; | 1423 | | | 1424 | 75.6M | if (!SkipArgCountCheck) { | 1425 | 75.6M | if (A.getMinArgs() == A.getMaxArgs()) { | 1426 | | // If there are no optional arguments, then checking for the argument | 1427 | | // count is trivial. | 1428 | 74.4M | if (!A.checkExactlyNumArgs(S, A.getMinArgs())) | 1429 | 254 | return true; | 1430 | 74.4M | } else { | 1431 | | // There are optional arguments, so checking is slightly more involved. | 1432 | 1.17M | if (A.getMinArgs() && !A.checkAtLeastNumArgs(S, A.getMinArgs())6.31k ) | 1433 | 42 | return true; | 1434 | 1.17M | else if (!A.hasVariadicArg() && A.getMaxArgs()110k && | 1435 | 1.17M | !A.checkAtMostNumArgs(S, A.getMaxArgs())110k ) | 1436 | 13 | return true; | 1437 | 1.17M | } | 1438 | 75.6M | } | 1439 | | | 1440 | 75.6M | return false; | 1441 | 75.6M | } |
SemaAttr.cpp:bool checkCommonAttributeFeatures<clang::Stmt>(clang::Sema&, clang::Stmt const*, clang::ParsedAttr const&, bool) Line | Count | Source | 1398 | 1.84k | bool SkipArgCountCheck) { | 1399 | | // Several attributes carry different semantics than the parsing requires, so | 1400 | | // those are opted out of the common argument checks. | 1401 | | // | 1402 | | // We also bail on unknown and ignored attributes because those are handled | 1403 | | // as part of the target-specific handling logic. | 1404 | 1.84k | if (A.getKind() == ParsedAttr::UnknownAttribute) | 1405 | 0 | return false; | 1406 | | // Check whether the attribute requires specific language extensions to be | 1407 | | // enabled. | 1408 | 1.84k | if (!A.diagnoseLangOpts(S)) | 1409 | 0 | return true; | 1410 | | // Check whether the attribute appertains to the given subject. | 1411 | 1.84k | if (!A.diagnoseAppertainsTo(S, Node)) | 1412 | 48 | return true; | 1413 | | // Check whether the attribute is mutually exclusive with other attributes | 1414 | | // that have already been applied to the declaration. | 1415 | 1.79k | if (!A.diagnoseMutualExclusion(S, Node)) | 1416 | 0 | return true; | 1417 | | // Check whether the attribute exists in the target architecture. | 1418 | 1.79k | if (S.CheckAttrTarget(A)) | 1419 | 0 | return true; | 1420 | | | 1421 | 1.79k | if (A.hasCustomParsing()) | 1422 | 353 | return false; | 1423 | | | 1424 | 1.44k | if (!SkipArgCountCheck) { | 1425 | 1.44k | if (A.getMinArgs() == A.getMaxArgs()) { | 1426 | | // If there are no optional arguments, then checking for the argument | 1427 | | // count is trivial. | 1428 | 1.41k | if (!A.checkExactlyNumArgs(S, A.getMinArgs())) | 1429 | 5 | return true; | 1430 | 1.41k | } else { | 1431 | | // There are optional arguments, so checking is slightly more involved. | 1432 | 29 | if (A.getMinArgs() && !A.checkAtLeastNumArgs(S, A.getMinArgs())0 ) | 1433 | 0 | return true; | 1434 | 29 | else if (!A.hasVariadicArg() && A.getMaxArgs()24 && | 1435 | 29 | !A.checkAtMostNumArgs(S, A.getMaxArgs())24 ) | 1436 | 1 | return true; | 1437 | 29 | } | 1438 | 1.44k | } | 1439 | | | 1440 | 1.43k | return false; | 1441 | 1.44k | } |
|
1442 | | |
1443 | | bool Sema::checkCommonAttributeFeatures(const Decl *D, const ParsedAttr &A, |
1444 | 81.6M | bool SkipArgCountCheck) { |
1445 | 81.6M | return ::checkCommonAttributeFeatures(*this, D, A, SkipArgCountCheck); |
1446 | 81.6M | } |
1447 | | bool Sema::checkCommonAttributeFeatures(const Stmt *S, const ParsedAttr &A, |
1448 | 1.84k | bool SkipArgCountCheck) { |
1449 | 1.84k | return ::checkCommonAttributeFeatures(*this, S, A, SkipArgCountCheck); |
1450 | 1.84k | } |