1e5dd7070Spatrick //===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick //
9e5dd7070Spatrick // This file implements the language specific #pragma handlers.
10e5dd7070Spatrick //
11e5dd7070Spatrick //===----------------------------------------------------------------------===//
12e5dd7070Spatrick
13e5dd7070Spatrick #include "clang/AST/ASTContext.h"
14e5dd7070Spatrick #include "clang/Basic/PragmaKinds.h"
15e5dd7070Spatrick #include "clang/Basic/TargetInfo.h"
16e5dd7070Spatrick #include "clang/Lex/Preprocessor.h"
17a9ac8606Spatrick #include "clang/Lex/Token.h"
18e5dd7070Spatrick #include "clang/Parse/LoopHint.h"
19e5dd7070Spatrick #include "clang/Parse/ParseDiagnostic.h"
20e5dd7070Spatrick #include "clang/Parse/Parser.h"
21e5dd7070Spatrick #include "clang/Parse/RAIIObjectsForParser.h"
22e5dd7070Spatrick #include "clang/Sema/Scope.h"
23a9ac8606Spatrick #include "llvm/ADT/ArrayRef.h"
24e5dd7070Spatrick #include "llvm/ADT/StringSwitch.h"
25*12c85518Srobert #include <optional>
26e5dd7070Spatrick using namespace clang;
27e5dd7070Spatrick
28e5dd7070Spatrick namespace {
29e5dd7070Spatrick
30e5dd7070Spatrick struct PragmaAlignHandler : public PragmaHandler {
PragmaAlignHandler__anon4a1872ae0111::PragmaAlignHandler31e5dd7070Spatrick explicit PragmaAlignHandler() : PragmaHandler("align") {}
32e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
33e5dd7070Spatrick Token &FirstToken) override;
34e5dd7070Spatrick };
35e5dd7070Spatrick
36e5dd7070Spatrick struct PragmaGCCVisibilityHandler : public PragmaHandler {
PragmaGCCVisibilityHandler__anon4a1872ae0111::PragmaGCCVisibilityHandler37e5dd7070Spatrick explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
38e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
39e5dd7070Spatrick Token &FirstToken) override;
40e5dd7070Spatrick };
41e5dd7070Spatrick
42e5dd7070Spatrick struct PragmaOptionsHandler : public PragmaHandler {
PragmaOptionsHandler__anon4a1872ae0111::PragmaOptionsHandler43e5dd7070Spatrick explicit PragmaOptionsHandler() : PragmaHandler("options") {}
44e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
45e5dd7070Spatrick Token &FirstToken) override;
46e5dd7070Spatrick };
47e5dd7070Spatrick
48e5dd7070Spatrick struct PragmaPackHandler : public PragmaHandler {
PragmaPackHandler__anon4a1872ae0111::PragmaPackHandler49e5dd7070Spatrick explicit PragmaPackHandler() : PragmaHandler("pack") {}
50e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
51e5dd7070Spatrick Token &FirstToken) override;
52e5dd7070Spatrick };
53e5dd7070Spatrick
54e5dd7070Spatrick struct PragmaClangSectionHandler : public PragmaHandler {
PragmaClangSectionHandler__anon4a1872ae0111::PragmaClangSectionHandler55e5dd7070Spatrick explicit PragmaClangSectionHandler(Sema &S)
56e5dd7070Spatrick : PragmaHandler("section"), Actions(S) {}
57e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
58e5dd7070Spatrick Token &FirstToken) override;
59e5dd7070Spatrick
60e5dd7070Spatrick private:
61e5dd7070Spatrick Sema &Actions;
62e5dd7070Spatrick };
63e5dd7070Spatrick
64e5dd7070Spatrick struct PragmaMSStructHandler : public PragmaHandler {
PragmaMSStructHandler__anon4a1872ae0111::PragmaMSStructHandler65e5dd7070Spatrick explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
66e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
67e5dd7070Spatrick Token &FirstToken) override;
68e5dd7070Spatrick };
69e5dd7070Spatrick
70e5dd7070Spatrick struct PragmaUnusedHandler : public PragmaHandler {
PragmaUnusedHandler__anon4a1872ae0111::PragmaUnusedHandler71e5dd7070Spatrick PragmaUnusedHandler() : PragmaHandler("unused") {}
72e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
73e5dd7070Spatrick Token &FirstToken) override;
74e5dd7070Spatrick };
75e5dd7070Spatrick
76e5dd7070Spatrick struct PragmaWeakHandler : public PragmaHandler {
PragmaWeakHandler__anon4a1872ae0111::PragmaWeakHandler77e5dd7070Spatrick explicit PragmaWeakHandler() : PragmaHandler("weak") {}
78e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
79e5dd7070Spatrick Token &FirstToken) override;
80e5dd7070Spatrick };
81e5dd7070Spatrick
82e5dd7070Spatrick struct PragmaRedefineExtnameHandler : public PragmaHandler {
PragmaRedefineExtnameHandler__anon4a1872ae0111::PragmaRedefineExtnameHandler83e5dd7070Spatrick explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
84e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
85e5dd7070Spatrick Token &FirstToken) override;
86e5dd7070Spatrick };
87e5dd7070Spatrick
88e5dd7070Spatrick struct PragmaOpenCLExtensionHandler : public PragmaHandler {
PragmaOpenCLExtensionHandler__anon4a1872ae0111::PragmaOpenCLExtensionHandler89e5dd7070Spatrick PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
90e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
91e5dd7070Spatrick Token &FirstToken) override;
92e5dd7070Spatrick };
93e5dd7070Spatrick
94e5dd7070Spatrick
95e5dd7070Spatrick struct PragmaFPContractHandler : public PragmaHandler {
PragmaFPContractHandler__anon4a1872ae0111::PragmaFPContractHandler96e5dd7070Spatrick PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
97e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
98e5dd7070Spatrick Token &FirstToken) override;
99e5dd7070Spatrick };
100e5dd7070Spatrick
101e5dd7070Spatrick // Pragma STDC implementations.
102e5dd7070Spatrick
103e5dd7070Spatrick /// PragmaSTDC_FENV_ACCESSHandler - "\#pragma STDC FENV_ACCESS ...".
104e5dd7070Spatrick struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler {
PragmaSTDC_FENV_ACCESSHandler__anon4a1872ae0111::PragmaSTDC_FENV_ACCESSHandler105e5dd7070Spatrick PragmaSTDC_FENV_ACCESSHandler() : PragmaHandler("FENV_ACCESS") {}
106e5dd7070Spatrick
HandlePragma__anon4a1872ae0111::PragmaSTDC_FENV_ACCESSHandler107e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
108e5dd7070Spatrick Token &Tok) override {
109a9ac8606Spatrick Token PragmaName = Tok;
110a9ac8606Spatrick if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
111a9ac8606Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
112a9ac8606Spatrick << PragmaName.getIdentifierInfo()->getName();
113a9ac8606Spatrick return;
114a9ac8606Spatrick }
115e5dd7070Spatrick tok::OnOffSwitch OOS;
116e5dd7070Spatrick if (PP.LexOnOffSwitch(OOS))
117e5dd7070Spatrick return;
118e5dd7070Spatrick
119e5dd7070Spatrick MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
120e5dd7070Spatrick 1);
121e5dd7070Spatrick Toks[0].startToken();
122e5dd7070Spatrick Toks[0].setKind(tok::annot_pragma_fenv_access);
123e5dd7070Spatrick Toks[0].setLocation(Tok.getLocation());
124e5dd7070Spatrick Toks[0].setAnnotationEndLoc(Tok.getLocation());
125e5dd7070Spatrick Toks[0].setAnnotationValue(reinterpret_cast<void*>(
126e5dd7070Spatrick static_cast<uintptr_t>(OOS)));
127e5dd7070Spatrick PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
128e5dd7070Spatrick /*IsReinject=*/false);
129e5dd7070Spatrick }
130e5dd7070Spatrick };
131e5dd7070Spatrick
132e5dd7070Spatrick /// PragmaSTDC_CX_LIMITED_RANGEHandler - "\#pragma STDC CX_LIMITED_RANGE ...".
133e5dd7070Spatrick struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler {
PragmaSTDC_CX_LIMITED_RANGEHandler__anon4a1872ae0111::PragmaSTDC_CX_LIMITED_RANGEHandler134e5dd7070Spatrick PragmaSTDC_CX_LIMITED_RANGEHandler() : PragmaHandler("CX_LIMITED_RANGE") {}
135e5dd7070Spatrick
HandlePragma__anon4a1872ae0111::PragmaSTDC_CX_LIMITED_RANGEHandler136e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
137e5dd7070Spatrick Token &Tok) override {
138e5dd7070Spatrick tok::OnOffSwitch OOS;
139e5dd7070Spatrick PP.LexOnOffSwitch(OOS);
140e5dd7070Spatrick }
141e5dd7070Spatrick };
142e5dd7070Spatrick
143a9ac8606Spatrick /// Handler for "\#pragma STDC FENV_ROUND ...".
144a9ac8606Spatrick struct PragmaSTDC_FENV_ROUNDHandler : public PragmaHandler {
PragmaSTDC_FENV_ROUNDHandler__anon4a1872ae0111::PragmaSTDC_FENV_ROUNDHandler145a9ac8606Spatrick PragmaSTDC_FENV_ROUNDHandler() : PragmaHandler("FENV_ROUND") {}
146a9ac8606Spatrick
147a9ac8606Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
148a9ac8606Spatrick Token &Tok) override;
149a9ac8606Spatrick };
150a9ac8606Spatrick
151e5dd7070Spatrick /// PragmaSTDC_UnknownHandler - "\#pragma STDC ...".
152e5dd7070Spatrick struct PragmaSTDC_UnknownHandler : public PragmaHandler {
153e5dd7070Spatrick PragmaSTDC_UnknownHandler() = default;
154e5dd7070Spatrick
HandlePragma__anon4a1872ae0111::PragmaSTDC_UnknownHandler155e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
156e5dd7070Spatrick Token &UnknownTok) override {
157e5dd7070Spatrick // C99 6.10.6p2, unknown forms are not allowed.
158e5dd7070Spatrick PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored);
159e5dd7070Spatrick }
160e5dd7070Spatrick };
161e5dd7070Spatrick
162e5dd7070Spatrick struct PragmaFPHandler : public PragmaHandler {
PragmaFPHandler__anon4a1872ae0111::PragmaFPHandler163e5dd7070Spatrick PragmaFPHandler() : PragmaHandler("fp") {}
164e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
165e5dd7070Spatrick Token &FirstToken) override;
166e5dd7070Spatrick };
167e5dd7070Spatrick
168e5dd7070Spatrick struct PragmaNoOpenMPHandler : public PragmaHandler {
PragmaNoOpenMPHandler__anon4a1872ae0111::PragmaNoOpenMPHandler169e5dd7070Spatrick PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
170e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
171e5dd7070Spatrick Token &FirstToken) override;
172e5dd7070Spatrick };
173e5dd7070Spatrick
174e5dd7070Spatrick struct PragmaOpenMPHandler : public PragmaHandler {
PragmaOpenMPHandler__anon4a1872ae0111::PragmaOpenMPHandler175e5dd7070Spatrick PragmaOpenMPHandler() : PragmaHandler("omp") { }
176e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
177e5dd7070Spatrick Token &FirstToken) override;
178e5dd7070Spatrick };
179e5dd7070Spatrick
180e5dd7070Spatrick /// PragmaCommentHandler - "\#pragma comment ...".
181e5dd7070Spatrick struct PragmaCommentHandler : public PragmaHandler {
PragmaCommentHandler__anon4a1872ae0111::PragmaCommentHandler182e5dd7070Spatrick PragmaCommentHandler(Sema &Actions)
183e5dd7070Spatrick : PragmaHandler("comment"), Actions(Actions) {}
184e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
185e5dd7070Spatrick Token &FirstToken) override;
186e5dd7070Spatrick
187e5dd7070Spatrick private:
188e5dd7070Spatrick Sema &Actions;
189e5dd7070Spatrick };
190e5dd7070Spatrick
191e5dd7070Spatrick struct PragmaDetectMismatchHandler : public PragmaHandler {
PragmaDetectMismatchHandler__anon4a1872ae0111::PragmaDetectMismatchHandler192e5dd7070Spatrick PragmaDetectMismatchHandler(Sema &Actions)
193e5dd7070Spatrick : PragmaHandler("detect_mismatch"), Actions(Actions) {}
194e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
195e5dd7070Spatrick Token &FirstToken) override;
196e5dd7070Spatrick
197e5dd7070Spatrick private:
198e5dd7070Spatrick Sema &Actions;
199e5dd7070Spatrick };
200e5dd7070Spatrick
201ec727ea7Spatrick struct PragmaFloatControlHandler : public PragmaHandler {
PragmaFloatControlHandler__anon4a1872ae0111::PragmaFloatControlHandler202ec727ea7Spatrick PragmaFloatControlHandler(Sema &Actions)
203ec727ea7Spatrick : PragmaHandler("float_control") {}
204ec727ea7Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
205ec727ea7Spatrick Token &FirstToken) override;
206ec727ea7Spatrick };
207ec727ea7Spatrick
208e5dd7070Spatrick struct PragmaMSPointersToMembers : public PragmaHandler {
PragmaMSPointersToMembers__anon4a1872ae0111::PragmaMSPointersToMembers209e5dd7070Spatrick explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
210e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
211e5dd7070Spatrick Token &FirstToken) override;
212e5dd7070Spatrick };
213e5dd7070Spatrick
214e5dd7070Spatrick struct PragmaMSVtorDisp : public PragmaHandler {
PragmaMSVtorDisp__anon4a1872ae0111::PragmaMSVtorDisp215e5dd7070Spatrick explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
216e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
217e5dd7070Spatrick Token &FirstToken) override;
218e5dd7070Spatrick };
219e5dd7070Spatrick
220e5dd7070Spatrick struct PragmaMSPragma : public PragmaHandler {
PragmaMSPragma__anon4a1872ae0111::PragmaMSPragma221e5dd7070Spatrick explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
222e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
223e5dd7070Spatrick Token &FirstToken) override;
224e5dd7070Spatrick };
225e5dd7070Spatrick
226e5dd7070Spatrick /// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
227e5dd7070Spatrick struct PragmaOptimizeHandler : public PragmaHandler {
PragmaOptimizeHandler__anon4a1872ae0111::PragmaOptimizeHandler228e5dd7070Spatrick PragmaOptimizeHandler(Sema &S)
229e5dd7070Spatrick : PragmaHandler("optimize"), Actions(S) {}
230e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
231e5dd7070Spatrick Token &FirstToken) override;
232e5dd7070Spatrick
233e5dd7070Spatrick private:
234e5dd7070Spatrick Sema &Actions;
235e5dd7070Spatrick };
236e5dd7070Spatrick
237e5dd7070Spatrick struct PragmaLoopHintHandler : public PragmaHandler {
PragmaLoopHintHandler__anon4a1872ae0111::PragmaLoopHintHandler238e5dd7070Spatrick PragmaLoopHintHandler() : PragmaHandler("loop") {}
239e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
240e5dd7070Spatrick Token &FirstToken) override;
241e5dd7070Spatrick };
242e5dd7070Spatrick
243e5dd7070Spatrick struct PragmaUnrollHintHandler : public PragmaHandler {
PragmaUnrollHintHandler__anon4a1872ae0111::PragmaUnrollHintHandler244e5dd7070Spatrick PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {}
245e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
246e5dd7070Spatrick Token &FirstToken) override;
247e5dd7070Spatrick };
248e5dd7070Spatrick
249e5dd7070Spatrick struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler {
PragmaMSRuntimeChecksHandler__anon4a1872ae0111::PragmaMSRuntimeChecksHandler250e5dd7070Spatrick PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {}
251e5dd7070Spatrick };
252e5dd7070Spatrick
253e5dd7070Spatrick struct PragmaMSIntrinsicHandler : public PragmaHandler {
PragmaMSIntrinsicHandler__anon4a1872ae0111::PragmaMSIntrinsicHandler254e5dd7070Spatrick PragmaMSIntrinsicHandler() : PragmaHandler("intrinsic") {}
255e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
256e5dd7070Spatrick Token &FirstToken) override;
257e5dd7070Spatrick };
258e5dd7070Spatrick
259*12c85518Srobert // "\#pragma fenv_access (on)".
260*12c85518Srobert struct PragmaMSFenvAccessHandler : public PragmaHandler {
PragmaMSFenvAccessHandler__anon4a1872ae0111::PragmaMSFenvAccessHandler261*12c85518Srobert PragmaMSFenvAccessHandler() : PragmaHandler("fenv_access") {}
HandlePragma__anon4a1872ae0111::PragmaMSFenvAccessHandler262e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
263*12c85518Srobert Token &FirstToken) override {
264*12c85518Srobert StringRef PragmaName = FirstToken.getIdentifierInfo()->getName();
265*12c85518Srobert if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
266*12c85518Srobert PP.Diag(FirstToken.getLocation(), diag::warn_pragma_fp_ignored)
267*12c85518Srobert << PragmaName;
268*12c85518Srobert return;
269*12c85518Srobert }
270*12c85518Srobert
271*12c85518Srobert Token Tok;
272*12c85518Srobert PP.Lex(Tok);
273*12c85518Srobert if (Tok.isNot(tok::l_paren)) {
274*12c85518Srobert PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
275*12c85518Srobert << PragmaName;
276*12c85518Srobert return;
277*12c85518Srobert }
278*12c85518Srobert PP.Lex(Tok); // Consume the l_paren.
279*12c85518Srobert if (Tok.isNot(tok::identifier)) {
280*12c85518Srobert PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_fenv_access);
281*12c85518Srobert return;
282*12c85518Srobert }
283*12c85518Srobert const IdentifierInfo *II = Tok.getIdentifierInfo();
284*12c85518Srobert tok::OnOffSwitch OOS;
285*12c85518Srobert if (II->isStr("on")) {
286*12c85518Srobert OOS = tok::OOS_ON;
287*12c85518Srobert PP.Lex(Tok);
288*12c85518Srobert } else if (II->isStr("off")) {
289*12c85518Srobert OOS = tok::OOS_OFF;
290*12c85518Srobert PP.Lex(Tok);
291*12c85518Srobert } else {
292*12c85518Srobert PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_fenv_access);
293*12c85518Srobert return;
294*12c85518Srobert }
295*12c85518Srobert if (Tok.isNot(tok::r_paren)) {
296*12c85518Srobert PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
297*12c85518Srobert << PragmaName;
298*12c85518Srobert return;
299*12c85518Srobert }
300*12c85518Srobert PP.Lex(Tok); // Consume the r_paren.
301*12c85518Srobert
302*12c85518Srobert if (Tok.isNot(tok::eod)) {
303*12c85518Srobert PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
304*12c85518Srobert << PragmaName;
305*12c85518Srobert return;
306*12c85518Srobert }
307*12c85518Srobert
308*12c85518Srobert MutableArrayRef<Token> Toks(
309*12c85518Srobert PP.getPreprocessorAllocator().Allocate<Token>(1), 1);
310*12c85518Srobert Toks[0].startToken();
311*12c85518Srobert Toks[0].setKind(tok::annot_pragma_fenv_access_ms);
312*12c85518Srobert Toks[0].setLocation(FirstToken.getLocation());
313*12c85518Srobert Toks[0].setAnnotationEndLoc(Tok.getLocation());
314*12c85518Srobert Toks[0].setAnnotationValue(
315*12c85518Srobert reinterpret_cast<void*>(static_cast<uintptr_t>(OOS)));
316*12c85518Srobert PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
317*12c85518Srobert /*IsReinject=*/false);
318*12c85518Srobert }
319e5dd7070Spatrick };
320e5dd7070Spatrick
321e5dd7070Spatrick struct PragmaForceCUDAHostDeviceHandler : public PragmaHandler {
PragmaForceCUDAHostDeviceHandler__anon4a1872ae0111::PragmaForceCUDAHostDeviceHandler322e5dd7070Spatrick PragmaForceCUDAHostDeviceHandler(Sema &Actions)
323e5dd7070Spatrick : PragmaHandler("force_cuda_host_device"), Actions(Actions) {}
324e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
325e5dd7070Spatrick Token &FirstToken) override;
326e5dd7070Spatrick
327e5dd7070Spatrick private:
328e5dd7070Spatrick Sema &Actions;
329e5dd7070Spatrick };
330e5dd7070Spatrick
331e5dd7070Spatrick /// PragmaAttributeHandler - "\#pragma clang attribute ...".
332e5dd7070Spatrick struct PragmaAttributeHandler : public PragmaHandler {
PragmaAttributeHandler__anon4a1872ae0111::PragmaAttributeHandler333e5dd7070Spatrick PragmaAttributeHandler(AttributeFactory &AttrFactory)
334e5dd7070Spatrick : PragmaHandler("attribute"), AttributesForPragmaAttribute(AttrFactory) {}
335e5dd7070Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
336e5dd7070Spatrick Token &FirstToken) override;
337e5dd7070Spatrick
338e5dd7070Spatrick /// A pool of attributes that were parsed in \#pragma clang attribute.
339e5dd7070Spatrick ParsedAttributes AttributesForPragmaAttribute;
340e5dd7070Spatrick };
341e5dd7070Spatrick
342ec727ea7Spatrick struct PragmaMaxTokensHereHandler : public PragmaHandler {
PragmaMaxTokensHereHandler__anon4a1872ae0111::PragmaMaxTokensHereHandler343ec727ea7Spatrick PragmaMaxTokensHereHandler() : PragmaHandler("max_tokens_here") {}
344ec727ea7Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
345ec727ea7Spatrick Token &FirstToken) override;
346ec727ea7Spatrick };
347ec727ea7Spatrick
348ec727ea7Spatrick struct PragmaMaxTokensTotalHandler : public PragmaHandler {
PragmaMaxTokensTotalHandler__anon4a1872ae0111::PragmaMaxTokensTotalHandler349ec727ea7Spatrick PragmaMaxTokensTotalHandler() : PragmaHandler("max_tokens_total") {}
350ec727ea7Spatrick void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
351ec727ea7Spatrick Token &FirstToken) override;
352ec727ea7Spatrick };
353ec727ea7Spatrick
354*12c85518Srobert struct PragmaRISCVHandler : public PragmaHandler {
PragmaRISCVHandler__anon4a1872ae0111::PragmaRISCVHandler355*12c85518Srobert PragmaRISCVHandler(Sema &Actions)
356*12c85518Srobert : PragmaHandler("riscv"), Actions(Actions) {}
357*12c85518Srobert void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
358*12c85518Srobert Token &FirstToken) override;
359*12c85518Srobert
360*12c85518Srobert private:
361*12c85518Srobert Sema &Actions;
362*12c85518Srobert };
363*12c85518Srobert
markAsReinjectedForRelexing(llvm::MutableArrayRef<clang::Token> Toks)364a9ac8606Spatrick void markAsReinjectedForRelexing(llvm::MutableArrayRef<clang::Token> Toks) {
365a9ac8606Spatrick for (auto &T : Toks)
366a9ac8606Spatrick T.setFlag(clang::Token::IsReinjected);
367a9ac8606Spatrick }
368e5dd7070Spatrick } // end namespace
369e5dd7070Spatrick
initializePragmaHandlers()370e5dd7070Spatrick void Parser::initializePragmaHandlers() {
371e5dd7070Spatrick AlignHandler = std::make_unique<PragmaAlignHandler>();
372e5dd7070Spatrick PP.AddPragmaHandler(AlignHandler.get());
373e5dd7070Spatrick
374e5dd7070Spatrick GCCVisibilityHandler = std::make_unique<PragmaGCCVisibilityHandler>();
375e5dd7070Spatrick PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
376e5dd7070Spatrick
377e5dd7070Spatrick OptionsHandler = std::make_unique<PragmaOptionsHandler>();
378e5dd7070Spatrick PP.AddPragmaHandler(OptionsHandler.get());
379e5dd7070Spatrick
380e5dd7070Spatrick PackHandler = std::make_unique<PragmaPackHandler>();
381e5dd7070Spatrick PP.AddPragmaHandler(PackHandler.get());
382e5dd7070Spatrick
383e5dd7070Spatrick MSStructHandler = std::make_unique<PragmaMSStructHandler>();
384e5dd7070Spatrick PP.AddPragmaHandler(MSStructHandler.get());
385e5dd7070Spatrick
386e5dd7070Spatrick UnusedHandler = std::make_unique<PragmaUnusedHandler>();
387e5dd7070Spatrick PP.AddPragmaHandler(UnusedHandler.get());
388e5dd7070Spatrick
389e5dd7070Spatrick WeakHandler = std::make_unique<PragmaWeakHandler>();
390e5dd7070Spatrick PP.AddPragmaHandler(WeakHandler.get());
391e5dd7070Spatrick
392e5dd7070Spatrick RedefineExtnameHandler = std::make_unique<PragmaRedefineExtnameHandler>();
393e5dd7070Spatrick PP.AddPragmaHandler(RedefineExtnameHandler.get());
394e5dd7070Spatrick
395e5dd7070Spatrick FPContractHandler = std::make_unique<PragmaFPContractHandler>();
396e5dd7070Spatrick PP.AddPragmaHandler("STDC", FPContractHandler.get());
397e5dd7070Spatrick
398a9ac8606Spatrick STDCFenvAccessHandler = std::make_unique<PragmaSTDC_FENV_ACCESSHandler>();
399a9ac8606Spatrick PP.AddPragmaHandler("STDC", STDCFenvAccessHandler.get());
400a9ac8606Spatrick
401a9ac8606Spatrick STDCFenvRoundHandler = std::make_unique<PragmaSTDC_FENV_ROUNDHandler>();
402a9ac8606Spatrick PP.AddPragmaHandler("STDC", STDCFenvRoundHandler.get());
403e5dd7070Spatrick
404e5dd7070Spatrick STDCCXLIMITHandler = std::make_unique<PragmaSTDC_CX_LIMITED_RANGEHandler>();
405e5dd7070Spatrick PP.AddPragmaHandler("STDC", STDCCXLIMITHandler.get());
406e5dd7070Spatrick
407e5dd7070Spatrick STDCUnknownHandler = std::make_unique<PragmaSTDC_UnknownHandler>();
408e5dd7070Spatrick PP.AddPragmaHandler("STDC", STDCUnknownHandler.get());
409e5dd7070Spatrick
410e5dd7070Spatrick PCSectionHandler = std::make_unique<PragmaClangSectionHandler>(Actions);
411e5dd7070Spatrick PP.AddPragmaHandler("clang", PCSectionHandler.get());
412e5dd7070Spatrick
413e5dd7070Spatrick if (getLangOpts().OpenCL) {
414e5dd7070Spatrick OpenCLExtensionHandler = std::make_unique<PragmaOpenCLExtensionHandler>();
415e5dd7070Spatrick PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
416e5dd7070Spatrick
417e5dd7070Spatrick PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
418e5dd7070Spatrick }
419e5dd7070Spatrick if (getLangOpts().OpenMP)
420e5dd7070Spatrick OpenMPHandler = std::make_unique<PragmaOpenMPHandler>();
421e5dd7070Spatrick else
422e5dd7070Spatrick OpenMPHandler = std::make_unique<PragmaNoOpenMPHandler>();
423e5dd7070Spatrick PP.AddPragmaHandler(OpenMPHandler.get());
424e5dd7070Spatrick
425e5dd7070Spatrick if (getLangOpts().MicrosoftExt ||
426e5dd7070Spatrick getTargetInfo().getTriple().isOSBinFormatELF()) {
427e5dd7070Spatrick MSCommentHandler = std::make_unique<PragmaCommentHandler>(Actions);
428e5dd7070Spatrick PP.AddPragmaHandler(MSCommentHandler.get());
429e5dd7070Spatrick }
430e5dd7070Spatrick
431ec727ea7Spatrick FloatControlHandler = std::make_unique<PragmaFloatControlHandler>(Actions);
432ec727ea7Spatrick PP.AddPragmaHandler(FloatControlHandler.get());
433e5dd7070Spatrick if (getLangOpts().MicrosoftExt) {
434e5dd7070Spatrick MSDetectMismatchHandler =
435e5dd7070Spatrick std::make_unique<PragmaDetectMismatchHandler>(Actions);
436e5dd7070Spatrick PP.AddPragmaHandler(MSDetectMismatchHandler.get());
437e5dd7070Spatrick MSPointersToMembers = std::make_unique<PragmaMSPointersToMembers>();
438e5dd7070Spatrick PP.AddPragmaHandler(MSPointersToMembers.get());
439e5dd7070Spatrick MSVtorDisp = std::make_unique<PragmaMSVtorDisp>();
440e5dd7070Spatrick PP.AddPragmaHandler(MSVtorDisp.get());
441e5dd7070Spatrick MSInitSeg = std::make_unique<PragmaMSPragma>("init_seg");
442e5dd7070Spatrick PP.AddPragmaHandler(MSInitSeg.get());
443e5dd7070Spatrick MSDataSeg = std::make_unique<PragmaMSPragma>("data_seg");
444e5dd7070Spatrick PP.AddPragmaHandler(MSDataSeg.get());
445e5dd7070Spatrick MSBSSSeg = std::make_unique<PragmaMSPragma>("bss_seg");
446e5dd7070Spatrick PP.AddPragmaHandler(MSBSSSeg.get());
447e5dd7070Spatrick MSConstSeg = std::make_unique<PragmaMSPragma>("const_seg");
448e5dd7070Spatrick PP.AddPragmaHandler(MSConstSeg.get());
449e5dd7070Spatrick MSCodeSeg = std::make_unique<PragmaMSPragma>("code_seg");
450e5dd7070Spatrick PP.AddPragmaHandler(MSCodeSeg.get());
451e5dd7070Spatrick MSSection = std::make_unique<PragmaMSPragma>("section");
452e5dd7070Spatrick PP.AddPragmaHandler(MSSection.get());
453*12c85518Srobert MSStrictGuardStackCheck =
454*12c85518Srobert std::make_unique<PragmaMSPragma>("strict_gs_check");
455*12c85518Srobert PP.AddPragmaHandler(MSStrictGuardStackCheck.get());
456*12c85518Srobert MSFunction = std::make_unique<PragmaMSPragma>("function");
457*12c85518Srobert PP.AddPragmaHandler(MSFunction.get());
458*12c85518Srobert MSAllocText = std::make_unique<PragmaMSPragma>("alloc_text");
459*12c85518Srobert PP.AddPragmaHandler(MSAllocText.get());
460*12c85518Srobert MSOptimize = std::make_unique<PragmaMSPragma>("optimize");
461*12c85518Srobert PP.AddPragmaHandler(MSOptimize.get());
462e5dd7070Spatrick MSRuntimeChecks = std::make_unique<PragmaMSRuntimeChecksHandler>();
463e5dd7070Spatrick PP.AddPragmaHandler(MSRuntimeChecks.get());
464e5dd7070Spatrick MSIntrinsic = std::make_unique<PragmaMSIntrinsicHandler>();
465e5dd7070Spatrick PP.AddPragmaHandler(MSIntrinsic.get());
466*12c85518Srobert MSFenvAccess = std::make_unique<PragmaMSFenvAccessHandler>();
467*12c85518Srobert PP.AddPragmaHandler(MSFenvAccess.get());
468e5dd7070Spatrick }
469e5dd7070Spatrick
470e5dd7070Spatrick if (getLangOpts().CUDA) {
471e5dd7070Spatrick CUDAForceHostDeviceHandler =
472e5dd7070Spatrick std::make_unique<PragmaForceCUDAHostDeviceHandler>(Actions);
473e5dd7070Spatrick PP.AddPragmaHandler("clang", CUDAForceHostDeviceHandler.get());
474e5dd7070Spatrick }
475e5dd7070Spatrick
476e5dd7070Spatrick OptimizeHandler = std::make_unique<PragmaOptimizeHandler>(Actions);
477e5dd7070Spatrick PP.AddPragmaHandler("clang", OptimizeHandler.get());
478e5dd7070Spatrick
479e5dd7070Spatrick LoopHintHandler = std::make_unique<PragmaLoopHintHandler>();
480e5dd7070Spatrick PP.AddPragmaHandler("clang", LoopHintHandler.get());
481e5dd7070Spatrick
482e5dd7070Spatrick UnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("unroll");
483e5dd7070Spatrick PP.AddPragmaHandler(UnrollHintHandler.get());
484a9ac8606Spatrick PP.AddPragmaHandler("GCC", UnrollHintHandler.get());
485e5dd7070Spatrick
486e5dd7070Spatrick NoUnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("nounroll");
487e5dd7070Spatrick PP.AddPragmaHandler(NoUnrollHintHandler.get());
488a9ac8606Spatrick PP.AddPragmaHandler("GCC", NoUnrollHintHandler.get());
489e5dd7070Spatrick
490e5dd7070Spatrick UnrollAndJamHintHandler =
491e5dd7070Spatrick std::make_unique<PragmaUnrollHintHandler>("unroll_and_jam");
492e5dd7070Spatrick PP.AddPragmaHandler(UnrollAndJamHintHandler.get());
493e5dd7070Spatrick
494e5dd7070Spatrick NoUnrollAndJamHintHandler =
495e5dd7070Spatrick std::make_unique<PragmaUnrollHintHandler>("nounroll_and_jam");
496e5dd7070Spatrick PP.AddPragmaHandler(NoUnrollAndJamHintHandler.get());
497e5dd7070Spatrick
498e5dd7070Spatrick FPHandler = std::make_unique<PragmaFPHandler>();
499e5dd7070Spatrick PP.AddPragmaHandler("clang", FPHandler.get());
500e5dd7070Spatrick
501e5dd7070Spatrick AttributePragmaHandler =
502e5dd7070Spatrick std::make_unique<PragmaAttributeHandler>(AttrFactory);
503e5dd7070Spatrick PP.AddPragmaHandler("clang", AttributePragmaHandler.get());
504ec727ea7Spatrick
505ec727ea7Spatrick MaxTokensHerePragmaHandler = std::make_unique<PragmaMaxTokensHereHandler>();
506ec727ea7Spatrick PP.AddPragmaHandler("clang", MaxTokensHerePragmaHandler.get());
507ec727ea7Spatrick
508ec727ea7Spatrick MaxTokensTotalPragmaHandler = std::make_unique<PragmaMaxTokensTotalHandler>();
509ec727ea7Spatrick PP.AddPragmaHandler("clang", MaxTokensTotalPragmaHandler.get());
510*12c85518Srobert
511*12c85518Srobert if (getTargetInfo().getTriple().isRISCV()) {
512*12c85518Srobert RISCVPragmaHandler = std::make_unique<PragmaRISCVHandler>(Actions);
513*12c85518Srobert PP.AddPragmaHandler("clang", RISCVPragmaHandler.get());
514*12c85518Srobert }
515e5dd7070Spatrick }
516e5dd7070Spatrick
resetPragmaHandlers()517e5dd7070Spatrick void Parser::resetPragmaHandlers() {
518e5dd7070Spatrick // Remove the pragma handlers we installed.
519e5dd7070Spatrick PP.RemovePragmaHandler(AlignHandler.get());
520e5dd7070Spatrick AlignHandler.reset();
521e5dd7070Spatrick PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
522e5dd7070Spatrick GCCVisibilityHandler.reset();
523e5dd7070Spatrick PP.RemovePragmaHandler(OptionsHandler.get());
524e5dd7070Spatrick OptionsHandler.reset();
525e5dd7070Spatrick PP.RemovePragmaHandler(PackHandler.get());
526e5dd7070Spatrick PackHandler.reset();
527e5dd7070Spatrick PP.RemovePragmaHandler(MSStructHandler.get());
528e5dd7070Spatrick MSStructHandler.reset();
529e5dd7070Spatrick PP.RemovePragmaHandler(UnusedHandler.get());
530e5dd7070Spatrick UnusedHandler.reset();
531e5dd7070Spatrick PP.RemovePragmaHandler(WeakHandler.get());
532e5dd7070Spatrick WeakHandler.reset();
533e5dd7070Spatrick PP.RemovePragmaHandler(RedefineExtnameHandler.get());
534e5dd7070Spatrick RedefineExtnameHandler.reset();
535e5dd7070Spatrick
536e5dd7070Spatrick if (getLangOpts().OpenCL) {
537e5dd7070Spatrick PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
538e5dd7070Spatrick OpenCLExtensionHandler.reset();
539e5dd7070Spatrick PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
540e5dd7070Spatrick }
541e5dd7070Spatrick PP.RemovePragmaHandler(OpenMPHandler.get());
542e5dd7070Spatrick OpenMPHandler.reset();
543e5dd7070Spatrick
544e5dd7070Spatrick if (getLangOpts().MicrosoftExt ||
545e5dd7070Spatrick getTargetInfo().getTriple().isOSBinFormatELF()) {
546e5dd7070Spatrick PP.RemovePragmaHandler(MSCommentHandler.get());
547e5dd7070Spatrick MSCommentHandler.reset();
548e5dd7070Spatrick }
549e5dd7070Spatrick
550e5dd7070Spatrick PP.RemovePragmaHandler("clang", PCSectionHandler.get());
551e5dd7070Spatrick PCSectionHandler.reset();
552e5dd7070Spatrick
553ec727ea7Spatrick PP.RemovePragmaHandler(FloatControlHandler.get());
554ec727ea7Spatrick FloatControlHandler.reset();
555e5dd7070Spatrick if (getLangOpts().MicrosoftExt) {
556e5dd7070Spatrick PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
557e5dd7070Spatrick MSDetectMismatchHandler.reset();
558e5dd7070Spatrick PP.RemovePragmaHandler(MSPointersToMembers.get());
559e5dd7070Spatrick MSPointersToMembers.reset();
560e5dd7070Spatrick PP.RemovePragmaHandler(MSVtorDisp.get());
561e5dd7070Spatrick MSVtorDisp.reset();
562e5dd7070Spatrick PP.RemovePragmaHandler(MSInitSeg.get());
563e5dd7070Spatrick MSInitSeg.reset();
564e5dd7070Spatrick PP.RemovePragmaHandler(MSDataSeg.get());
565e5dd7070Spatrick MSDataSeg.reset();
566e5dd7070Spatrick PP.RemovePragmaHandler(MSBSSSeg.get());
567e5dd7070Spatrick MSBSSSeg.reset();
568e5dd7070Spatrick PP.RemovePragmaHandler(MSConstSeg.get());
569e5dd7070Spatrick MSConstSeg.reset();
570e5dd7070Spatrick PP.RemovePragmaHandler(MSCodeSeg.get());
571e5dd7070Spatrick MSCodeSeg.reset();
572e5dd7070Spatrick PP.RemovePragmaHandler(MSSection.get());
573e5dd7070Spatrick MSSection.reset();
574*12c85518Srobert PP.RemovePragmaHandler(MSStrictGuardStackCheck.get());
575*12c85518Srobert MSStrictGuardStackCheck.reset();
576*12c85518Srobert PP.RemovePragmaHandler(MSFunction.get());
577*12c85518Srobert MSFunction.reset();
578*12c85518Srobert PP.RemovePragmaHandler(MSAllocText.get());
579*12c85518Srobert MSAllocText.reset();
580e5dd7070Spatrick PP.RemovePragmaHandler(MSRuntimeChecks.get());
581e5dd7070Spatrick MSRuntimeChecks.reset();
582e5dd7070Spatrick PP.RemovePragmaHandler(MSIntrinsic.get());
583e5dd7070Spatrick MSIntrinsic.reset();
584e5dd7070Spatrick PP.RemovePragmaHandler(MSOptimize.get());
585e5dd7070Spatrick MSOptimize.reset();
586*12c85518Srobert PP.RemovePragmaHandler(MSFenvAccess.get());
587*12c85518Srobert MSFenvAccess.reset();
588e5dd7070Spatrick }
589e5dd7070Spatrick
590e5dd7070Spatrick if (getLangOpts().CUDA) {
591e5dd7070Spatrick PP.RemovePragmaHandler("clang", CUDAForceHostDeviceHandler.get());
592e5dd7070Spatrick CUDAForceHostDeviceHandler.reset();
593e5dd7070Spatrick }
594e5dd7070Spatrick
595e5dd7070Spatrick PP.RemovePragmaHandler("STDC", FPContractHandler.get());
596e5dd7070Spatrick FPContractHandler.reset();
597e5dd7070Spatrick
598a9ac8606Spatrick PP.RemovePragmaHandler("STDC", STDCFenvAccessHandler.get());
599a9ac8606Spatrick STDCFenvAccessHandler.reset();
600a9ac8606Spatrick
601a9ac8606Spatrick PP.RemovePragmaHandler("STDC", STDCFenvRoundHandler.get());
602a9ac8606Spatrick STDCFenvRoundHandler.reset();
603e5dd7070Spatrick
604e5dd7070Spatrick PP.RemovePragmaHandler("STDC", STDCCXLIMITHandler.get());
605e5dd7070Spatrick STDCCXLIMITHandler.reset();
606e5dd7070Spatrick
607e5dd7070Spatrick PP.RemovePragmaHandler("STDC", STDCUnknownHandler.get());
608e5dd7070Spatrick STDCUnknownHandler.reset();
609e5dd7070Spatrick
610e5dd7070Spatrick PP.RemovePragmaHandler("clang", OptimizeHandler.get());
611e5dd7070Spatrick OptimizeHandler.reset();
612e5dd7070Spatrick
613e5dd7070Spatrick PP.RemovePragmaHandler("clang", LoopHintHandler.get());
614e5dd7070Spatrick LoopHintHandler.reset();
615e5dd7070Spatrick
616e5dd7070Spatrick PP.RemovePragmaHandler(UnrollHintHandler.get());
617a9ac8606Spatrick PP.RemovePragmaHandler("GCC", UnrollHintHandler.get());
618e5dd7070Spatrick UnrollHintHandler.reset();
619e5dd7070Spatrick
620e5dd7070Spatrick PP.RemovePragmaHandler(NoUnrollHintHandler.get());
621a9ac8606Spatrick PP.RemovePragmaHandler("GCC", NoUnrollHintHandler.get());
622e5dd7070Spatrick NoUnrollHintHandler.reset();
623e5dd7070Spatrick
624e5dd7070Spatrick PP.RemovePragmaHandler(UnrollAndJamHintHandler.get());
625e5dd7070Spatrick UnrollAndJamHintHandler.reset();
626e5dd7070Spatrick
627e5dd7070Spatrick PP.RemovePragmaHandler(NoUnrollAndJamHintHandler.get());
628e5dd7070Spatrick NoUnrollAndJamHintHandler.reset();
629e5dd7070Spatrick
630e5dd7070Spatrick PP.RemovePragmaHandler("clang", FPHandler.get());
631e5dd7070Spatrick FPHandler.reset();
632e5dd7070Spatrick
633e5dd7070Spatrick PP.RemovePragmaHandler("clang", AttributePragmaHandler.get());
634e5dd7070Spatrick AttributePragmaHandler.reset();
635ec727ea7Spatrick
636ec727ea7Spatrick PP.RemovePragmaHandler("clang", MaxTokensHerePragmaHandler.get());
637ec727ea7Spatrick MaxTokensHerePragmaHandler.reset();
638ec727ea7Spatrick
639ec727ea7Spatrick PP.RemovePragmaHandler("clang", MaxTokensTotalPragmaHandler.get());
640ec727ea7Spatrick MaxTokensTotalPragmaHandler.reset();
641*12c85518Srobert
642*12c85518Srobert if (getTargetInfo().getTriple().isRISCV()) {
643*12c85518Srobert PP.RemovePragmaHandler("clang", RISCVPragmaHandler.get());
644*12c85518Srobert RISCVPragmaHandler.reset();
645*12c85518Srobert }
646e5dd7070Spatrick }
647e5dd7070Spatrick
648e5dd7070Spatrick /// Handle the annotation token produced for #pragma unused(...)
649e5dd7070Spatrick ///
650e5dd7070Spatrick /// Each annot_pragma_unused is followed by the argument token so e.g.
651e5dd7070Spatrick /// "#pragma unused(x,y)" becomes:
652e5dd7070Spatrick /// annot_pragma_unused 'x' annot_pragma_unused 'y'
HandlePragmaUnused()653e5dd7070Spatrick void Parser::HandlePragmaUnused() {
654e5dd7070Spatrick assert(Tok.is(tok::annot_pragma_unused));
655e5dd7070Spatrick SourceLocation UnusedLoc = ConsumeAnnotationToken();
656e5dd7070Spatrick Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
657e5dd7070Spatrick ConsumeToken(); // The argument token.
658e5dd7070Spatrick }
659e5dd7070Spatrick
HandlePragmaVisibility()660e5dd7070Spatrick void Parser::HandlePragmaVisibility() {
661e5dd7070Spatrick assert(Tok.is(tok::annot_pragma_vis));
662e5dd7070Spatrick const IdentifierInfo *VisType =
663e5dd7070Spatrick static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
664e5dd7070Spatrick SourceLocation VisLoc = ConsumeAnnotationToken();
665e5dd7070Spatrick Actions.ActOnPragmaVisibility(VisType, VisLoc);
666e5dd7070Spatrick }
667e5dd7070Spatrick
668e5dd7070Spatrick namespace {
669e5dd7070Spatrick struct PragmaPackInfo {
670e5dd7070Spatrick Sema::PragmaMsStackAction Action;
671e5dd7070Spatrick StringRef SlotLabel;
672e5dd7070Spatrick Token Alignment;
673e5dd7070Spatrick };
674e5dd7070Spatrick } // end anonymous namespace
675e5dd7070Spatrick
HandlePragmaPack()676e5dd7070Spatrick void Parser::HandlePragmaPack() {
677e5dd7070Spatrick assert(Tok.is(tok::annot_pragma_pack));
678e5dd7070Spatrick PragmaPackInfo *Info =
679e5dd7070Spatrick static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
680e5dd7070Spatrick SourceLocation PragmaLoc = Tok.getLocation();
681e5dd7070Spatrick ExprResult Alignment;
682e5dd7070Spatrick if (Info->Alignment.is(tok::numeric_constant)) {
683e5dd7070Spatrick Alignment = Actions.ActOnNumericConstant(Info->Alignment);
684e5dd7070Spatrick if (Alignment.isInvalid()) {
685e5dd7070Spatrick ConsumeAnnotationToken();
686e5dd7070Spatrick return;
687e5dd7070Spatrick }
688e5dd7070Spatrick }
689e5dd7070Spatrick Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel,
690e5dd7070Spatrick Alignment.get());
691e5dd7070Spatrick // Consume the token after processing the pragma to enable pragma-specific
692e5dd7070Spatrick // #include warnings.
693e5dd7070Spatrick ConsumeAnnotationToken();
694e5dd7070Spatrick }
695e5dd7070Spatrick
HandlePragmaMSStruct()696e5dd7070Spatrick void Parser::HandlePragmaMSStruct() {
697e5dd7070Spatrick assert(Tok.is(tok::annot_pragma_msstruct));
698e5dd7070Spatrick PragmaMSStructKind Kind = static_cast<PragmaMSStructKind>(
699e5dd7070Spatrick reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
700e5dd7070Spatrick Actions.ActOnPragmaMSStruct(Kind);
701e5dd7070Spatrick ConsumeAnnotationToken();
702e5dd7070Spatrick }
703e5dd7070Spatrick
HandlePragmaAlign()704e5dd7070Spatrick void Parser::HandlePragmaAlign() {
705e5dd7070Spatrick assert(Tok.is(tok::annot_pragma_align));
706e5dd7070Spatrick Sema::PragmaOptionsAlignKind Kind =
707e5dd7070Spatrick static_cast<Sema::PragmaOptionsAlignKind>(
708e5dd7070Spatrick reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
709e5dd7070Spatrick Actions.ActOnPragmaOptionsAlign(Kind, Tok.getLocation());
710e5dd7070Spatrick // Consume the token after processing the pragma to enable pragma-specific
711e5dd7070Spatrick // #include warnings.
712e5dd7070Spatrick ConsumeAnnotationToken();
713e5dd7070Spatrick }
714e5dd7070Spatrick
HandlePragmaDump()715e5dd7070Spatrick void Parser::HandlePragmaDump() {
716e5dd7070Spatrick assert(Tok.is(tok::annot_pragma_dump));
717e5dd7070Spatrick IdentifierInfo *II =
718e5dd7070Spatrick reinterpret_cast<IdentifierInfo *>(Tok.getAnnotationValue());
719e5dd7070Spatrick Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II);
720e5dd7070Spatrick ConsumeAnnotationToken();
721e5dd7070Spatrick }
722e5dd7070Spatrick
HandlePragmaWeak()723e5dd7070Spatrick void Parser::HandlePragmaWeak() {
724e5dd7070Spatrick assert(Tok.is(tok::annot_pragma_weak));
725e5dd7070Spatrick SourceLocation PragmaLoc = ConsumeAnnotationToken();
726e5dd7070Spatrick Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
727e5dd7070Spatrick Tok.getLocation());
728e5dd7070Spatrick ConsumeToken(); // The weak name.
729e5dd7070Spatrick }
730e5dd7070Spatrick
HandlePragmaWeakAlias()731e5dd7070Spatrick void Parser::HandlePragmaWeakAlias() {
732e5dd7070Spatrick assert(Tok.is(tok::annot_pragma_weakalias));
733e5dd7070Spatrick SourceLocation PragmaLoc = ConsumeAnnotationToken();
734e5dd7070Spatrick IdentifierInfo *WeakName = Tok.getIdentifierInfo();
735e5dd7070Spatrick SourceLocation WeakNameLoc = Tok.getLocation();
736e5dd7070Spatrick ConsumeToken();
737e5dd7070Spatrick IdentifierInfo *AliasName = Tok.getIdentifierInfo();
738e5dd7070Spatrick SourceLocation AliasNameLoc = Tok.getLocation();
739e5dd7070Spatrick ConsumeToken();
740e5dd7070Spatrick Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
741e5dd7070Spatrick WeakNameLoc, AliasNameLoc);
742e5dd7070Spatrick
743e5dd7070Spatrick }
744e5dd7070Spatrick
HandlePragmaRedefineExtname()745e5dd7070Spatrick void Parser::HandlePragmaRedefineExtname() {
746e5dd7070Spatrick assert(Tok.is(tok::annot_pragma_redefine_extname));
747e5dd7070Spatrick SourceLocation RedefLoc = ConsumeAnnotationToken();
748e5dd7070Spatrick IdentifierInfo *RedefName = Tok.getIdentifierInfo();
749e5dd7070Spatrick SourceLocation RedefNameLoc = Tok.getLocation();
750e5dd7070Spatrick ConsumeToken();
751e5dd7070Spatrick IdentifierInfo *AliasName = Tok.getIdentifierInfo();
752e5dd7070Spatrick SourceLocation AliasNameLoc = Tok.getLocation();
753e5dd7070Spatrick ConsumeToken();
754e5dd7070Spatrick Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
755e5dd7070Spatrick RedefNameLoc, AliasNameLoc);
756e5dd7070Spatrick }
757e5dd7070Spatrick
HandlePragmaFPContract()758e5dd7070Spatrick void Parser::HandlePragmaFPContract() {
759e5dd7070Spatrick assert(Tok.is(tok::annot_pragma_fp_contract));
760e5dd7070Spatrick tok::OnOffSwitch OOS =
761e5dd7070Spatrick static_cast<tok::OnOffSwitch>(
762e5dd7070Spatrick reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
763e5dd7070Spatrick
764ec727ea7Spatrick LangOptions::FPModeKind FPC;
765e5dd7070Spatrick switch (OOS) {
766e5dd7070Spatrick case tok::OOS_ON:
767ec727ea7Spatrick FPC = LangOptions::FPM_On;
768e5dd7070Spatrick break;
769e5dd7070Spatrick case tok::OOS_OFF:
770ec727ea7Spatrick FPC = LangOptions::FPM_Off;
771e5dd7070Spatrick break;
772e5dd7070Spatrick case tok::OOS_DEFAULT:
773e5dd7070Spatrick FPC = getLangOpts().getDefaultFPContractMode();
774e5dd7070Spatrick break;
775e5dd7070Spatrick }
776e5dd7070Spatrick
777ec727ea7Spatrick SourceLocation PragmaLoc = ConsumeAnnotationToken();
778ec727ea7Spatrick Actions.ActOnPragmaFPContract(PragmaLoc, FPC);
779ec727ea7Spatrick }
780ec727ea7Spatrick
HandlePragmaFloatControl()781ec727ea7Spatrick void Parser::HandlePragmaFloatControl() {
782ec727ea7Spatrick assert(Tok.is(tok::annot_pragma_float_control));
783ec727ea7Spatrick
784ec727ea7Spatrick // The value that is held on the PragmaFloatControlStack encodes
785ec727ea7Spatrick // the PragmaFloatControl kind and the MSStackAction kind
786ec727ea7Spatrick // into a single 32-bit word. The MsStackAction is the high 16 bits
787ec727ea7Spatrick // and the FloatControl is the lower 16 bits. Use shift and bit-and
788ec727ea7Spatrick // to decode the parts.
789ec727ea7Spatrick uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
790ec727ea7Spatrick Sema::PragmaMsStackAction Action =
791ec727ea7Spatrick static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
792ec727ea7Spatrick PragmaFloatControlKind Kind = PragmaFloatControlKind(Value & 0xFFFF);
793ec727ea7Spatrick SourceLocation PragmaLoc = ConsumeAnnotationToken();
794ec727ea7Spatrick Actions.ActOnPragmaFloatControl(PragmaLoc, Action, Kind);
795e5dd7070Spatrick }
796e5dd7070Spatrick
HandlePragmaFEnvAccess()797e5dd7070Spatrick void Parser::HandlePragmaFEnvAccess() {
798*12c85518Srobert assert(Tok.is(tok::annot_pragma_fenv_access) ||
799*12c85518Srobert Tok.is(tok::annot_pragma_fenv_access_ms));
800e5dd7070Spatrick tok::OnOffSwitch OOS =
801e5dd7070Spatrick static_cast<tok::OnOffSwitch>(
802e5dd7070Spatrick reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
803e5dd7070Spatrick
804ec727ea7Spatrick bool IsEnabled;
805e5dd7070Spatrick switch (OOS) {
806e5dd7070Spatrick case tok::OOS_ON:
807ec727ea7Spatrick IsEnabled = true;
808e5dd7070Spatrick break;
809e5dd7070Spatrick case tok::OOS_OFF:
810ec727ea7Spatrick IsEnabled = false;
811e5dd7070Spatrick break;
812e5dd7070Spatrick case tok::OOS_DEFAULT: // FIXME: Add this cli option when it makes sense.
813ec727ea7Spatrick IsEnabled = false;
814e5dd7070Spatrick break;
815e5dd7070Spatrick }
816e5dd7070Spatrick
817ec727ea7Spatrick SourceLocation PragmaLoc = ConsumeAnnotationToken();
818ec727ea7Spatrick Actions.ActOnPragmaFEnvAccess(PragmaLoc, IsEnabled);
819e5dd7070Spatrick }
820e5dd7070Spatrick
HandlePragmaFEnvRound()821a9ac8606Spatrick void Parser::HandlePragmaFEnvRound() {
822a9ac8606Spatrick assert(Tok.is(tok::annot_pragma_fenv_round));
823a9ac8606Spatrick auto RM = static_cast<llvm::RoundingMode>(
824a9ac8606Spatrick reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
825a9ac8606Spatrick
826a9ac8606Spatrick SourceLocation PragmaLoc = ConsumeAnnotationToken();
827*12c85518Srobert Actions.ActOnPragmaFEnvRound(PragmaLoc, RM);
828a9ac8606Spatrick }
829e5dd7070Spatrick
HandlePragmaCaptured()830e5dd7070Spatrick StmtResult Parser::HandlePragmaCaptured()
831e5dd7070Spatrick {
832e5dd7070Spatrick assert(Tok.is(tok::annot_pragma_captured));
833e5dd7070Spatrick ConsumeAnnotationToken();
834e5dd7070Spatrick
835e5dd7070Spatrick if (Tok.isNot(tok::l_brace)) {
836e5dd7070Spatrick PP.Diag(Tok, diag::err_expected) << tok::l_brace;
837e5dd7070Spatrick return StmtError();
838e5dd7070Spatrick }
839e5dd7070Spatrick
840e5dd7070Spatrick SourceLocation Loc = Tok.getLocation();
841e5dd7070Spatrick
842e5dd7070Spatrick ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope |
843e5dd7070Spatrick Scope::CompoundStmtScope);
844e5dd7070Spatrick Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
845e5dd7070Spatrick /*NumParams=*/1);
846e5dd7070Spatrick
847e5dd7070Spatrick StmtResult R = ParseCompoundStatement();
848e5dd7070Spatrick CapturedRegionScope.Exit();
849e5dd7070Spatrick
850e5dd7070Spatrick if (R.isInvalid()) {
851e5dd7070Spatrick Actions.ActOnCapturedRegionError();
852e5dd7070Spatrick return StmtError();
853e5dd7070Spatrick }
854e5dd7070Spatrick
855e5dd7070Spatrick return Actions.ActOnCapturedRegionEnd(R.get());
856e5dd7070Spatrick }
857e5dd7070Spatrick
858e5dd7070Spatrick namespace {
859e5dd7070Spatrick enum OpenCLExtState : char {
860e5dd7070Spatrick Disable, Enable, Begin, End
861e5dd7070Spatrick };
862e5dd7070Spatrick typedef std::pair<const IdentifierInfo *, OpenCLExtState> OpenCLExtData;
863e5dd7070Spatrick }
864e5dd7070Spatrick
HandlePragmaOpenCLExtension()865e5dd7070Spatrick void Parser::HandlePragmaOpenCLExtension() {
866e5dd7070Spatrick assert(Tok.is(tok::annot_pragma_opencl_extension));
867e5dd7070Spatrick OpenCLExtData *Data = static_cast<OpenCLExtData*>(Tok.getAnnotationValue());
868e5dd7070Spatrick auto State = Data->second;
869e5dd7070Spatrick auto Ident = Data->first;
870e5dd7070Spatrick SourceLocation NameLoc = Tok.getLocation();
871e5dd7070Spatrick ConsumeAnnotationToken();
872e5dd7070Spatrick
873e5dd7070Spatrick auto &Opt = Actions.getOpenCLOptions();
874e5dd7070Spatrick auto Name = Ident->getName();
875e5dd7070Spatrick // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
876e5dd7070Spatrick // overriding all previously issued extension directives, but only if the
877e5dd7070Spatrick // behavior is set to disable."
878e5dd7070Spatrick if (Name == "all") {
879a9ac8606Spatrick if (State == Disable)
880e5dd7070Spatrick Opt.disableAll();
881a9ac8606Spatrick else
882e5dd7070Spatrick PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1;
883e5dd7070Spatrick } else if (State == Begin) {
884e5dd7070Spatrick if (!Opt.isKnown(Name) || !Opt.isSupported(Name, getLangOpts())) {
885e5dd7070Spatrick Opt.support(Name);
886a9ac8606Spatrick // FIXME: Default behavior of the extension pragma is not defined.
887a9ac8606Spatrick // Therefore, it should never be added by default.
888a9ac8606Spatrick Opt.acceptsPragma(Name);
889e5dd7070Spatrick }
890e5dd7070Spatrick } else if (State == End) {
891a9ac8606Spatrick // There is no behavior for this directive. We only accept this for
892a9ac8606Spatrick // backward compatibility.
893a9ac8606Spatrick } else if (!Opt.isKnown(Name) || !Opt.isWithPragma(Name))
894e5dd7070Spatrick PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;
895e5dd7070Spatrick else if (Opt.isSupportedExtension(Name, getLangOpts()))
896e5dd7070Spatrick Opt.enable(Name, State == Enable);
897a9ac8606Spatrick else if (Opt.isSupportedCoreOrOptionalCore(Name, getLangOpts()))
898e5dd7070Spatrick PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident;
899e5dd7070Spatrick else
900e5dd7070Spatrick PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident;
901e5dd7070Spatrick }
902e5dd7070Spatrick
HandlePragmaMSPointersToMembers()903e5dd7070Spatrick void Parser::HandlePragmaMSPointersToMembers() {
904e5dd7070Spatrick assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
905e5dd7070Spatrick LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
906e5dd7070Spatrick static_cast<LangOptions::PragmaMSPointersToMembersKind>(
907e5dd7070Spatrick reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
908e5dd7070Spatrick SourceLocation PragmaLoc = ConsumeAnnotationToken();
909e5dd7070Spatrick Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
910e5dd7070Spatrick }
911e5dd7070Spatrick
HandlePragmaMSVtorDisp()912e5dd7070Spatrick void Parser::HandlePragmaMSVtorDisp() {
913e5dd7070Spatrick assert(Tok.is(tok::annot_pragma_ms_vtordisp));
914e5dd7070Spatrick uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
915e5dd7070Spatrick Sema::PragmaMsStackAction Action =
916e5dd7070Spatrick static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
917e5dd7070Spatrick MSVtorDispMode Mode = MSVtorDispMode(Value & 0xFFFF);
918e5dd7070Spatrick SourceLocation PragmaLoc = ConsumeAnnotationToken();
919e5dd7070Spatrick Actions.ActOnPragmaMSVtorDisp(Action, PragmaLoc, Mode);
920e5dd7070Spatrick }
921e5dd7070Spatrick
HandlePragmaMSPragma()922e5dd7070Spatrick void Parser::HandlePragmaMSPragma() {
923e5dd7070Spatrick assert(Tok.is(tok::annot_pragma_ms_pragma));
924e5dd7070Spatrick // Grab the tokens out of the annotation and enter them into the stream.
925e5dd7070Spatrick auto TheTokens =
926e5dd7070Spatrick (std::pair<std::unique_ptr<Token[]>, size_t> *)Tok.getAnnotationValue();
927e5dd7070Spatrick PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true,
928e5dd7070Spatrick /*IsReinject=*/true);
929e5dd7070Spatrick SourceLocation PragmaLocation = ConsumeAnnotationToken();
930e5dd7070Spatrick assert(Tok.isAnyIdentifier());
931e5dd7070Spatrick StringRef PragmaName = Tok.getIdentifierInfo()->getName();
932e5dd7070Spatrick PP.Lex(Tok); // pragma kind
933e5dd7070Spatrick
934e5dd7070Spatrick // Figure out which #pragma we're dealing with. The switch has no default
935e5dd7070Spatrick // because lex shouldn't emit the annotation token for unrecognized pragmas.
936e5dd7070Spatrick typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
937*12c85518Srobert PragmaHandler Handler =
938*12c85518Srobert llvm::StringSwitch<PragmaHandler>(PragmaName)
939e5dd7070Spatrick .Case("data_seg", &Parser::HandlePragmaMSSegment)
940e5dd7070Spatrick .Case("bss_seg", &Parser::HandlePragmaMSSegment)
941e5dd7070Spatrick .Case("const_seg", &Parser::HandlePragmaMSSegment)
942e5dd7070Spatrick .Case("code_seg", &Parser::HandlePragmaMSSegment)
943e5dd7070Spatrick .Case("section", &Parser::HandlePragmaMSSection)
944*12c85518Srobert .Case("init_seg", &Parser::HandlePragmaMSInitSeg)
945*12c85518Srobert .Case("strict_gs_check", &Parser::HandlePragmaMSStrictGuardStackCheck)
946*12c85518Srobert .Case("function", &Parser::HandlePragmaMSFunction)
947*12c85518Srobert .Case("alloc_text", &Parser::HandlePragmaMSAllocText)
948*12c85518Srobert .Case("optimize", &Parser::HandlePragmaMSOptimize);
949e5dd7070Spatrick
950e5dd7070Spatrick if (!(this->*Handler)(PragmaName, PragmaLocation)) {
951e5dd7070Spatrick // Pragma handling failed, and has been diagnosed. Slurp up the tokens
952e5dd7070Spatrick // until eof (really end of line) to prevent follow-on errors.
953e5dd7070Spatrick while (Tok.isNot(tok::eof))
954e5dd7070Spatrick PP.Lex(Tok);
955e5dd7070Spatrick PP.Lex(Tok);
956e5dd7070Spatrick }
957e5dd7070Spatrick }
958e5dd7070Spatrick
HandlePragmaMSSection(StringRef PragmaName,SourceLocation PragmaLocation)959e5dd7070Spatrick bool Parser::HandlePragmaMSSection(StringRef PragmaName,
960e5dd7070Spatrick SourceLocation PragmaLocation) {
961e5dd7070Spatrick if (Tok.isNot(tok::l_paren)) {
962e5dd7070Spatrick PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
963e5dd7070Spatrick return false;
964e5dd7070Spatrick }
965e5dd7070Spatrick PP.Lex(Tok); // (
966e5dd7070Spatrick // Parsing code for pragma section
967e5dd7070Spatrick if (Tok.isNot(tok::string_literal)) {
968e5dd7070Spatrick PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
969e5dd7070Spatrick << PragmaName;
970e5dd7070Spatrick return false;
971e5dd7070Spatrick }
972e5dd7070Spatrick ExprResult StringResult = ParseStringLiteralExpression();
973e5dd7070Spatrick if (StringResult.isInvalid())
974e5dd7070Spatrick return false; // Already diagnosed.
975e5dd7070Spatrick StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
976e5dd7070Spatrick if (SegmentName->getCharByteWidth() != 1) {
977e5dd7070Spatrick PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
978e5dd7070Spatrick << PragmaName;
979e5dd7070Spatrick return false;
980e5dd7070Spatrick }
981e5dd7070Spatrick int SectionFlags = ASTContext::PSF_Read;
982e5dd7070Spatrick bool SectionFlagsAreDefault = true;
983e5dd7070Spatrick while (Tok.is(tok::comma)) {
984e5dd7070Spatrick PP.Lex(Tok); // ,
985e5dd7070Spatrick // Ignore "long" and "short".
986e5dd7070Spatrick // They are undocumented, but widely used, section attributes which appear
987e5dd7070Spatrick // to do nothing.
988e5dd7070Spatrick if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) {
989e5dd7070Spatrick PP.Lex(Tok); // long/short
990e5dd7070Spatrick continue;
991e5dd7070Spatrick }
992e5dd7070Spatrick
993e5dd7070Spatrick if (!Tok.isAnyIdentifier()) {
994e5dd7070Spatrick PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
995e5dd7070Spatrick << PragmaName;
996e5dd7070Spatrick return false;
997e5dd7070Spatrick }
998e5dd7070Spatrick ASTContext::PragmaSectionFlag Flag =
999e5dd7070Spatrick llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
1000e5dd7070Spatrick Tok.getIdentifierInfo()->getName())
1001e5dd7070Spatrick .Case("read", ASTContext::PSF_Read)
1002e5dd7070Spatrick .Case("write", ASTContext::PSF_Write)
1003e5dd7070Spatrick .Case("execute", ASTContext::PSF_Execute)
1004e5dd7070Spatrick .Case("shared", ASTContext::PSF_Invalid)
1005e5dd7070Spatrick .Case("nopage", ASTContext::PSF_Invalid)
1006e5dd7070Spatrick .Case("nocache", ASTContext::PSF_Invalid)
1007e5dd7070Spatrick .Case("discard", ASTContext::PSF_Invalid)
1008e5dd7070Spatrick .Case("remove", ASTContext::PSF_Invalid)
1009e5dd7070Spatrick .Default(ASTContext::PSF_None);
1010e5dd7070Spatrick if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) {
1011e5dd7070Spatrick PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
1012e5dd7070Spatrick ? diag::warn_pragma_invalid_specific_action
1013e5dd7070Spatrick : diag::warn_pragma_unsupported_action)
1014e5dd7070Spatrick << PragmaName << Tok.getIdentifierInfo()->getName();
1015e5dd7070Spatrick return false;
1016e5dd7070Spatrick }
1017e5dd7070Spatrick SectionFlags |= Flag;
1018e5dd7070Spatrick SectionFlagsAreDefault = false;
1019e5dd7070Spatrick PP.Lex(Tok); // Identifier
1020e5dd7070Spatrick }
1021e5dd7070Spatrick // If no section attributes are specified, the section will be marked as
1022e5dd7070Spatrick // read/write.
1023e5dd7070Spatrick if (SectionFlagsAreDefault)
1024e5dd7070Spatrick SectionFlags |= ASTContext::PSF_Write;
1025e5dd7070Spatrick if (Tok.isNot(tok::r_paren)) {
1026e5dd7070Spatrick PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
1027e5dd7070Spatrick return false;
1028e5dd7070Spatrick }
1029e5dd7070Spatrick PP.Lex(Tok); // )
1030e5dd7070Spatrick if (Tok.isNot(tok::eof)) {
1031e5dd7070Spatrick PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
1032e5dd7070Spatrick << PragmaName;
1033e5dd7070Spatrick return false;
1034e5dd7070Spatrick }
1035e5dd7070Spatrick PP.Lex(Tok); // eof
1036e5dd7070Spatrick Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
1037e5dd7070Spatrick return true;
1038e5dd7070Spatrick }
1039e5dd7070Spatrick
HandlePragmaMSSegment(StringRef PragmaName,SourceLocation PragmaLocation)1040e5dd7070Spatrick bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
1041e5dd7070Spatrick SourceLocation PragmaLocation) {
1042e5dd7070Spatrick if (Tok.isNot(tok::l_paren)) {
1043e5dd7070Spatrick PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
1044e5dd7070Spatrick return false;
1045e5dd7070Spatrick }
1046e5dd7070Spatrick PP.Lex(Tok); // (
1047e5dd7070Spatrick Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
1048e5dd7070Spatrick StringRef SlotLabel;
1049e5dd7070Spatrick if (Tok.isAnyIdentifier()) {
1050e5dd7070Spatrick StringRef PushPop = Tok.getIdentifierInfo()->getName();
1051e5dd7070Spatrick if (PushPop == "push")
1052e5dd7070Spatrick Action = Sema::PSK_Push;
1053e5dd7070Spatrick else if (PushPop == "pop")
1054e5dd7070Spatrick Action = Sema::PSK_Pop;
1055e5dd7070Spatrick else {
1056e5dd7070Spatrick PP.Diag(PragmaLocation,
1057e5dd7070Spatrick diag::warn_pragma_expected_section_push_pop_or_name)
1058e5dd7070Spatrick << PragmaName;
1059e5dd7070Spatrick return false;
1060e5dd7070Spatrick }
1061e5dd7070Spatrick if (Action != Sema::PSK_Reset) {
1062e5dd7070Spatrick PP.Lex(Tok); // push | pop
1063e5dd7070Spatrick if (Tok.is(tok::comma)) {
1064e5dd7070Spatrick PP.Lex(Tok); // ,
1065e5dd7070Spatrick // If we've got a comma, we either need a label or a string.
1066e5dd7070Spatrick if (Tok.isAnyIdentifier()) {
1067e5dd7070Spatrick SlotLabel = Tok.getIdentifierInfo()->getName();
1068e5dd7070Spatrick PP.Lex(Tok); // identifier
1069e5dd7070Spatrick if (Tok.is(tok::comma))
1070e5dd7070Spatrick PP.Lex(Tok);
1071e5dd7070Spatrick else if (Tok.isNot(tok::r_paren)) {
1072e5dd7070Spatrick PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
1073e5dd7070Spatrick << PragmaName;
1074e5dd7070Spatrick return false;
1075e5dd7070Spatrick }
1076e5dd7070Spatrick }
1077e5dd7070Spatrick } else if (Tok.isNot(tok::r_paren)) {
1078e5dd7070Spatrick PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
1079e5dd7070Spatrick return false;
1080e5dd7070Spatrick }
1081e5dd7070Spatrick }
1082e5dd7070Spatrick }
1083e5dd7070Spatrick // Grab the string literal for our section name.
1084e5dd7070Spatrick StringLiteral *SegmentName = nullptr;
1085e5dd7070Spatrick if (Tok.isNot(tok::r_paren)) {
1086e5dd7070Spatrick if (Tok.isNot(tok::string_literal)) {
1087e5dd7070Spatrick unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
1088e5dd7070Spatrick diag::warn_pragma_expected_section_name :
1089e5dd7070Spatrick diag::warn_pragma_expected_section_label_or_name :
1090e5dd7070Spatrick diag::warn_pragma_expected_section_push_pop_or_name;
1091e5dd7070Spatrick PP.Diag(PragmaLocation, DiagID) << PragmaName;
1092e5dd7070Spatrick return false;
1093e5dd7070Spatrick }
1094e5dd7070Spatrick ExprResult StringResult = ParseStringLiteralExpression();
1095e5dd7070Spatrick if (StringResult.isInvalid())
1096e5dd7070Spatrick return false; // Already diagnosed.
1097e5dd7070Spatrick SegmentName = cast<StringLiteral>(StringResult.get());
1098e5dd7070Spatrick if (SegmentName->getCharByteWidth() != 1) {
1099e5dd7070Spatrick PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
1100e5dd7070Spatrick << PragmaName;
1101e5dd7070Spatrick return false;
1102e5dd7070Spatrick }
1103e5dd7070Spatrick // Setting section "" has no effect
1104e5dd7070Spatrick if (SegmentName->getLength())
1105e5dd7070Spatrick Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
1106e5dd7070Spatrick }
1107e5dd7070Spatrick if (Tok.isNot(tok::r_paren)) {
1108e5dd7070Spatrick PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
1109e5dd7070Spatrick return false;
1110e5dd7070Spatrick }
1111e5dd7070Spatrick PP.Lex(Tok); // )
1112e5dd7070Spatrick if (Tok.isNot(tok::eof)) {
1113e5dd7070Spatrick PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
1114e5dd7070Spatrick << PragmaName;
1115e5dd7070Spatrick return false;
1116e5dd7070Spatrick }
1117e5dd7070Spatrick PP.Lex(Tok); // eof
1118e5dd7070Spatrick Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
1119e5dd7070Spatrick SegmentName, PragmaName);
1120e5dd7070Spatrick return true;
1121e5dd7070Spatrick }
1122e5dd7070Spatrick
1123e5dd7070Spatrick // #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
HandlePragmaMSInitSeg(StringRef PragmaName,SourceLocation PragmaLocation)1124e5dd7070Spatrick bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
1125e5dd7070Spatrick SourceLocation PragmaLocation) {
1126e5dd7070Spatrick if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
1127e5dd7070Spatrick PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
1128e5dd7070Spatrick return false;
1129e5dd7070Spatrick }
1130e5dd7070Spatrick
1131e5dd7070Spatrick if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
1132e5dd7070Spatrick PragmaName))
1133e5dd7070Spatrick return false;
1134e5dd7070Spatrick
1135e5dd7070Spatrick // Parse either the known section names or the string section name.
1136e5dd7070Spatrick StringLiteral *SegmentName = nullptr;
1137e5dd7070Spatrick if (Tok.isAnyIdentifier()) {
1138e5dd7070Spatrick auto *II = Tok.getIdentifierInfo();
1139e5dd7070Spatrick StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
1140e5dd7070Spatrick .Case("compiler", "\".CRT$XCC\"")
1141e5dd7070Spatrick .Case("lib", "\".CRT$XCL\"")
1142e5dd7070Spatrick .Case("user", "\".CRT$XCU\"")
1143e5dd7070Spatrick .Default("");
1144e5dd7070Spatrick
1145e5dd7070Spatrick if (!Section.empty()) {
1146e5dd7070Spatrick // Pretend the user wrote the appropriate string literal here.
1147e5dd7070Spatrick Token Toks[1];
1148e5dd7070Spatrick Toks[0].startToken();
1149e5dd7070Spatrick Toks[0].setKind(tok::string_literal);
1150e5dd7070Spatrick Toks[0].setLocation(Tok.getLocation());
1151e5dd7070Spatrick Toks[0].setLiteralData(Section.data());
1152e5dd7070Spatrick Toks[0].setLength(Section.size());
1153e5dd7070Spatrick SegmentName =
1154e5dd7070Spatrick cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
1155e5dd7070Spatrick PP.Lex(Tok);
1156e5dd7070Spatrick }
1157e5dd7070Spatrick } else if (Tok.is(tok::string_literal)) {
1158e5dd7070Spatrick ExprResult StringResult = ParseStringLiteralExpression();
1159e5dd7070Spatrick if (StringResult.isInvalid())
1160e5dd7070Spatrick return false;
1161e5dd7070Spatrick SegmentName = cast<StringLiteral>(StringResult.get());
1162e5dd7070Spatrick if (SegmentName->getCharByteWidth() != 1) {
1163e5dd7070Spatrick PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
1164e5dd7070Spatrick << PragmaName;
1165e5dd7070Spatrick return false;
1166e5dd7070Spatrick }
1167e5dd7070Spatrick // FIXME: Add support for the '[, func-name]' part of the pragma.
1168e5dd7070Spatrick }
1169e5dd7070Spatrick
1170e5dd7070Spatrick if (!SegmentName) {
1171e5dd7070Spatrick PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
1172e5dd7070Spatrick return false;
1173e5dd7070Spatrick }
1174e5dd7070Spatrick
1175e5dd7070Spatrick if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
1176e5dd7070Spatrick PragmaName) ||
1177e5dd7070Spatrick ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
1178e5dd7070Spatrick PragmaName))
1179e5dd7070Spatrick return false;
1180e5dd7070Spatrick
1181e5dd7070Spatrick Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
1182e5dd7070Spatrick return true;
1183e5dd7070Spatrick }
1184e5dd7070Spatrick
1185*12c85518Srobert // #pragma strict_gs_check(pop)
1186*12c85518Srobert // #pragma strict_gs_check(push, "on" | "off")
1187*12c85518Srobert // #pragma strict_gs_check("on" | "off")
HandlePragmaMSStrictGuardStackCheck(StringRef PragmaName,SourceLocation PragmaLocation)1188*12c85518Srobert bool Parser::HandlePragmaMSStrictGuardStackCheck(
1189*12c85518Srobert StringRef PragmaName, SourceLocation PragmaLocation) {
1190*12c85518Srobert if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
1191*12c85518Srobert PragmaName))
1192*12c85518Srobert return false;
1193*12c85518Srobert
1194*12c85518Srobert Sema::PragmaMsStackAction Action = Sema::PSK_Set;
1195*12c85518Srobert if (Tok.is(tok::identifier)) {
1196*12c85518Srobert StringRef PushPop = Tok.getIdentifierInfo()->getName();
1197*12c85518Srobert if (PushPop == "push") {
1198*12c85518Srobert PP.Lex(Tok);
1199*12c85518Srobert Action = Sema::PSK_Push;
1200*12c85518Srobert if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_punc,
1201*12c85518Srobert PragmaName))
1202*12c85518Srobert return false;
1203*12c85518Srobert } else if (PushPop == "pop") {
1204*12c85518Srobert PP.Lex(Tok);
1205*12c85518Srobert Action = Sema::PSK_Pop;
1206*12c85518Srobert }
1207*12c85518Srobert }
1208*12c85518Srobert
1209*12c85518Srobert bool Value = false;
1210*12c85518Srobert if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {
1211*12c85518Srobert const IdentifierInfo *II = Tok.getIdentifierInfo();
1212*12c85518Srobert if (II && II->isStr("off")) {
1213*12c85518Srobert PP.Lex(Tok);
1214*12c85518Srobert Value = false;
1215*12c85518Srobert } else if (II && II->isStr("on")) {
1216*12c85518Srobert PP.Lex(Tok);
1217*12c85518Srobert Value = true;
1218*12c85518Srobert } else {
1219*12c85518Srobert PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
1220*12c85518Srobert << PragmaName;
1221*12c85518Srobert return false;
1222*12c85518Srobert }
1223*12c85518Srobert }
1224*12c85518Srobert
1225*12c85518Srobert // Finish the pragma: ')' $
1226*12c85518Srobert if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
1227*12c85518Srobert PragmaName))
1228*12c85518Srobert return false;
1229*12c85518Srobert
1230*12c85518Srobert if (ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
1231*12c85518Srobert PragmaName))
1232*12c85518Srobert return false;
1233*12c85518Srobert
1234*12c85518Srobert Actions.ActOnPragmaMSStrictGuardStackCheck(PragmaLocation, Action, Value);
1235*12c85518Srobert return true;
1236*12c85518Srobert }
1237*12c85518Srobert
HandlePragmaMSAllocText(StringRef PragmaName,SourceLocation PragmaLocation)1238*12c85518Srobert bool Parser::HandlePragmaMSAllocText(StringRef PragmaName,
1239*12c85518Srobert SourceLocation PragmaLocation) {
1240*12c85518Srobert Token FirstTok = Tok;
1241*12c85518Srobert if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
1242*12c85518Srobert PragmaName))
1243*12c85518Srobert return false;
1244*12c85518Srobert
1245*12c85518Srobert StringRef Section;
1246*12c85518Srobert if (Tok.is(tok::string_literal)) {
1247*12c85518Srobert ExprResult StringResult = ParseStringLiteralExpression();
1248*12c85518Srobert if (StringResult.isInvalid())
1249*12c85518Srobert return false; // Already diagnosed.
1250*12c85518Srobert StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
1251*12c85518Srobert if (SegmentName->getCharByteWidth() != 1) {
1252*12c85518Srobert PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
1253*12c85518Srobert << PragmaName;
1254*12c85518Srobert return false;
1255*12c85518Srobert }
1256*12c85518Srobert Section = SegmentName->getString();
1257*12c85518Srobert } else if (Tok.is(tok::identifier)) {
1258*12c85518Srobert Section = Tok.getIdentifierInfo()->getName();
1259*12c85518Srobert PP.Lex(Tok);
1260*12c85518Srobert } else {
1261*12c85518Srobert PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
1262*12c85518Srobert << PragmaName;
1263*12c85518Srobert return false;
1264*12c85518Srobert }
1265*12c85518Srobert
1266*12c85518Srobert if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_comma,
1267*12c85518Srobert PragmaName))
1268*12c85518Srobert return false;
1269*12c85518Srobert
1270*12c85518Srobert SmallVector<std::tuple<IdentifierInfo *, SourceLocation>> Functions;
1271*12c85518Srobert while (true) {
1272*12c85518Srobert if (Tok.isNot(tok::identifier)) {
1273*12c85518Srobert PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1274*12c85518Srobert << PragmaName;
1275*12c85518Srobert return false;
1276*12c85518Srobert }
1277*12c85518Srobert
1278*12c85518Srobert IdentifierInfo *II = Tok.getIdentifierInfo();
1279*12c85518Srobert Functions.emplace_back(II, Tok.getLocation());
1280*12c85518Srobert
1281*12c85518Srobert PP.Lex(Tok);
1282*12c85518Srobert if (Tok.isNot(tok::comma))
1283*12c85518Srobert break;
1284*12c85518Srobert PP.Lex(Tok);
1285*12c85518Srobert }
1286*12c85518Srobert
1287*12c85518Srobert if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
1288*12c85518Srobert PragmaName) ||
1289*12c85518Srobert ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
1290*12c85518Srobert PragmaName))
1291*12c85518Srobert return false;
1292*12c85518Srobert
1293*12c85518Srobert Actions.ActOnPragmaMSAllocText(FirstTok.getLocation(), Section, Functions);
1294*12c85518Srobert return true;
1295*12c85518Srobert }
1296e5dd7070Spatrick
PragmaLoopHintString(Token PragmaName,Token Option)1297e5dd7070Spatrick static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
1298e5dd7070Spatrick StringRef Str = PragmaName.getIdentifierInfo()->getName();
1299*12c85518Srobert std::string ClangLoopStr("clang loop ");
1300*12c85518Srobert if (Str == "loop" && Option.getIdentifierInfo())
1301*12c85518Srobert ClangLoopStr += Option.getIdentifierInfo()->getName();
1302ec727ea7Spatrick return std::string(llvm::StringSwitch<StringRef>(Str)
1303e5dd7070Spatrick .Case("loop", ClangLoopStr)
1304e5dd7070Spatrick .Case("unroll_and_jam", Str)
1305e5dd7070Spatrick .Case("unroll", Str)
1306ec727ea7Spatrick .Default(""));
1307e5dd7070Spatrick }
1308e5dd7070Spatrick
HandlePragmaLoopHint(LoopHint & Hint)1309e5dd7070Spatrick bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
1310e5dd7070Spatrick assert(Tok.is(tok::annot_pragma_loop_hint));
1311e5dd7070Spatrick PragmaLoopHintInfo *Info =
1312e5dd7070Spatrick static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
1313e5dd7070Spatrick
1314e5dd7070Spatrick IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
1315e5dd7070Spatrick Hint.PragmaNameLoc = IdentifierLoc::create(
1316e5dd7070Spatrick Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);
1317e5dd7070Spatrick
1318e5dd7070Spatrick // It is possible that the loop hint has no option identifier, such as
1319e5dd7070Spatrick // #pragma unroll(4).
1320e5dd7070Spatrick IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
1321e5dd7070Spatrick ? Info->Option.getIdentifierInfo()
1322e5dd7070Spatrick : nullptr;
1323e5dd7070Spatrick Hint.OptionLoc = IdentifierLoc::create(
1324e5dd7070Spatrick Actions.Context, Info->Option.getLocation(), OptionInfo);
1325e5dd7070Spatrick
1326e5dd7070Spatrick llvm::ArrayRef<Token> Toks = Info->Toks;
1327e5dd7070Spatrick
1328e5dd7070Spatrick // Return a valid hint if pragma unroll or nounroll were specified
1329e5dd7070Spatrick // without an argument.
1330e5dd7070Spatrick auto IsLoopHint = llvm::StringSwitch<bool>(PragmaNameInfo->getName())
1331e5dd7070Spatrick .Cases("unroll", "nounroll", "unroll_and_jam",
1332e5dd7070Spatrick "nounroll_and_jam", true)
1333e5dd7070Spatrick .Default(false);
1334e5dd7070Spatrick
1335e5dd7070Spatrick if (Toks.empty() && IsLoopHint) {
1336e5dd7070Spatrick ConsumeAnnotationToken();
1337e5dd7070Spatrick Hint.Range = Info->PragmaName.getLocation();
1338e5dd7070Spatrick return true;
1339e5dd7070Spatrick }
1340e5dd7070Spatrick
1341e5dd7070Spatrick // The constant expression is always followed by an eof token, which increases
1342e5dd7070Spatrick // the TokSize by 1.
1343e5dd7070Spatrick assert(!Toks.empty() &&
1344e5dd7070Spatrick "PragmaLoopHintInfo::Toks must contain at least one token.");
1345e5dd7070Spatrick
1346e5dd7070Spatrick // If no option is specified the argument is assumed to be a constant expr.
1347e5dd7070Spatrick bool OptionUnroll = false;
1348e5dd7070Spatrick bool OptionUnrollAndJam = false;
1349e5dd7070Spatrick bool OptionDistribute = false;
1350e5dd7070Spatrick bool OptionPipelineDisabled = false;
1351e5dd7070Spatrick bool StateOption = false;
1352e5dd7070Spatrick if (OptionInfo) { // Pragma Unroll does not specify an option.
1353e5dd7070Spatrick OptionUnroll = OptionInfo->isStr("unroll");
1354e5dd7070Spatrick OptionUnrollAndJam = OptionInfo->isStr("unroll_and_jam");
1355e5dd7070Spatrick OptionDistribute = OptionInfo->isStr("distribute");
1356e5dd7070Spatrick OptionPipelineDisabled = OptionInfo->isStr("pipeline");
1357e5dd7070Spatrick StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
1358e5dd7070Spatrick .Case("vectorize", true)
1359e5dd7070Spatrick .Case("interleave", true)
1360e5dd7070Spatrick .Case("vectorize_predicate", true)
1361e5dd7070Spatrick .Default(false) ||
1362e5dd7070Spatrick OptionUnroll || OptionUnrollAndJam || OptionDistribute ||
1363e5dd7070Spatrick OptionPipelineDisabled;
1364e5dd7070Spatrick }
1365e5dd7070Spatrick
1366e5dd7070Spatrick bool AssumeSafetyArg = !OptionUnroll && !OptionUnrollAndJam &&
1367e5dd7070Spatrick !OptionDistribute && !OptionPipelineDisabled;
1368e5dd7070Spatrick // Verify loop hint has an argument.
1369e5dd7070Spatrick if (Toks[0].is(tok::eof)) {
1370e5dd7070Spatrick ConsumeAnnotationToken();
1371e5dd7070Spatrick Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
1372e5dd7070Spatrick << /*StateArgument=*/StateOption
1373e5dd7070Spatrick << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
1374e5dd7070Spatrick << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
1375e5dd7070Spatrick return false;
1376e5dd7070Spatrick }
1377e5dd7070Spatrick
1378e5dd7070Spatrick // Validate the argument.
1379e5dd7070Spatrick if (StateOption) {
1380e5dd7070Spatrick ConsumeAnnotationToken();
1381e5dd7070Spatrick SourceLocation StateLoc = Toks[0].getLocation();
1382e5dd7070Spatrick IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
1383e5dd7070Spatrick
1384e5dd7070Spatrick bool Valid = StateInfo &&
1385e5dd7070Spatrick llvm::StringSwitch<bool>(StateInfo->getName())
1386e5dd7070Spatrick .Case("disable", true)
1387e5dd7070Spatrick .Case("enable", !OptionPipelineDisabled)
1388e5dd7070Spatrick .Case("full", OptionUnroll || OptionUnrollAndJam)
1389e5dd7070Spatrick .Case("assume_safety", AssumeSafetyArg)
1390e5dd7070Spatrick .Default(false);
1391e5dd7070Spatrick if (!Valid) {
1392e5dd7070Spatrick if (OptionPipelineDisabled) {
1393e5dd7070Spatrick Diag(Toks[0].getLocation(), diag::err_pragma_pipeline_invalid_keyword);
1394e5dd7070Spatrick } else {
1395e5dd7070Spatrick Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
1396e5dd7070Spatrick << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
1397e5dd7070Spatrick << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
1398e5dd7070Spatrick }
1399e5dd7070Spatrick return false;
1400e5dd7070Spatrick }
1401e5dd7070Spatrick if (Toks.size() > 2)
1402e5dd7070Spatrick Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1403e5dd7070Spatrick << PragmaLoopHintString(Info->PragmaName, Info->Option);
1404e5dd7070Spatrick Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
1405a9ac8606Spatrick } else if (OptionInfo && OptionInfo->getName() == "vectorize_width") {
1406a9ac8606Spatrick PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false,
1407a9ac8606Spatrick /*IsReinject=*/false);
1408a9ac8606Spatrick ConsumeAnnotationToken();
1409a9ac8606Spatrick
1410a9ac8606Spatrick SourceLocation StateLoc = Toks[0].getLocation();
1411a9ac8606Spatrick IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
1412a9ac8606Spatrick StringRef IsScalableStr = StateInfo ? StateInfo->getName() : "";
1413a9ac8606Spatrick
1414a9ac8606Spatrick // Look for vectorize_width(fixed|scalable)
1415a9ac8606Spatrick if (IsScalableStr == "scalable" || IsScalableStr == "fixed") {
1416a9ac8606Spatrick PP.Lex(Tok); // Identifier
1417a9ac8606Spatrick
1418a9ac8606Spatrick if (Toks.size() > 2) {
1419a9ac8606Spatrick Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1420a9ac8606Spatrick << PragmaLoopHintString(Info->PragmaName, Info->Option);
1421a9ac8606Spatrick while (Tok.isNot(tok::eof))
1422a9ac8606Spatrick ConsumeAnyToken();
1423a9ac8606Spatrick }
1424a9ac8606Spatrick
1425a9ac8606Spatrick Hint.StateLoc =
1426a9ac8606Spatrick IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
1427a9ac8606Spatrick
1428a9ac8606Spatrick ConsumeToken(); // Consume the constant expression eof terminator.
1429a9ac8606Spatrick } else {
1430a9ac8606Spatrick // Enter constant expression including eof terminator into token stream.
1431a9ac8606Spatrick ExprResult R = ParseConstantExpression();
1432a9ac8606Spatrick
1433a9ac8606Spatrick if (R.isInvalid() && !Tok.is(tok::comma))
1434a9ac8606Spatrick Diag(Toks[0].getLocation(),
1435a9ac8606Spatrick diag::note_pragma_loop_invalid_vectorize_option);
1436a9ac8606Spatrick
1437a9ac8606Spatrick bool Arg2Error = false;
1438a9ac8606Spatrick if (Tok.is(tok::comma)) {
1439a9ac8606Spatrick PP.Lex(Tok); // ,
1440a9ac8606Spatrick
1441a9ac8606Spatrick StateInfo = Tok.getIdentifierInfo();
1442a9ac8606Spatrick IsScalableStr = StateInfo->getName();
1443a9ac8606Spatrick
1444a9ac8606Spatrick if (IsScalableStr != "scalable" && IsScalableStr != "fixed") {
1445a9ac8606Spatrick Diag(Tok.getLocation(),
1446a9ac8606Spatrick diag::err_pragma_loop_invalid_vectorize_option);
1447a9ac8606Spatrick Arg2Error = true;
1448a9ac8606Spatrick } else
1449a9ac8606Spatrick Hint.StateLoc =
1450a9ac8606Spatrick IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
1451a9ac8606Spatrick
1452a9ac8606Spatrick PP.Lex(Tok); // Identifier
1453a9ac8606Spatrick }
1454a9ac8606Spatrick
1455a9ac8606Spatrick // Tokens following an error in an ill-formed constant expression will
1456a9ac8606Spatrick // remain in the token stream and must be removed.
1457a9ac8606Spatrick if (Tok.isNot(tok::eof)) {
1458a9ac8606Spatrick Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1459a9ac8606Spatrick << PragmaLoopHintString(Info->PragmaName, Info->Option);
1460a9ac8606Spatrick while (Tok.isNot(tok::eof))
1461a9ac8606Spatrick ConsumeAnyToken();
1462a9ac8606Spatrick }
1463a9ac8606Spatrick
1464a9ac8606Spatrick ConsumeToken(); // Consume the constant expression eof terminator.
1465a9ac8606Spatrick
1466a9ac8606Spatrick if (Arg2Error || R.isInvalid() ||
1467a9ac8606Spatrick Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
1468a9ac8606Spatrick return false;
1469a9ac8606Spatrick
1470a9ac8606Spatrick // Argument is a constant expression with an integer type.
1471a9ac8606Spatrick Hint.ValueExpr = R.get();
1472a9ac8606Spatrick }
1473e5dd7070Spatrick } else {
1474e5dd7070Spatrick // Enter constant expression including eof terminator into token stream.
1475e5dd7070Spatrick PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false,
1476e5dd7070Spatrick /*IsReinject=*/false);
1477e5dd7070Spatrick ConsumeAnnotationToken();
1478e5dd7070Spatrick ExprResult R = ParseConstantExpression();
1479e5dd7070Spatrick
1480e5dd7070Spatrick // Tokens following an error in an ill-formed constant expression will
1481e5dd7070Spatrick // remain in the token stream and must be removed.
1482e5dd7070Spatrick if (Tok.isNot(tok::eof)) {
1483e5dd7070Spatrick Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1484e5dd7070Spatrick << PragmaLoopHintString(Info->PragmaName, Info->Option);
1485e5dd7070Spatrick while (Tok.isNot(tok::eof))
1486e5dd7070Spatrick ConsumeAnyToken();
1487e5dd7070Spatrick }
1488e5dd7070Spatrick
1489e5dd7070Spatrick ConsumeToken(); // Consume the constant expression eof terminator.
1490e5dd7070Spatrick
1491e5dd7070Spatrick if (R.isInvalid() ||
1492e5dd7070Spatrick Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
1493e5dd7070Spatrick return false;
1494e5dd7070Spatrick
1495e5dd7070Spatrick // Argument is a constant expression with an integer type.
1496e5dd7070Spatrick Hint.ValueExpr = R.get();
1497e5dd7070Spatrick }
1498e5dd7070Spatrick
1499e5dd7070Spatrick Hint.Range = SourceRange(Info->PragmaName.getLocation(),
1500e5dd7070Spatrick Info->Toks.back().getLocation());
1501e5dd7070Spatrick return true;
1502e5dd7070Spatrick }
1503e5dd7070Spatrick
1504e5dd7070Spatrick namespace {
1505e5dd7070Spatrick struct PragmaAttributeInfo {
1506e5dd7070Spatrick enum ActionType { Push, Pop, Attribute };
1507e5dd7070Spatrick ParsedAttributes &Attributes;
1508e5dd7070Spatrick ActionType Action;
1509e5dd7070Spatrick const IdentifierInfo *Namespace = nullptr;
1510e5dd7070Spatrick ArrayRef<Token> Tokens;
1511e5dd7070Spatrick
PragmaAttributeInfo__anon4a1872ae0411::PragmaAttributeInfo1512e5dd7070Spatrick PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {}
1513e5dd7070Spatrick };
1514e5dd7070Spatrick
1515e5dd7070Spatrick #include "clang/Parse/AttrSubMatchRulesParserStringSwitches.inc"
1516e5dd7070Spatrick
1517e5dd7070Spatrick } // end anonymous namespace
1518e5dd7070Spatrick
getIdentifier(const Token & Tok)1519e5dd7070Spatrick static StringRef getIdentifier(const Token &Tok) {
1520e5dd7070Spatrick if (Tok.is(tok::identifier))
1521e5dd7070Spatrick return Tok.getIdentifierInfo()->getName();
1522e5dd7070Spatrick const char *S = tok::getKeywordSpelling(Tok.getKind());
1523e5dd7070Spatrick if (!S)
1524e5dd7070Spatrick return "";
1525e5dd7070Spatrick return S;
1526e5dd7070Spatrick }
1527e5dd7070Spatrick
isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule)1528e5dd7070Spatrick static bool isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule) {
1529e5dd7070Spatrick using namespace attr;
1530e5dd7070Spatrick switch (Rule) {
1531e5dd7070Spatrick #define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) \
1532e5dd7070Spatrick case Value: \
1533e5dd7070Spatrick return IsAbstract;
1534e5dd7070Spatrick #include "clang/Basic/AttrSubMatchRulesList.inc"
1535e5dd7070Spatrick }
1536e5dd7070Spatrick llvm_unreachable("Invalid attribute subject match rule");
1537e5dd7070Spatrick return false;
1538e5dd7070Spatrick }
1539e5dd7070Spatrick
diagnoseExpectedAttributeSubjectSubRule(Parser & PRef,attr::SubjectMatchRule PrimaryRule,StringRef PrimaryRuleName,SourceLocation SubRuleLoc)1540e5dd7070Spatrick static void diagnoseExpectedAttributeSubjectSubRule(
1541e5dd7070Spatrick Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1542e5dd7070Spatrick SourceLocation SubRuleLoc) {
1543e5dd7070Spatrick auto Diagnostic =
1544e5dd7070Spatrick PRef.Diag(SubRuleLoc,
1545e5dd7070Spatrick diag::err_pragma_attribute_expected_subject_sub_identifier)
1546e5dd7070Spatrick << PrimaryRuleName;
1547e5dd7070Spatrick if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1548e5dd7070Spatrick Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1549e5dd7070Spatrick else
1550e5dd7070Spatrick Diagnostic << /*SubRulesSupported=*/0;
1551e5dd7070Spatrick }
1552e5dd7070Spatrick
diagnoseUnknownAttributeSubjectSubRule(Parser & PRef,attr::SubjectMatchRule PrimaryRule,StringRef PrimaryRuleName,StringRef SubRuleName,SourceLocation SubRuleLoc)1553e5dd7070Spatrick static void diagnoseUnknownAttributeSubjectSubRule(
1554e5dd7070Spatrick Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1555e5dd7070Spatrick StringRef SubRuleName, SourceLocation SubRuleLoc) {
1556e5dd7070Spatrick
1557e5dd7070Spatrick auto Diagnostic =
1558e5dd7070Spatrick PRef.Diag(SubRuleLoc, diag::err_pragma_attribute_unknown_subject_sub_rule)
1559e5dd7070Spatrick << SubRuleName << PrimaryRuleName;
1560e5dd7070Spatrick if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1561e5dd7070Spatrick Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1562e5dd7070Spatrick else
1563e5dd7070Spatrick Diagnostic << /*SubRulesSupported=*/0;
1564e5dd7070Spatrick }
1565e5dd7070Spatrick
ParsePragmaAttributeSubjectMatchRuleSet(attr::ParsedSubjectMatchRuleSet & SubjectMatchRules,SourceLocation & AnyLoc,SourceLocation & LastMatchRuleEndLoc)1566e5dd7070Spatrick bool Parser::ParsePragmaAttributeSubjectMatchRuleSet(
1567e5dd7070Spatrick attr::ParsedSubjectMatchRuleSet &SubjectMatchRules, SourceLocation &AnyLoc,
1568e5dd7070Spatrick SourceLocation &LastMatchRuleEndLoc) {
1569e5dd7070Spatrick bool IsAny = false;
1570e5dd7070Spatrick BalancedDelimiterTracker AnyParens(*this, tok::l_paren);
1571e5dd7070Spatrick if (getIdentifier(Tok) == "any") {
1572e5dd7070Spatrick AnyLoc = ConsumeToken();
1573e5dd7070Spatrick IsAny = true;
1574e5dd7070Spatrick if (AnyParens.expectAndConsume())
1575e5dd7070Spatrick return true;
1576e5dd7070Spatrick }
1577e5dd7070Spatrick
1578e5dd7070Spatrick do {
1579e5dd7070Spatrick // Parse the subject matcher rule.
1580e5dd7070Spatrick StringRef Name = getIdentifier(Tok);
1581e5dd7070Spatrick if (Name.empty()) {
1582e5dd7070Spatrick Diag(Tok, diag::err_pragma_attribute_expected_subject_identifier);
1583e5dd7070Spatrick return true;
1584e5dd7070Spatrick }
1585*12c85518Srobert std::pair<std::optional<attr::SubjectMatchRule>,
1586*12c85518Srobert std::optional<attr::SubjectMatchRule> (*)(StringRef, bool)>
1587e5dd7070Spatrick Rule = isAttributeSubjectMatchRule(Name);
1588e5dd7070Spatrick if (!Rule.first) {
1589e5dd7070Spatrick Diag(Tok, diag::err_pragma_attribute_unknown_subject_rule) << Name;
1590e5dd7070Spatrick return true;
1591e5dd7070Spatrick }
1592e5dd7070Spatrick attr::SubjectMatchRule PrimaryRule = *Rule.first;
1593e5dd7070Spatrick SourceLocation RuleLoc = ConsumeToken();
1594e5dd7070Spatrick
1595e5dd7070Spatrick BalancedDelimiterTracker Parens(*this, tok::l_paren);
1596e5dd7070Spatrick if (isAbstractAttrMatcherRule(PrimaryRule)) {
1597e5dd7070Spatrick if (Parens.expectAndConsume())
1598e5dd7070Spatrick return true;
1599e5dd7070Spatrick } else if (Parens.consumeOpen()) {
1600e5dd7070Spatrick if (!SubjectMatchRules
1601e5dd7070Spatrick .insert(
1602e5dd7070Spatrick std::make_pair(PrimaryRule, SourceRange(RuleLoc, RuleLoc)))
1603e5dd7070Spatrick .second)
1604e5dd7070Spatrick Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1605e5dd7070Spatrick << Name
1606e5dd7070Spatrick << FixItHint::CreateRemoval(SourceRange(
1607e5dd7070Spatrick RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleLoc));
1608e5dd7070Spatrick LastMatchRuleEndLoc = RuleLoc;
1609e5dd7070Spatrick continue;
1610e5dd7070Spatrick }
1611e5dd7070Spatrick
1612e5dd7070Spatrick // Parse the sub-rules.
1613e5dd7070Spatrick StringRef SubRuleName = getIdentifier(Tok);
1614e5dd7070Spatrick if (SubRuleName.empty()) {
1615e5dd7070Spatrick diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1616e5dd7070Spatrick Tok.getLocation());
1617e5dd7070Spatrick return true;
1618e5dd7070Spatrick }
1619e5dd7070Spatrick attr::SubjectMatchRule SubRule;
1620e5dd7070Spatrick if (SubRuleName == "unless") {
1621e5dd7070Spatrick SourceLocation SubRuleLoc = ConsumeToken();
1622e5dd7070Spatrick BalancedDelimiterTracker Parens(*this, tok::l_paren);
1623e5dd7070Spatrick if (Parens.expectAndConsume())
1624e5dd7070Spatrick return true;
1625e5dd7070Spatrick SubRuleName = getIdentifier(Tok);
1626e5dd7070Spatrick if (SubRuleName.empty()) {
1627e5dd7070Spatrick diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1628e5dd7070Spatrick SubRuleLoc);
1629e5dd7070Spatrick return true;
1630e5dd7070Spatrick }
1631e5dd7070Spatrick auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/true);
1632e5dd7070Spatrick if (!SubRuleOrNone) {
1633e5dd7070Spatrick std::string SubRuleUnlessName = "unless(" + SubRuleName.str() + ")";
1634e5dd7070Spatrick diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1635e5dd7070Spatrick SubRuleUnlessName, SubRuleLoc);
1636e5dd7070Spatrick return true;
1637e5dd7070Spatrick }
1638e5dd7070Spatrick SubRule = *SubRuleOrNone;
1639e5dd7070Spatrick ConsumeToken();
1640e5dd7070Spatrick if (Parens.consumeClose())
1641e5dd7070Spatrick return true;
1642e5dd7070Spatrick } else {
1643e5dd7070Spatrick auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/false);
1644e5dd7070Spatrick if (!SubRuleOrNone) {
1645e5dd7070Spatrick diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1646e5dd7070Spatrick SubRuleName, Tok.getLocation());
1647e5dd7070Spatrick return true;
1648e5dd7070Spatrick }
1649e5dd7070Spatrick SubRule = *SubRuleOrNone;
1650e5dd7070Spatrick ConsumeToken();
1651e5dd7070Spatrick }
1652e5dd7070Spatrick SourceLocation RuleEndLoc = Tok.getLocation();
1653e5dd7070Spatrick LastMatchRuleEndLoc = RuleEndLoc;
1654e5dd7070Spatrick if (Parens.consumeClose())
1655e5dd7070Spatrick return true;
1656e5dd7070Spatrick if (!SubjectMatchRules
1657e5dd7070Spatrick .insert(std::make_pair(SubRule, SourceRange(RuleLoc, RuleEndLoc)))
1658e5dd7070Spatrick .second) {
1659e5dd7070Spatrick Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1660e5dd7070Spatrick << attr::getSubjectMatchRuleSpelling(SubRule)
1661e5dd7070Spatrick << FixItHint::CreateRemoval(SourceRange(
1662e5dd7070Spatrick RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleEndLoc));
1663e5dd7070Spatrick continue;
1664e5dd7070Spatrick }
1665e5dd7070Spatrick } while (IsAny && TryConsumeToken(tok::comma));
1666e5dd7070Spatrick
1667e5dd7070Spatrick if (IsAny)
1668e5dd7070Spatrick if (AnyParens.consumeClose())
1669e5dd7070Spatrick return true;
1670e5dd7070Spatrick
1671e5dd7070Spatrick return false;
1672e5dd7070Spatrick }
1673e5dd7070Spatrick
1674e5dd7070Spatrick namespace {
1675e5dd7070Spatrick
1676e5dd7070Spatrick /// Describes the stage at which attribute subject rule parsing was interrupted.
1677e5dd7070Spatrick enum class MissingAttributeSubjectRulesRecoveryPoint {
1678e5dd7070Spatrick Comma,
1679e5dd7070Spatrick ApplyTo,
1680e5dd7070Spatrick Equals,
1681e5dd7070Spatrick Any,
1682e5dd7070Spatrick None,
1683e5dd7070Spatrick };
1684e5dd7070Spatrick
1685e5dd7070Spatrick MissingAttributeSubjectRulesRecoveryPoint
getAttributeSubjectRulesRecoveryPointForToken(const Token & Tok)1686e5dd7070Spatrick getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) {
1687e5dd7070Spatrick if (const auto *II = Tok.getIdentifierInfo()) {
1688e5dd7070Spatrick if (II->isStr("apply_to"))
1689e5dd7070Spatrick return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo;
1690e5dd7070Spatrick if (II->isStr("any"))
1691e5dd7070Spatrick return MissingAttributeSubjectRulesRecoveryPoint::Any;
1692e5dd7070Spatrick }
1693e5dd7070Spatrick if (Tok.is(tok::equal))
1694e5dd7070Spatrick return MissingAttributeSubjectRulesRecoveryPoint::Equals;
1695e5dd7070Spatrick return MissingAttributeSubjectRulesRecoveryPoint::None;
1696e5dd7070Spatrick }
1697e5dd7070Spatrick
1698e5dd7070Spatrick /// Creates a diagnostic for the attribute subject rule parsing diagnostic that
1699e5dd7070Spatrick /// suggests the possible attribute subject rules in a fix-it together with
1700e5dd7070Spatrick /// any other missing tokens.
createExpectedAttributeSubjectRulesTokenDiagnostic(unsigned DiagID,ParsedAttributes & Attrs,MissingAttributeSubjectRulesRecoveryPoint Point,Parser & PRef)1701e5dd7070Spatrick DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic(
1702*12c85518Srobert unsigned DiagID, ParsedAttributes &Attrs,
1703e5dd7070Spatrick MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) {
1704e5dd7070Spatrick SourceLocation Loc = PRef.getEndOfPreviousToken();
1705e5dd7070Spatrick if (Loc.isInvalid())
1706e5dd7070Spatrick Loc = PRef.getCurToken().getLocation();
1707e5dd7070Spatrick auto Diagnostic = PRef.Diag(Loc, DiagID);
1708e5dd7070Spatrick std::string FixIt;
1709e5dd7070Spatrick MissingAttributeSubjectRulesRecoveryPoint EndPoint =
1710e5dd7070Spatrick getAttributeSubjectRulesRecoveryPointForToken(PRef.getCurToken());
1711e5dd7070Spatrick if (Point == MissingAttributeSubjectRulesRecoveryPoint::Comma)
1712e5dd7070Spatrick FixIt = ", ";
1713e5dd7070Spatrick if (Point <= MissingAttributeSubjectRulesRecoveryPoint::ApplyTo &&
1714e5dd7070Spatrick EndPoint > MissingAttributeSubjectRulesRecoveryPoint::ApplyTo)
1715e5dd7070Spatrick FixIt += "apply_to";
1716e5dd7070Spatrick if (Point <= MissingAttributeSubjectRulesRecoveryPoint::Equals &&
1717e5dd7070Spatrick EndPoint > MissingAttributeSubjectRulesRecoveryPoint::Equals)
1718e5dd7070Spatrick FixIt += " = ";
1719e5dd7070Spatrick SourceRange FixItRange(Loc);
1720e5dd7070Spatrick if (EndPoint == MissingAttributeSubjectRulesRecoveryPoint::None) {
1721e5dd7070Spatrick // Gather the subject match rules that are supported by the attribute.
1722*12c85518Srobert // Add all the possible rules initially.
1723*12c85518Srobert llvm::BitVector IsMatchRuleAvailable(attr::SubjectMatchRule_Last + 1, true);
1724*12c85518Srobert // Remove the ones that are not supported by any of the attributes.
1725*12c85518Srobert for (const ParsedAttr &Attribute : Attrs) {
1726*12c85518Srobert SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> MatchRules;
1727*12c85518Srobert Attribute.getMatchRules(PRef.getLangOpts(), MatchRules);
1728*12c85518Srobert llvm::BitVector IsSupported(attr::SubjectMatchRule_Last + 1);
1729*12c85518Srobert for (const auto &Rule : MatchRules) {
1730*12c85518Srobert // Ensure that the missing rule is reported in the fix-it only when it's
1731*12c85518Srobert // supported in the current language mode.
1732*12c85518Srobert if (!Rule.second)
1733*12c85518Srobert continue;
1734*12c85518Srobert IsSupported[Rule.first] = true;
1735*12c85518Srobert }
1736*12c85518Srobert IsMatchRuleAvailable &= IsSupported;
1737*12c85518Srobert }
1738*12c85518Srobert if (IsMatchRuleAvailable.count() == 0) {
1739e5dd7070Spatrick // FIXME: We can emit a "fix-it" with a subject list placeholder when
1740e5dd7070Spatrick // placeholders will be supported by the fix-its.
1741e5dd7070Spatrick return Diagnostic;
1742e5dd7070Spatrick }
1743e5dd7070Spatrick FixIt += "any(";
1744e5dd7070Spatrick bool NeedsComma = false;
1745*12c85518Srobert for (unsigned I = 0; I <= attr::SubjectMatchRule_Last; I++) {
1746*12c85518Srobert if (!IsMatchRuleAvailable[I])
1747e5dd7070Spatrick continue;
1748e5dd7070Spatrick if (NeedsComma)
1749e5dd7070Spatrick FixIt += ", ";
1750e5dd7070Spatrick else
1751e5dd7070Spatrick NeedsComma = true;
1752*12c85518Srobert FixIt += attr::getSubjectMatchRuleSpelling(
1753*12c85518Srobert static_cast<attr::SubjectMatchRule>(I));
1754e5dd7070Spatrick }
1755e5dd7070Spatrick FixIt += ")";
1756e5dd7070Spatrick // Check if we need to remove the range
1757e5dd7070Spatrick PRef.SkipUntil(tok::eof, Parser::StopBeforeMatch);
1758e5dd7070Spatrick FixItRange.setEnd(PRef.getCurToken().getLocation());
1759e5dd7070Spatrick }
1760e5dd7070Spatrick if (FixItRange.getBegin() == FixItRange.getEnd())
1761e5dd7070Spatrick Diagnostic << FixItHint::CreateInsertion(FixItRange.getBegin(), FixIt);
1762e5dd7070Spatrick else
1763e5dd7070Spatrick Diagnostic << FixItHint::CreateReplacement(
1764e5dd7070Spatrick CharSourceRange::getCharRange(FixItRange), FixIt);
1765e5dd7070Spatrick return Diagnostic;
1766e5dd7070Spatrick }
1767e5dd7070Spatrick
1768e5dd7070Spatrick } // end anonymous namespace
1769e5dd7070Spatrick
HandlePragmaAttribute()1770e5dd7070Spatrick void Parser::HandlePragmaAttribute() {
1771e5dd7070Spatrick assert(Tok.is(tok::annot_pragma_attribute) &&
1772e5dd7070Spatrick "Expected #pragma attribute annotation token");
1773e5dd7070Spatrick SourceLocation PragmaLoc = Tok.getLocation();
1774e5dd7070Spatrick auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue());
1775e5dd7070Spatrick if (Info->Action == PragmaAttributeInfo::Pop) {
1776e5dd7070Spatrick ConsumeAnnotationToken();
1777e5dd7070Spatrick Actions.ActOnPragmaAttributePop(PragmaLoc, Info->Namespace);
1778e5dd7070Spatrick return;
1779e5dd7070Spatrick }
1780e5dd7070Spatrick // Parse the actual attribute with its arguments.
1781e5dd7070Spatrick assert((Info->Action == PragmaAttributeInfo::Push ||
1782e5dd7070Spatrick Info->Action == PragmaAttributeInfo::Attribute) &&
1783e5dd7070Spatrick "Unexpected #pragma attribute command");
1784e5dd7070Spatrick
1785e5dd7070Spatrick if (Info->Action == PragmaAttributeInfo::Push && Info->Tokens.empty()) {
1786e5dd7070Spatrick ConsumeAnnotationToken();
1787e5dd7070Spatrick Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
1788e5dd7070Spatrick return;
1789e5dd7070Spatrick }
1790e5dd7070Spatrick
1791e5dd7070Spatrick PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false,
1792e5dd7070Spatrick /*IsReinject=*/false);
1793e5dd7070Spatrick ConsumeAnnotationToken();
1794e5dd7070Spatrick
1795e5dd7070Spatrick ParsedAttributes &Attrs = Info->Attributes;
1796e5dd7070Spatrick Attrs.clearListOnly();
1797e5dd7070Spatrick
1798e5dd7070Spatrick auto SkipToEnd = [this]() {
1799e5dd7070Spatrick SkipUntil(tok::eof, StopBeforeMatch);
1800e5dd7070Spatrick ConsumeToken();
1801e5dd7070Spatrick };
1802e5dd7070Spatrick
1803e5dd7070Spatrick if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) {
1804e5dd7070Spatrick // Parse the CXX11 style attribute.
1805e5dd7070Spatrick ParseCXX11AttributeSpecifier(Attrs);
1806e5dd7070Spatrick } else if (Tok.is(tok::kw___attribute)) {
1807e5dd7070Spatrick ConsumeToken();
1808e5dd7070Spatrick if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
1809e5dd7070Spatrick "attribute"))
1810e5dd7070Spatrick return SkipToEnd();
1811e5dd7070Spatrick if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "("))
1812e5dd7070Spatrick return SkipToEnd();
1813e5dd7070Spatrick
1814*12c85518Srobert // FIXME: The practical usefulness of completion here is limited because
1815*12c85518Srobert // we only get here if the line has balanced parens.
1816*12c85518Srobert if (Tok.is(tok::code_completion)) {
1817*12c85518Srobert cutOffParsing();
1818*12c85518Srobert // FIXME: suppress completion of unsupported attributes?
1819*12c85518Srobert Actions.CodeCompleteAttribute(AttributeCommonInfo::Syntax::AS_GNU);
1820*12c85518Srobert return SkipToEnd();
1821*12c85518Srobert }
1822*12c85518Srobert
1823*12c85518Srobert // Parse the comma-separated list of attributes.
1824*12c85518Srobert do {
1825e5dd7070Spatrick if (Tok.isNot(tok::identifier)) {
1826e5dd7070Spatrick Diag(Tok, diag::err_pragma_attribute_expected_attribute_name);
1827e5dd7070Spatrick SkipToEnd();
1828e5dd7070Spatrick return;
1829e5dd7070Spatrick }
1830e5dd7070Spatrick IdentifierInfo *AttrName = Tok.getIdentifierInfo();
1831e5dd7070Spatrick SourceLocation AttrNameLoc = ConsumeToken();
1832e5dd7070Spatrick
1833e5dd7070Spatrick if (Tok.isNot(tok::l_paren))
1834e5dd7070Spatrick Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
1835e5dd7070Spatrick ParsedAttr::AS_GNU);
1836e5dd7070Spatrick else
1837e5dd7070Spatrick ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr,
1838e5dd7070Spatrick /*ScopeName=*/nullptr,
1839e5dd7070Spatrick /*ScopeLoc=*/SourceLocation(), ParsedAttr::AS_GNU,
1840e5dd7070Spatrick /*Declarator=*/nullptr);
1841*12c85518Srobert } while (TryConsumeToken(tok::comma));
1842e5dd7070Spatrick
1843e5dd7070Spatrick if (ExpectAndConsume(tok::r_paren))
1844e5dd7070Spatrick return SkipToEnd();
1845e5dd7070Spatrick if (ExpectAndConsume(tok::r_paren))
1846e5dd7070Spatrick return SkipToEnd();
1847e5dd7070Spatrick } else if (Tok.is(tok::kw___declspec)) {
1848e5dd7070Spatrick ParseMicrosoftDeclSpecs(Attrs);
1849e5dd7070Spatrick } else {
1850e5dd7070Spatrick Diag(Tok, diag::err_pragma_attribute_expected_attribute_syntax);
1851e5dd7070Spatrick if (Tok.getIdentifierInfo()) {
1852e5dd7070Spatrick // If we suspect that this is an attribute suggest the use of
1853e5dd7070Spatrick // '__attribute__'.
1854e5dd7070Spatrick if (ParsedAttr::getParsedKind(
1855e5dd7070Spatrick Tok.getIdentifierInfo(), /*ScopeName=*/nullptr,
1856e5dd7070Spatrick ParsedAttr::AS_GNU) != ParsedAttr::UnknownAttribute) {
1857e5dd7070Spatrick SourceLocation InsertStartLoc = Tok.getLocation();
1858e5dd7070Spatrick ConsumeToken();
1859e5dd7070Spatrick if (Tok.is(tok::l_paren)) {
1860e5dd7070Spatrick ConsumeAnyToken();
1861e5dd7070Spatrick SkipUntil(tok::r_paren, StopBeforeMatch);
1862e5dd7070Spatrick if (Tok.isNot(tok::r_paren))
1863e5dd7070Spatrick return SkipToEnd();
1864e5dd7070Spatrick }
1865e5dd7070Spatrick Diag(Tok, diag::note_pragma_attribute_use_attribute_kw)
1866e5dd7070Spatrick << FixItHint::CreateInsertion(InsertStartLoc, "__attribute__((")
1867e5dd7070Spatrick << FixItHint::CreateInsertion(Tok.getEndLoc(), "))");
1868e5dd7070Spatrick }
1869e5dd7070Spatrick }
1870e5dd7070Spatrick SkipToEnd();
1871e5dd7070Spatrick return;
1872e5dd7070Spatrick }
1873e5dd7070Spatrick
1874e5dd7070Spatrick if (Attrs.empty() || Attrs.begin()->isInvalid()) {
1875e5dd7070Spatrick SkipToEnd();
1876e5dd7070Spatrick return;
1877e5dd7070Spatrick }
1878e5dd7070Spatrick
1879*12c85518Srobert for (const ParsedAttr &Attribute : Attrs) {
1880e5dd7070Spatrick if (!Attribute.isSupportedByPragmaAttribute()) {
1881e5dd7070Spatrick Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute)
1882e5dd7070Spatrick << Attribute;
1883e5dd7070Spatrick SkipToEnd();
1884e5dd7070Spatrick return;
1885e5dd7070Spatrick }
1886*12c85518Srobert }
1887e5dd7070Spatrick
1888e5dd7070Spatrick // Parse the subject-list.
1889e5dd7070Spatrick if (!TryConsumeToken(tok::comma)) {
1890e5dd7070Spatrick createExpectedAttributeSubjectRulesTokenDiagnostic(
1891*12c85518Srobert diag::err_expected, Attrs,
1892e5dd7070Spatrick MissingAttributeSubjectRulesRecoveryPoint::Comma, *this)
1893e5dd7070Spatrick << tok::comma;
1894e5dd7070Spatrick SkipToEnd();
1895e5dd7070Spatrick return;
1896e5dd7070Spatrick }
1897e5dd7070Spatrick
1898e5dd7070Spatrick if (Tok.isNot(tok::identifier)) {
1899e5dd7070Spatrick createExpectedAttributeSubjectRulesTokenDiagnostic(
1900*12c85518Srobert diag::err_pragma_attribute_invalid_subject_set_specifier, Attrs,
1901e5dd7070Spatrick MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1902e5dd7070Spatrick SkipToEnd();
1903e5dd7070Spatrick return;
1904e5dd7070Spatrick }
1905e5dd7070Spatrick const IdentifierInfo *II = Tok.getIdentifierInfo();
1906e5dd7070Spatrick if (!II->isStr("apply_to")) {
1907e5dd7070Spatrick createExpectedAttributeSubjectRulesTokenDiagnostic(
1908*12c85518Srobert diag::err_pragma_attribute_invalid_subject_set_specifier, Attrs,
1909e5dd7070Spatrick MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1910e5dd7070Spatrick SkipToEnd();
1911e5dd7070Spatrick return;
1912e5dd7070Spatrick }
1913e5dd7070Spatrick ConsumeToken();
1914e5dd7070Spatrick
1915e5dd7070Spatrick if (!TryConsumeToken(tok::equal)) {
1916e5dd7070Spatrick createExpectedAttributeSubjectRulesTokenDiagnostic(
1917*12c85518Srobert diag::err_expected, Attrs,
1918e5dd7070Spatrick MissingAttributeSubjectRulesRecoveryPoint::Equals, *this)
1919e5dd7070Spatrick << tok::equal;
1920e5dd7070Spatrick SkipToEnd();
1921e5dd7070Spatrick return;
1922e5dd7070Spatrick }
1923e5dd7070Spatrick
1924e5dd7070Spatrick attr::ParsedSubjectMatchRuleSet SubjectMatchRules;
1925e5dd7070Spatrick SourceLocation AnyLoc, LastMatchRuleEndLoc;
1926e5dd7070Spatrick if (ParsePragmaAttributeSubjectMatchRuleSet(SubjectMatchRules, AnyLoc,
1927e5dd7070Spatrick LastMatchRuleEndLoc)) {
1928e5dd7070Spatrick SkipToEnd();
1929e5dd7070Spatrick return;
1930e5dd7070Spatrick }
1931e5dd7070Spatrick
1932e5dd7070Spatrick // Tokens following an ill-formed attribute will remain in the token stream
1933e5dd7070Spatrick // and must be removed.
1934e5dd7070Spatrick if (Tok.isNot(tok::eof)) {
1935e5dd7070Spatrick Diag(Tok, diag::err_pragma_attribute_extra_tokens_after_attribute);
1936e5dd7070Spatrick SkipToEnd();
1937e5dd7070Spatrick return;
1938e5dd7070Spatrick }
1939e5dd7070Spatrick
1940e5dd7070Spatrick // Consume the eof terminator token.
1941e5dd7070Spatrick ConsumeToken();
1942e5dd7070Spatrick
1943e5dd7070Spatrick // Handle a mixed push/attribute by desurging to a push, then an attribute.
1944e5dd7070Spatrick if (Info->Action == PragmaAttributeInfo::Push)
1945e5dd7070Spatrick Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
1946e5dd7070Spatrick
1947*12c85518Srobert for (ParsedAttr &Attribute : Attrs) {
1948e5dd7070Spatrick Actions.ActOnPragmaAttributeAttribute(Attribute, PragmaLoc,
1949*12c85518Srobert SubjectMatchRules);
1950*12c85518Srobert }
1951e5dd7070Spatrick }
1952e5dd7070Spatrick
1953e5dd7070Spatrick // #pragma GCC visibility comes in two variants:
1954e5dd7070Spatrick // 'push' '(' [visibility] ')'
1955e5dd7070Spatrick // 'pop'
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & VisTok)1956e5dd7070Spatrick void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
1957e5dd7070Spatrick PragmaIntroducer Introducer,
1958e5dd7070Spatrick Token &VisTok) {
1959e5dd7070Spatrick SourceLocation VisLoc = VisTok.getLocation();
1960e5dd7070Spatrick
1961e5dd7070Spatrick Token Tok;
1962e5dd7070Spatrick PP.LexUnexpandedToken(Tok);
1963e5dd7070Spatrick
1964e5dd7070Spatrick const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
1965e5dd7070Spatrick
1966e5dd7070Spatrick const IdentifierInfo *VisType;
1967e5dd7070Spatrick if (PushPop && PushPop->isStr("pop")) {
1968e5dd7070Spatrick VisType = nullptr;
1969e5dd7070Spatrick } else if (PushPop && PushPop->isStr("push")) {
1970e5dd7070Spatrick PP.LexUnexpandedToken(Tok);
1971e5dd7070Spatrick if (Tok.isNot(tok::l_paren)) {
1972e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
1973e5dd7070Spatrick << "visibility";
1974e5dd7070Spatrick return;
1975e5dd7070Spatrick }
1976e5dd7070Spatrick PP.LexUnexpandedToken(Tok);
1977e5dd7070Spatrick VisType = Tok.getIdentifierInfo();
1978e5dd7070Spatrick if (!VisType) {
1979e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1980e5dd7070Spatrick << "visibility";
1981e5dd7070Spatrick return;
1982e5dd7070Spatrick }
1983e5dd7070Spatrick PP.LexUnexpandedToken(Tok);
1984e5dd7070Spatrick if (Tok.isNot(tok::r_paren)) {
1985e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
1986e5dd7070Spatrick << "visibility";
1987e5dd7070Spatrick return;
1988e5dd7070Spatrick }
1989e5dd7070Spatrick } else {
1990e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1991e5dd7070Spatrick << "visibility";
1992e5dd7070Spatrick return;
1993e5dd7070Spatrick }
1994e5dd7070Spatrick SourceLocation EndLoc = Tok.getLocation();
1995e5dd7070Spatrick PP.LexUnexpandedToken(Tok);
1996e5dd7070Spatrick if (Tok.isNot(tok::eod)) {
1997e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1998e5dd7070Spatrick << "visibility";
1999e5dd7070Spatrick return;
2000e5dd7070Spatrick }
2001e5dd7070Spatrick
2002e5dd7070Spatrick auto Toks = std::make_unique<Token[]>(1);
2003e5dd7070Spatrick Toks[0].startToken();
2004e5dd7070Spatrick Toks[0].setKind(tok::annot_pragma_vis);
2005e5dd7070Spatrick Toks[0].setLocation(VisLoc);
2006e5dd7070Spatrick Toks[0].setAnnotationEndLoc(EndLoc);
2007e5dd7070Spatrick Toks[0].setAnnotationValue(
2008e5dd7070Spatrick const_cast<void *>(static_cast<const void *>(VisType)));
2009e5dd7070Spatrick PP.EnterTokenStream(std::move(Toks), 1, /*DisableMacroExpansion=*/true,
2010e5dd7070Spatrick /*IsReinject=*/false);
2011e5dd7070Spatrick }
2012e5dd7070Spatrick
2013e5dd7070Spatrick // #pragma pack(...) comes in the following delicious flavors:
2014e5dd7070Spatrick // pack '(' [integer] ')'
2015e5dd7070Spatrick // pack '(' 'show' ')'
2016e5dd7070Spatrick // pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & PackTok)2017e5dd7070Spatrick void PragmaPackHandler::HandlePragma(Preprocessor &PP,
2018e5dd7070Spatrick PragmaIntroducer Introducer,
2019e5dd7070Spatrick Token &PackTok) {
2020e5dd7070Spatrick SourceLocation PackLoc = PackTok.getLocation();
2021e5dd7070Spatrick
2022e5dd7070Spatrick Token Tok;
2023e5dd7070Spatrick PP.Lex(Tok);
2024e5dd7070Spatrick if (Tok.isNot(tok::l_paren)) {
2025e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
2026e5dd7070Spatrick return;
2027e5dd7070Spatrick }
2028e5dd7070Spatrick
2029e5dd7070Spatrick Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
2030e5dd7070Spatrick StringRef SlotLabel;
2031e5dd7070Spatrick Token Alignment;
2032e5dd7070Spatrick Alignment.startToken();
2033e5dd7070Spatrick PP.Lex(Tok);
2034e5dd7070Spatrick if (Tok.is(tok::numeric_constant)) {
2035e5dd7070Spatrick Alignment = Tok;
2036e5dd7070Spatrick
2037e5dd7070Spatrick PP.Lex(Tok);
2038e5dd7070Spatrick
2039e5dd7070Spatrick // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
2040e5dd7070Spatrick // the push/pop stack.
2041a9ac8606Spatrick // In Apple gcc/XL, #pragma pack(4) is equivalent to #pragma pack(push, 4)
2042a9ac8606Spatrick Action = (PP.getLangOpts().ApplePragmaPack || PP.getLangOpts().XLPragmaPack)
2043a9ac8606Spatrick ? Sema::PSK_Push_Set
2044a9ac8606Spatrick : Sema::PSK_Set;
2045e5dd7070Spatrick } else if (Tok.is(tok::identifier)) {
2046e5dd7070Spatrick const IdentifierInfo *II = Tok.getIdentifierInfo();
2047e5dd7070Spatrick if (II->isStr("show")) {
2048e5dd7070Spatrick Action = Sema::PSK_Show;
2049e5dd7070Spatrick PP.Lex(Tok);
2050e5dd7070Spatrick } else {
2051e5dd7070Spatrick if (II->isStr("push")) {
2052e5dd7070Spatrick Action = Sema::PSK_Push;
2053e5dd7070Spatrick } else if (II->isStr("pop")) {
2054e5dd7070Spatrick Action = Sema::PSK_Pop;
2055e5dd7070Spatrick } else {
2056e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
2057e5dd7070Spatrick return;
2058e5dd7070Spatrick }
2059e5dd7070Spatrick PP.Lex(Tok);
2060e5dd7070Spatrick
2061e5dd7070Spatrick if (Tok.is(tok::comma)) {
2062e5dd7070Spatrick PP.Lex(Tok);
2063e5dd7070Spatrick
2064e5dd7070Spatrick if (Tok.is(tok::numeric_constant)) {
2065e5dd7070Spatrick Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
2066e5dd7070Spatrick Alignment = Tok;
2067e5dd7070Spatrick
2068e5dd7070Spatrick PP.Lex(Tok);
2069e5dd7070Spatrick } else if (Tok.is(tok::identifier)) {
2070e5dd7070Spatrick SlotLabel = Tok.getIdentifierInfo()->getName();
2071e5dd7070Spatrick PP.Lex(Tok);
2072e5dd7070Spatrick
2073e5dd7070Spatrick if (Tok.is(tok::comma)) {
2074e5dd7070Spatrick PP.Lex(Tok);
2075e5dd7070Spatrick
2076e5dd7070Spatrick if (Tok.isNot(tok::numeric_constant)) {
2077e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
2078e5dd7070Spatrick return;
2079e5dd7070Spatrick }
2080e5dd7070Spatrick
2081e5dd7070Spatrick Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
2082e5dd7070Spatrick Alignment = Tok;
2083e5dd7070Spatrick
2084e5dd7070Spatrick PP.Lex(Tok);
2085e5dd7070Spatrick }
2086e5dd7070Spatrick } else {
2087e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
2088e5dd7070Spatrick return;
2089e5dd7070Spatrick }
2090e5dd7070Spatrick }
2091e5dd7070Spatrick }
2092a9ac8606Spatrick } else if (PP.getLangOpts().ApplePragmaPack ||
2093a9ac8606Spatrick PP.getLangOpts().XLPragmaPack) {
2094e5dd7070Spatrick // In MSVC/gcc, #pragma pack() resets the alignment without affecting
2095e5dd7070Spatrick // the push/pop stack.
2096a9ac8606Spatrick // In Apple gcc and IBM XL, #pragma pack() is equivalent to #pragma
2097a9ac8606Spatrick // pack(pop).
2098e5dd7070Spatrick Action = Sema::PSK_Pop;
2099e5dd7070Spatrick }
2100e5dd7070Spatrick
2101e5dd7070Spatrick if (Tok.isNot(tok::r_paren)) {
2102e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
2103e5dd7070Spatrick return;
2104e5dd7070Spatrick }
2105e5dd7070Spatrick
2106e5dd7070Spatrick SourceLocation RParenLoc = Tok.getLocation();
2107e5dd7070Spatrick PP.Lex(Tok);
2108e5dd7070Spatrick if (Tok.isNot(tok::eod)) {
2109e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
2110e5dd7070Spatrick return;
2111e5dd7070Spatrick }
2112e5dd7070Spatrick
2113e5dd7070Spatrick PragmaPackInfo *Info =
2114e5dd7070Spatrick PP.getPreprocessorAllocator().Allocate<PragmaPackInfo>(1);
2115e5dd7070Spatrick Info->Action = Action;
2116e5dd7070Spatrick Info->SlotLabel = SlotLabel;
2117e5dd7070Spatrick Info->Alignment = Alignment;
2118e5dd7070Spatrick
2119e5dd7070Spatrick MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2120e5dd7070Spatrick 1);
2121e5dd7070Spatrick Toks[0].startToken();
2122e5dd7070Spatrick Toks[0].setKind(tok::annot_pragma_pack);
2123e5dd7070Spatrick Toks[0].setLocation(PackLoc);
2124e5dd7070Spatrick Toks[0].setAnnotationEndLoc(RParenLoc);
2125e5dd7070Spatrick Toks[0].setAnnotationValue(static_cast<void*>(Info));
2126e5dd7070Spatrick PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2127e5dd7070Spatrick /*IsReinject=*/false);
2128e5dd7070Spatrick }
2129e5dd7070Spatrick
2130e5dd7070Spatrick // #pragma ms_struct on
2131e5dd7070Spatrick // #pragma ms_struct off
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & MSStructTok)2132e5dd7070Spatrick void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
2133e5dd7070Spatrick PragmaIntroducer Introducer,
2134e5dd7070Spatrick Token &MSStructTok) {
2135e5dd7070Spatrick PragmaMSStructKind Kind = PMSST_OFF;
2136e5dd7070Spatrick
2137e5dd7070Spatrick Token Tok;
2138e5dd7070Spatrick PP.Lex(Tok);
2139e5dd7070Spatrick if (Tok.isNot(tok::identifier)) {
2140e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
2141e5dd7070Spatrick return;
2142e5dd7070Spatrick }
2143e5dd7070Spatrick SourceLocation EndLoc = Tok.getLocation();
2144e5dd7070Spatrick const IdentifierInfo *II = Tok.getIdentifierInfo();
2145e5dd7070Spatrick if (II->isStr("on")) {
2146e5dd7070Spatrick Kind = PMSST_ON;
2147e5dd7070Spatrick PP.Lex(Tok);
2148e5dd7070Spatrick }
2149e5dd7070Spatrick else if (II->isStr("off") || II->isStr("reset"))
2150e5dd7070Spatrick PP.Lex(Tok);
2151e5dd7070Spatrick else {
2152e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
2153e5dd7070Spatrick return;
2154e5dd7070Spatrick }
2155e5dd7070Spatrick
2156e5dd7070Spatrick if (Tok.isNot(tok::eod)) {
2157e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2158e5dd7070Spatrick << "ms_struct";
2159e5dd7070Spatrick return;
2160e5dd7070Spatrick }
2161e5dd7070Spatrick
2162e5dd7070Spatrick MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2163e5dd7070Spatrick 1);
2164e5dd7070Spatrick Toks[0].startToken();
2165e5dd7070Spatrick Toks[0].setKind(tok::annot_pragma_msstruct);
2166e5dd7070Spatrick Toks[0].setLocation(MSStructTok.getLocation());
2167e5dd7070Spatrick Toks[0].setAnnotationEndLoc(EndLoc);
2168e5dd7070Spatrick Toks[0].setAnnotationValue(reinterpret_cast<void*>(
2169e5dd7070Spatrick static_cast<uintptr_t>(Kind)));
2170e5dd7070Spatrick PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2171e5dd7070Spatrick /*IsReinject=*/false);
2172e5dd7070Spatrick }
2173e5dd7070Spatrick
2174e5dd7070Spatrick // #pragma clang section bss="abc" data="" rodata="def" text="" relro=""
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & FirstToken)2175e5dd7070Spatrick void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP,
2176e5dd7070Spatrick PragmaIntroducer Introducer,
2177e5dd7070Spatrick Token &FirstToken) {
2178e5dd7070Spatrick
2179e5dd7070Spatrick Token Tok;
2180e5dd7070Spatrick auto SecKind = Sema::PragmaClangSectionKind::PCSK_Invalid;
2181e5dd7070Spatrick
2182e5dd7070Spatrick PP.Lex(Tok); // eat 'section'
2183e5dd7070Spatrick while (Tok.isNot(tok::eod)) {
2184e5dd7070Spatrick if (Tok.isNot(tok::identifier)) {
2185e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
2186e5dd7070Spatrick return;
2187e5dd7070Spatrick }
2188e5dd7070Spatrick
2189e5dd7070Spatrick const IdentifierInfo *SecType = Tok.getIdentifierInfo();
2190e5dd7070Spatrick if (SecType->isStr("bss"))
2191e5dd7070Spatrick SecKind = Sema::PragmaClangSectionKind::PCSK_BSS;
2192e5dd7070Spatrick else if (SecType->isStr("data"))
2193e5dd7070Spatrick SecKind = Sema::PragmaClangSectionKind::PCSK_Data;
2194e5dd7070Spatrick else if (SecType->isStr("rodata"))
2195e5dd7070Spatrick SecKind = Sema::PragmaClangSectionKind::PCSK_Rodata;
2196e5dd7070Spatrick else if (SecType->isStr("relro"))
2197e5dd7070Spatrick SecKind = Sema::PragmaClangSectionKind::PCSK_Relro;
2198e5dd7070Spatrick else if (SecType->isStr("text"))
2199e5dd7070Spatrick SecKind = Sema::PragmaClangSectionKind::PCSK_Text;
2200e5dd7070Spatrick else {
2201e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
2202e5dd7070Spatrick return;
2203e5dd7070Spatrick }
2204e5dd7070Spatrick
2205ec727ea7Spatrick SourceLocation PragmaLocation = Tok.getLocation();
2206e5dd7070Spatrick PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text']
2207e5dd7070Spatrick if (Tok.isNot(tok::equal)) {
2208e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind;
2209e5dd7070Spatrick return;
2210e5dd7070Spatrick }
2211e5dd7070Spatrick
2212e5dd7070Spatrick std::string SecName;
2213e5dd7070Spatrick if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false))
2214e5dd7070Spatrick return;
2215e5dd7070Spatrick
2216ec727ea7Spatrick Actions.ActOnPragmaClangSection(
2217ec727ea7Spatrick PragmaLocation,
2218ec727ea7Spatrick (SecName.size() ? Sema::PragmaClangSectionAction::PCSA_Set
2219ec727ea7Spatrick : Sema::PragmaClangSectionAction::PCSA_Clear),
2220e5dd7070Spatrick SecKind, SecName);
2221e5dd7070Spatrick }
2222e5dd7070Spatrick }
2223e5dd7070Spatrick
2224e5dd7070Spatrick // #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
2225e5dd7070Spatrick // #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
2226a9ac8606Spatrick // #pragma 'align' '(' {'native','natural','mac68k','power','reset'} ')'
ParseAlignPragma(Preprocessor & PP,Token & FirstTok,bool IsOptions)2227e5dd7070Spatrick static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
2228e5dd7070Spatrick bool IsOptions) {
2229e5dd7070Spatrick Token Tok;
2230e5dd7070Spatrick
2231e5dd7070Spatrick if (IsOptions) {
2232e5dd7070Spatrick PP.Lex(Tok);
2233e5dd7070Spatrick if (Tok.isNot(tok::identifier) ||
2234e5dd7070Spatrick !Tok.getIdentifierInfo()->isStr("align")) {
2235e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
2236e5dd7070Spatrick return;
2237e5dd7070Spatrick }
2238e5dd7070Spatrick }
2239e5dd7070Spatrick
2240e5dd7070Spatrick PP.Lex(Tok);
2241a9ac8606Spatrick if (PP.getLangOpts().XLPragmaPack) {
2242a9ac8606Spatrick if (Tok.isNot(tok::l_paren)) {
2243a9ac8606Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "align";
2244a9ac8606Spatrick return;
2245a9ac8606Spatrick }
2246a9ac8606Spatrick } else if (Tok.isNot(tok::equal)) {
2247e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
2248e5dd7070Spatrick << IsOptions;
2249e5dd7070Spatrick return;
2250e5dd7070Spatrick }
2251e5dd7070Spatrick
2252e5dd7070Spatrick PP.Lex(Tok);
2253e5dd7070Spatrick if (Tok.isNot(tok::identifier)) {
2254e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2255e5dd7070Spatrick << (IsOptions ? "options" : "align");
2256e5dd7070Spatrick return;
2257e5dd7070Spatrick }
2258e5dd7070Spatrick
2259e5dd7070Spatrick Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
2260e5dd7070Spatrick const IdentifierInfo *II = Tok.getIdentifierInfo();
2261e5dd7070Spatrick if (II->isStr("native"))
2262e5dd7070Spatrick Kind = Sema::POAK_Native;
2263e5dd7070Spatrick else if (II->isStr("natural"))
2264e5dd7070Spatrick Kind = Sema::POAK_Natural;
2265e5dd7070Spatrick else if (II->isStr("packed"))
2266e5dd7070Spatrick Kind = Sema::POAK_Packed;
2267e5dd7070Spatrick else if (II->isStr("power"))
2268e5dd7070Spatrick Kind = Sema::POAK_Power;
2269e5dd7070Spatrick else if (II->isStr("mac68k"))
2270e5dd7070Spatrick Kind = Sema::POAK_Mac68k;
2271e5dd7070Spatrick else if (II->isStr("reset"))
2272e5dd7070Spatrick Kind = Sema::POAK_Reset;
2273e5dd7070Spatrick else {
2274e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
2275e5dd7070Spatrick << IsOptions;
2276e5dd7070Spatrick return;
2277e5dd7070Spatrick }
2278e5dd7070Spatrick
2279a9ac8606Spatrick if (PP.getLangOpts().XLPragmaPack) {
2280a9ac8606Spatrick PP.Lex(Tok);
2281a9ac8606Spatrick if (Tok.isNot(tok::r_paren)) {
2282a9ac8606Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "align";
2283a9ac8606Spatrick return;
2284a9ac8606Spatrick }
2285a9ac8606Spatrick }
2286a9ac8606Spatrick
2287e5dd7070Spatrick SourceLocation EndLoc = Tok.getLocation();
2288e5dd7070Spatrick PP.Lex(Tok);
2289e5dd7070Spatrick if (Tok.isNot(tok::eod)) {
2290e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2291e5dd7070Spatrick << (IsOptions ? "options" : "align");
2292e5dd7070Spatrick return;
2293e5dd7070Spatrick }
2294e5dd7070Spatrick
2295e5dd7070Spatrick MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2296e5dd7070Spatrick 1);
2297e5dd7070Spatrick Toks[0].startToken();
2298e5dd7070Spatrick Toks[0].setKind(tok::annot_pragma_align);
2299e5dd7070Spatrick Toks[0].setLocation(FirstTok.getLocation());
2300e5dd7070Spatrick Toks[0].setAnnotationEndLoc(EndLoc);
2301e5dd7070Spatrick Toks[0].setAnnotationValue(reinterpret_cast<void*>(
2302e5dd7070Spatrick static_cast<uintptr_t>(Kind)));
2303e5dd7070Spatrick PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2304e5dd7070Spatrick /*IsReinject=*/false);
2305e5dd7070Spatrick }
2306e5dd7070Spatrick
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & AlignTok)2307e5dd7070Spatrick void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
2308e5dd7070Spatrick PragmaIntroducer Introducer,
2309e5dd7070Spatrick Token &AlignTok) {
2310e5dd7070Spatrick ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
2311e5dd7070Spatrick }
2312e5dd7070Spatrick
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & OptionsTok)2313e5dd7070Spatrick void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
2314e5dd7070Spatrick PragmaIntroducer Introducer,
2315e5dd7070Spatrick Token &OptionsTok) {
2316e5dd7070Spatrick ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
2317e5dd7070Spatrick }
2318e5dd7070Spatrick
2319e5dd7070Spatrick // #pragma unused(identifier)
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & UnusedTok)2320e5dd7070Spatrick void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
2321e5dd7070Spatrick PragmaIntroducer Introducer,
2322e5dd7070Spatrick Token &UnusedTok) {
2323e5dd7070Spatrick // FIXME: Should we be expanding macros here? My guess is no.
2324e5dd7070Spatrick SourceLocation UnusedLoc = UnusedTok.getLocation();
2325e5dd7070Spatrick
2326e5dd7070Spatrick // Lex the left '('.
2327e5dd7070Spatrick Token Tok;
2328e5dd7070Spatrick PP.Lex(Tok);
2329e5dd7070Spatrick if (Tok.isNot(tok::l_paren)) {
2330e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
2331e5dd7070Spatrick return;
2332e5dd7070Spatrick }
2333e5dd7070Spatrick
2334e5dd7070Spatrick // Lex the declaration reference(s).
2335e5dd7070Spatrick SmallVector<Token, 5> Identifiers;
2336e5dd7070Spatrick SourceLocation RParenLoc;
2337e5dd7070Spatrick bool LexID = true;
2338e5dd7070Spatrick
2339e5dd7070Spatrick while (true) {
2340e5dd7070Spatrick PP.Lex(Tok);
2341e5dd7070Spatrick
2342e5dd7070Spatrick if (LexID) {
2343e5dd7070Spatrick if (Tok.is(tok::identifier)) {
2344e5dd7070Spatrick Identifiers.push_back(Tok);
2345e5dd7070Spatrick LexID = false;
2346e5dd7070Spatrick continue;
2347e5dd7070Spatrick }
2348e5dd7070Spatrick
2349e5dd7070Spatrick // Illegal token!
2350e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
2351e5dd7070Spatrick return;
2352e5dd7070Spatrick }
2353e5dd7070Spatrick
2354e5dd7070Spatrick // We are execting a ')' or a ','.
2355e5dd7070Spatrick if (Tok.is(tok::comma)) {
2356e5dd7070Spatrick LexID = true;
2357e5dd7070Spatrick continue;
2358e5dd7070Spatrick }
2359e5dd7070Spatrick
2360e5dd7070Spatrick if (Tok.is(tok::r_paren)) {
2361e5dd7070Spatrick RParenLoc = Tok.getLocation();
2362e5dd7070Spatrick break;
2363e5dd7070Spatrick }
2364e5dd7070Spatrick
2365e5dd7070Spatrick // Illegal token!
2366e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
2367e5dd7070Spatrick return;
2368e5dd7070Spatrick }
2369e5dd7070Spatrick
2370e5dd7070Spatrick PP.Lex(Tok);
2371e5dd7070Spatrick if (Tok.isNot(tok::eod)) {
2372e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2373e5dd7070Spatrick "unused";
2374e5dd7070Spatrick return;
2375e5dd7070Spatrick }
2376e5dd7070Spatrick
2377e5dd7070Spatrick // Verify that we have a location for the right parenthesis.
2378e5dd7070Spatrick assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
2379e5dd7070Spatrick assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
2380e5dd7070Spatrick
2381e5dd7070Spatrick // For each identifier token, insert into the token stream a
2382e5dd7070Spatrick // annot_pragma_unused token followed by the identifier token.
2383e5dd7070Spatrick // This allows us to cache a "#pragma unused" that occurs inside an inline
2384e5dd7070Spatrick // C++ member function.
2385e5dd7070Spatrick
2386e5dd7070Spatrick MutableArrayRef<Token> Toks(
2387e5dd7070Spatrick PP.getPreprocessorAllocator().Allocate<Token>(2 * Identifiers.size()),
2388e5dd7070Spatrick 2 * Identifiers.size());
2389e5dd7070Spatrick for (unsigned i=0; i != Identifiers.size(); i++) {
2390e5dd7070Spatrick Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
2391e5dd7070Spatrick pragmaUnusedTok.startToken();
2392e5dd7070Spatrick pragmaUnusedTok.setKind(tok::annot_pragma_unused);
2393e5dd7070Spatrick pragmaUnusedTok.setLocation(UnusedLoc);
2394e5dd7070Spatrick idTok = Identifiers[i];
2395e5dd7070Spatrick }
2396e5dd7070Spatrick PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2397e5dd7070Spatrick /*IsReinject=*/false);
2398e5dd7070Spatrick }
2399e5dd7070Spatrick
2400e5dd7070Spatrick // #pragma weak identifier
2401e5dd7070Spatrick // #pragma weak identifier '=' identifier
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & WeakTok)2402e5dd7070Spatrick void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
2403e5dd7070Spatrick PragmaIntroducer Introducer,
2404e5dd7070Spatrick Token &WeakTok) {
2405e5dd7070Spatrick SourceLocation WeakLoc = WeakTok.getLocation();
2406e5dd7070Spatrick
2407e5dd7070Spatrick Token Tok;
2408e5dd7070Spatrick PP.Lex(Tok);
2409e5dd7070Spatrick if (Tok.isNot(tok::identifier)) {
2410e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
2411e5dd7070Spatrick return;
2412e5dd7070Spatrick }
2413e5dd7070Spatrick
2414e5dd7070Spatrick Token WeakName = Tok;
2415e5dd7070Spatrick bool HasAlias = false;
2416e5dd7070Spatrick Token AliasName;
2417e5dd7070Spatrick
2418e5dd7070Spatrick PP.Lex(Tok);
2419e5dd7070Spatrick if (Tok.is(tok::equal)) {
2420e5dd7070Spatrick HasAlias = true;
2421e5dd7070Spatrick PP.Lex(Tok);
2422e5dd7070Spatrick if (Tok.isNot(tok::identifier)) {
2423e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2424e5dd7070Spatrick << "weak";
2425e5dd7070Spatrick return;
2426e5dd7070Spatrick }
2427e5dd7070Spatrick AliasName = Tok;
2428e5dd7070Spatrick PP.Lex(Tok);
2429e5dd7070Spatrick }
2430e5dd7070Spatrick
2431e5dd7070Spatrick if (Tok.isNot(tok::eod)) {
2432e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
2433e5dd7070Spatrick return;
2434e5dd7070Spatrick }
2435e5dd7070Spatrick
2436e5dd7070Spatrick if (HasAlias) {
2437e5dd7070Spatrick MutableArrayRef<Token> Toks(
2438e5dd7070Spatrick PP.getPreprocessorAllocator().Allocate<Token>(3), 3);
2439e5dd7070Spatrick Token &pragmaUnusedTok = Toks[0];
2440e5dd7070Spatrick pragmaUnusedTok.startToken();
2441e5dd7070Spatrick pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
2442e5dd7070Spatrick pragmaUnusedTok.setLocation(WeakLoc);
2443e5dd7070Spatrick pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation());
2444e5dd7070Spatrick Toks[1] = WeakName;
2445e5dd7070Spatrick Toks[2] = AliasName;
2446e5dd7070Spatrick PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2447e5dd7070Spatrick /*IsReinject=*/false);
2448e5dd7070Spatrick } else {
2449e5dd7070Spatrick MutableArrayRef<Token> Toks(
2450e5dd7070Spatrick PP.getPreprocessorAllocator().Allocate<Token>(2), 2);
2451e5dd7070Spatrick Token &pragmaUnusedTok = Toks[0];
2452e5dd7070Spatrick pragmaUnusedTok.startToken();
2453e5dd7070Spatrick pragmaUnusedTok.setKind(tok::annot_pragma_weak);
2454e5dd7070Spatrick pragmaUnusedTok.setLocation(WeakLoc);
2455e5dd7070Spatrick pragmaUnusedTok.setAnnotationEndLoc(WeakLoc);
2456e5dd7070Spatrick Toks[1] = WeakName;
2457e5dd7070Spatrick PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2458e5dd7070Spatrick /*IsReinject=*/false);
2459e5dd7070Spatrick }
2460e5dd7070Spatrick }
2461e5dd7070Spatrick
2462e5dd7070Spatrick // #pragma redefine_extname identifier identifier
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & RedefToken)2463e5dd7070Spatrick void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
2464e5dd7070Spatrick PragmaIntroducer Introducer,
2465e5dd7070Spatrick Token &RedefToken) {
2466e5dd7070Spatrick SourceLocation RedefLoc = RedefToken.getLocation();
2467e5dd7070Spatrick
2468e5dd7070Spatrick Token Tok;
2469e5dd7070Spatrick PP.Lex(Tok);
2470e5dd7070Spatrick if (Tok.isNot(tok::identifier)) {
2471e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
2472e5dd7070Spatrick "redefine_extname";
2473e5dd7070Spatrick return;
2474e5dd7070Spatrick }
2475e5dd7070Spatrick
2476e5dd7070Spatrick Token RedefName = Tok;
2477e5dd7070Spatrick PP.Lex(Tok);
2478e5dd7070Spatrick
2479e5dd7070Spatrick if (Tok.isNot(tok::identifier)) {
2480e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2481e5dd7070Spatrick << "redefine_extname";
2482e5dd7070Spatrick return;
2483e5dd7070Spatrick }
2484e5dd7070Spatrick
2485e5dd7070Spatrick Token AliasName = Tok;
2486e5dd7070Spatrick PP.Lex(Tok);
2487e5dd7070Spatrick
2488e5dd7070Spatrick if (Tok.isNot(tok::eod)) {
2489e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2490e5dd7070Spatrick "redefine_extname";
2491e5dd7070Spatrick return;
2492e5dd7070Spatrick }
2493e5dd7070Spatrick
2494e5dd7070Spatrick MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(3),
2495e5dd7070Spatrick 3);
2496e5dd7070Spatrick Token &pragmaRedefTok = Toks[0];
2497e5dd7070Spatrick pragmaRedefTok.startToken();
2498e5dd7070Spatrick pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
2499e5dd7070Spatrick pragmaRedefTok.setLocation(RedefLoc);
2500e5dd7070Spatrick pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation());
2501e5dd7070Spatrick Toks[1] = RedefName;
2502e5dd7070Spatrick Toks[2] = AliasName;
2503e5dd7070Spatrick PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2504e5dd7070Spatrick /*IsReinject=*/false);
2505e5dd7070Spatrick }
2506e5dd7070Spatrick
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2507e5dd7070Spatrick void PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
2508e5dd7070Spatrick PragmaIntroducer Introducer,
2509e5dd7070Spatrick Token &Tok) {
2510e5dd7070Spatrick tok::OnOffSwitch OOS;
2511e5dd7070Spatrick if (PP.LexOnOffSwitch(OOS))
2512e5dd7070Spatrick return;
2513e5dd7070Spatrick
2514e5dd7070Spatrick MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2515e5dd7070Spatrick 1);
2516e5dd7070Spatrick Toks[0].startToken();
2517e5dd7070Spatrick Toks[0].setKind(tok::annot_pragma_fp_contract);
2518e5dd7070Spatrick Toks[0].setLocation(Tok.getLocation());
2519e5dd7070Spatrick Toks[0].setAnnotationEndLoc(Tok.getLocation());
2520e5dd7070Spatrick Toks[0].setAnnotationValue(reinterpret_cast<void*>(
2521e5dd7070Spatrick static_cast<uintptr_t>(OOS)));
2522e5dd7070Spatrick PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2523e5dd7070Spatrick /*IsReinject=*/false);
2524e5dd7070Spatrick }
2525e5dd7070Spatrick
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2526e5dd7070Spatrick void PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
2527e5dd7070Spatrick PragmaIntroducer Introducer,
2528e5dd7070Spatrick Token &Tok) {
2529e5dd7070Spatrick PP.LexUnexpandedToken(Tok);
2530e5dd7070Spatrick if (Tok.isNot(tok::identifier)) {
2531e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
2532e5dd7070Spatrick "OPENCL";
2533e5dd7070Spatrick return;
2534e5dd7070Spatrick }
2535e5dd7070Spatrick IdentifierInfo *Ext = Tok.getIdentifierInfo();
2536e5dd7070Spatrick SourceLocation NameLoc = Tok.getLocation();
2537e5dd7070Spatrick
2538e5dd7070Spatrick PP.Lex(Tok);
2539e5dd7070Spatrick if (Tok.isNot(tok::colon)) {
2540e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext;
2541e5dd7070Spatrick return;
2542e5dd7070Spatrick }
2543e5dd7070Spatrick
2544e5dd7070Spatrick PP.Lex(Tok);
2545e5dd7070Spatrick if (Tok.isNot(tok::identifier)) {
2546e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0;
2547e5dd7070Spatrick return;
2548e5dd7070Spatrick }
2549e5dd7070Spatrick IdentifierInfo *Pred = Tok.getIdentifierInfo();
2550e5dd7070Spatrick
2551e5dd7070Spatrick OpenCLExtState State;
2552e5dd7070Spatrick if (Pred->isStr("enable")) {
2553e5dd7070Spatrick State = Enable;
2554e5dd7070Spatrick } else if (Pred->isStr("disable")) {
2555e5dd7070Spatrick State = Disable;
2556e5dd7070Spatrick } else if (Pred->isStr("begin"))
2557e5dd7070Spatrick State = Begin;
2558e5dd7070Spatrick else if (Pred->isStr("end"))
2559e5dd7070Spatrick State = End;
2560e5dd7070Spatrick else {
2561e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate)
2562e5dd7070Spatrick << Ext->isStr("all");
2563e5dd7070Spatrick return;
2564e5dd7070Spatrick }
2565e5dd7070Spatrick SourceLocation StateLoc = Tok.getLocation();
2566e5dd7070Spatrick
2567e5dd7070Spatrick PP.Lex(Tok);
2568e5dd7070Spatrick if (Tok.isNot(tok::eod)) {
2569e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2570e5dd7070Spatrick "OPENCL EXTENSION";
2571e5dd7070Spatrick return;
2572e5dd7070Spatrick }
2573e5dd7070Spatrick
2574e5dd7070Spatrick auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1);
2575e5dd7070Spatrick Info->first = Ext;
2576e5dd7070Spatrick Info->second = State;
2577e5dd7070Spatrick MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2578e5dd7070Spatrick 1);
2579e5dd7070Spatrick Toks[0].startToken();
2580e5dd7070Spatrick Toks[0].setKind(tok::annot_pragma_opencl_extension);
2581e5dd7070Spatrick Toks[0].setLocation(NameLoc);
2582e5dd7070Spatrick Toks[0].setAnnotationValue(static_cast<void*>(Info));
2583e5dd7070Spatrick Toks[0].setAnnotationEndLoc(StateLoc);
2584e5dd7070Spatrick PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2585e5dd7070Spatrick /*IsReinject=*/false);
2586e5dd7070Spatrick
2587e5dd7070Spatrick if (PP.getPPCallbacks())
2588e5dd7070Spatrick PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext,
2589e5dd7070Spatrick StateLoc, State);
2590e5dd7070Spatrick }
2591e5dd7070Spatrick
2592e5dd7070Spatrick /// Handle '#pragma omp ...' when OpenMP is disabled.
2593e5dd7070Spatrick ///
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & FirstTok)2594e5dd7070Spatrick void PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
2595e5dd7070Spatrick PragmaIntroducer Introducer,
2596e5dd7070Spatrick Token &FirstTok) {
2597e5dd7070Spatrick if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
2598e5dd7070Spatrick FirstTok.getLocation())) {
2599e5dd7070Spatrick PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
2600e5dd7070Spatrick PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
2601e5dd7070Spatrick diag::Severity::Ignored, SourceLocation());
2602e5dd7070Spatrick }
2603e5dd7070Spatrick PP.DiscardUntilEndOfDirective();
2604e5dd7070Spatrick }
2605e5dd7070Spatrick
2606e5dd7070Spatrick /// Handle '#pragma omp ...' when OpenMP is enabled.
2607e5dd7070Spatrick ///
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & FirstTok)2608e5dd7070Spatrick void PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
2609e5dd7070Spatrick PragmaIntroducer Introducer,
2610e5dd7070Spatrick Token &FirstTok) {
2611e5dd7070Spatrick SmallVector<Token, 16> Pragma;
2612e5dd7070Spatrick Token Tok;
2613e5dd7070Spatrick Tok.startToken();
2614e5dd7070Spatrick Tok.setKind(tok::annot_pragma_openmp);
2615e5dd7070Spatrick Tok.setLocation(Introducer.Loc);
2616e5dd7070Spatrick
2617e5dd7070Spatrick while (Tok.isNot(tok::eod) && Tok.isNot(tok::eof)) {
2618e5dd7070Spatrick Pragma.push_back(Tok);
2619e5dd7070Spatrick PP.Lex(Tok);
2620e5dd7070Spatrick if (Tok.is(tok::annot_pragma_openmp)) {
2621e5dd7070Spatrick PP.Diag(Tok, diag::err_omp_unexpected_directive) << 0;
2622e5dd7070Spatrick unsigned InnerPragmaCnt = 1;
2623e5dd7070Spatrick while (InnerPragmaCnt != 0) {
2624e5dd7070Spatrick PP.Lex(Tok);
2625e5dd7070Spatrick if (Tok.is(tok::annot_pragma_openmp))
2626e5dd7070Spatrick ++InnerPragmaCnt;
2627e5dd7070Spatrick else if (Tok.is(tok::annot_pragma_openmp_end))
2628e5dd7070Spatrick --InnerPragmaCnt;
2629e5dd7070Spatrick }
2630e5dd7070Spatrick PP.Lex(Tok);
2631e5dd7070Spatrick }
2632e5dd7070Spatrick }
2633e5dd7070Spatrick SourceLocation EodLoc = Tok.getLocation();
2634e5dd7070Spatrick Tok.startToken();
2635e5dd7070Spatrick Tok.setKind(tok::annot_pragma_openmp_end);
2636e5dd7070Spatrick Tok.setLocation(EodLoc);
2637e5dd7070Spatrick Pragma.push_back(Tok);
2638e5dd7070Spatrick
2639e5dd7070Spatrick auto Toks = std::make_unique<Token[]>(Pragma.size());
2640e5dd7070Spatrick std::copy(Pragma.begin(), Pragma.end(), Toks.get());
2641e5dd7070Spatrick PP.EnterTokenStream(std::move(Toks), Pragma.size(),
2642e5dd7070Spatrick /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
2643e5dd7070Spatrick }
2644e5dd7070Spatrick
2645e5dd7070Spatrick /// Handle '#pragma pointers_to_members'
2646e5dd7070Spatrick // The grammar for this pragma is as follows:
2647e5dd7070Spatrick //
2648e5dd7070Spatrick // <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
2649e5dd7070Spatrick //
2650e5dd7070Spatrick // #pragma pointers_to_members '(' 'best_case' ')'
2651e5dd7070Spatrick // #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
2652e5dd7070Spatrick // #pragma pointers_to_members '(' inheritance-model ')'
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2653e5dd7070Spatrick void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
2654e5dd7070Spatrick PragmaIntroducer Introducer,
2655e5dd7070Spatrick Token &Tok) {
2656e5dd7070Spatrick SourceLocation PointersToMembersLoc = Tok.getLocation();
2657e5dd7070Spatrick PP.Lex(Tok);
2658e5dd7070Spatrick if (Tok.isNot(tok::l_paren)) {
2659e5dd7070Spatrick PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
2660e5dd7070Spatrick << "pointers_to_members";
2661e5dd7070Spatrick return;
2662e5dd7070Spatrick }
2663e5dd7070Spatrick PP.Lex(Tok);
2664e5dd7070Spatrick const IdentifierInfo *Arg = Tok.getIdentifierInfo();
2665e5dd7070Spatrick if (!Arg) {
2666e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2667e5dd7070Spatrick << "pointers_to_members";
2668e5dd7070Spatrick return;
2669e5dd7070Spatrick }
2670e5dd7070Spatrick PP.Lex(Tok);
2671e5dd7070Spatrick
2672e5dd7070Spatrick LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
2673e5dd7070Spatrick if (Arg->isStr("best_case")) {
2674e5dd7070Spatrick RepresentationMethod = LangOptions::PPTMK_BestCase;
2675e5dd7070Spatrick } else {
2676e5dd7070Spatrick if (Arg->isStr("full_generality")) {
2677e5dd7070Spatrick if (Tok.is(tok::comma)) {
2678e5dd7070Spatrick PP.Lex(Tok);
2679e5dd7070Spatrick
2680e5dd7070Spatrick Arg = Tok.getIdentifierInfo();
2681e5dd7070Spatrick if (!Arg) {
2682e5dd7070Spatrick PP.Diag(Tok.getLocation(),
2683e5dd7070Spatrick diag::err_pragma_pointers_to_members_unknown_kind)
2684e5dd7070Spatrick << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
2685e5dd7070Spatrick return;
2686e5dd7070Spatrick }
2687e5dd7070Spatrick PP.Lex(Tok);
2688e5dd7070Spatrick } else if (Tok.is(tok::r_paren)) {
2689e5dd7070Spatrick // #pragma pointers_to_members(full_generality) implicitly specifies
2690e5dd7070Spatrick // virtual_inheritance.
2691e5dd7070Spatrick Arg = nullptr;
2692e5dd7070Spatrick RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
2693e5dd7070Spatrick } else {
2694e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_expected_punc)
2695e5dd7070Spatrick << "full_generality";
2696e5dd7070Spatrick return;
2697e5dd7070Spatrick }
2698e5dd7070Spatrick }
2699e5dd7070Spatrick
2700e5dd7070Spatrick if (Arg) {
2701e5dd7070Spatrick if (Arg->isStr("single_inheritance")) {
2702e5dd7070Spatrick RepresentationMethod =
2703e5dd7070Spatrick LangOptions::PPTMK_FullGeneralitySingleInheritance;
2704e5dd7070Spatrick } else if (Arg->isStr("multiple_inheritance")) {
2705e5dd7070Spatrick RepresentationMethod =
2706e5dd7070Spatrick LangOptions::PPTMK_FullGeneralityMultipleInheritance;
2707e5dd7070Spatrick } else if (Arg->isStr("virtual_inheritance")) {
2708e5dd7070Spatrick RepresentationMethod =
2709e5dd7070Spatrick LangOptions::PPTMK_FullGeneralityVirtualInheritance;
2710e5dd7070Spatrick } else {
2711e5dd7070Spatrick PP.Diag(Tok.getLocation(),
2712e5dd7070Spatrick diag::err_pragma_pointers_to_members_unknown_kind)
2713e5dd7070Spatrick << Arg << /*HasPointerDeclaration*/ 1;
2714e5dd7070Spatrick return;
2715e5dd7070Spatrick }
2716e5dd7070Spatrick }
2717e5dd7070Spatrick }
2718e5dd7070Spatrick
2719e5dd7070Spatrick if (Tok.isNot(tok::r_paren)) {
2720e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
2721e5dd7070Spatrick << (Arg ? Arg->getName() : "full_generality");
2722e5dd7070Spatrick return;
2723e5dd7070Spatrick }
2724e5dd7070Spatrick
2725e5dd7070Spatrick SourceLocation EndLoc = Tok.getLocation();
2726e5dd7070Spatrick PP.Lex(Tok);
2727e5dd7070Spatrick if (Tok.isNot(tok::eod)) {
2728e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2729e5dd7070Spatrick << "pointers_to_members";
2730e5dd7070Spatrick return;
2731e5dd7070Spatrick }
2732e5dd7070Spatrick
2733e5dd7070Spatrick Token AnnotTok;
2734e5dd7070Spatrick AnnotTok.startToken();
2735e5dd7070Spatrick AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
2736e5dd7070Spatrick AnnotTok.setLocation(PointersToMembersLoc);
2737e5dd7070Spatrick AnnotTok.setAnnotationEndLoc(EndLoc);
2738e5dd7070Spatrick AnnotTok.setAnnotationValue(
2739e5dd7070Spatrick reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
2740e5dd7070Spatrick PP.EnterToken(AnnotTok, /*IsReinject=*/true);
2741e5dd7070Spatrick }
2742e5dd7070Spatrick
2743e5dd7070Spatrick /// Handle '#pragma vtordisp'
2744e5dd7070Spatrick // The grammar for this pragma is as follows:
2745e5dd7070Spatrick //
2746e5dd7070Spatrick // <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
2747e5dd7070Spatrick //
2748e5dd7070Spatrick // #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
2749e5dd7070Spatrick // #pragma vtordisp '(' 'pop' ')'
2750e5dd7070Spatrick // #pragma vtordisp '(' ')'
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2751e5dd7070Spatrick void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
2752e5dd7070Spatrick PragmaIntroducer Introducer, Token &Tok) {
2753e5dd7070Spatrick SourceLocation VtorDispLoc = Tok.getLocation();
2754e5dd7070Spatrick PP.Lex(Tok);
2755e5dd7070Spatrick if (Tok.isNot(tok::l_paren)) {
2756e5dd7070Spatrick PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
2757e5dd7070Spatrick return;
2758e5dd7070Spatrick }
2759e5dd7070Spatrick PP.Lex(Tok);
2760e5dd7070Spatrick
2761e5dd7070Spatrick Sema::PragmaMsStackAction Action = Sema::PSK_Set;
2762e5dd7070Spatrick const IdentifierInfo *II = Tok.getIdentifierInfo();
2763e5dd7070Spatrick if (II) {
2764e5dd7070Spatrick if (II->isStr("push")) {
2765e5dd7070Spatrick // #pragma vtordisp(push, mode)
2766e5dd7070Spatrick PP.Lex(Tok);
2767e5dd7070Spatrick if (Tok.isNot(tok::comma)) {
2768e5dd7070Spatrick PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
2769e5dd7070Spatrick return;
2770e5dd7070Spatrick }
2771e5dd7070Spatrick PP.Lex(Tok);
2772e5dd7070Spatrick Action = Sema::PSK_Push_Set;
2773e5dd7070Spatrick // not push, could be on/off
2774e5dd7070Spatrick } else if (II->isStr("pop")) {
2775e5dd7070Spatrick // #pragma vtordisp(pop)
2776e5dd7070Spatrick PP.Lex(Tok);
2777e5dd7070Spatrick Action = Sema::PSK_Pop;
2778e5dd7070Spatrick }
2779e5dd7070Spatrick // not push or pop, could be on/off
2780e5dd7070Spatrick } else {
2781e5dd7070Spatrick if (Tok.is(tok::r_paren)) {
2782e5dd7070Spatrick // #pragma vtordisp()
2783e5dd7070Spatrick Action = Sema::PSK_Reset;
2784e5dd7070Spatrick }
2785e5dd7070Spatrick }
2786e5dd7070Spatrick
2787e5dd7070Spatrick
2788e5dd7070Spatrick uint64_t Value = 0;
2789e5dd7070Spatrick if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {
2790e5dd7070Spatrick const IdentifierInfo *II = Tok.getIdentifierInfo();
2791e5dd7070Spatrick if (II && II->isStr("off")) {
2792e5dd7070Spatrick PP.Lex(Tok);
2793e5dd7070Spatrick Value = 0;
2794e5dd7070Spatrick } else if (II && II->isStr("on")) {
2795e5dd7070Spatrick PP.Lex(Tok);
2796e5dd7070Spatrick Value = 1;
2797e5dd7070Spatrick } else if (Tok.is(tok::numeric_constant) &&
2798e5dd7070Spatrick PP.parseSimpleIntegerLiteral(Tok, Value)) {
2799e5dd7070Spatrick if (Value > 2) {
2800e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
2801e5dd7070Spatrick << 0 << 2 << "vtordisp";
2802e5dd7070Spatrick return;
2803e5dd7070Spatrick }
2804e5dd7070Spatrick } else {
2805e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
2806e5dd7070Spatrick << "vtordisp";
2807e5dd7070Spatrick return;
2808e5dd7070Spatrick }
2809e5dd7070Spatrick }
2810e5dd7070Spatrick
2811e5dd7070Spatrick // Finish the pragma: ')' $
2812e5dd7070Spatrick if (Tok.isNot(tok::r_paren)) {
2813e5dd7070Spatrick PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
2814e5dd7070Spatrick return;
2815e5dd7070Spatrick }
2816e5dd7070Spatrick SourceLocation EndLoc = Tok.getLocation();
2817e5dd7070Spatrick PP.Lex(Tok);
2818e5dd7070Spatrick if (Tok.isNot(tok::eod)) {
2819e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2820e5dd7070Spatrick << "vtordisp";
2821e5dd7070Spatrick return;
2822e5dd7070Spatrick }
2823e5dd7070Spatrick
2824e5dd7070Spatrick // Enter the annotation.
2825e5dd7070Spatrick Token AnnotTok;
2826e5dd7070Spatrick AnnotTok.startToken();
2827e5dd7070Spatrick AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
2828e5dd7070Spatrick AnnotTok.setLocation(VtorDispLoc);
2829e5dd7070Spatrick AnnotTok.setAnnotationEndLoc(EndLoc);
2830e5dd7070Spatrick AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
2831e5dd7070Spatrick static_cast<uintptr_t>((Action << 16) | (Value & 0xFFFF))));
2832e5dd7070Spatrick PP.EnterToken(AnnotTok, /*IsReinject=*/false);
2833e5dd7070Spatrick }
2834e5dd7070Spatrick
2835e5dd7070Spatrick /// Handle all MS pragmas. Simply forwards the tokens after inserting
2836e5dd7070Spatrick /// an annotation token.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2837e5dd7070Spatrick void PragmaMSPragma::HandlePragma(Preprocessor &PP,
2838e5dd7070Spatrick PragmaIntroducer Introducer, Token &Tok) {
2839e5dd7070Spatrick Token EoF, AnnotTok;
2840e5dd7070Spatrick EoF.startToken();
2841e5dd7070Spatrick EoF.setKind(tok::eof);
2842e5dd7070Spatrick AnnotTok.startToken();
2843e5dd7070Spatrick AnnotTok.setKind(tok::annot_pragma_ms_pragma);
2844e5dd7070Spatrick AnnotTok.setLocation(Tok.getLocation());
2845e5dd7070Spatrick AnnotTok.setAnnotationEndLoc(Tok.getLocation());
2846e5dd7070Spatrick SmallVector<Token, 8> TokenVector;
2847e5dd7070Spatrick // Suck up all of the tokens before the eod.
2848e5dd7070Spatrick for (; Tok.isNot(tok::eod); PP.Lex(Tok)) {
2849e5dd7070Spatrick TokenVector.push_back(Tok);
2850e5dd7070Spatrick AnnotTok.setAnnotationEndLoc(Tok.getLocation());
2851e5dd7070Spatrick }
2852e5dd7070Spatrick // Add a sentinel EoF token to the end of the list.
2853e5dd7070Spatrick TokenVector.push_back(EoF);
2854e5dd7070Spatrick // We must allocate this array with new because EnterTokenStream is going to
2855e5dd7070Spatrick // delete it later.
2856a9ac8606Spatrick markAsReinjectedForRelexing(TokenVector);
2857e5dd7070Spatrick auto TokenArray = std::make_unique<Token[]>(TokenVector.size());
2858e5dd7070Spatrick std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get());
2859e5dd7070Spatrick auto Value = new (PP.getPreprocessorAllocator())
2860e5dd7070Spatrick std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray),
2861e5dd7070Spatrick TokenVector.size());
2862e5dd7070Spatrick AnnotTok.setAnnotationValue(Value);
2863e5dd7070Spatrick PP.EnterToken(AnnotTok, /*IsReinject*/ false);
2864e5dd7070Spatrick }
2865e5dd7070Spatrick
2866ec727ea7Spatrick /// Handle the \#pragma float_control extension.
2867ec727ea7Spatrick ///
2868ec727ea7Spatrick /// The syntax is:
2869ec727ea7Spatrick /// \code
2870ec727ea7Spatrick /// #pragma float_control(keyword[, setting] [,push])
2871ec727ea7Spatrick /// \endcode
2872ec727ea7Spatrick /// Where 'keyword' and 'setting' are identifiers.
2873ec727ea7Spatrick // 'keyword' can be: precise, except, push, pop
2874ec727ea7Spatrick // 'setting' can be: on, off
2875ec727ea7Spatrick /// The optional arguments 'setting' and 'push' are supported only
2876ec727ea7Spatrick /// when the keyword is 'precise' or 'except'.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)2877ec727ea7Spatrick void PragmaFloatControlHandler::HandlePragma(Preprocessor &PP,
2878ec727ea7Spatrick PragmaIntroducer Introducer,
2879ec727ea7Spatrick Token &Tok) {
2880ec727ea7Spatrick Sema::PragmaMsStackAction Action = Sema::PSK_Set;
2881ec727ea7Spatrick SourceLocation FloatControlLoc = Tok.getLocation();
2882a9ac8606Spatrick Token PragmaName = Tok;
2883a9ac8606Spatrick if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
2884a9ac8606Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
2885a9ac8606Spatrick << PragmaName.getIdentifierInfo()->getName();
2886a9ac8606Spatrick return;
2887a9ac8606Spatrick }
2888ec727ea7Spatrick PP.Lex(Tok);
2889ec727ea7Spatrick if (Tok.isNot(tok::l_paren)) {
2890ec727ea7Spatrick PP.Diag(FloatControlLoc, diag::err_expected) << tok::l_paren;
2891ec727ea7Spatrick return;
2892ec727ea7Spatrick }
2893ec727ea7Spatrick
2894ec727ea7Spatrick // Read the identifier.
2895ec727ea7Spatrick PP.Lex(Tok);
2896ec727ea7Spatrick if (Tok.isNot(tok::identifier)) {
2897ec727ea7Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2898ec727ea7Spatrick return;
2899ec727ea7Spatrick }
2900ec727ea7Spatrick
2901ec727ea7Spatrick // Verify that this is one of the float control options.
2902ec727ea7Spatrick IdentifierInfo *II = Tok.getIdentifierInfo();
2903ec727ea7Spatrick PragmaFloatControlKind Kind =
2904ec727ea7Spatrick llvm::StringSwitch<PragmaFloatControlKind>(II->getName())
2905ec727ea7Spatrick .Case("precise", PFC_Precise)
2906ec727ea7Spatrick .Case("except", PFC_Except)
2907ec727ea7Spatrick .Case("push", PFC_Push)
2908ec727ea7Spatrick .Case("pop", PFC_Pop)
2909ec727ea7Spatrick .Default(PFC_Unknown);
2910ec727ea7Spatrick PP.Lex(Tok); // the identifier
2911ec727ea7Spatrick if (Kind == PFC_Unknown) {
2912ec727ea7Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2913ec727ea7Spatrick return;
2914ec727ea7Spatrick } else if (Kind == PFC_Push || Kind == PFC_Pop) {
2915ec727ea7Spatrick if (Tok.isNot(tok::r_paren)) {
2916ec727ea7Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2917ec727ea7Spatrick return;
2918ec727ea7Spatrick }
2919ec727ea7Spatrick PP.Lex(Tok); // Eat the r_paren
2920ec727ea7Spatrick Action = (Kind == PFC_Pop) ? Sema::PSK_Pop : Sema::PSK_Push;
2921ec727ea7Spatrick } else {
2922ec727ea7Spatrick if (Tok.is(tok::r_paren))
2923ec727ea7Spatrick // Selecting Precise or Except
2924ec727ea7Spatrick PP.Lex(Tok); // the r_paren
2925ec727ea7Spatrick else if (Tok.isNot(tok::comma)) {
2926ec727ea7Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2927ec727ea7Spatrick return;
2928ec727ea7Spatrick } else {
2929ec727ea7Spatrick PP.Lex(Tok); // ,
2930ec727ea7Spatrick if (!Tok.isAnyIdentifier()) {
2931ec727ea7Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2932ec727ea7Spatrick return;
2933ec727ea7Spatrick }
2934ec727ea7Spatrick StringRef PushOnOff = Tok.getIdentifierInfo()->getName();
2935ec727ea7Spatrick if (PushOnOff == "on")
2936ec727ea7Spatrick // Kind is set correctly
2937ec727ea7Spatrick ;
2938ec727ea7Spatrick else if (PushOnOff == "off") {
2939ec727ea7Spatrick if (Kind == PFC_Precise)
2940ec727ea7Spatrick Kind = PFC_NoPrecise;
2941ec727ea7Spatrick if (Kind == PFC_Except)
2942ec727ea7Spatrick Kind = PFC_NoExcept;
2943ec727ea7Spatrick } else if (PushOnOff == "push") {
2944ec727ea7Spatrick Action = Sema::PSK_Push_Set;
2945ec727ea7Spatrick } else {
2946ec727ea7Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2947ec727ea7Spatrick return;
2948ec727ea7Spatrick }
2949ec727ea7Spatrick PP.Lex(Tok); // the identifier
2950ec727ea7Spatrick if (Tok.is(tok::comma)) {
2951ec727ea7Spatrick PP.Lex(Tok); // ,
2952ec727ea7Spatrick if (!Tok.isAnyIdentifier()) {
2953ec727ea7Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2954ec727ea7Spatrick return;
2955ec727ea7Spatrick }
2956ec727ea7Spatrick StringRef ExpectedPush = Tok.getIdentifierInfo()->getName();
2957ec727ea7Spatrick if (ExpectedPush == "push") {
2958ec727ea7Spatrick Action = Sema::PSK_Push_Set;
2959ec727ea7Spatrick } else {
2960ec727ea7Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2961ec727ea7Spatrick return;
2962ec727ea7Spatrick }
2963ec727ea7Spatrick PP.Lex(Tok); // the push identifier
2964ec727ea7Spatrick }
2965ec727ea7Spatrick if (Tok.isNot(tok::r_paren)) {
2966ec727ea7Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2967ec727ea7Spatrick return;
2968ec727ea7Spatrick }
2969ec727ea7Spatrick PP.Lex(Tok); // the r_paren
2970ec727ea7Spatrick }
2971ec727ea7Spatrick }
2972ec727ea7Spatrick SourceLocation EndLoc = Tok.getLocation();
2973ec727ea7Spatrick if (Tok.isNot(tok::eod)) {
2974ec727ea7Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2975ec727ea7Spatrick << "float_control";
2976ec727ea7Spatrick return;
2977ec727ea7Spatrick }
2978ec727ea7Spatrick
2979ec727ea7Spatrick // Note: there is no accomodation for PP callback for this pragma.
2980ec727ea7Spatrick
2981ec727ea7Spatrick // Enter the annotation.
2982ec727ea7Spatrick auto TokenArray = std::make_unique<Token[]>(1);
2983ec727ea7Spatrick TokenArray[0].startToken();
2984ec727ea7Spatrick TokenArray[0].setKind(tok::annot_pragma_float_control);
2985ec727ea7Spatrick TokenArray[0].setLocation(FloatControlLoc);
2986ec727ea7Spatrick TokenArray[0].setAnnotationEndLoc(EndLoc);
2987ec727ea7Spatrick // Create an encoding of Action and Value by shifting the Action into
2988ec727ea7Spatrick // the high 16 bits then union with the Kind.
2989ec727ea7Spatrick TokenArray[0].setAnnotationValue(reinterpret_cast<void *>(
2990ec727ea7Spatrick static_cast<uintptr_t>((Action << 16) | (Kind & 0xFFFF))));
2991ec727ea7Spatrick PP.EnterTokenStream(std::move(TokenArray), 1,
2992ec727ea7Spatrick /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
2993ec727ea7Spatrick }
2994ec727ea7Spatrick
2995e5dd7070Spatrick /// Handle the Microsoft \#pragma detect_mismatch extension.
2996e5dd7070Spatrick ///
2997e5dd7070Spatrick /// The syntax is:
2998e5dd7070Spatrick /// \code
2999e5dd7070Spatrick /// #pragma detect_mismatch("name", "value")
3000e5dd7070Spatrick /// \endcode
3001e5dd7070Spatrick /// Where 'name' and 'value' are quoted strings. The values are embedded in
3002e5dd7070Spatrick /// the object file and passed along to the linker. If the linker detects a
3003e5dd7070Spatrick /// mismatch in the object file's values for the given name, a LNK2038 error
3004e5dd7070Spatrick /// is emitted. See MSDN for more details.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3005e5dd7070Spatrick void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
3006e5dd7070Spatrick PragmaIntroducer Introducer,
3007e5dd7070Spatrick Token &Tok) {
3008e5dd7070Spatrick SourceLocation DetectMismatchLoc = Tok.getLocation();
3009e5dd7070Spatrick PP.Lex(Tok);
3010e5dd7070Spatrick if (Tok.isNot(tok::l_paren)) {
3011e5dd7070Spatrick PP.Diag(DetectMismatchLoc, diag::err_expected) << tok::l_paren;
3012e5dd7070Spatrick return;
3013e5dd7070Spatrick }
3014e5dd7070Spatrick
3015e5dd7070Spatrick // Read the name to embed, which must be a string literal.
3016e5dd7070Spatrick std::string NameString;
3017e5dd7070Spatrick if (!PP.LexStringLiteral(Tok, NameString,
3018e5dd7070Spatrick "pragma detect_mismatch",
3019e5dd7070Spatrick /*AllowMacroExpansion=*/true))
3020e5dd7070Spatrick return;
3021e5dd7070Spatrick
3022e5dd7070Spatrick // Read the comma followed by a second string literal.
3023e5dd7070Spatrick std::string ValueString;
3024e5dd7070Spatrick if (Tok.isNot(tok::comma)) {
3025e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
3026e5dd7070Spatrick return;
3027e5dd7070Spatrick }
3028e5dd7070Spatrick
3029e5dd7070Spatrick if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
3030e5dd7070Spatrick /*AllowMacroExpansion=*/true))
3031e5dd7070Spatrick return;
3032e5dd7070Spatrick
3033e5dd7070Spatrick if (Tok.isNot(tok::r_paren)) {
3034e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3035e5dd7070Spatrick return;
3036e5dd7070Spatrick }
3037e5dd7070Spatrick PP.Lex(Tok); // Eat the r_paren.
3038e5dd7070Spatrick
3039e5dd7070Spatrick if (Tok.isNot(tok::eod)) {
3040e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
3041e5dd7070Spatrick return;
3042e5dd7070Spatrick }
3043e5dd7070Spatrick
3044e5dd7070Spatrick // If the pragma is lexically sound, notify any interested PPCallbacks.
3045e5dd7070Spatrick if (PP.getPPCallbacks())
3046e5dd7070Spatrick PP.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc, NameString,
3047e5dd7070Spatrick ValueString);
3048e5dd7070Spatrick
3049e5dd7070Spatrick Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString);
3050e5dd7070Spatrick }
3051e5dd7070Spatrick
3052e5dd7070Spatrick /// Handle the microsoft \#pragma comment extension.
3053e5dd7070Spatrick ///
3054e5dd7070Spatrick /// The syntax is:
3055e5dd7070Spatrick /// \code
3056e5dd7070Spatrick /// #pragma comment(linker, "foo")
3057e5dd7070Spatrick /// \endcode
3058e5dd7070Spatrick /// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
3059e5dd7070Spatrick /// "foo" is a string, which is fully macro expanded, and permits string
3060e5dd7070Spatrick /// concatenation, embedded escape characters etc. See MSDN for more details.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3061e5dd7070Spatrick void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
3062e5dd7070Spatrick PragmaIntroducer Introducer,
3063e5dd7070Spatrick Token &Tok) {
3064e5dd7070Spatrick SourceLocation CommentLoc = Tok.getLocation();
3065e5dd7070Spatrick PP.Lex(Tok);
3066e5dd7070Spatrick if (Tok.isNot(tok::l_paren)) {
3067e5dd7070Spatrick PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
3068e5dd7070Spatrick return;
3069e5dd7070Spatrick }
3070e5dd7070Spatrick
3071e5dd7070Spatrick // Read the identifier.
3072e5dd7070Spatrick PP.Lex(Tok);
3073e5dd7070Spatrick if (Tok.isNot(tok::identifier)) {
3074e5dd7070Spatrick PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
3075e5dd7070Spatrick return;
3076e5dd7070Spatrick }
3077e5dd7070Spatrick
3078ec727ea7Spatrick // Verify that this is one of the 5 explicitly listed options.
3079e5dd7070Spatrick IdentifierInfo *II = Tok.getIdentifierInfo();
3080e5dd7070Spatrick PragmaMSCommentKind Kind =
3081e5dd7070Spatrick llvm::StringSwitch<PragmaMSCommentKind>(II->getName())
3082e5dd7070Spatrick .Case("linker", PCK_Linker)
3083e5dd7070Spatrick .Case("lib", PCK_Lib)
3084e5dd7070Spatrick .Case("compiler", PCK_Compiler)
3085e5dd7070Spatrick .Case("exestr", PCK_ExeStr)
3086e5dd7070Spatrick .Case("user", PCK_User)
3087e5dd7070Spatrick .Default(PCK_Unknown);
3088e5dd7070Spatrick if (Kind == PCK_Unknown) {
3089e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
3090e5dd7070Spatrick return;
3091e5dd7070Spatrick }
3092e5dd7070Spatrick
3093e5dd7070Spatrick if (PP.getTargetInfo().getTriple().isOSBinFormatELF() && Kind != PCK_Lib) {
3094e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
3095e5dd7070Spatrick << II->getName();
3096e5dd7070Spatrick return;
3097e5dd7070Spatrick }
3098e5dd7070Spatrick
3099e5dd7070Spatrick // Read the optional string if present.
3100e5dd7070Spatrick PP.Lex(Tok);
3101e5dd7070Spatrick std::string ArgumentString;
3102e5dd7070Spatrick if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
3103e5dd7070Spatrick "pragma comment",
3104e5dd7070Spatrick /*AllowMacroExpansion=*/true))
3105e5dd7070Spatrick return;
3106e5dd7070Spatrick
3107e5dd7070Spatrick // FIXME: warn that 'exestr' is deprecated.
3108e5dd7070Spatrick // FIXME: If the kind is "compiler" warn if the string is present (it is
3109e5dd7070Spatrick // ignored).
3110e5dd7070Spatrick // The MSDN docs say that "lib" and "linker" require a string and have a short
3111ec727ea7Spatrick // list of linker options they support, but in practice MSVC doesn't
3112e5dd7070Spatrick // issue a diagnostic. Therefore neither does clang.
3113e5dd7070Spatrick
3114e5dd7070Spatrick if (Tok.isNot(tok::r_paren)) {
3115e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
3116e5dd7070Spatrick return;
3117e5dd7070Spatrick }
3118e5dd7070Spatrick PP.Lex(Tok); // eat the r_paren.
3119e5dd7070Spatrick
3120e5dd7070Spatrick if (Tok.isNot(tok::eod)) {
3121e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
3122e5dd7070Spatrick return;
3123e5dd7070Spatrick }
3124e5dd7070Spatrick
3125e5dd7070Spatrick // If the pragma is lexically sound, notify any interested PPCallbacks.
3126e5dd7070Spatrick if (PP.getPPCallbacks())
3127e5dd7070Spatrick PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
3128e5dd7070Spatrick
3129e5dd7070Spatrick Actions.ActOnPragmaMSComment(CommentLoc, Kind, ArgumentString);
3130e5dd7070Spatrick }
3131e5dd7070Spatrick
3132e5dd7070Spatrick // #pragma clang optimize off
3133e5dd7070Spatrick // #pragma clang optimize on
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & FirstToken)3134e5dd7070Spatrick void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
3135e5dd7070Spatrick PragmaIntroducer Introducer,
3136e5dd7070Spatrick Token &FirstToken) {
3137e5dd7070Spatrick Token Tok;
3138e5dd7070Spatrick PP.Lex(Tok);
3139e5dd7070Spatrick if (Tok.is(tok::eod)) {
3140e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
3141e5dd7070Spatrick << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
3142e5dd7070Spatrick return;
3143e5dd7070Spatrick }
3144e5dd7070Spatrick if (Tok.isNot(tok::identifier)) {
3145e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
3146e5dd7070Spatrick << PP.getSpelling(Tok);
3147e5dd7070Spatrick return;
3148e5dd7070Spatrick }
3149e5dd7070Spatrick const IdentifierInfo *II = Tok.getIdentifierInfo();
3150e5dd7070Spatrick // The only accepted values are 'on' or 'off'.
3151e5dd7070Spatrick bool IsOn = false;
3152e5dd7070Spatrick if (II->isStr("on")) {
3153e5dd7070Spatrick IsOn = true;
3154e5dd7070Spatrick } else if (!II->isStr("off")) {
3155e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
3156e5dd7070Spatrick << PP.getSpelling(Tok);
3157e5dd7070Spatrick return;
3158e5dd7070Spatrick }
3159e5dd7070Spatrick PP.Lex(Tok);
3160e5dd7070Spatrick
3161e5dd7070Spatrick if (Tok.isNot(tok::eod)) {
3162e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
3163e5dd7070Spatrick << PP.getSpelling(Tok);
3164e5dd7070Spatrick return;
3165e5dd7070Spatrick }
3166e5dd7070Spatrick
3167e5dd7070Spatrick Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
3168e5dd7070Spatrick }
3169e5dd7070Spatrick
3170e5dd7070Spatrick namespace {
3171e5dd7070Spatrick /// Used as the annotation value for tok::annot_pragma_fp.
3172e5dd7070Spatrick struct TokFPAnnotValue {
3173*12c85518Srobert enum FlagKinds { Contract, Reassociate, Exceptions, EvalMethod };
3174e5dd7070Spatrick enum FlagValues { On, Off, Fast };
3175e5dd7070Spatrick
3176*12c85518Srobert std::optional<LangOptions::FPModeKind> ContractValue;
3177*12c85518Srobert std::optional<LangOptions::FPModeKind> ReassociateValue;
3178*12c85518Srobert std::optional<LangOptions::FPExceptionModeKind> ExceptionsValue;
3179*12c85518Srobert std::optional<LangOptions::FPEvalMethodKind> EvalMethodValue;
3180e5dd7070Spatrick };
3181e5dd7070Spatrick } // end anonymous namespace
3182e5dd7070Spatrick
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3183e5dd7070Spatrick void PragmaFPHandler::HandlePragma(Preprocessor &PP,
3184e5dd7070Spatrick PragmaIntroducer Introducer, Token &Tok) {
3185e5dd7070Spatrick // fp
3186e5dd7070Spatrick Token PragmaName = Tok;
3187e5dd7070Spatrick SmallVector<Token, 1> TokenList;
3188e5dd7070Spatrick
3189e5dd7070Spatrick PP.Lex(Tok);
3190e5dd7070Spatrick if (Tok.isNot(tok::identifier)) {
3191e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
3192e5dd7070Spatrick << /*MissingOption=*/true << "";
3193e5dd7070Spatrick return;
3194e5dd7070Spatrick }
3195e5dd7070Spatrick
3196a9ac8606Spatrick auto *AnnotValue = new (PP.getPreprocessorAllocator()) TokFPAnnotValue;
3197e5dd7070Spatrick while (Tok.is(tok::identifier)) {
3198e5dd7070Spatrick IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
3199e5dd7070Spatrick
3200e5dd7070Spatrick auto FlagKind =
3201*12c85518Srobert llvm::StringSwitch<std::optional<TokFPAnnotValue::FlagKinds>>(
3202e5dd7070Spatrick OptionInfo->getName())
3203e5dd7070Spatrick .Case("contract", TokFPAnnotValue::Contract)
3204ec727ea7Spatrick .Case("reassociate", TokFPAnnotValue::Reassociate)
3205a9ac8606Spatrick .Case("exceptions", TokFPAnnotValue::Exceptions)
3206*12c85518Srobert .Case("eval_method", TokFPAnnotValue::EvalMethod)
3207*12c85518Srobert .Default(std::nullopt);
3208e5dd7070Spatrick if (!FlagKind) {
3209e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
3210e5dd7070Spatrick << /*MissingOption=*/false << OptionInfo;
3211e5dd7070Spatrick return;
3212e5dd7070Spatrick }
3213e5dd7070Spatrick PP.Lex(Tok);
3214e5dd7070Spatrick
3215e5dd7070Spatrick // Read '('
3216e5dd7070Spatrick if (Tok.isNot(tok::l_paren)) {
3217e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
3218e5dd7070Spatrick return;
3219e5dd7070Spatrick }
3220e5dd7070Spatrick PP.Lex(Tok);
3221*12c85518Srobert bool isEvalMethodDouble =
3222*12c85518Srobert Tok.is(tok::kw_double) && FlagKind == TokFPAnnotValue::EvalMethod;
3223e5dd7070Spatrick
3224*12c85518Srobert // Don't diagnose if we have an eval_metod pragma with "double" kind.
3225*12c85518Srobert if (Tok.isNot(tok::identifier) && !isEvalMethodDouble) {
3226e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3227ec727ea7Spatrick << PP.getSpelling(Tok) << OptionInfo->getName()
3228a9ac8606Spatrick << static_cast<int>(*FlagKind);
3229e5dd7070Spatrick return;
3230e5dd7070Spatrick }
3231e5dd7070Spatrick const IdentifierInfo *II = Tok.getIdentifierInfo();
3232e5dd7070Spatrick
3233a9ac8606Spatrick if (FlagKind == TokFPAnnotValue::Contract) {
3234a9ac8606Spatrick AnnotValue->ContractValue =
3235*12c85518Srobert llvm::StringSwitch<std::optional<LangOptions::FPModeKind>>(
3236e5dd7070Spatrick II->getName())
3237a9ac8606Spatrick .Case("on", LangOptions::FPModeKind::FPM_On)
3238a9ac8606Spatrick .Case("off", LangOptions::FPModeKind::FPM_Off)
3239a9ac8606Spatrick .Case("fast", LangOptions::FPModeKind::FPM_Fast)
3240*12c85518Srobert .Default(std::nullopt);
3241a9ac8606Spatrick if (!AnnotValue->ContractValue) {
3242e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3243a9ac8606Spatrick << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
3244e5dd7070Spatrick return;
3245e5dd7070Spatrick }
3246a9ac8606Spatrick } else if (FlagKind == TokFPAnnotValue::Reassociate) {
3247a9ac8606Spatrick AnnotValue->ReassociateValue =
3248*12c85518Srobert llvm::StringSwitch<std::optional<LangOptions::FPModeKind>>(
3249a9ac8606Spatrick II->getName())
3250a9ac8606Spatrick .Case("on", LangOptions::FPModeKind::FPM_On)
3251a9ac8606Spatrick .Case("off", LangOptions::FPModeKind::FPM_Off)
3252*12c85518Srobert .Default(std::nullopt);
3253a9ac8606Spatrick if (!AnnotValue->ReassociateValue) {
3254a9ac8606Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3255a9ac8606Spatrick << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
3256a9ac8606Spatrick return;
3257a9ac8606Spatrick }
3258a9ac8606Spatrick } else if (FlagKind == TokFPAnnotValue::Exceptions) {
3259a9ac8606Spatrick AnnotValue->ExceptionsValue =
3260*12c85518Srobert llvm::StringSwitch<std::optional<LangOptions::FPExceptionModeKind>>(
3261a9ac8606Spatrick II->getName())
3262a9ac8606Spatrick .Case("ignore", LangOptions::FPE_Ignore)
3263a9ac8606Spatrick .Case("maytrap", LangOptions::FPE_MayTrap)
3264a9ac8606Spatrick .Case("strict", LangOptions::FPE_Strict)
3265*12c85518Srobert .Default(std::nullopt);
3266a9ac8606Spatrick if (!AnnotValue->ExceptionsValue) {
3267a9ac8606Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3268a9ac8606Spatrick << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
3269a9ac8606Spatrick return;
3270a9ac8606Spatrick }
3271*12c85518Srobert } else if (FlagKind == TokFPAnnotValue::EvalMethod) {
3272*12c85518Srobert AnnotValue->EvalMethodValue =
3273*12c85518Srobert llvm::StringSwitch<std::optional<LangOptions::FPEvalMethodKind>>(
3274*12c85518Srobert II->getName())
3275*12c85518Srobert .Case("source", LangOptions::FPEvalMethodKind::FEM_Source)
3276*12c85518Srobert .Case("double", LangOptions::FPEvalMethodKind::FEM_Double)
3277*12c85518Srobert .Case("extended", LangOptions::FPEvalMethodKind::FEM_Extended)
3278*12c85518Srobert .Default(std::nullopt);
3279*12c85518Srobert if (!AnnotValue->EvalMethodValue) {
3280*12c85518Srobert PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
3281*12c85518Srobert << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind;
3282*12c85518Srobert return;
3283*12c85518Srobert }
3284a9ac8606Spatrick }
3285e5dd7070Spatrick PP.Lex(Tok);
3286e5dd7070Spatrick
3287e5dd7070Spatrick // Read ')'
3288e5dd7070Spatrick if (Tok.isNot(tok::r_paren)) {
3289e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3290e5dd7070Spatrick return;
3291e5dd7070Spatrick }
3292e5dd7070Spatrick PP.Lex(Tok);
3293e5dd7070Spatrick }
3294e5dd7070Spatrick
3295e5dd7070Spatrick if (Tok.isNot(tok::eod)) {
3296e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3297e5dd7070Spatrick << "clang fp";
3298e5dd7070Spatrick return;
3299e5dd7070Spatrick }
3300e5dd7070Spatrick
3301a9ac8606Spatrick Token FPTok;
3302a9ac8606Spatrick FPTok.startToken();
3303a9ac8606Spatrick FPTok.setKind(tok::annot_pragma_fp);
3304a9ac8606Spatrick FPTok.setLocation(PragmaName.getLocation());
3305a9ac8606Spatrick FPTok.setAnnotationEndLoc(PragmaName.getLocation());
3306a9ac8606Spatrick FPTok.setAnnotationValue(reinterpret_cast<void *>(AnnotValue));
3307a9ac8606Spatrick TokenList.push_back(FPTok);
3308a9ac8606Spatrick
3309e5dd7070Spatrick auto TokenArray = std::make_unique<Token[]>(TokenList.size());
3310e5dd7070Spatrick std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
3311e5dd7070Spatrick
3312e5dd7070Spatrick PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
3313e5dd7070Spatrick /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3314e5dd7070Spatrick }
3315e5dd7070Spatrick
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3316a9ac8606Spatrick void PragmaSTDC_FENV_ROUNDHandler::HandlePragma(Preprocessor &PP,
3317a9ac8606Spatrick PragmaIntroducer Introducer,
3318a9ac8606Spatrick Token &Tok) {
3319a9ac8606Spatrick Token PragmaName = Tok;
3320a9ac8606Spatrick SmallVector<Token, 1> TokenList;
3321a9ac8606Spatrick if (!PP.getTargetInfo().hasStrictFP() && !PP.getLangOpts().ExpStrictFP) {
3322a9ac8606Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_fp_ignored)
3323a9ac8606Spatrick << PragmaName.getIdentifierInfo()->getName();
3324a9ac8606Spatrick return;
3325a9ac8606Spatrick }
3326a9ac8606Spatrick
3327a9ac8606Spatrick PP.Lex(Tok);
3328a9ac8606Spatrick if (Tok.isNot(tok::identifier)) {
3329a9ac8606Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
3330a9ac8606Spatrick << PragmaName.getIdentifierInfo()->getName();
3331a9ac8606Spatrick return;
3332a9ac8606Spatrick }
3333a9ac8606Spatrick IdentifierInfo *II = Tok.getIdentifierInfo();
3334a9ac8606Spatrick
3335a9ac8606Spatrick auto RM =
3336a9ac8606Spatrick llvm::StringSwitch<llvm::RoundingMode>(II->getName())
3337a9ac8606Spatrick .Case("FE_TOWARDZERO", llvm::RoundingMode::TowardZero)
3338a9ac8606Spatrick .Case("FE_TONEAREST", llvm::RoundingMode::NearestTiesToEven)
3339a9ac8606Spatrick .Case("FE_UPWARD", llvm::RoundingMode::TowardPositive)
3340a9ac8606Spatrick .Case("FE_DOWNWARD", llvm::RoundingMode::TowardNegative)
3341a9ac8606Spatrick .Case("FE_TONEARESTFROMZERO", llvm::RoundingMode::NearestTiesToAway)
3342a9ac8606Spatrick .Case("FE_DYNAMIC", llvm::RoundingMode::Dynamic)
3343a9ac8606Spatrick .Default(llvm::RoundingMode::Invalid);
3344a9ac8606Spatrick if (RM == llvm::RoundingMode::Invalid) {
3345a9ac8606Spatrick PP.Diag(Tok.getLocation(), diag::warn_stdc_unknown_rounding_mode);
3346a9ac8606Spatrick return;
3347a9ac8606Spatrick }
3348a9ac8606Spatrick PP.Lex(Tok);
3349a9ac8606Spatrick
3350a9ac8606Spatrick if (Tok.isNot(tok::eod)) {
3351a9ac8606Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3352a9ac8606Spatrick << "STDC FENV_ROUND";
3353a9ac8606Spatrick return;
3354a9ac8606Spatrick }
3355a9ac8606Spatrick
3356a9ac8606Spatrick // Until the pragma is fully implemented, issue a warning.
3357a9ac8606Spatrick PP.Diag(Tok.getLocation(), diag::warn_stdc_fenv_round_not_supported);
3358a9ac8606Spatrick
3359a9ac8606Spatrick MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
3360a9ac8606Spatrick 1);
3361a9ac8606Spatrick Toks[0].startToken();
3362a9ac8606Spatrick Toks[0].setKind(tok::annot_pragma_fenv_round);
3363a9ac8606Spatrick Toks[0].setLocation(Tok.getLocation());
3364a9ac8606Spatrick Toks[0].setAnnotationEndLoc(Tok.getLocation());
3365a9ac8606Spatrick Toks[0].setAnnotationValue(
3366a9ac8606Spatrick reinterpret_cast<void *>(static_cast<uintptr_t>(RM)));
3367a9ac8606Spatrick PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
3368a9ac8606Spatrick /*IsReinject=*/false);
3369a9ac8606Spatrick }
3370a9ac8606Spatrick
HandlePragmaFP()3371e5dd7070Spatrick void Parser::HandlePragmaFP() {
3372e5dd7070Spatrick assert(Tok.is(tok::annot_pragma_fp));
3373e5dd7070Spatrick auto *AnnotValue =
3374e5dd7070Spatrick reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue());
3375e5dd7070Spatrick
3376a9ac8606Spatrick if (AnnotValue->ReassociateValue)
3377a9ac8606Spatrick Actions.ActOnPragmaFPReassociate(Tok.getLocation(),
3378a9ac8606Spatrick *AnnotValue->ReassociateValue ==
3379a9ac8606Spatrick LangOptions::FPModeKind::FPM_On);
3380a9ac8606Spatrick if (AnnotValue->ContractValue)
3381a9ac8606Spatrick Actions.ActOnPragmaFPContract(Tok.getLocation(),
3382a9ac8606Spatrick *AnnotValue->ContractValue);
3383a9ac8606Spatrick if (AnnotValue->ExceptionsValue)
3384a9ac8606Spatrick Actions.ActOnPragmaFPExceptions(Tok.getLocation(),
3385a9ac8606Spatrick *AnnotValue->ExceptionsValue);
3386*12c85518Srobert if (AnnotValue->EvalMethodValue)
3387*12c85518Srobert Actions.ActOnPragmaFPEvalMethod(Tok.getLocation(),
3388*12c85518Srobert *AnnotValue->EvalMethodValue);
3389e5dd7070Spatrick ConsumeAnnotationToken();
3390e5dd7070Spatrick }
3391e5dd7070Spatrick
3392e5dd7070Spatrick /// Parses loop or unroll pragma hint value and fills in Info.
ParseLoopHintValue(Preprocessor & PP,Token & Tok,Token PragmaName,Token Option,bool ValueInParens,PragmaLoopHintInfo & Info)3393e5dd7070Spatrick static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
3394e5dd7070Spatrick Token Option, bool ValueInParens,
3395e5dd7070Spatrick PragmaLoopHintInfo &Info) {
3396e5dd7070Spatrick SmallVector<Token, 1> ValueList;
3397e5dd7070Spatrick int OpenParens = ValueInParens ? 1 : 0;
3398e5dd7070Spatrick // Read constant expression.
3399e5dd7070Spatrick while (Tok.isNot(tok::eod)) {
3400e5dd7070Spatrick if (Tok.is(tok::l_paren))
3401e5dd7070Spatrick OpenParens++;
3402e5dd7070Spatrick else if (Tok.is(tok::r_paren)) {
3403e5dd7070Spatrick OpenParens--;
3404e5dd7070Spatrick if (OpenParens == 0 && ValueInParens)
3405e5dd7070Spatrick break;
3406e5dd7070Spatrick }
3407e5dd7070Spatrick
3408e5dd7070Spatrick ValueList.push_back(Tok);
3409e5dd7070Spatrick PP.Lex(Tok);
3410e5dd7070Spatrick }
3411e5dd7070Spatrick
3412e5dd7070Spatrick if (ValueInParens) {
3413e5dd7070Spatrick // Read ')'
3414e5dd7070Spatrick if (Tok.isNot(tok::r_paren)) {
3415e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3416e5dd7070Spatrick return true;
3417e5dd7070Spatrick }
3418e5dd7070Spatrick PP.Lex(Tok);
3419e5dd7070Spatrick }
3420e5dd7070Spatrick
3421e5dd7070Spatrick Token EOFTok;
3422e5dd7070Spatrick EOFTok.startToken();
3423e5dd7070Spatrick EOFTok.setKind(tok::eof);
3424e5dd7070Spatrick EOFTok.setLocation(Tok.getLocation());
3425e5dd7070Spatrick ValueList.push_back(EOFTok); // Terminates expression for parsing.
3426e5dd7070Spatrick
3427a9ac8606Spatrick markAsReinjectedForRelexing(ValueList);
3428*12c85518Srobert Info.Toks = llvm::ArrayRef(ValueList).copy(PP.getPreprocessorAllocator());
3429e5dd7070Spatrick
3430e5dd7070Spatrick Info.PragmaName = PragmaName;
3431e5dd7070Spatrick Info.Option = Option;
3432e5dd7070Spatrick return false;
3433e5dd7070Spatrick }
3434e5dd7070Spatrick
3435e5dd7070Spatrick /// Handle the \#pragma clang loop directive.
3436e5dd7070Spatrick /// #pragma clang 'loop' loop-hints
3437e5dd7070Spatrick ///
3438e5dd7070Spatrick /// loop-hints:
3439e5dd7070Spatrick /// loop-hint loop-hints[opt]
3440e5dd7070Spatrick ///
3441e5dd7070Spatrick /// loop-hint:
3442e5dd7070Spatrick /// 'vectorize' '(' loop-hint-keyword ')'
3443e5dd7070Spatrick /// 'interleave' '(' loop-hint-keyword ')'
3444e5dd7070Spatrick /// 'unroll' '(' unroll-hint-keyword ')'
3445e5dd7070Spatrick /// 'vectorize_predicate' '(' loop-hint-keyword ')'
3446e5dd7070Spatrick /// 'vectorize_width' '(' loop-hint-value ')'
3447e5dd7070Spatrick /// 'interleave_count' '(' loop-hint-value ')'
3448e5dd7070Spatrick /// 'unroll_count' '(' loop-hint-value ')'
3449e5dd7070Spatrick /// 'pipeline' '(' disable ')'
3450e5dd7070Spatrick /// 'pipeline_initiation_interval' '(' loop-hint-value ')'
3451e5dd7070Spatrick ///
3452e5dd7070Spatrick /// loop-hint-keyword:
3453e5dd7070Spatrick /// 'enable'
3454e5dd7070Spatrick /// 'disable'
3455e5dd7070Spatrick /// 'assume_safety'
3456e5dd7070Spatrick ///
3457e5dd7070Spatrick /// unroll-hint-keyword:
3458e5dd7070Spatrick /// 'enable'
3459e5dd7070Spatrick /// 'disable'
3460e5dd7070Spatrick /// 'full'
3461e5dd7070Spatrick ///
3462e5dd7070Spatrick /// loop-hint-value:
3463e5dd7070Spatrick /// constant-expression
3464e5dd7070Spatrick ///
3465e5dd7070Spatrick /// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
3466e5dd7070Spatrick /// try vectorizing the instructions of the loop it precedes. Specifying
3467e5dd7070Spatrick /// interleave(enable) or interleave_count(_value_) instructs llvm to try
3468e5dd7070Spatrick /// interleaving multiple iterations of the loop it precedes. The width of the
3469e5dd7070Spatrick /// vector instructions is specified by vectorize_width() and the number of
3470e5dd7070Spatrick /// interleaved loop iterations is specified by interleave_count(). Specifying a
3471e5dd7070Spatrick /// value of 1 effectively disables vectorization/interleaving, even if it is
3472e5dd7070Spatrick /// possible and profitable, and 0 is invalid. The loop vectorizer currently
3473e5dd7070Spatrick /// only works on inner loops.
3474e5dd7070Spatrick ///
3475e5dd7070Spatrick /// The unroll and unroll_count directives control the concatenation
3476e5dd7070Spatrick /// unroller. Specifying unroll(enable) instructs llvm to unroll the loop
3477e5dd7070Spatrick /// completely if the trip count is known at compile time and unroll partially
3478e5dd7070Spatrick /// if the trip count is not known. Specifying unroll(full) is similar to
3479e5dd7070Spatrick /// unroll(enable) but will unroll the loop only if the trip count is known at
3480e5dd7070Spatrick /// compile time. Specifying unroll(disable) disables unrolling for the
3481e5dd7070Spatrick /// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the
3482e5dd7070Spatrick /// loop the number of times indicated by the value.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3483e5dd7070Spatrick void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
3484e5dd7070Spatrick PragmaIntroducer Introducer,
3485e5dd7070Spatrick Token &Tok) {
3486e5dd7070Spatrick // Incoming token is "loop" from "#pragma clang loop".
3487e5dd7070Spatrick Token PragmaName = Tok;
3488e5dd7070Spatrick SmallVector<Token, 1> TokenList;
3489e5dd7070Spatrick
3490e5dd7070Spatrick // Lex the optimization option and verify it is an identifier.
3491e5dd7070Spatrick PP.Lex(Tok);
3492e5dd7070Spatrick if (Tok.isNot(tok::identifier)) {
3493e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
3494e5dd7070Spatrick << /*MissingOption=*/true << "";
3495e5dd7070Spatrick return;
3496e5dd7070Spatrick }
3497e5dd7070Spatrick
3498e5dd7070Spatrick while (Tok.is(tok::identifier)) {
3499e5dd7070Spatrick Token Option = Tok;
3500e5dd7070Spatrick IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
3501e5dd7070Spatrick
3502e5dd7070Spatrick bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
3503e5dd7070Spatrick .Case("vectorize", true)
3504e5dd7070Spatrick .Case("interleave", true)
3505e5dd7070Spatrick .Case("unroll", true)
3506e5dd7070Spatrick .Case("distribute", true)
3507e5dd7070Spatrick .Case("vectorize_predicate", true)
3508e5dd7070Spatrick .Case("vectorize_width", true)
3509e5dd7070Spatrick .Case("interleave_count", true)
3510e5dd7070Spatrick .Case("unroll_count", true)
3511e5dd7070Spatrick .Case("pipeline", true)
3512e5dd7070Spatrick .Case("pipeline_initiation_interval", true)
3513e5dd7070Spatrick .Default(false);
3514e5dd7070Spatrick if (!OptionValid) {
3515e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
3516e5dd7070Spatrick << /*MissingOption=*/false << OptionInfo;
3517e5dd7070Spatrick return;
3518e5dd7070Spatrick }
3519e5dd7070Spatrick PP.Lex(Tok);
3520e5dd7070Spatrick
3521e5dd7070Spatrick // Read '('
3522e5dd7070Spatrick if (Tok.isNot(tok::l_paren)) {
3523e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
3524e5dd7070Spatrick return;
3525e5dd7070Spatrick }
3526e5dd7070Spatrick PP.Lex(Tok);
3527e5dd7070Spatrick
3528e5dd7070Spatrick auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
3529e5dd7070Spatrick if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
3530e5dd7070Spatrick *Info))
3531e5dd7070Spatrick return;
3532e5dd7070Spatrick
3533e5dd7070Spatrick // Generate the loop hint token.
3534e5dd7070Spatrick Token LoopHintTok;
3535e5dd7070Spatrick LoopHintTok.startToken();
3536e5dd7070Spatrick LoopHintTok.setKind(tok::annot_pragma_loop_hint);
3537ec727ea7Spatrick LoopHintTok.setLocation(Introducer.Loc);
3538e5dd7070Spatrick LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());
3539e5dd7070Spatrick LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
3540e5dd7070Spatrick TokenList.push_back(LoopHintTok);
3541e5dd7070Spatrick }
3542e5dd7070Spatrick
3543e5dd7070Spatrick if (Tok.isNot(tok::eod)) {
3544e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3545e5dd7070Spatrick << "clang loop";
3546e5dd7070Spatrick return;
3547e5dd7070Spatrick }
3548e5dd7070Spatrick
3549e5dd7070Spatrick auto TokenArray = std::make_unique<Token[]>(TokenList.size());
3550e5dd7070Spatrick std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
3551e5dd7070Spatrick
3552e5dd7070Spatrick PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
3553e5dd7070Spatrick /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3554e5dd7070Spatrick }
3555e5dd7070Spatrick
3556e5dd7070Spatrick /// Handle the loop unroll optimization pragmas.
3557e5dd7070Spatrick /// #pragma unroll
3558e5dd7070Spatrick /// #pragma unroll unroll-hint-value
3559e5dd7070Spatrick /// #pragma unroll '(' unroll-hint-value ')'
3560e5dd7070Spatrick /// #pragma nounroll
3561e5dd7070Spatrick /// #pragma unroll_and_jam
3562e5dd7070Spatrick /// #pragma unroll_and_jam unroll-hint-value
3563e5dd7070Spatrick /// #pragma unroll_and_jam '(' unroll-hint-value ')'
3564e5dd7070Spatrick /// #pragma nounroll_and_jam
3565e5dd7070Spatrick ///
3566e5dd7070Spatrick /// unroll-hint-value:
3567e5dd7070Spatrick /// constant-expression
3568e5dd7070Spatrick ///
3569e5dd7070Spatrick /// Loop unrolling hints can be specified with '#pragma unroll' or
3570e5dd7070Spatrick /// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
3571e5dd7070Spatrick /// contained in parentheses. With no argument the directive instructs llvm to
3572e5dd7070Spatrick /// try to unroll the loop completely. A positive integer argument can be
3573e5dd7070Spatrick /// specified to indicate the number of times the loop should be unrolled. To
3574e5dd7070Spatrick /// maximize compatibility with other compilers the unroll count argument can be
3575e5dd7070Spatrick /// specified with or without parentheses. Specifying, '#pragma nounroll'
3576e5dd7070Spatrick /// disables unrolling of the loop.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3577e5dd7070Spatrick void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
3578e5dd7070Spatrick PragmaIntroducer Introducer,
3579e5dd7070Spatrick Token &Tok) {
3580e5dd7070Spatrick // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
3581e5dd7070Spatrick // "#pragma nounroll".
3582e5dd7070Spatrick Token PragmaName = Tok;
3583e5dd7070Spatrick PP.Lex(Tok);
3584e5dd7070Spatrick auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
3585e5dd7070Spatrick if (Tok.is(tok::eod)) {
3586e5dd7070Spatrick // nounroll or unroll pragma without an argument.
3587e5dd7070Spatrick Info->PragmaName = PragmaName;
3588e5dd7070Spatrick Info->Option.startToken();
3589e5dd7070Spatrick } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll" ||
3590e5dd7070Spatrick PragmaName.getIdentifierInfo()->getName() == "nounroll_and_jam") {
3591e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3592e5dd7070Spatrick << PragmaName.getIdentifierInfo()->getName();
3593e5dd7070Spatrick return;
3594e5dd7070Spatrick } else {
3595e5dd7070Spatrick // Unroll pragma with an argument: "#pragma unroll N" or
3596e5dd7070Spatrick // "#pragma unroll(N)".
3597e5dd7070Spatrick // Read '(' if it exists.
3598e5dd7070Spatrick bool ValueInParens = Tok.is(tok::l_paren);
3599e5dd7070Spatrick if (ValueInParens)
3600e5dd7070Spatrick PP.Lex(Tok);
3601e5dd7070Spatrick
3602e5dd7070Spatrick Token Option;
3603e5dd7070Spatrick Option.startToken();
3604e5dd7070Spatrick if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
3605e5dd7070Spatrick return;
3606e5dd7070Spatrick
3607e5dd7070Spatrick // In CUDA, the argument to '#pragma unroll' should not be contained in
3608e5dd7070Spatrick // parentheses.
3609e5dd7070Spatrick if (PP.getLangOpts().CUDA && ValueInParens)
3610e5dd7070Spatrick PP.Diag(Info->Toks[0].getLocation(),
3611e5dd7070Spatrick diag::warn_pragma_unroll_cuda_value_in_parens);
3612e5dd7070Spatrick
3613e5dd7070Spatrick if (Tok.isNot(tok::eod)) {
3614e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3615e5dd7070Spatrick << "unroll";
3616e5dd7070Spatrick return;
3617e5dd7070Spatrick }
3618e5dd7070Spatrick }
3619e5dd7070Spatrick
3620e5dd7070Spatrick // Generate the hint token.
3621e5dd7070Spatrick auto TokenArray = std::make_unique<Token[]>(1);
3622e5dd7070Spatrick TokenArray[0].startToken();
3623e5dd7070Spatrick TokenArray[0].setKind(tok::annot_pragma_loop_hint);
3624ec727ea7Spatrick TokenArray[0].setLocation(Introducer.Loc);
3625e5dd7070Spatrick TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());
3626e5dd7070Spatrick TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
3627e5dd7070Spatrick PP.EnterTokenStream(std::move(TokenArray), 1,
3628e5dd7070Spatrick /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3629e5dd7070Spatrick }
3630e5dd7070Spatrick
3631e5dd7070Spatrick /// Handle the Microsoft \#pragma intrinsic extension.
3632e5dd7070Spatrick ///
3633e5dd7070Spatrick /// The syntax is:
3634e5dd7070Spatrick /// \code
3635e5dd7070Spatrick /// #pragma intrinsic(memset)
3636e5dd7070Spatrick /// #pragma intrinsic(strlen, memcpy)
3637e5dd7070Spatrick /// \endcode
3638e5dd7070Spatrick ///
3639e5dd7070Spatrick /// Pragma intrisic tells the compiler to use a builtin version of the
3640e5dd7070Spatrick /// function. Clang does it anyway, so the pragma doesn't really do anything.
3641e5dd7070Spatrick /// Anyway, we emit a warning if the function specified in \#pragma intrinsic
3642e5dd7070Spatrick /// isn't an intrinsic in clang and suggest to include intrin.h.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3643e5dd7070Spatrick void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP,
3644e5dd7070Spatrick PragmaIntroducer Introducer,
3645e5dd7070Spatrick Token &Tok) {
3646e5dd7070Spatrick PP.Lex(Tok);
3647e5dd7070Spatrick
3648e5dd7070Spatrick if (Tok.isNot(tok::l_paren)) {
3649e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
3650e5dd7070Spatrick << "intrinsic";
3651e5dd7070Spatrick return;
3652e5dd7070Spatrick }
3653e5dd7070Spatrick PP.Lex(Tok);
3654e5dd7070Spatrick
3655e5dd7070Spatrick bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
3656e5dd7070Spatrick
3657e5dd7070Spatrick while (Tok.is(tok::identifier)) {
3658e5dd7070Spatrick IdentifierInfo *II = Tok.getIdentifierInfo();
3659e5dd7070Spatrick if (!II->getBuiltinID())
3660e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
3661e5dd7070Spatrick << II << SuggestIntrinH;
3662e5dd7070Spatrick
3663e5dd7070Spatrick PP.Lex(Tok);
3664e5dd7070Spatrick if (Tok.isNot(tok::comma))
3665e5dd7070Spatrick break;
3666e5dd7070Spatrick PP.Lex(Tok);
3667e5dd7070Spatrick }
3668e5dd7070Spatrick
3669e5dd7070Spatrick if (Tok.isNot(tok::r_paren)) {
3670e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
3671e5dd7070Spatrick << "intrinsic";
3672e5dd7070Spatrick return;
3673e5dd7070Spatrick }
3674e5dd7070Spatrick PP.Lex(Tok);
3675e5dd7070Spatrick
3676e5dd7070Spatrick if (Tok.isNot(tok::eod))
3677e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3678e5dd7070Spatrick << "intrinsic";
3679e5dd7070Spatrick }
3680e5dd7070Spatrick
HandlePragmaMSFunction(StringRef PragmaName,SourceLocation PragmaLocation)3681*12c85518Srobert bool Parser::HandlePragmaMSFunction(StringRef PragmaName,
3682*12c85518Srobert SourceLocation PragmaLocation) {
3683*12c85518Srobert Token FirstTok = Tok;
3684e5dd7070Spatrick
3685*12c85518Srobert if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
3686*12c85518Srobert PragmaName))
3687*12c85518Srobert return false;
3688*12c85518Srobert
3689*12c85518Srobert bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
3690*12c85518Srobert
3691*12c85518Srobert llvm::SmallVector<StringRef> NoBuiltins;
3692*12c85518Srobert while (Tok.is(tok::identifier)) {
3693*12c85518Srobert IdentifierInfo *II = Tok.getIdentifierInfo();
3694*12c85518Srobert if (!II->getBuiltinID())
3695*12c85518Srobert PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
3696*12c85518Srobert << II << SuggestIntrinH;
3697*12c85518Srobert else
3698*12c85518Srobert NoBuiltins.emplace_back(II->getName());
3699*12c85518Srobert
3700e5dd7070Spatrick PP.Lex(Tok);
3701*12c85518Srobert if (Tok.isNot(tok::comma))
3702*12c85518Srobert break;
3703*12c85518Srobert PP.Lex(Tok); // ,
3704*12c85518Srobert }
3705*12c85518Srobert
3706*12c85518Srobert if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
3707*12c85518Srobert PragmaName) ||
3708*12c85518Srobert ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
3709*12c85518Srobert PragmaName))
3710*12c85518Srobert return false;
3711*12c85518Srobert
3712*12c85518Srobert Actions.ActOnPragmaMSFunction(FirstTok.getLocation(), NoBuiltins);
3713*12c85518Srobert return true;
3714*12c85518Srobert }
3715*12c85518Srobert
3716*12c85518Srobert // #pragma optimize("gsty", on|off)
HandlePragmaMSOptimize(StringRef PragmaName,SourceLocation PragmaLocation)3717*12c85518Srobert bool Parser::HandlePragmaMSOptimize(StringRef PragmaName,
3718*12c85518Srobert SourceLocation PragmaLocation) {
3719*12c85518Srobert Token FirstTok = Tok;
3720*12c85518Srobert if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
3721*12c85518Srobert PragmaName))
3722*12c85518Srobert return false;
3723e5dd7070Spatrick
3724e5dd7070Spatrick if (Tok.isNot(tok::string_literal)) {
3725*12c85518Srobert PP.Diag(PragmaLocation, diag::warn_pragma_expected_string) << PragmaName;
3726*12c85518Srobert return false;
3727e5dd7070Spatrick }
3728*12c85518Srobert ExprResult StringResult = ParseStringLiteralExpression();
3729*12c85518Srobert if (StringResult.isInvalid())
3730*12c85518Srobert return false; // Already diagnosed.
3731*12c85518Srobert StringLiteral *OptimizationList = cast<StringLiteral>(StringResult.get());
3732*12c85518Srobert if (OptimizationList->getCharByteWidth() != 1) {
3733*12c85518Srobert PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
3734*12c85518Srobert << PragmaName;
3735*12c85518Srobert return false;
3736e5dd7070Spatrick }
3737e5dd7070Spatrick
3738*12c85518Srobert if (ExpectAndConsume(tok::comma, diag::warn_pragma_expected_comma,
3739*12c85518Srobert PragmaName))
3740*12c85518Srobert return false;
3741*12c85518Srobert
3742*12c85518Srobert if (Tok.is(tok::eof) || Tok.is(tok::r_paren)) {
3743*12c85518Srobert PP.Diag(PragmaLocation, diag::warn_pragma_missing_argument)
3744*12c85518Srobert << PragmaName << /*Expected=*/true << "'on' or 'off'";
3745*12c85518Srobert return false;
3746e5dd7070Spatrick }
3747e5dd7070Spatrick IdentifierInfo *II = Tok.getIdentifierInfo();
3748e5dd7070Spatrick if (!II || (!II->isStr("on") && !II->isStr("off"))) {
3749*12c85518Srobert PP.Diag(PragmaLocation, diag::warn_pragma_invalid_argument)
3750*12c85518Srobert << PP.getSpelling(Tok) << PragmaName << /*Expected=*/true
3751e5dd7070Spatrick << "'on' or 'off'";
3752*12c85518Srobert return false;
3753e5dd7070Spatrick }
3754*12c85518Srobert bool IsOn = II->isStr("on");
3755e5dd7070Spatrick PP.Lex(Tok);
3756e5dd7070Spatrick
3757*12c85518Srobert if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
3758*12c85518Srobert PragmaName))
3759*12c85518Srobert return false;
3760e5dd7070Spatrick
3761*12c85518Srobert // TODO: Add support for "sgty"
3762*12c85518Srobert if (!OptimizationList->getString().empty()) {
3763*12c85518Srobert PP.Diag(PragmaLocation, diag::warn_pragma_invalid_argument)
3764*12c85518Srobert << OptimizationList->getString() << PragmaName << /*Expected=*/true
3765*12c85518Srobert << "\"\"";
3766*12c85518Srobert return false;
3767e5dd7070Spatrick }
3768*12c85518Srobert
3769*12c85518Srobert if (ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
3770*12c85518Srobert PragmaName))
3771*12c85518Srobert return false;
3772*12c85518Srobert
3773*12c85518Srobert Actions.ActOnPragmaMSOptimize(FirstTok.getLocation(), IsOn);
3774*12c85518Srobert return true;
3775e5dd7070Spatrick }
3776e5dd7070Spatrick
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3777e5dd7070Spatrick void PragmaForceCUDAHostDeviceHandler::HandlePragma(
3778e5dd7070Spatrick Preprocessor &PP, PragmaIntroducer Introducer, Token &Tok) {
3779e5dd7070Spatrick Token FirstTok = Tok;
3780e5dd7070Spatrick
3781e5dd7070Spatrick PP.Lex(Tok);
3782e5dd7070Spatrick IdentifierInfo *Info = Tok.getIdentifierInfo();
3783e5dd7070Spatrick if (!Info || (!Info->isStr("begin") && !Info->isStr("end"))) {
3784e5dd7070Spatrick PP.Diag(FirstTok.getLocation(),
3785e5dd7070Spatrick diag::warn_pragma_force_cuda_host_device_bad_arg);
3786e5dd7070Spatrick return;
3787e5dd7070Spatrick }
3788e5dd7070Spatrick
3789e5dd7070Spatrick if (Info->isStr("begin"))
3790e5dd7070Spatrick Actions.PushForceCUDAHostDevice();
3791e5dd7070Spatrick else if (!Actions.PopForceCUDAHostDevice())
3792e5dd7070Spatrick PP.Diag(FirstTok.getLocation(),
3793e5dd7070Spatrick diag::err_pragma_cannot_end_force_cuda_host_device);
3794e5dd7070Spatrick
3795e5dd7070Spatrick PP.Lex(Tok);
3796e5dd7070Spatrick if (!Tok.is(tok::eod))
3797e5dd7070Spatrick PP.Diag(FirstTok.getLocation(),
3798e5dd7070Spatrick diag::warn_pragma_force_cuda_host_device_bad_arg);
3799e5dd7070Spatrick }
3800e5dd7070Spatrick
3801e5dd7070Spatrick /// Handle the #pragma clang attribute directive.
3802e5dd7070Spatrick ///
3803e5dd7070Spatrick /// The syntax is:
3804e5dd7070Spatrick /// \code
3805e5dd7070Spatrick /// #pragma clang attribute push (attribute, subject-set)
3806e5dd7070Spatrick /// #pragma clang attribute push
3807e5dd7070Spatrick /// #pragma clang attribute (attribute, subject-set)
3808e5dd7070Spatrick /// #pragma clang attribute pop
3809e5dd7070Spatrick /// \endcode
3810e5dd7070Spatrick ///
3811e5dd7070Spatrick /// There are also 'namespace' variants of push and pop directives. The bare
3812e5dd7070Spatrick /// '#pragma clang attribute (attribute, subject-set)' version doesn't require a
3813e5dd7070Spatrick /// namespace, since it always applies attributes to the most recently pushed
3814e5dd7070Spatrick /// group, regardless of namespace.
3815e5dd7070Spatrick /// \code
3816e5dd7070Spatrick /// #pragma clang attribute namespace.push (attribute, subject-set)
3817e5dd7070Spatrick /// #pragma clang attribute namespace.push
3818e5dd7070Spatrick /// #pragma clang attribute namespace.pop
3819e5dd7070Spatrick /// \endcode
3820e5dd7070Spatrick ///
3821e5dd7070Spatrick /// The subject-set clause defines the set of declarations which receive the
3822e5dd7070Spatrick /// attribute. Its exact syntax is described in the LanguageExtensions document
3823e5dd7070Spatrick /// in Clang's documentation.
3824e5dd7070Spatrick ///
3825e5dd7070Spatrick /// This directive instructs the compiler to begin/finish applying the specified
3826e5dd7070Spatrick /// attribute to the set of attribute-specific declarations in the active range
3827e5dd7070Spatrick /// of the pragma.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & FirstToken)3828e5dd7070Spatrick void PragmaAttributeHandler::HandlePragma(Preprocessor &PP,
3829e5dd7070Spatrick PragmaIntroducer Introducer,
3830e5dd7070Spatrick Token &FirstToken) {
3831e5dd7070Spatrick Token Tok;
3832e5dd7070Spatrick PP.Lex(Tok);
3833e5dd7070Spatrick auto *Info = new (PP.getPreprocessorAllocator())
3834e5dd7070Spatrick PragmaAttributeInfo(AttributesForPragmaAttribute);
3835e5dd7070Spatrick
3836e5dd7070Spatrick // Parse the optional namespace followed by a period.
3837e5dd7070Spatrick if (Tok.is(tok::identifier)) {
3838e5dd7070Spatrick IdentifierInfo *II = Tok.getIdentifierInfo();
3839e5dd7070Spatrick if (!II->isStr("push") && !II->isStr("pop")) {
3840e5dd7070Spatrick Info->Namespace = II;
3841e5dd7070Spatrick PP.Lex(Tok);
3842e5dd7070Spatrick
3843e5dd7070Spatrick if (!Tok.is(tok::period)) {
3844e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_period)
3845e5dd7070Spatrick << II;
3846e5dd7070Spatrick return;
3847e5dd7070Spatrick }
3848e5dd7070Spatrick PP.Lex(Tok);
3849e5dd7070Spatrick }
3850e5dd7070Spatrick }
3851e5dd7070Spatrick
3852e5dd7070Spatrick if (!Tok.isOneOf(tok::identifier, tok::l_paren)) {
3853e5dd7070Spatrick PP.Diag(Tok.getLocation(),
3854e5dd7070Spatrick diag::err_pragma_attribute_expected_push_pop_paren);
3855e5dd7070Spatrick return;
3856e5dd7070Spatrick }
3857e5dd7070Spatrick
3858e5dd7070Spatrick // Determine what action this pragma clang attribute represents.
3859e5dd7070Spatrick if (Tok.is(tok::l_paren)) {
3860e5dd7070Spatrick if (Info->Namespace) {
3861e5dd7070Spatrick PP.Diag(Tok.getLocation(),
3862e5dd7070Spatrick diag::err_pragma_attribute_namespace_on_attribute);
3863e5dd7070Spatrick PP.Diag(Tok.getLocation(),
3864e5dd7070Spatrick diag::note_pragma_attribute_namespace_on_attribute);
3865e5dd7070Spatrick return;
3866e5dd7070Spatrick }
3867e5dd7070Spatrick Info->Action = PragmaAttributeInfo::Attribute;
3868e5dd7070Spatrick } else {
3869e5dd7070Spatrick const IdentifierInfo *II = Tok.getIdentifierInfo();
3870e5dd7070Spatrick if (II->isStr("push"))
3871e5dd7070Spatrick Info->Action = PragmaAttributeInfo::Push;
3872e5dd7070Spatrick else if (II->isStr("pop"))
3873e5dd7070Spatrick Info->Action = PragmaAttributeInfo::Pop;
3874e5dd7070Spatrick else {
3875e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument)
3876e5dd7070Spatrick << PP.getSpelling(Tok);
3877e5dd7070Spatrick return;
3878e5dd7070Spatrick }
3879e5dd7070Spatrick
3880e5dd7070Spatrick PP.Lex(Tok);
3881e5dd7070Spatrick }
3882e5dd7070Spatrick
3883e5dd7070Spatrick // Parse the actual attribute.
3884e5dd7070Spatrick if ((Info->Action == PragmaAttributeInfo::Push && Tok.isNot(tok::eod)) ||
3885e5dd7070Spatrick Info->Action == PragmaAttributeInfo::Attribute) {
3886e5dd7070Spatrick if (Tok.isNot(tok::l_paren)) {
3887e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
3888e5dd7070Spatrick return;
3889e5dd7070Spatrick }
3890e5dd7070Spatrick PP.Lex(Tok);
3891e5dd7070Spatrick
3892e5dd7070Spatrick // Lex the attribute tokens.
3893e5dd7070Spatrick SmallVector<Token, 16> AttributeTokens;
3894e5dd7070Spatrick int OpenParens = 1;
3895e5dd7070Spatrick while (Tok.isNot(tok::eod)) {
3896e5dd7070Spatrick if (Tok.is(tok::l_paren))
3897e5dd7070Spatrick OpenParens++;
3898e5dd7070Spatrick else if (Tok.is(tok::r_paren)) {
3899e5dd7070Spatrick OpenParens--;
3900e5dd7070Spatrick if (OpenParens == 0)
3901e5dd7070Spatrick break;
3902e5dd7070Spatrick }
3903e5dd7070Spatrick
3904e5dd7070Spatrick AttributeTokens.push_back(Tok);
3905e5dd7070Spatrick PP.Lex(Tok);
3906e5dd7070Spatrick }
3907e5dd7070Spatrick
3908e5dd7070Spatrick if (AttributeTokens.empty()) {
3909e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_attribute);
3910e5dd7070Spatrick return;
3911e5dd7070Spatrick }
3912e5dd7070Spatrick if (Tok.isNot(tok::r_paren)) {
3913e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3914e5dd7070Spatrick return;
3915e5dd7070Spatrick }
3916e5dd7070Spatrick SourceLocation EndLoc = Tok.getLocation();
3917e5dd7070Spatrick PP.Lex(Tok);
3918e5dd7070Spatrick
3919e5dd7070Spatrick // Terminate the attribute for parsing.
3920e5dd7070Spatrick Token EOFTok;
3921e5dd7070Spatrick EOFTok.startToken();
3922e5dd7070Spatrick EOFTok.setKind(tok::eof);
3923e5dd7070Spatrick EOFTok.setLocation(EndLoc);
3924e5dd7070Spatrick AttributeTokens.push_back(EOFTok);
3925e5dd7070Spatrick
3926a9ac8606Spatrick markAsReinjectedForRelexing(AttributeTokens);
3927e5dd7070Spatrick Info->Tokens =
3928*12c85518Srobert llvm::ArrayRef(AttributeTokens).copy(PP.getPreprocessorAllocator());
3929e5dd7070Spatrick }
3930e5dd7070Spatrick
3931e5dd7070Spatrick if (Tok.isNot(tok::eod))
3932e5dd7070Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3933e5dd7070Spatrick << "clang attribute";
3934e5dd7070Spatrick
3935e5dd7070Spatrick // Generate the annotated pragma token.
3936e5dd7070Spatrick auto TokenArray = std::make_unique<Token[]>(1);
3937e5dd7070Spatrick TokenArray[0].startToken();
3938e5dd7070Spatrick TokenArray[0].setKind(tok::annot_pragma_attribute);
3939e5dd7070Spatrick TokenArray[0].setLocation(FirstToken.getLocation());
3940e5dd7070Spatrick TokenArray[0].setAnnotationEndLoc(FirstToken.getLocation());
3941e5dd7070Spatrick TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
3942e5dd7070Spatrick PP.EnterTokenStream(std::move(TokenArray), 1,
3943e5dd7070Spatrick /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
3944e5dd7070Spatrick }
3945ec727ea7Spatrick
3946ec727ea7Spatrick // Handle '#pragma clang max_tokens 12345'.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3947ec727ea7Spatrick void PragmaMaxTokensHereHandler::HandlePragma(Preprocessor &PP,
3948ec727ea7Spatrick PragmaIntroducer Introducer,
3949ec727ea7Spatrick Token &Tok) {
3950ec727ea7Spatrick PP.Lex(Tok);
3951ec727ea7Spatrick if (Tok.is(tok::eod)) {
3952ec727ea7Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
3953ec727ea7Spatrick << "clang max_tokens_here" << /*Expected=*/true << "integer";
3954ec727ea7Spatrick return;
3955ec727ea7Spatrick }
3956ec727ea7Spatrick
3957ec727ea7Spatrick SourceLocation Loc = Tok.getLocation();
3958ec727ea7Spatrick uint64_t MaxTokens;
3959ec727ea7Spatrick if (Tok.isNot(tok::numeric_constant) ||
3960ec727ea7Spatrick !PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) {
3961ec727ea7Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer)
3962ec727ea7Spatrick << "clang max_tokens_here";
3963ec727ea7Spatrick return;
3964ec727ea7Spatrick }
3965ec727ea7Spatrick
3966ec727ea7Spatrick if (Tok.isNot(tok::eod)) {
3967ec727ea7Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3968ec727ea7Spatrick << "clang max_tokens_here";
3969ec727ea7Spatrick return;
3970ec727ea7Spatrick }
3971ec727ea7Spatrick
3972ec727ea7Spatrick if (PP.getTokenCount() > MaxTokens) {
3973ec727ea7Spatrick PP.Diag(Loc, diag::warn_max_tokens)
3974ec727ea7Spatrick << PP.getTokenCount() << (unsigned)MaxTokens;
3975ec727ea7Spatrick }
3976ec727ea7Spatrick }
3977ec727ea7Spatrick
3978ec727ea7Spatrick // Handle '#pragma clang max_tokens_total 12345'.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & Tok)3979ec727ea7Spatrick void PragmaMaxTokensTotalHandler::HandlePragma(Preprocessor &PP,
3980ec727ea7Spatrick PragmaIntroducer Introducer,
3981ec727ea7Spatrick Token &Tok) {
3982ec727ea7Spatrick PP.Lex(Tok);
3983ec727ea7Spatrick if (Tok.is(tok::eod)) {
3984ec727ea7Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
3985ec727ea7Spatrick << "clang max_tokens_total" << /*Expected=*/true << "integer";
3986ec727ea7Spatrick return;
3987ec727ea7Spatrick }
3988ec727ea7Spatrick
3989ec727ea7Spatrick SourceLocation Loc = Tok.getLocation();
3990ec727ea7Spatrick uint64_t MaxTokens;
3991ec727ea7Spatrick if (Tok.isNot(tok::numeric_constant) ||
3992ec727ea7Spatrick !PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) {
3993ec727ea7Spatrick PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer)
3994ec727ea7Spatrick << "clang max_tokens_total";
3995ec727ea7Spatrick return;
3996ec727ea7Spatrick }
3997ec727ea7Spatrick
3998ec727ea7Spatrick if (Tok.isNot(tok::eod)) {
3999ec727ea7Spatrick PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
4000ec727ea7Spatrick << "clang max_tokens_total";
4001ec727ea7Spatrick return;
4002ec727ea7Spatrick }
4003ec727ea7Spatrick
4004ec727ea7Spatrick PP.overrideMaxTokens(MaxTokens, Loc);
4005ec727ea7Spatrick }
4006*12c85518Srobert
4007*12c85518Srobert // Handle '#pragma clang riscv intrinsic vector'.
HandlePragma(Preprocessor & PP,PragmaIntroducer Introducer,Token & FirstToken)4008*12c85518Srobert void PragmaRISCVHandler::HandlePragma(Preprocessor &PP,
4009*12c85518Srobert PragmaIntroducer Introducer,
4010*12c85518Srobert Token &FirstToken) {
4011*12c85518Srobert Token Tok;
4012*12c85518Srobert PP.Lex(Tok);
4013*12c85518Srobert IdentifierInfo *II = Tok.getIdentifierInfo();
4014*12c85518Srobert
4015*12c85518Srobert if (!II || !II->isStr("intrinsic")) {
4016*12c85518Srobert PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)
4017*12c85518Srobert << PP.getSpelling(Tok) << "riscv" << /*Expected=*/true << "'intrinsic'";
4018*12c85518Srobert return;
4019*12c85518Srobert }
4020*12c85518Srobert
4021*12c85518Srobert PP.Lex(Tok);
4022*12c85518Srobert II = Tok.getIdentifierInfo();
4023*12c85518Srobert if (!II || !II->isStr("vector")) {
4024*12c85518Srobert PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)
4025*12c85518Srobert << PP.getSpelling(Tok) << "riscv" << /*Expected=*/true << "'vector'";
4026*12c85518Srobert return;
4027*12c85518Srobert }
4028*12c85518Srobert
4029*12c85518Srobert PP.Lex(Tok);
4030*12c85518Srobert if (Tok.isNot(tok::eod)) {
4031*12c85518Srobert PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
4032*12c85518Srobert << "clang riscv intrinsic";
4033*12c85518Srobert return;
4034*12c85518Srobert }
4035*12c85518Srobert
4036*12c85518Srobert Actions.DeclareRISCVVBuiltins = true;
4037*12c85518Srobert }
4038