blob: 6402b31d00b296729902cfbf69ce14a364b1c466 [file] [log] [blame]
Daniel Dunbar921b9682008-10-04 19:21:03 +00001//===--- ParsePragma.cpp - Language specific pragma parsing ---------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Daniel Dunbar921b9682008-10-04 19:21:03 +00006//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the language specific #pragma handlers.
10//
11//===----------------------------------------------------------------------===//
12
Hans Wennborg899ded92014-10-16 20:52:46 +000013#include "clang/AST/ASTContext.h"
Nico Weber66220292016-03-02 17:28:48 +000014#include "clang/Basic/PragmaKinds.h"
David Majnemerad2986e2014-08-14 06:35:08 +000015#include "clang/Basic/TargetInfo.h"
Eli Bendersky06a40422014-06-06 20:31:48 +000016#include "clang/Lex/Preprocessor.h"
Richard Trieu0614cff2018-11-28 04:36:31 +000017#include "clang/Parse/LoopHint.h"
Eli Bendersky06a40422014-06-06 20:31:48 +000018#include "clang/Parse/ParseDiagnostic.h"
19#include "clang/Parse/Parser.h"
Vassil Vassilev11ad3392017-03-23 15:11:07 +000020#include "clang/Parse/RAIIObjectsForParser.h"
Eli Bendersky06a40422014-06-06 20:31:48 +000021#include "clang/Sema/Scope.h"
22#include "llvm/ADT/StringSwitch.h"
23using namespace clang;
Daniel Dunbar921b9682008-10-04 19:21:03 +000024
Reid Kleckner5b086462014-02-20 22:52:09 +000025namespace {
26
27struct PragmaAlignHandler : public PragmaHandler {
28 explicit PragmaAlignHandler() : PragmaHandler("align") {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +000029 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Craig Topper2b07f022014-03-12 05:09:18 +000030 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000031};
32
33struct PragmaGCCVisibilityHandler : public PragmaHandler {
34 explicit PragmaGCCVisibilityHandler() : PragmaHandler("visibility") {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +000035 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Craig Topper2b07f022014-03-12 05:09:18 +000036 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000037};
38
39struct PragmaOptionsHandler : public PragmaHandler {
40 explicit PragmaOptionsHandler() : PragmaHandler("options") {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +000041 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Craig Topper2b07f022014-03-12 05:09:18 +000042 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000043};
44
45struct PragmaPackHandler : public PragmaHandler {
46 explicit PragmaPackHandler() : PragmaHandler("pack") {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +000047 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Craig Topper2b07f022014-03-12 05:09:18 +000048 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000049};
50
Javed Absar2a67c9e2017-06-05 10:11:57 +000051struct PragmaClangSectionHandler : public PragmaHandler {
52 explicit PragmaClangSectionHandler(Sema &S)
53 : PragmaHandler("section"), Actions(S) {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +000054 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Javed Absar2a67c9e2017-06-05 10:11:57 +000055 Token &FirstToken) override;
Joel E. Dennyddde0ec2019-05-21 23:51:38 +000056
Javed Absar2a67c9e2017-06-05 10:11:57 +000057private:
58 Sema &Actions;
59};
60
Reid Kleckner5b086462014-02-20 22:52:09 +000061struct PragmaMSStructHandler : public PragmaHandler {
62 explicit PragmaMSStructHandler() : PragmaHandler("ms_struct") {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +000063 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Craig Topper2b07f022014-03-12 05:09:18 +000064 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000065};
66
67struct PragmaUnusedHandler : public PragmaHandler {
68 PragmaUnusedHandler() : PragmaHandler("unused") {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +000069 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Craig Topper2b07f022014-03-12 05:09:18 +000070 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000071};
72
73struct PragmaWeakHandler : public PragmaHandler {
74 explicit PragmaWeakHandler() : PragmaHandler("weak") {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +000075 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Craig Topper2b07f022014-03-12 05:09:18 +000076 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000077};
78
79struct PragmaRedefineExtnameHandler : public PragmaHandler {
80 explicit PragmaRedefineExtnameHandler() : PragmaHandler("redefine_extname") {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +000081 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Craig Topper2b07f022014-03-12 05:09:18 +000082 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000083};
84
85struct PragmaOpenCLExtensionHandler : public PragmaHandler {
86 PragmaOpenCLExtensionHandler() : PragmaHandler("EXTENSION") {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +000087 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Craig Topper2b07f022014-03-12 05:09:18 +000088 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000089};
90
91
92struct PragmaFPContractHandler : public PragmaHandler {
93 PragmaFPContractHandler() : PragmaHandler("FP_CONTRACT") {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +000094 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Craig Topper2b07f022014-03-12 05:09:18 +000095 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +000096};
97
Steven Wub96a3a42018-01-05 22:45:03 +000098// Pragma STDC implementations.
99
100/// PragmaSTDC_FENV_ACCESSHandler - "\#pragma STDC FENV_ACCESS ...".
101struct PragmaSTDC_FENV_ACCESSHandler : public PragmaHandler {
102 PragmaSTDC_FENV_ACCESSHandler() : PragmaHandler("FENV_ACCESS") {}
103
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000104 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Steven Wub96a3a42018-01-05 22:45:03 +0000105 Token &Tok) override {
106 tok::OnOffSwitch OOS;
107 if (PP.LexOnOffSwitch(OOS))
108 return;
Kevin P. Neal2c0bc8b2018-08-14 17:06:56 +0000109 if (OOS == tok::OOS_ON) {
Steven Wub96a3a42018-01-05 22:45:03 +0000110 PP.Diag(Tok, diag::warn_stdc_fenv_access_not_supported);
Melanie Blowere5578012020-05-06 11:45:55 -0700111 return;
Kevin P. Neal2c0bc8b2018-08-14 17:06:56 +0000112 }
113
114 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
115 1);
116 Toks[0].startToken();
117 Toks[0].setKind(tok::annot_pragma_fenv_access);
118 Toks[0].setLocation(Tok.getLocation());
119 Toks[0].setAnnotationEndLoc(Tok.getLocation());
120 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
121 static_cast<uintptr_t>(OOS)));
Ilya Biryukov929af672019-05-17 09:32:05 +0000122 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
123 /*IsReinject=*/false);
Steven Wub96a3a42018-01-05 22:45:03 +0000124 }
125};
126
127/// PragmaSTDC_CX_LIMITED_RANGEHandler - "\#pragma STDC CX_LIMITED_RANGE ...".
128struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler {
129 PragmaSTDC_CX_LIMITED_RANGEHandler() : PragmaHandler("CX_LIMITED_RANGE") {}
130
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000131 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Steven Wub96a3a42018-01-05 22:45:03 +0000132 Token &Tok) override {
133 tok::OnOffSwitch OOS;
134 PP.LexOnOffSwitch(OOS);
135 }
136};
137
138/// PragmaSTDC_UnknownHandler - "\#pragma STDC ...".
139struct PragmaSTDC_UnknownHandler : public PragmaHandler {
140 PragmaSTDC_UnknownHandler() = default;
141
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000142 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Steven Wub96a3a42018-01-05 22:45:03 +0000143 Token &UnknownTok) override {
144 // C99 6.10.6p2, unknown forms are not allowed.
145 PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored);
146 }
147};
148
Adam Nemet60d32642017-04-04 21:18:36 +0000149struct PragmaFPHandler : public PragmaHandler {
150 PragmaFPHandler() : PragmaHandler("fp") {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000151 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Adam Nemet60d32642017-04-04 21:18:36 +0000152 Token &FirstToken) override;
153};
154
Reid Kleckner5b086462014-02-20 22:52:09 +0000155struct PragmaNoOpenMPHandler : public PragmaHandler {
156 PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000157 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Craig Topper2b07f022014-03-12 05:09:18 +0000158 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000159};
160
161struct PragmaOpenMPHandler : public PragmaHandler {
162 PragmaOpenMPHandler() : PragmaHandler("omp") { }
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000163 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Craig Topper2b07f022014-03-12 05:09:18 +0000164 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000165};
166
167/// PragmaCommentHandler - "\#pragma comment ...".
168struct PragmaCommentHandler : public PragmaHandler {
169 PragmaCommentHandler(Sema &Actions)
170 : PragmaHandler("comment"), Actions(Actions) {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000171 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Craig Topper2b07f022014-03-12 05:09:18 +0000172 Token &FirstToken) override;
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000173
Reid Kleckner5b086462014-02-20 22:52:09 +0000174private:
175 Sema &Actions;
176};
177
178struct PragmaDetectMismatchHandler : public PragmaHandler {
179 PragmaDetectMismatchHandler(Sema &Actions)
180 : PragmaHandler("detect_mismatch"), Actions(Actions) {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000181 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Craig Topper2b07f022014-03-12 05:09:18 +0000182 Token &FirstToken) override;
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000183
Reid Kleckner5b086462014-02-20 22:52:09 +0000184private:
185 Sema &Actions;
186};
187
Melanie Blowerf5360d42020-05-01 10:32:06 -0700188struct PragmaFloatControlHandler : public PragmaHandler {
189 PragmaFloatControlHandler(Sema &Actions)
190 : PragmaHandler("float_control") {}
191 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
192 Token &FirstToken) override;
193};
194
Reid Kleckner5b086462014-02-20 22:52:09 +0000195struct PragmaMSPointersToMembers : public PragmaHandler {
196 explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000197 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Craig Topper2b07f022014-03-12 05:09:18 +0000198 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000199};
200
201struct PragmaMSVtorDisp : public PragmaHandler {
202 explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000203 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Craig Topper2b07f022014-03-12 05:09:18 +0000204 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000205};
206
Warren Huntc3b18962014-04-08 22:30:47 +0000207struct PragmaMSPragma : public PragmaHandler {
208 explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000209 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000210 Token &FirstToken) override;
211};
212
Dario Domizioli13a0a382014-05-23 12:13:25 +0000213/// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
214struct PragmaOptimizeHandler : public PragmaHandler {
215 PragmaOptimizeHandler(Sema &S)
216 : PragmaHandler("optimize"), Actions(S) {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000217 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Dario Domizioli13a0a382014-05-23 12:13:25 +0000218 Token &FirstToken) override;
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000219
Dario Domizioli13a0a382014-05-23 12:13:25 +0000220private:
Eli Bendersky06a40422014-06-06 20:31:48 +0000221 Sema &Actions;
222};
223
224struct PragmaLoopHintHandler : public PragmaHandler {
225 PragmaLoopHintHandler() : PragmaHandler("loop") {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000226 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Eli Bendersky06a40422014-06-06 20:31:48 +0000227 Token &FirstToken) override;
228};
229
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000230struct PragmaUnrollHintHandler : public PragmaHandler {
231 PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000232 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000233 Token &FirstToken) override;
234};
235
Hans Wennborg7357bbc2015-10-12 20:47:58 +0000236struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler {
237 PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {}
238};
239
Reid Kleckner3f1ec622016-09-07 16:38:32 +0000240struct PragmaMSIntrinsicHandler : public PragmaHandler {
241 PragmaMSIntrinsicHandler() : PragmaHandler("intrinsic") {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000242 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Reid Kleckner3f1ec622016-09-07 16:38:32 +0000243 Token &FirstToken) override;
244};
245
Hans Wennborg1bbe00e2018-03-20 08:53:11 +0000246struct PragmaMSOptimizeHandler : public PragmaHandler {
247 PragmaMSOptimizeHandler() : PragmaHandler("optimize") {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000248 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Hans Wennborg1bbe00e2018-03-20 08:53:11 +0000249 Token &FirstToken) override;
250};
251
Justin Lebar67a78a62016-10-08 22:15:58 +0000252struct PragmaForceCUDAHostDeviceHandler : public PragmaHandler {
253 PragmaForceCUDAHostDeviceHandler(Sema &Actions)
254 : PragmaHandler("force_cuda_host_device"), Actions(Actions) {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000255 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Justin Lebar67a78a62016-10-08 22:15:58 +0000256 Token &FirstToken) override;
257
258private:
259 Sema &Actions;
260};
261
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000262/// PragmaAttributeHandler - "\#pragma clang attribute ...".
263struct PragmaAttributeHandler : public PragmaHandler {
264 PragmaAttributeHandler(AttributeFactory &AttrFactory)
265 : PragmaHandler("attribute"), AttributesForPragmaAttribute(AttrFactory) {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000266 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000267 Token &FirstToken) override;
268
269 /// A pool of attributes that were parsed in \#pragma clang attribute.
270 ParsedAttributes AttributesForPragmaAttribute;
271};
272
Hans Wennborg739b4102019-10-09 15:22:38 +0200273struct PragmaMaxTokensHereHandler : public PragmaHandler {
274 PragmaMaxTokensHereHandler() : PragmaHandler("max_tokens_here") {}
275 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
276 Token &FirstToken) override;
277};
278
279struct PragmaMaxTokensTotalHandler : public PragmaHandler {
280 PragmaMaxTokensTotalHandler() : PragmaHandler("max_tokens_total") {}
281 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
282 Token &FirstToken) override;
283};
284
Eli Bendersky06a40422014-06-06 20:31:48 +0000285} // end namespace
286
287void Parser::initializePragmaHandlers() {
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000288 AlignHandler = std::make_unique<PragmaAlignHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000289 PP.AddPragmaHandler(AlignHandler.get());
290
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000291 GCCVisibilityHandler = std::make_unique<PragmaGCCVisibilityHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000292 PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
293
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000294 OptionsHandler = std::make_unique<PragmaOptionsHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000295 PP.AddPragmaHandler(OptionsHandler.get());
296
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000297 PackHandler = std::make_unique<PragmaPackHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000298 PP.AddPragmaHandler(PackHandler.get());
299
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000300 MSStructHandler = std::make_unique<PragmaMSStructHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000301 PP.AddPragmaHandler(MSStructHandler.get());
302
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000303 UnusedHandler = std::make_unique<PragmaUnusedHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000304 PP.AddPragmaHandler(UnusedHandler.get());
305
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000306 WeakHandler = std::make_unique<PragmaWeakHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000307 PP.AddPragmaHandler(WeakHandler.get());
308
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000309 RedefineExtnameHandler = std::make_unique<PragmaRedefineExtnameHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000310 PP.AddPragmaHandler(RedefineExtnameHandler.get());
311
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000312 FPContractHandler = std::make_unique<PragmaFPContractHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000313 PP.AddPragmaHandler("STDC", FPContractHandler.get());
314
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000315 STDCFENVHandler = std::make_unique<PragmaSTDC_FENV_ACCESSHandler>();
Steven Wub96a3a42018-01-05 22:45:03 +0000316 PP.AddPragmaHandler("STDC", STDCFENVHandler.get());
317
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000318 STDCCXLIMITHandler = std::make_unique<PragmaSTDC_CX_LIMITED_RANGEHandler>();
Steven Wub96a3a42018-01-05 22:45:03 +0000319 PP.AddPragmaHandler("STDC", STDCCXLIMITHandler.get());
320
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000321 STDCUnknownHandler = std::make_unique<PragmaSTDC_UnknownHandler>();
Steven Wub96a3a42018-01-05 22:45:03 +0000322 PP.AddPragmaHandler("STDC", STDCUnknownHandler.get());
323
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000324 PCSectionHandler = std::make_unique<PragmaClangSectionHandler>(Actions);
Javed Absar2a67c9e2017-06-05 10:11:57 +0000325 PP.AddPragmaHandler("clang", PCSectionHandler.get());
326
Reid Kleckner5b086462014-02-20 22:52:09 +0000327 if (getLangOpts().OpenCL) {
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000328 OpenCLExtensionHandler = std::make_unique<PragmaOpenCLExtensionHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000329 PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
330
331 PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
332 }
333 if (getLangOpts().OpenMP)
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000334 OpenMPHandler = std::make_unique<PragmaOpenMPHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000335 else
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000336 OpenMPHandler = std::make_unique<PragmaNoOpenMPHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000337 PP.AddPragmaHandler(OpenMPHandler.get());
338
Saleem Abdulrasoolfd4db532018-02-07 01:46:46 +0000339 if (getLangOpts().MicrosoftExt ||
340 getTargetInfo().getTriple().isOSBinFormatELF()) {
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000341 MSCommentHandler = std::make_unique<PragmaCommentHandler>(Actions);
Reid Kleckner5b086462014-02-20 22:52:09 +0000342 PP.AddPragmaHandler(MSCommentHandler.get());
Yunzhong Gao99efc032015-03-23 20:41:42 +0000343 }
344
Melanie Blowerf5360d42020-05-01 10:32:06 -0700345 FloatControlHandler = std::make_unique<PragmaFloatControlHandler>(Actions);
346 PP.AddPragmaHandler(FloatControlHandler.get());
Yunzhong Gao99efc032015-03-23 20:41:42 +0000347 if (getLangOpts().MicrosoftExt) {
David Blaikiee0cfc042018-11-15 03:04:23 +0000348 MSDetectMismatchHandler =
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000349 std::make_unique<PragmaDetectMismatchHandler>(Actions);
Reid Kleckner5b086462014-02-20 22:52:09 +0000350 PP.AddPragmaHandler(MSDetectMismatchHandler.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000351 MSPointersToMembers = std::make_unique<PragmaMSPointersToMembers>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000352 PP.AddPragmaHandler(MSPointersToMembers.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000353 MSVtorDisp = std::make_unique<PragmaMSVtorDisp>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000354 PP.AddPragmaHandler(MSVtorDisp.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000355 MSInitSeg = std::make_unique<PragmaMSPragma>("init_seg");
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000356 PP.AddPragmaHandler(MSInitSeg.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000357 MSDataSeg = std::make_unique<PragmaMSPragma>("data_seg");
Warren Huntc3b18962014-04-08 22:30:47 +0000358 PP.AddPragmaHandler(MSDataSeg.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000359 MSBSSSeg = std::make_unique<PragmaMSPragma>("bss_seg");
Warren Huntc3b18962014-04-08 22:30:47 +0000360 PP.AddPragmaHandler(MSBSSSeg.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000361 MSConstSeg = std::make_unique<PragmaMSPragma>("const_seg");
Warren Huntc3b18962014-04-08 22:30:47 +0000362 PP.AddPragmaHandler(MSConstSeg.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000363 MSCodeSeg = std::make_unique<PragmaMSPragma>("code_seg");
Warren Huntc3b18962014-04-08 22:30:47 +0000364 PP.AddPragmaHandler(MSCodeSeg.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000365 MSSection = std::make_unique<PragmaMSPragma>("section");
Warren Huntc3b18962014-04-08 22:30:47 +0000366 PP.AddPragmaHandler(MSSection.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000367 MSRuntimeChecks = std::make_unique<PragmaMSRuntimeChecksHandler>();
Hans Wennborg7357bbc2015-10-12 20:47:58 +0000368 PP.AddPragmaHandler(MSRuntimeChecks.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000369 MSIntrinsic = std::make_unique<PragmaMSIntrinsicHandler>();
Reid Kleckner3f1ec622016-09-07 16:38:32 +0000370 PP.AddPragmaHandler(MSIntrinsic.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000371 MSOptimize = std::make_unique<PragmaMSOptimizeHandler>();
Hans Wennborg1bbe00e2018-03-20 08:53:11 +0000372 PP.AddPragmaHandler(MSOptimize.get());
Reid Kleckner5b086462014-02-20 22:52:09 +0000373 }
Eli Bendersky06a40422014-06-06 20:31:48 +0000374
Justin Lebar67a78a62016-10-08 22:15:58 +0000375 if (getLangOpts().CUDA) {
David Blaikiee0cfc042018-11-15 03:04:23 +0000376 CUDAForceHostDeviceHandler =
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000377 std::make_unique<PragmaForceCUDAHostDeviceHandler>(Actions);
Justin Lebar67a78a62016-10-08 22:15:58 +0000378 PP.AddPragmaHandler("clang", CUDAForceHostDeviceHandler.get());
379 }
380
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000381 OptimizeHandler = std::make_unique<PragmaOptimizeHandler>(Actions);
Eli Bendersky06a40422014-06-06 20:31:48 +0000382 PP.AddPragmaHandler("clang", OptimizeHandler.get());
383
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000384 LoopHintHandler = std::make_unique<PragmaLoopHintHandler>();
Eli Bendersky06a40422014-06-06 20:31:48 +0000385 PP.AddPragmaHandler("clang", LoopHintHandler.get());
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000386
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000387 UnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("unroll");
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000388 PP.AddPragmaHandler(UnrollHintHandler.get());
Mark Heffernanc888e412014-07-24 18:09:38 +0000389
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000390 NoUnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("nounroll");
Mark Heffernanc888e412014-07-24 18:09:38 +0000391 PP.AddPragmaHandler(NoUnrollHintHandler.get());
Adam Nemet60d32642017-04-04 21:18:36 +0000392
David Blaikiee0cfc042018-11-15 03:04:23 +0000393 UnrollAndJamHintHandler =
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000394 std::make_unique<PragmaUnrollHintHandler>("unroll_and_jam");
David Greenc8e39242018-08-01 14:36:12 +0000395 PP.AddPragmaHandler(UnrollAndJamHintHandler.get());
396
David Blaikiee0cfc042018-11-15 03:04:23 +0000397 NoUnrollAndJamHintHandler =
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000398 std::make_unique<PragmaUnrollHintHandler>("nounroll_and_jam");
David Greenc8e39242018-08-01 14:36:12 +0000399 PP.AddPragmaHandler(NoUnrollAndJamHintHandler.get());
400
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000401 FPHandler = std::make_unique<PragmaFPHandler>();
Adam Nemet60d32642017-04-04 21:18:36 +0000402 PP.AddPragmaHandler("clang", FPHandler.get());
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000403
David Blaikiee0cfc042018-11-15 03:04:23 +0000404 AttributePragmaHandler =
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000405 std::make_unique<PragmaAttributeHandler>(AttrFactory);
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000406 PP.AddPragmaHandler("clang", AttributePragmaHandler.get());
Hans Wennborg739b4102019-10-09 15:22:38 +0200407
408 MaxTokensHerePragmaHandler = std::make_unique<PragmaMaxTokensHereHandler>();
409 PP.AddPragmaHandler("clang", MaxTokensHerePragmaHandler.get());
410
411 MaxTokensTotalPragmaHandler = std::make_unique<PragmaMaxTokensTotalHandler>();
412 PP.AddPragmaHandler("clang", MaxTokensTotalPragmaHandler.get());
Eli Bendersky06a40422014-06-06 20:31:48 +0000413}
414
415void Parser::resetPragmaHandlers() {
Reid Kleckner5b086462014-02-20 22:52:09 +0000416 // Remove the pragma handlers we installed.
417 PP.RemovePragmaHandler(AlignHandler.get());
418 AlignHandler.reset();
419 PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
420 GCCVisibilityHandler.reset();
421 PP.RemovePragmaHandler(OptionsHandler.get());
422 OptionsHandler.reset();
423 PP.RemovePragmaHandler(PackHandler.get());
424 PackHandler.reset();
425 PP.RemovePragmaHandler(MSStructHandler.get());
426 MSStructHandler.reset();
427 PP.RemovePragmaHandler(UnusedHandler.get());
428 UnusedHandler.reset();
429 PP.RemovePragmaHandler(WeakHandler.get());
430 WeakHandler.reset();
431 PP.RemovePragmaHandler(RedefineExtnameHandler.get());
432 RedefineExtnameHandler.reset();
433
434 if (getLangOpts().OpenCL) {
435 PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
436 OpenCLExtensionHandler.reset();
437 PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
438 }
439 PP.RemovePragmaHandler(OpenMPHandler.get());
440 OpenMPHandler.reset();
441
Saleem Abdulrasoolfd4db532018-02-07 01:46:46 +0000442 if (getLangOpts().MicrosoftExt ||
443 getTargetInfo().getTriple().isOSBinFormatELF()) {
Reid Kleckner5b086462014-02-20 22:52:09 +0000444 PP.RemovePragmaHandler(MSCommentHandler.get());
445 MSCommentHandler.reset();
Yunzhong Gao99efc032015-03-23 20:41:42 +0000446 }
447
Javed Absar2a67c9e2017-06-05 10:11:57 +0000448 PP.RemovePragmaHandler("clang", PCSectionHandler.get());
449 PCSectionHandler.reset();
450
Melanie Blowerf5360d42020-05-01 10:32:06 -0700451 PP.RemovePragmaHandler(FloatControlHandler.get());
452 FloatControlHandler.reset();
Yunzhong Gao99efc032015-03-23 20:41:42 +0000453 if (getLangOpts().MicrosoftExt) {
Reid Kleckner5b086462014-02-20 22:52:09 +0000454 PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
455 MSDetectMismatchHandler.reset();
456 PP.RemovePragmaHandler(MSPointersToMembers.get());
457 MSPointersToMembers.reset();
458 PP.RemovePragmaHandler(MSVtorDisp.get());
459 MSVtorDisp.reset();
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000460 PP.RemovePragmaHandler(MSInitSeg.get());
461 MSInitSeg.reset();
Warren Huntc3b18962014-04-08 22:30:47 +0000462 PP.RemovePragmaHandler(MSDataSeg.get());
463 MSDataSeg.reset();
464 PP.RemovePragmaHandler(MSBSSSeg.get());
465 MSBSSSeg.reset();
466 PP.RemovePragmaHandler(MSConstSeg.get());
467 MSConstSeg.reset();
468 PP.RemovePragmaHandler(MSCodeSeg.get());
469 MSCodeSeg.reset();
470 PP.RemovePragmaHandler(MSSection.get());
471 MSSection.reset();
Hans Wennborg7357bbc2015-10-12 20:47:58 +0000472 PP.RemovePragmaHandler(MSRuntimeChecks.get());
473 MSRuntimeChecks.reset();
Reid Kleckner3f1ec622016-09-07 16:38:32 +0000474 PP.RemovePragmaHandler(MSIntrinsic.get());
475 MSIntrinsic.reset();
Hans Wennborg1bbe00e2018-03-20 08:53:11 +0000476 PP.RemovePragmaHandler(MSOptimize.get());
477 MSOptimize.reset();
Reid Kleckner5b086462014-02-20 22:52:09 +0000478 }
479
Justin Lebar67a78a62016-10-08 22:15:58 +0000480 if (getLangOpts().CUDA) {
481 PP.RemovePragmaHandler("clang", CUDAForceHostDeviceHandler.get());
482 CUDAForceHostDeviceHandler.reset();
483 }
484
Reid Kleckner5b086462014-02-20 22:52:09 +0000485 PP.RemovePragmaHandler("STDC", FPContractHandler.get());
486 FPContractHandler.reset();
Eli Bendersky06a40422014-06-06 20:31:48 +0000487
Steven Wub96a3a42018-01-05 22:45:03 +0000488 PP.RemovePragmaHandler("STDC", STDCFENVHandler.get());
489 STDCFENVHandler.reset();
490
491 PP.RemovePragmaHandler("STDC", STDCCXLIMITHandler.get());
492 STDCCXLIMITHandler.reset();
493
494 PP.RemovePragmaHandler("STDC", STDCUnknownHandler.get());
495 STDCUnknownHandler.reset();
496
Eli Bendersky06a40422014-06-06 20:31:48 +0000497 PP.RemovePragmaHandler("clang", OptimizeHandler.get());
498 OptimizeHandler.reset();
499
500 PP.RemovePragmaHandler("clang", LoopHintHandler.get());
501 LoopHintHandler.reset();
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000502
503 PP.RemovePragmaHandler(UnrollHintHandler.get());
504 UnrollHintHandler.reset();
Mark Heffernanc888e412014-07-24 18:09:38 +0000505
506 PP.RemovePragmaHandler(NoUnrollHintHandler.get());
507 NoUnrollHintHandler.reset();
Adam Nemet60d32642017-04-04 21:18:36 +0000508
David Greenc8e39242018-08-01 14:36:12 +0000509 PP.RemovePragmaHandler(UnrollAndJamHintHandler.get());
510 UnrollAndJamHintHandler.reset();
511
512 PP.RemovePragmaHandler(NoUnrollAndJamHintHandler.get());
513 NoUnrollAndJamHintHandler.reset();
514
Adam Nemet60d32642017-04-04 21:18:36 +0000515 PP.RemovePragmaHandler("clang", FPHandler.get());
516 FPHandler.reset();
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000517
518 PP.RemovePragmaHandler("clang", AttributePragmaHandler.get());
519 AttributePragmaHandler.reset();
Hans Wennborg739b4102019-10-09 15:22:38 +0200520
521 PP.RemovePragmaHandler("clang", MaxTokensHerePragmaHandler.get());
522 MaxTokensHerePragmaHandler.reset();
523
524 PP.RemovePragmaHandler("clang", MaxTokensTotalPragmaHandler.get());
525 MaxTokensTotalPragmaHandler.reset();
Eli Bendersky06a40422014-06-06 20:31:48 +0000526}
527
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000528/// Handle the annotation token produced for #pragma unused(...)
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000529///
530/// Each annot_pragma_unused is followed by the argument token so e.g.
531/// "#pragma unused(x,y)" becomes:
532/// annot_pragma_unused 'x' annot_pragma_unused 'y'
533void Parser::HandlePragmaUnused() {
534 assert(Tok.is(tok::annot_pragma_unused));
Richard Smithaf3b3252017-05-18 19:21:48 +0000535 SourceLocation UnusedLoc = ConsumeAnnotationToken();
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000536 Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
537 ConsumeToken(); // The argument token.
538}
Eli Friedman570024a2010-08-05 06:57:20 +0000539
Rafael Espindola273fd772012-01-26 02:02:57 +0000540void Parser::HandlePragmaVisibility() {
541 assert(Tok.is(tok::annot_pragma_vis));
542 const IdentifierInfo *VisType =
543 static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
Richard Smithaf3b3252017-05-18 19:21:48 +0000544 SourceLocation VisLoc = ConsumeAnnotationToken();
Rafael Espindola273fd772012-01-26 02:02:57 +0000545 Actions.ActOnPragmaVisibility(VisType, VisLoc);
546}
547
Benjamin Kramere003ca22015-10-28 13:54:16 +0000548namespace {
Eli Friedmanec52f922012-02-23 23:47:16 +0000549struct PragmaPackInfo {
Denis Zobnin10c4f452016-04-29 18:17:40 +0000550 Sema::PragmaMsStackAction Action;
551 StringRef SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +0000552 Token Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +0000553};
Benjamin Kramere003ca22015-10-28 13:54:16 +0000554} // end anonymous namespace
Eli Friedmanec52f922012-02-23 23:47:16 +0000555
556void Parser::HandlePragmaPack() {
557 assert(Tok.is(tok::annot_pragma_pack));
558 PragmaPackInfo *Info =
559 static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
Alex Lorenz45b40142017-07-28 14:41:21 +0000560 SourceLocation PragmaLoc = Tok.getLocation();
Eli Friedman68be1642012-10-04 02:36:51 +0000561 ExprResult Alignment;
562 if (Info->Alignment.is(tok::numeric_constant)) {
563 Alignment = Actions.ActOnNumericConstant(Info->Alignment);
Alex Lorenz45b40142017-07-28 14:41:21 +0000564 if (Alignment.isInvalid()) {
565 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000566 return;
Alex Lorenz45b40142017-07-28 14:41:21 +0000567 }
Eli Friedman68be1642012-10-04 02:36:51 +0000568 }
Denis Zobnin10c4f452016-04-29 18:17:40 +0000569 Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel,
570 Alignment.get());
Alex Lorenz45b40142017-07-28 14:41:21 +0000571 // Consume the token after processing the pragma to enable pragma-specific
572 // #include warnings.
573 ConsumeAnnotationToken();
Eli Friedmanec52f922012-02-23 23:47:16 +0000574}
575
Eli Friedman68be1642012-10-04 02:36:51 +0000576void Parser::HandlePragmaMSStruct() {
577 assert(Tok.is(tok::annot_pragma_msstruct));
Nico Weber779355f2016-03-02 23:22:00 +0000578 PragmaMSStructKind Kind = static_cast<PragmaMSStructKind>(
579 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Eli Friedman68be1642012-10-04 02:36:51 +0000580 Actions.ActOnPragmaMSStruct(Kind);
Richard Smithaf3b3252017-05-18 19:21:48 +0000581 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000582}
583
584void Parser::HandlePragmaAlign() {
585 assert(Tok.is(tok::annot_pragma_align));
586 Sema::PragmaOptionsAlignKind Kind =
587 static_cast<Sema::PragmaOptionsAlignKind>(
588 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Alex Lorenz692821a2018-02-08 21:20:43 +0000589 Actions.ActOnPragmaOptionsAlign(Kind, Tok.getLocation());
590 // Consume the token after processing the pragma to enable pragma-specific
591 // #include warnings.
592 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000593}
594
Richard Smithba3a4f92016-01-12 21:59:26 +0000595void Parser::HandlePragmaDump() {
596 assert(Tok.is(tok::annot_pragma_dump));
597 IdentifierInfo *II =
598 reinterpret_cast<IdentifierInfo *>(Tok.getAnnotationValue());
599 Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II);
Richard Smithaf3b3252017-05-18 19:21:48 +0000600 ConsumeAnnotationToken();
Richard Smithba3a4f92016-01-12 21:59:26 +0000601}
602
Eli Friedman68be1642012-10-04 02:36:51 +0000603void Parser::HandlePragmaWeak() {
604 assert(Tok.is(tok::annot_pragma_weak));
Richard Smithaf3b3252017-05-18 19:21:48 +0000605 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000606 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
607 Tok.getLocation());
608 ConsumeToken(); // The weak name.
609}
610
611void Parser::HandlePragmaWeakAlias() {
612 assert(Tok.is(tok::annot_pragma_weakalias));
Richard Smithaf3b3252017-05-18 19:21:48 +0000613 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000614 IdentifierInfo *WeakName = Tok.getIdentifierInfo();
615 SourceLocation WeakNameLoc = Tok.getLocation();
616 ConsumeToken();
617 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
618 SourceLocation AliasNameLoc = Tok.getLocation();
619 ConsumeToken();
620 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
621 WeakNameLoc, AliasNameLoc);
622
623}
624
625void Parser::HandlePragmaRedefineExtname() {
626 assert(Tok.is(tok::annot_pragma_redefine_extname));
Richard Smithaf3b3252017-05-18 19:21:48 +0000627 SourceLocation RedefLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000628 IdentifierInfo *RedefName = Tok.getIdentifierInfo();
629 SourceLocation RedefNameLoc = Tok.getLocation();
630 ConsumeToken();
631 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
632 SourceLocation AliasNameLoc = Tok.getLocation();
633 ConsumeToken();
634 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
635 RedefNameLoc, AliasNameLoc);
636}
637
638void Parser::HandlePragmaFPContract() {
639 assert(Tok.is(tok::annot_pragma_fp_contract));
640 tok::OnOffSwitch OOS =
641 static_cast<tok::OnOffSwitch>(
642 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Adam Nemet60d32642017-04-04 21:18:36 +0000643
Melanie Blowerc355bec2020-05-04 10:48:12 -0700644 LangOptions::FPModeKind FPC;
Adam Nemet60d32642017-04-04 21:18:36 +0000645 switch (OOS) {
646 case tok::OOS_ON:
Melanie Blowerc355bec2020-05-04 10:48:12 -0700647 FPC = LangOptions::FPM_On;
Adam Nemet60d32642017-04-04 21:18:36 +0000648 break;
649 case tok::OOS_OFF:
Melanie Blowerc355bec2020-05-04 10:48:12 -0700650 FPC = LangOptions::FPM_Off;
Adam Nemet60d32642017-04-04 21:18:36 +0000651 break;
652 case tok::OOS_DEFAULT:
653 FPC = getLangOpts().getDefaultFPContractMode();
654 break;
655 }
656
Melanie Blowerf4aaed32020-06-26 09:23:45 -0700657 SourceLocation PragmaLoc = ConsumeAnnotationToken();
658 Actions.ActOnPragmaFPContract(PragmaLoc, FPC);
Eli Friedman68be1642012-10-04 02:36:51 +0000659}
660
Melanie Blowerf5360d42020-05-01 10:32:06 -0700661void Parser::HandlePragmaFloatControl() {
662 assert(Tok.is(tok::annot_pragma_float_control));
663
664 // The value that is held on the PragmaFloatControlStack encodes
665 // the PragmaFloatControl kind and the MSStackAction kind
666 // into a single 32-bit word. The MsStackAction is the high 16 bits
667 // and the FloatControl is the lower 16 bits. Use shift and bit-and
668 // to decode the parts.
669 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
670 Sema::PragmaMsStackAction Action =
671 static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
672 PragmaFloatControlKind Kind = PragmaFloatControlKind(Value & 0xFFFF);
673 SourceLocation PragmaLoc = ConsumeAnnotationToken();
674 Actions.ActOnPragmaFloatControl(PragmaLoc, Action, Kind);
675}
676
Kevin P. Neal2c0bc8b2018-08-14 17:06:56 +0000677void Parser::HandlePragmaFEnvAccess() {
678 assert(Tok.is(tok::annot_pragma_fenv_access));
679 tok::OnOffSwitch OOS =
680 static_cast<tok::OnOffSwitch>(
681 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
682
Melanie Blowerc355bec2020-05-04 10:48:12 -0700683 bool IsEnabled;
Kevin P. Neal2c0bc8b2018-08-14 17:06:56 +0000684 switch (OOS) {
685 case tok::OOS_ON:
Melanie Blowerc355bec2020-05-04 10:48:12 -0700686 IsEnabled = true;
Kevin P. Neal2c0bc8b2018-08-14 17:06:56 +0000687 break;
688 case tok::OOS_OFF:
Melanie Blowerc355bec2020-05-04 10:48:12 -0700689 IsEnabled = false;
Kevin P. Neal2c0bc8b2018-08-14 17:06:56 +0000690 break;
691 case tok::OOS_DEFAULT: // FIXME: Add this cli option when it makes sense.
Melanie Blowerc355bec2020-05-04 10:48:12 -0700692 IsEnabled = false;
Kevin P. Neal2c0bc8b2018-08-14 17:06:56 +0000693 break;
694 }
695
Melanie Blowerf5360d42020-05-01 10:32:06 -0700696 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Melanie Blowerc355bec2020-05-04 10:48:12 -0700697 Actions.ActOnPragmaFEnvAccess(PragmaLoc, IsEnabled);
Kevin P. Neal2c0bc8b2018-08-14 17:06:56 +0000698}
699
700
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000701StmtResult Parser::HandlePragmaCaptured()
702{
703 assert(Tok.is(tok::annot_pragma_captured));
Richard Smithaf3b3252017-05-18 19:21:48 +0000704 ConsumeAnnotationToken();
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000705
706 if (Tok.isNot(tok::l_brace)) {
Alp Tokerec543272013-12-24 09:48:30 +0000707 PP.Diag(Tok, diag::err_expected) << tok::l_brace;
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000708 return StmtError();
709 }
710
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000711 SourceLocation Loc = Tok.getLocation();
712
Momchil Velikov57c681f2017-08-10 15:43:06 +0000713 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope |
714 Scope::CompoundStmtScope);
Ben Langmuir37943a72013-05-03 19:00:33 +0000715 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
716 /*NumParams=*/1);
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000717
718 StmtResult R = ParseCompoundStatement();
719 CapturedRegionScope.Exit();
720
721 if (R.isInvalid()) {
722 Actions.ActOnCapturedRegionError();
723 return StmtError();
724 }
725
726 return Actions.ActOnCapturedRegionEnd(R.get());
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000727}
728
Eli Friedman68be1642012-10-04 02:36:51 +0000729namespace {
Yaxun Liu5b746652016-12-18 05:18:55 +0000730 enum OpenCLExtState : char {
731 Disable, Enable, Begin, End
732 };
733 typedef std::pair<const IdentifierInfo *, OpenCLExtState> OpenCLExtData;
Eli Friedman68be1642012-10-04 02:36:51 +0000734}
735
736void Parser::HandlePragmaOpenCLExtension() {
737 assert(Tok.is(tok::annot_pragma_opencl_extension));
Yaxun Liu5b746652016-12-18 05:18:55 +0000738 OpenCLExtData *Data = static_cast<OpenCLExtData*>(Tok.getAnnotationValue());
739 auto State = Data->second;
740 auto Ident = Data->first;
Eli Friedman68be1642012-10-04 02:36:51 +0000741 SourceLocation NameLoc = Tok.getLocation();
Richard Smithaf3b3252017-05-18 19:21:48 +0000742 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000743
Yaxun Liu5b746652016-12-18 05:18:55 +0000744 auto &Opt = Actions.getOpenCLOptions();
745 auto Name = Ident->getName();
Eli Friedman68be1642012-10-04 02:36:51 +0000746 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
747 // overriding all previously issued extension directives, but only if the
748 // behavior is set to disable."
Yaxun Liu5b746652016-12-18 05:18:55 +0000749 if (Name == "all") {
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000750 if (State == Disable) {
Yaxun Liu5b746652016-12-18 05:18:55 +0000751 Opt.disableAll();
Anastasia Stulovae88e2b92019-02-07 17:32:37 +0000752 Opt.enableSupportedCore(getLangOpts());
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000753 } else {
Yaxun Liu5b746652016-12-18 05:18:55 +0000754 PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1;
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000755 }
Yaxun Liu5b746652016-12-18 05:18:55 +0000756 } else if (State == Begin) {
Anastasia Stulovae88e2b92019-02-07 17:32:37 +0000757 if (!Opt.isKnown(Name) || !Opt.isSupported(Name, getLangOpts())) {
Yaxun Liu5b746652016-12-18 05:18:55 +0000758 Opt.support(Name);
759 }
760 Actions.setCurrentOpenCLExtension(Name);
761 } else if (State == End) {
762 if (Name != Actions.getCurrentOpenCLExtension())
763 PP.Diag(NameLoc, diag::warn_pragma_begin_end_mismatch);
764 Actions.setCurrentOpenCLExtension("");
765 } else if (!Opt.isKnown(Name))
766 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;
Anastasia Stulovae88e2b92019-02-07 17:32:37 +0000767 else if (Opt.isSupportedExtension(Name, getLangOpts()))
Yaxun Liu5b746652016-12-18 05:18:55 +0000768 Opt.enable(Name, State == Enable);
Anastasia Stulovae88e2b92019-02-07 17:32:37 +0000769 else if (Opt.isSupportedCore(Name, getLangOpts()))
Yaxun Liu5b746652016-12-18 05:18:55 +0000770 PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident;
771 else
772 PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident;
Eli Friedman68be1642012-10-04 02:36:51 +0000773}
774
David Majnemer4bb09802014-02-10 19:50:15 +0000775void Parser::HandlePragmaMSPointersToMembers() {
776 assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
David Majnemer86c318f2014-02-11 21:05:00 +0000777 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
778 static_cast<LangOptions::PragmaMSPointersToMembersKind>(
David Majnemer4bb09802014-02-10 19:50:15 +0000779 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Richard Smithaf3b3252017-05-18 19:21:48 +0000780 SourceLocation PragmaLoc = ConsumeAnnotationToken();
David Majnemer4bb09802014-02-10 19:50:15 +0000781 Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
782}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000783
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000784void Parser::HandlePragmaMSVtorDisp() {
785 assert(Tok.is(tok::annot_pragma_ms_vtordisp));
786 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
Denis Zobnin2290dac2016-04-29 11:27:00 +0000787 Sema::PragmaMsStackAction Action =
788 static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
Reid Kleckner2692eb02019-11-22 14:55:49 -0800789 MSVtorDispMode Mode = MSVtorDispMode(Value & 0xFFFF);
Richard Smithaf3b3252017-05-18 19:21:48 +0000790 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Denis Zobnin2290dac2016-04-29 11:27:00 +0000791 Actions.ActOnPragmaMSVtorDisp(Action, PragmaLoc, Mode);
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000792}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000793
Warren Huntc3b18962014-04-08 22:30:47 +0000794void Parser::HandlePragmaMSPragma() {
795 assert(Tok.is(tok::annot_pragma_ms_pragma));
796 // Grab the tokens out of the annotation and enter them into the stream.
David Blaikie2eabcc92016-02-09 18:52:09 +0000797 auto TheTokens =
798 (std::pair<std::unique_ptr<Token[]>, size_t> *)Tok.getAnnotationValue();
Ilya Biryukov929af672019-05-17 09:32:05 +0000799 PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true,
800 /*IsReinject=*/true);
Richard Smithaf3b3252017-05-18 19:21:48 +0000801 SourceLocation PragmaLocation = ConsumeAnnotationToken();
Warren Huntc3b18962014-04-08 22:30:47 +0000802 assert(Tok.isAnyIdentifier());
Reid Kleckner722b1df2014-07-18 00:13:16 +0000803 StringRef PragmaName = Tok.getIdentifierInfo()->getName();
Warren Huntc3b18962014-04-08 22:30:47 +0000804 PP.Lex(Tok); // pragma kind
Reid Kleckner722b1df2014-07-18 00:13:16 +0000805
Warren Huntc3b18962014-04-08 22:30:47 +0000806 // Figure out which #pragma we're dealing with. The switch has no default
807 // because lex shouldn't emit the annotation token for unrecognized pragmas.
Reid Kleckner722b1df2014-07-18 00:13:16 +0000808 typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
Warren Huntc3b18962014-04-08 22:30:47 +0000809 PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
810 .Case("data_seg", &Parser::HandlePragmaMSSegment)
811 .Case("bss_seg", &Parser::HandlePragmaMSSegment)
812 .Case("const_seg", &Parser::HandlePragmaMSSegment)
813 .Case("code_seg", &Parser::HandlePragmaMSSegment)
814 .Case("section", &Parser::HandlePragmaMSSection)
815 .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000816
817 if (!(this->*Handler)(PragmaName, PragmaLocation)) {
818 // Pragma handling failed, and has been diagnosed. Slurp up the tokens
819 // until eof (really end of line) to prevent follow-on errors.
Warren Huntc3b18962014-04-08 22:30:47 +0000820 while (Tok.isNot(tok::eof))
821 PP.Lex(Tok);
822 PP.Lex(Tok);
823 }
824}
825
Reid Kleckner722b1df2014-07-18 00:13:16 +0000826bool Parser::HandlePragmaMSSection(StringRef PragmaName,
827 SourceLocation PragmaLocation) {
828 if (Tok.isNot(tok::l_paren)) {
829 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
830 return false;
831 }
Warren Huntc3b18962014-04-08 22:30:47 +0000832 PP.Lex(Tok); // (
833 // Parsing code for pragma section
Reid Kleckner722b1df2014-07-18 00:13:16 +0000834 if (Tok.isNot(tok::string_literal)) {
835 PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
836 << PragmaName;
837 return false;
838 }
839 ExprResult StringResult = ParseStringLiteralExpression();
840 if (StringResult.isInvalid())
841 return false; // Already diagnosed.
842 StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
843 if (SegmentName->getCharByteWidth() != 1) {
844 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
845 << PragmaName;
846 return false;
847 }
David Majnemer48c28fa2014-10-22 21:08:43 +0000848 int SectionFlags = ASTContext::PSF_Read;
849 bool SectionFlagsAreDefault = true;
Warren Huntc3b18962014-04-08 22:30:47 +0000850 while (Tok.is(tok::comma)) {
851 PP.Lex(Tok); // ,
David Majnemer48c28fa2014-10-22 21:08:43 +0000852 // Ignore "long" and "short".
853 // They are undocumented, but widely used, section attributes which appear
854 // to do nothing.
855 if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) {
856 PP.Lex(Tok); // long/short
857 continue;
858 }
859
Reid Kleckner722b1df2014-07-18 00:13:16 +0000860 if (!Tok.isAnyIdentifier()) {
861 PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
862 << PragmaName;
863 return false;
864 }
Hans Wennborg899ded92014-10-16 20:52:46 +0000865 ASTContext::PragmaSectionFlag Flag =
866 llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
Warren Huntc3b18962014-04-08 22:30:47 +0000867 Tok.getIdentifierInfo()->getName())
Hans Wennborg899ded92014-10-16 20:52:46 +0000868 .Case("read", ASTContext::PSF_Read)
869 .Case("write", ASTContext::PSF_Write)
870 .Case("execute", ASTContext::PSF_Execute)
871 .Case("shared", ASTContext::PSF_Invalid)
872 .Case("nopage", ASTContext::PSF_Invalid)
873 .Case("nocache", ASTContext::PSF_Invalid)
874 .Case("discard", ASTContext::PSF_Invalid)
875 .Case("remove", ASTContext::PSF_Invalid)
876 .Default(ASTContext::PSF_None);
877 if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) {
878 PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
Reid Kleckner722b1df2014-07-18 00:13:16 +0000879 ? diag::warn_pragma_invalid_specific_action
880 : diag::warn_pragma_unsupported_action)
Warren Huntc3b18962014-04-08 22:30:47 +0000881 << PragmaName << Tok.getIdentifierInfo()->getName();
Reid Kleckner722b1df2014-07-18 00:13:16 +0000882 return false;
Warren Huntc3b18962014-04-08 22:30:47 +0000883 }
884 SectionFlags |= Flag;
David Majnemer48c28fa2014-10-22 21:08:43 +0000885 SectionFlagsAreDefault = false;
Warren Huntc3b18962014-04-08 22:30:47 +0000886 PP.Lex(Tok); // Identifier
887 }
David Majnemer48c28fa2014-10-22 21:08:43 +0000888 // If no section attributes are specified, the section will be marked as
889 // read/write.
890 if (SectionFlagsAreDefault)
891 SectionFlags |= ASTContext::PSF_Write;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000892 if (Tok.isNot(tok::r_paren)) {
893 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
894 return false;
895 }
Warren Huntc3b18962014-04-08 22:30:47 +0000896 PP.Lex(Tok); // )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000897 if (Tok.isNot(tok::eof)) {
898 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
899 << PragmaName;
900 return false;
901 }
Warren Huntc3b18962014-04-08 22:30:47 +0000902 PP.Lex(Tok); // eof
903 Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000904 return true;
Warren Huntc3b18962014-04-08 22:30:47 +0000905}
906
Reid Kleckner722b1df2014-07-18 00:13:16 +0000907bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
908 SourceLocation PragmaLocation) {
909 if (Tok.isNot(tok::l_paren)) {
910 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
911 return false;
912 }
Warren Huntc3b18962014-04-08 22:30:47 +0000913 PP.Lex(Tok); // (
914 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000915 StringRef SlotLabel;
Warren Huntc3b18962014-04-08 22:30:47 +0000916 if (Tok.isAnyIdentifier()) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000917 StringRef PushPop = Tok.getIdentifierInfo()->getName();
Warren Huntc3b18962014-04-08 22:30:47 +0000918 if (PushPop == "push")
919 Action = Sema::PSK_Push;
920 else if (PushPop == "pop")
921 Action = Sema::PSK_Pop;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000922 else {
923 PP.Diag(PragmaLocation,
924 diag::warn_pragma_expected_section_push_pop_or_name)
925 << PragmaName;
926 return false;
927 }
Warren Huntc3b18962014-04-08 22:30:47 +0000928 if (Action != Sema::PSK_Reset) {
929 PP.Lex(Tok); // push | pop
930 if (Tok.is(tok::comma)) {
931 PP.Lex(Tok); // ,
932 // If we've got a comma, we either need a label or a string.
933 if (Tok.isAnyIdentifier()) {
934 SlotLabel = Tok.getIdentifierInfo()->getName();
935 PP.Lex(Tok); // identifier
936 if (Tok.is(tok::comma))
937 PP.Lex(Tok);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000938 else if (Tok.isNot(tok::r_paren)) {
939 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
940 << PragmaName;
941 return false;
942 }
Warren Huntc3b18962014-04-08 22:30:47 +0000943 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000944 } else if (Tok.isNot(tok::r_paren)) {
945 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
946 return false;
947 }
Warren Huntc3b18962014-04-08 22:30:47 +0000948 }
949 }
950 // Grab the string literal for our section name.
951 StringLiteral *SegmentName = nullptr;
952 if (Tok.isNot(tok::r_paren)) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000953 if (Tok.isNot(tok::string_literal)) {
954 unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
Warren Huntc3b18962014-04-08 22:30:47 +0000955 diag::warn_pragma_expected_section_name :
956 diag::warn_pragma_expected_section_label_or_name :
957 diag::warn_pragma_expected_section_push_pop_or_name;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000958 PP.Diag(PragmaLocation, DiagID) << PragmaName;
959 return false;
960 }
961 ExprResult StringResult = ParseStringLiteralExpression();
962 if (StringResult.isInvalid())
963 return false; // Already diagnosed.
964 SegmentName = cast<StringLiteral>(StringResult.get());
965 if (SegmentName->getCharByteWidth() != 1) {
966 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
967 << PragmaName;
968 return false;
969 }
Warren Huntc3b18962014-04-08 22:30:47 +0000970 // Setting section "" has no effect
971 if (SegmentName->getLength())
972 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
973 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000974 if (Tok.isNot(tok::r_paren)) {
975 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
976 return false;
977 }
Warren Huntc3b18962014-04-08 22:30:47 +0000978 PP.Lex(Tok); // )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000979 if (Tok.isNot(tok::eof)) {
980 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
981 << PragmaName;
982 return false;
983 }
Warren Huntc3b18962014-04-08 22:30:47 +0000984 PP.Lex(Tok); // eof
985 Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
986 SegmentName, PragmaName);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000987 return true;
Warren Huntc3b18962014-04-08 22:30:47 +0000988}
989
Reid Kleckner1a711b12014-07-22 00:53:05 +0000990// #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000991bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
992 SourceLocation PragmaLocation) {
David Majnemerad2986e2014-08-14 06:35:08 +0000993 if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
994 PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
995 return false;
996 }
997
Reid Kleckner1a711b12014-07-22 00:53:05 +0000998 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
999 PragmaName))
1000 return false;
1001
1002 // Parse either the known section names or the string section name.
1003 StringLiteral *SegmentName = nullptr;
1004 if (Tok.isAnyIdentifier()) {
1005 auto *II = Tok.getIdentifierInfo();
1006 StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
1007 .Case("compiler", "\".CRT$XCC\"")
1008 .Case("lib", "\".CRT$XCL\"")
1009 .Case("user", "\".CRT$XCU\"")
1010 .Default("");
1011
1012 if (!Section.empty()) {
1013 // Pretend the user wrote the appropriate string literal here.
1014 Token Toks[1];
1015 Toks[0].startToken();
1016 Toks[0].setKind(tok::string_literal);
1017 Toks[0].setLocation(Tok.getLocation());
1018 Toks[0].setLiteralData(Section.data());
1019 Toks[0].setLength(Section.size());
1020 SegmentName =
1021 cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
1022 PP.Lex(Tok);
1023 }
1024 } else if (Tok.is(tok::string_literal)) {
1025 ExprResult StringResult = ParseStringLiteralExpression();
1026 if (StringResult.isInvalid())
1027 return false;
1028 SegmentName = cast<StringLiteral>(StringResult.get());
1029 if (SegmentName->getCharByteWidth() != 1) {
1030 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
1031 << PragmaName;
1032 return false;
1033 }
1034 // FIXME: Add support for the '[, func-name]' part of the pragma.
1035 }
1036
1037 if (!SegmentName) {
1038 PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
1039 return false;
1040 }
1041
1042 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
1043 PragmaName) ||
1044 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
1045 PragmaName))
1046 return false;
1047
1048 Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
1049 return true;
Eli Bendersky06a40422014-06-06 20:31:48 +00001050}
1051
Benjamin Kramere003ca22015-10-28 13:54:16 +00001052namespace {
Eli Bendersky06a40422014-06-06 20:31:48 +00001053struct PragmaLoopHintInfo {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001054 Token PragmaName;
Eli Bendersky06a40422014-06-06 20:31:48 +00001055 Token Option;
Benjamin Kramerfa7f8552015-08-05 09:39:57 +00001056 ArrayRef<Token> Toks;
Eli Bendersky06a40422014-06-06 20:31:48 +00001057};
Benjamin Kramere003ca22015-10-28 13:54:16 +00001058} // end anonymous namespace
Eli Bendersky06a40422014-06-06 20:31:48 +00001059
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001060static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
Sjoerd Meijer90374f72019-08-15 07:39:05 +00001061 StringRef Str = PragmaName.getIdentifierInfo()->getName();
1062 std::string ClangLoopStr = (llvm::Twine("clang loop ") + Str).str();
Benjamin Krameradcd0262020-01-28 20:23:46 +01001063 return std::string(llvm::StringSwitch<StringRef>(Str)
1064 .Case("loop", ClangLoopStr)
1065 .Case("unroll_and_jam", Str)
1066 .Case("unroll", Str)
1067 .Default(""));
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001068}
1069
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001070bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
Eli Bendersky06a40422014-06-06 20:31:48 +00001071 assert(Tok.is(tok::annot_pragma_loop_hint));
1072 PragmaLoopHintInfo *Info =
1073 static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
1074
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001075 IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
1076 Hint.PragmaNameLoc = IdentifierLoc::create(
1077 Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);
Eli Bendersky06a40422014-06-06 20:31:48 +00001078
Aaron Ballmanef940aa2014-07-31 21:24:32 +00001079 // It is possible that the loop hint has no option identifier, such as
1080 // #pragma unroll(4).
1081 IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
1082 ? Info->Option.getIdentifierInfo()
1083 : nullptr;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001084 Hint.OptionLoc = IdentifierLoc::create(
1085 Actions.Context, Info->Option.getLocation(), OptionInfo);
1086
David Blaikie2eabcc92016-02-09 18:52:09 +00001087 llvm::ArrayRef<Token> Toks = Info->Toks;
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001088
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001089 // Return a valid hint if pragma unroll or nounroll were specified
1090 // without an argument.
Sjoerd Meijer90374f72019-08-15 07:39:05 +00001091 auto IsLoopHint = llvm::StringSwitch<bool>(PragmaNameInfo->getName())
1092 .Cases("unroll", "nounroll", "unroll_and_jam",
1093 "nounroll_and_jam", true)
1094 .Default(false);
1095
1096 if (Toks.empty() && IsLoopHint) {
Richard Smithaf3b3252017-05-18 19:21:48 +00001097 ConsumeAnnotationToken();
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001098 Hint.Range = Info->PragmaName.getLocation();
1099 return true;
1100 }
1101
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001102 // The constant expression is always followed by an eof token, which increases
1103 // the TokSize by 1.
David Blaikie2eabcc92016-02-09 18:52:09 +00001104 assert(!Toks.empty() &&
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001105 "PragmaLoopHintInfo::Toks must contain at least one token.");
1106
1107 // If no option is specified the argument is assumed to be a constant expr.
Tyler Nowicki24853c12015-06-08 23:13:43 +00001108 bool OptionUnroll = false;
David Greenc8e39242018-08-01 14:36:12 +00001109 bool OptionUnrollAndJam = false;
Adam Nemet2de463e2016-06-14 12:04:26 +00001110 bool OptionDistribute = false;
Aaron Ballman9bdf5152019-01-04 17:20:00 +00001111 bool OptionPipelineDisabled = false;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001112 bool StateOption = false;
Tyler Nowicki24853c12015-06-08 23:13:43 +00001113 if (OptionInfo) { // Pragma Unroll does not specify an option.
1114 OptionUnroll = OptionInfo->isStr("unroll");
David Greenc8e39242018-08-01 14:36:12 +00001115 OptionUnrollAndJam = OptionInfo->isStr("unroll_and_jam");
Adam Nemet2de463e2016-06-14 12:04:26 +00001116 OptionDistribute = OptionInfo->isStr("distribute");
Aaron Ballman9bdf5152019-01-04 17:20:00 +00001117 OptionPipelineDisabled = OptionInfo->isStr("pipeline");
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001118 StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
1119 .Case("vectorize", true)
1120 .Case("interleave", true)
Sjoerd Meijera48f58c2019-07-25 07:33:13 +00001121 .Case("vectorize_predicate", true)
Adam Nemet2de463e2016-06-14 12:04:26 +00001122 .Default(false) ||
Aaron Ballman9bdf5152019-01-04 17:20:00 +00001123 OptionUnroll || OptionUnrollAndJam || OptionDistribute ||
1124 OptionPipelineDisabled;
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001125 }
1126
Aaron Ballman9bdf5152019-01-04 17:20:00 +00001127 bool AssumeSafetyArg = !OptionUnroll && !OptionUnrollAndJam &&
1128 !OptionDistribute && !OptionPipelineDisabled;
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001129 // Verify loop hint has an argument.
1130 if (Toks[0].is(tok::eof)) {
Richard Smithaf3b3252017-05-18 19:21:48 +00001131 ConsumeAnnotationToken();
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001132 Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
David Greenc8e39242018-08-01 14:36:12 +00001133 << /*StateArgument=*/StateOption
1134 << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
Adam Nemet2de463e2016-06-14 12:04:26 +00001135 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001136 return false;
1137 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001138
1139 // Validate the argument.
1140 if (StateOption) {
Richard Smithaf3b3252017-05-18 19:21:48 +00001141 ConsumeAnnotationToken();
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001142 SourceLocation StateLoc = Toks[0].getLocation();
1143 IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
Adam Nemet50de4e82016-04-19 22:17:45 +00001144
Aaron Ballman9bdf5152019-01-04 17:20:00 +00001145 bool Valid = StateInfo &&
1146 llvm::StringSwitch<bool>(StateInfo->getName())
1147 .Case("disable", true)
1148 .Case("enable", !OptionPipelineDisabled)
1149 .Case("full", OptionUnroll || OptionUnrollAndJam)
1150 .Case("assume_safety", AssumeSafetyArg)
1151 .Default(false);
Adam Nemet50de4e82016-04-19 22:17:45 +00001152 if (!Valid) {
Aaron Ballman9bdf5152019-01-04 17:20:00 +00001153 if (OptionPipelineDisabled) {
1154 Diag(Toks[0].getLocation(), diag::err_pragma_pipeline_invalid_keyword);
1155 } else {
1156 Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
1157 << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
1158 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
1159 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001160 return false;
1161 }
David Blaikie2eabcc92016-02-09 18:52:09 +00001162 if (Toks.size() > 2)
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001163 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1164 << PragmaLoopHintString(Info->PragmaName, Info->Option);
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001165 Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
1166 } else {
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001167 // Enter constant expression including eof terminator into token stream.
Ilya Biryukov929af672019-05-17 09:32:05 +00001168 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false,
1169 /*IsReinject=*/false);
Richard Smithaf3b3252017-05-18 19:21:48 +00001170 ConsumeAnnotationToken();
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001171
1172 ExprResult R = ParseConstantExpression();
1173
1174 // Tokens following an error in an ill-formed constant expression will
1175 // remain in the token stream and must be removed.
1176 if (Tok.isNot(tok::eof)) {
1177 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1178 << PragmaLoopHintString(Info->PragmaName, Info->Option);
1179 while (Tok.isNot(tok::eof))
1180 ConsumeAnyToken();
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001181 }
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001182
1183 ConsumeToken(); // Consume the constant expression eof terminator.
1184
1185 if (R.isInvalid() ||
1186 Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
1187 return false;
1188
1189 // Argument is a constant expression with an integer type.
1190 Hint.ValueExpr = R.get();
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001191 }
Eli Bendersky06a40422014-06-06 20:31:48 +00001192
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001193 Hint.Range = SourceRange(Info->PragmaName.getLocation(),
David Blaikie2eabcc92016-02-09 18:52:09 +00001194 Info->Toks.back().getLocation());
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001195 return true;
Eli Bendersky06a40422014-06-06 20:31:48 +00001196}
1197
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001198namespace {
1199struct PragmaAttributeInfo {
Erik Pilkington7d180942018-10-29 17:38:42 +00001200 enum ActionType { Push, Pop, Attribute };
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001201 ParsedAttributes &Attributes;
1202 ActionType Action;
Erik Pilkington0876cae2018-12-20 22:32:04 +00001203 const IdentifierInfo *Namespace = nullptr;
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001204 ArrayRef<Token> Tokens;
1205
1206 PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {}
1207};
1208
1209#include "clang/Parse/AttrSubMatchRulesParserStringSwitches.inc"
1210
1211} // end anonymous namespace
1212
1213static StringRef getIdentifier(const Token &Tok) {
1214 if (Tok.is(tok::identifier))
1215 return Tok.getIdentifierInfo()->getName();
1216 const char *S = tok::getKeywordSpelling(Tok.getKind());
1217 if (!S)
1218 return "";
1219 return S;
1220}
1221
1222static bool isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule) {
1223 using namespace attr;
1224 switch (Rule) {
1225#define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) \
1226 case Value: \
1227 return IsAbstract;
1228#include "clang/Basic/AttrSubMatchRulesList.inc"
1229 }
1230 llvm_unreachable("Invalid attribute subject match rule");
1231 return false;
1232}
1233
1234static void diagnoseExpectedAttributeSubjectSubRule(
1235 Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1236 SourceLocation SubRuleLoc) {
1237 auto Diagnostic =
1238 PRef.Diag(SubRuleLoc,
1239 diag::err_pragma_attribute_expected_subject_sub_identifier)
1240 << PrimaryRuleName;
1241 if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1242 Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1243 else
1244 Diagnostic << /*SubRulesSupported=*/0;
1245}
1246
1247static void diagnoseUnknownAttributeSubjectSubRule(
1248 Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1249 StringRef SubRuleName, SourceLocation SubRuleLoc) {
1250
1251 auto Diagnostic =
1252 PRef.Diag(SubRuleLoc, diag::err_pragma_attribute_unknown_subject_sub_rule)
1253 << SubRuleName << PrimaryRuleName;
1254 if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1255 Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1256 else
1257 Diagnostic << /*SubRulesSupported=*/0;
1258}
1259
1260bool Parser::ParsePragmaAttributeSubjectMatchRuleSet(
1261 attr::ParsedSubjectMatchRuleSet &SubjectMatchRules, SourceLocation &AnyLoc,
1262 SourceLocation &LastMatchRuleEndLoc) {
1263 bool IsAny = false;
1264 BalancedDelimiterTracker AnyParens(*this, tok::l_paren);
1265 if (getIdentifier(Tok) == "any") {
1266 AnyLoc = ConsumeToken();
1267 IsAny = true;
1268 if (AnyParens.expectAndConsume())
1269 return true;
1270 }
1271
1272 do {
1273 // Parse the subject matcher rule.
1274 StringRef Name = getIdentifier(Tok);
1275 if (Name.empty()) {
1276 Diag(Tok, diag::err_pragma_attribute_expected_subject_identifier);
1277 return true;
1278 }
1279 std::pair<Optional<attr::SubjectMatchRule>,
1280 Optional<attr::SubjectMatchRule> (*)(StringRef, bool)>
1281 Rule = isAttributeSubjectMatchRule(Name);
1282 if (!Rule.first) {
1283 Diag(Tok, diag::err_pragma_attribute_unknown_subject_rule) << Name;
1284 return true;
1285 }
1286 attr::SubjectMatchRule PrimaryRule = *Rule.first;
1287 SourceLocation RuleLoc = ConsumeToken();
1288
1289 BalancedDelimiterTracker Parens(*this, tok::l_paren);
1290 if (isAbstractAttrMatcherRule(PrimaryRule)) {
1291 if (Parens.expectAndConsume())
1292 return true;
1293 } else if (Parens.consumeOpen()) {
1294 if (!SubjectMatchRules
1295 .insert(
1296 std::make_pair(PrimaryRule, SourceRange(RuleLoc, RuleLoc)))
1297 .second)
1298 Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1299 << Name
1300 << FixItHint::CreateRemoval(SourceRange(
1301 RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleLoc));
1302 LastMatchRuleEndLoc = RuleLoc;
1303 continue;
1304 }
1305
1306 // Parse the sub-rules.
1307 StringRef SubRuleName = getIdentifier(Tok);
1308 if (SubRuleName.empty()) {
1309 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1310 Tok.getLocation());
1311 return true;
1312 }
1313 attr::SubjectMatchRule SubRule;
1314 if (SubRuleName == "unless") {
1315 SourceLocation SubRuleLoc = ConsumeToken();
1316 BalancedDelimiterTracker Parens(*this, tok::l_paren);
1317 if (Parens.expectAndConsume())
1318 return true;
1319 SubRuleName = getIdentifier(Tok);
1320 if (SubRuleName.empty()) {
1321 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1322 SubRuleLoc);
1323 return true;
1324 }
1325 auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/true);
1326 if (!SubRuleOrNone) {
1327 std::string SubRuleUnlessName = "unless(" + SubRuleName.str() + ")";
1328 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1329 SubRuleUnlessName, SubRuleLoc);
1330 return true;
1331 }
1332 SubRule = *SubRuleOrNone;
1333 ConsumeToken();
1334 if (Parens.consumeClose())
1335 return true;
1336 } else {
1337 auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/false);
1338 if (!SubRuleOrNone) {
1339 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1340 SubRuleName, Tok.getLocation());
1341 return true;
1342 }
1343 SubRule = *SubRuleOrNone;
1344 ConsumeToken();
1345 }
1346 SourceLocation RuleEndLoc = Tok.getLocation();
1347 LastMatchRuleEndLoc = RuleEndLoc;
1348 if (Parens.consumeClose())
1349 return true;
1350 if (!SubjectMatchRules
1351 .insert(std::make_pair(SubRule, SourceRange(RuleLoc, RuleEndLoc)))
1352 .second) {
1353 Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1354 << attr::getSubjectMatchRuleSpelling(SubRule)
1355 << FixItHint::CreateRemoval(SourceRange(
1356 RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleEndLoc));
1357 continue;
1358 }
1359 } while (IsAny && TryConsumeToken(tok::comma));
1360
1361 if (IsAny)
1362 if (AnyParens.consumeClose())
1363 return true;
1364
1365 return false;
1366}
1367
1368namespace {
1369
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00001370/// Describes the stage at which attribute subject rule parsing was interrupted.
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001371enum class MissingAttributeSubjectRulesRecoveryPoint {
1372 Comma,
1373 ApplyTo,
1374 Equals,
1375 Any,
1376 None,
1377};
1378
1379MissingAttributeSubjectRulesRecoveryPoint
1380getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) {
1381 if (const auto *II = Tok.getIdentifierInfo()) {
1382 if (II->isStr("apply_to"))
1383 return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo;
1384 if (II->isStr("any"))
1385 return MissingAttributeSubjectRulesRecoveryPoint::Any;
1386 }
1387 if (Tok.is(tok::equal))
1388 return MissingAttributeSubjectRulesRecoveryPoint::Equals;
1389 return MissingAttributeSubjectRulesRecoveryPoint::None;
1390}
1391
1392/// Creates a diagnostic for the attribute subject rule parsing diagnostic that
1393/// suggests the possible attribute subject rules in a fix-it together with
1394/// any other missing tokens.
1395DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic(
Erich Keanee891aa92018-07-13 15:07:47 +00001396 unsigned DiagID, ParsedAttr &Attribute,
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001397 MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) {
1398 SourceLocation Loc = PRef.getEndOfPreviousToken();
1399 if (Loc.isInvalid())
1400 Loc = PRef.getCurToken().getLocation();
1401 auto Diagnostic = PRef.Diag(Loc, DiagID);
1402 std::string FixIt;
1403 MissingAttributeSubjectRulesRecoveryPoint EndPoint =
1404 getAttributeSubjectRulesRecoveryPointForToken(PRef.getCurToken());
1405 if (Point == MissingAttributeSubjectRulesRecoveryPoint::Comma)
1406 FixIt = ", ";
1407 if (Point <= MissingAttributeSubjectRulesRecoveryPoint::ApplyTo &&
1408 EndPoint > MissingAttributeSubjectRulesRecoveryPoint::ApplyTo)
1409 FixIt += "apply_to";
1410 if (Point <= MissingAttributeSubjectRulesRecoveryPoint::Equals &&
1411 EndPoint > MissingAttributeSubjectRulesRecoveryPoint::Equals)
1412 FixIt += " = ";
1413 SourceRange FixItRange(Loc);
1414 if (EndPoint == MissingAttributeSubjectRulesRecoveryPoint::None) {
1415 // Gather the subject match rules that are supported by the attribute.
1416 SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> SubjectMatchRuleSet;
1417 Attribute.getMatchRules(PRef.getLangOpts(), SubjectMatchRuleSet);
1418 if (SubjectMatchRuleSet.empty()) {
1419 // FIXME: We can emit a "fix-it" with a subject list placeholder when
1420 // placeholders will be supported by the fix-its.
1421 return Diagnostic;
1422 }
1423 FixIt += "any(";
1424 bool NeedsComma = false;
1425 for (const auto &I : SubjectMatchRuleSet) {
1426 // Ensure that the missing rule is reported in the fix-it only when it's
1427 // supported in the current language mode.
1428 if (!I.second)
1429 continue;
1430 if (NeedsComma)
1431 FixIt += ", ";
1432 else
1433 NeedsComma = true;
1434 FixIt += attr::getSubjectMatchRuleSpelling(I.first);
1435 }
1436 FixIt += ")";
1437 // Check if we need to remove the range
1438 PRef.SkipUntil(tok::eof, Parser::StopBeforeMatch);
1439 FixItRange.setEnd(PRef.getCurToken().getLocation());
1440 }
1441 if (FixItRange.getBegin() == FixItRange.getEnd())
1442 Diagnostic << FixItHint::CreateInsertion(FixItRange.getBegin(), FixIt);
1443 else
1444 Diagnostic << FixItHint::CreateReplacement(
1445 CharSourceRange::getCharRange(FixItRange), FixIt);
1446 return Diagnostic;
1447}
1448
1449} // end anonymous namespace
1450
1451void Parser::HandlePragmaAttribute() {
1452 assert(Tok.is(tok::annot_pragma_attribute) &&
1453 "Expected #pragma attribute annotation token");
1454 SourceLocation PragmaLoc = Tok.getLocation();
1455 auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue());
1456 if (Info->Action == PragmaAttributeInfo::Pop) {
Richard Smithaf3b3252017-05-18 19:21:48 +00001457 ConsumeAnnotationToken();
Erik Pilkington0876cae2018-12-20 22:32:04 +00001458 Actions.ActOnPragmaAttributePop(PragmaLoc, Info->Namespace);
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001459 return;
1460 }
1461 // Parse the actual attribute with its arguments.
Erik Pilkington7d180942018-10-29 17:38:42 +00001462 assert((Info->Action == PragmaAttributeInfo::Push ||
1463 Info->Action == PragmaAttributeInfo::Attribute) &&
Erik Pilkingtonb287a012018-10-29 03:24:16 +00001464 "Unexpected #pragma attribute command");
Erik Pilkington7d180942018-10-29 17:38:42 +00001465
1466 if (Info->Action == PragmaAttributeInfo::Push && Info->Tokens.empty()) {
1467 ConsumeAnnotationToken();
Erik Pilkington0876cae2018-12-20 22:32:04 +00001468 Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
Erik Pilkington7d180942018-10-29 17:38:42 +00001469 return;
1470 }
1471
Ilya Biryukov929af672019-05-17 09:32:05 +00001472 PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false,
1473 /*IsReinject=*/false);
Richard Smithaf3b3252017-05-18 19:21:48 +00001474 ConsumeAnnotationToken();
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001475
1476 ParsedAttributes &Attrs = Info->Attributes;
1477 Attrs.clearListOnly();
1478
1479 auto SkipToEnd = [this]() {
1480 SkipUntil(tok::eof, StopBeforeMatch);
1481 ConsumeToken();
1482 };
1483
1484 if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) {
1485 // Parse the CXX11 style attribute.
1486 ParseCXX11AttributeSpecifier(Attrs);
1487 } else if (Tok.is(tok::kw___attribute)) {
1488 ConsumeToken();
1489 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
1490 "attribute"))
1491 return SkipToEnd();
1492 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "("))
1493 return SkipToEnd();
1494
1495 if (Tok.isNot(tok::identifier)) {
1496 Diag(Tok, diag::err_pragma_attribute_expected_attribute_name);
1497 SkipToEnd();
1498 return;
1499 }
1500 IdentifierInfo *AttrName = Tok.getIdentifierInfo();
1501 SourceLocation AttrNameLoc = ConsumeToken();
1502
1503 if (Tok.isNot(tok::l_paren))
1504 Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
Erich Keanee891aa92018-07-13 15:07:47 +00001505 ParsedAttr::AS_GNU);
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001506 else
1507 ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr,
1508 /*ScopeName=*/nullptr,
Erich Keanee891aa92018-07-13 15:07:47 +00001509 /*ScopeLoc=*/SourceLocation(), ParsedAttr::AS_GNU,
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001510 /*Declarator=*/nullptr);
1511
1512 if (ExpectAndConsume(tok::r_paren))
1513 return SkipToEnd();
1514 if (ExpectAndConsume(tok::r_paren))
1515 return SkipToEnd();
1516 } else if (Tok.is(tok::kw___declspec)) {
1517 ParseMicrosoftDeclSpecs(Attrs);
1518 } else {
1519 Diag(Tok, diag::err_pragma_attribute_expected_attribute_syntax);
1520 if (Tok.getIdentifierInfo()) {
1521 // If we suspect that this is an attribute suggest the use of
1522 // '__attribute__'.
Erich Keane6a24e802019-09-13 17:39:31 +00001523 if (ParsedAttr::getParsedKind(
1524 Tok.getIdentifierInfo(), /*ScopeName=*/nullptr,
1525 ParsedAttr::AS_GNU) != ParsedAttr::UnknownAttribute) {
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001526 SourceLocation InsertStartLoc = Tok.getLocation();
1527 ConsumeToken();
1528 if (Tok.is(tok::l_paren)) {
1529 ConsumeAnyToken();
1530 SkipUntil(tok::r_paren, StopBeforeMatch);
1531 if (Tok.isNot(tok::r_paren))
1532 return SkipToEnd();
1533 }
1534 Diag(Tok, diag::note_pragma_attribute_use_attribute_kw)
1535 << FixItHint::CreateInsertion(InsertStartLoc, "__attribute__((")
1536 << FixItHint::CreateInsertion(Tok.getEndLoc(), "))");
1537 }
1538 }
1539 SkipToEnd();
1540 return;
1541 }
1542
Erich Keanec480f302018-07-12 21:09:05 +00001543 if (Attrs.empty() || Attrs.begin()->isInvalid()) {
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001544 SkipToEnd();
1545 return;
1546 }
1547
1548 // Ensure that we don't have more than one attribute.
Erich Keanec480f302018-07-12 21:09:05 +00001549 if (Attrs.size() > 1) {
1550 SourceLocation Loc = Attrs[1].getLoc();
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001551 Diag(Loc, diag::err_pragma_attribute_multiple_attributes);
1552 SkipToEnd();
1553 return;
1554 }
1555
Erich Keanee891aa92018-07-13 15:07:47 +00001556 ParsedAttr &Attribute = *Attrs.begin();
Erich Keanec480f302018-07-12 21:09:05 +00001557 if (!Attribute.isSupportedByPragmaAttribute()) {
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001558 Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute)
Erich Keane6a24e802019-09-13 17:39:31 +00001559 << Attribute;
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001560 SkipToEnd();
1561 return;
1562 }
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001563
1564 // Parse the subject-list.
1565 if (!TryConsumeToken(tok::comma)) {
1566 createExpectedAttributeSubjectRulesTokenDiagnostic(
1567 diag::err_expected, Attribute,
1568 MissingAttributeSubjectRulesRecoveryPoint::Comma, *this)
1569 << tok::comma;
1570 SkipToEnd();
1571 return;
1572 }
1573
1574 if (Tok.isNot(tok::identifier)) {
1575 createExpectedAttributeSubjectRulesTokenDiagnostic(
1576 diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute,
1577 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1578 SkipToEnd();
1579 return;
1580 }
1581 const IdentifierInfo *II = Tok.getIdentifierInfo();
1582 if (!II->isStr("apply_to")) {
1583 createExpectedAttributeSubjectRulesTokenDiagnostic(
1584 diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute,
1585 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1586 SkipToEnd();
1587 return;
1588 }
1589 ConsumeToken();
1590
1591 if (!TryConsumeToken(tok::equal)) {
1592 createExpectedAttributeSubjectRulesTokenDiagnostic(
1593 diag::err_expected, Attribute,
1594 MissingAttributeSubjectRulesRecoveryPoint::Equals, *this)
1595 << tok::equal;
1596 SkipToEnd();
1597 return;
1598 }
1599
1600 attr::ParsedSubjectMatchRuleSet SubjectMatchRules;
1601 SourceLocation AnyLoc, LastMatchRuleEndLoc;
1602 if (ParsePragmaAttributeSubjectMatchRuleSet(SubjectMatchRules, AnyLoc,
1603 LastMatchRuleEndLoc)) {
1604 SkipToEnd();
1605 return;
1606 }
1607
1608 // Tokens following an ill-formed attribute will remain in the token stream
1609 // and must be removed.
1610 if (Tok.isNot(tok::eof)) {
1611 Diag(Tok, diag::err_pragma_attribute_extra_tokens_after_attribute);
1612 SkipToEnd();
1613 return;
1614 }
1615
1616 // Consume the eof terminator token.
1617 ConsumeToken();
1618
Erik Pilkington7d180942018-10-29 17:38:42 +00001619 // Handle a mixed push/attribute by desurging to a push, then an attribute.
1620 if (Info->Action == PragmaAttributeInfo::Push)
Erik Pilkington0876cae2018-12-20 22:32:04 +00001621 Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
Erik Pilkington7d180942018-10-29 17:38:42 +00001622
1623 Actions.ActOnPragmaAttributeAttribute(Attribute, PragmaLoc,
1624 std::move(SubjectMatchRules));
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001625}
1626
Eli Bendersky06a40422014-06-06 20:31:48 +00001627// #pragma GCC visibility comes in two variants:
1628// 'push' '(' [visibility] ')'
1629// 'pop'
Fangrui Song6907ce22018-07-30 19:24:48 +00001630void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00001631 PragmaIntroducer Introducer,
Douglas Gregorc7d65762010-09-09 22:45:38 +00001632 Token &VisTok) {
Eli Friedman570024a2010-08-05 06:57:20 +00001633 SourceLocation VisLoc = VisTok.getLocation();
1634
1635 Token Tok;
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001636 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001637
1638 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
1639
Eli Friedman570024a2010-08-05 06:57:20 +00001640 const IdentifierInfo *VisType;
1641 if (PushPop && PushPop->isStr("pop")) {
Craig Topper161e4db2014-05-21 06:02:52 +00001642 VisType = nullptr;
Eli Friedman570024a2010-08-05 06:57:20 +00001643 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001644 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001645 if (Tok.isNot(tok::l_paren)) {
1646 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
1647 << "visibility";
1648 return;
1649 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001650 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001651 VisType = Tok.getIdentifierInfo();
1652 if (!VisType) {
1653 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1654 << "visibility";
1655 return;
1656 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001657 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001658 if (Tok.isNot(tok::r_paren)) {
1659 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
1660 << "visibility";
1661 return;
1662 }
1663 } else {
1664 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1665 << "visibility";
1666 return;
1667 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00001668 SourceLocation EndLoc = Tok.getLocation();
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001669 PP.LexUnexpandedToken(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001670 if (Tok.isNot(tok::eod)) {
Eli Friedman570024a2010-08-05 06:57:20 +00001671 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1672 << "visibility";
1673 return;
1674 }
1675
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +00001676 auto Toks = std::make_unique<Token[]>(1);
Rafael Espindola273fd772012-01-26 02:02:57 +00001677 Toks[0].startToken();
1678 Toks[0].setKind(tok::annot_pragma_vis);
1679 Toks[0].setLocation(VisLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001680 Toks[0].setAnnotationEndLoc(EndLoc);
Rafael Espindola273fd772012-01-26 02:02:57 +00001681 Toks[0].setAnnotationValue(
Ilya Biryukov929af672019-05-17 09:32:05 +00001682 const_cast<void *>(static_cast<const void *>(VisType)));
1683 PP.EnterTokenStream(std::move(Toks), 1, /*DisableMacroExpansion=*/true,
1684 /*IsReinject=*/false);
Eli Friedman570024a2010-08-05 06:57:20 +00001685}
1686
Daniel Dunbar921b9682008-10-04 19:21:03 +00001687// #pragma pack(...) comes in the following delicious flavors:
1688// pack '(' [integer] ')'
1689// pack '(' 'show' ')'
1690// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Fangrui Song6907ce22018-07-30 19:24:48 +00001691void PragmaPackHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00001692 PragmaIntroducer Introducer,
Douglas Gregorc7d65762010-09-09 22:45:38 +00001693 Token &PackTok) {
Daniel Dunbar921b9682008-10-04 19:21:03 +00001694 SourceLocation PackLoc = PackTok.getLocation();
1695
1696 Token Tok;
1697 PP.Lex(Tok);
1698 if (Tok.isNot(tok::l_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001699 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001700 return;
1701 }
1702
Denis Zobnin10c4f452016-04-29 18:17:40 +00001703 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
1704 StringRef SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +00001705 Token Alignment;
1706 Alignment.startToken();
Mike Stump11289f42009-09-09 15:08:12 +00001707 PP.Lex(Tok);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001708 if (Tok.is(tok::numeric_constant)) {
Eli Friedman68be1642012-10-04 02:36:51 +00001709 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001710
1711 PP.Lex(Tok);
Eli Friedman055c9702011-11-02 01:53:16 +00001712
1713 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
1714 // the push/pop stack.
1715 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
Denis Zobnin10c4f452016-04-29 18:17:40 +00001716 Action =
1717 PP.getLangOpts().ApplePragmaPack ? Sema::PSK_Push_Set : Sema::PSK_Set;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001718 } else if (Tok.is(tok::identifier)) {
1719 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattnere3d20d92008-11-23 21:45:46 +00001720 if (II->isStr("show")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001721 Action = Sema::PSK_Show;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001722 PP.Lex(Tok);
1723 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001724 if (II->isStr("push")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001725 Action = Sema::PSK_Push;
Chris Lattnere3d20d92008-11-23 21:45:46 +00001726 } else if (II->isStr("pop")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001727 Action = Sema::PSK_Pop;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001728 } else {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001729 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001730 return;
Mike Stump11289f42009-09-09 15:08:12 +00001731 }
Daniel Dunbar921b9682008-10-04 19:21:03 +00001732 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001733
Daniel Dunbar921b9682008-10-04 19:21:03 +00001734 if (Tok.is(tok::comma)) {
1735 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001736
Daniel Dunbar921b9682008-10-04 19:21:03 +00001737 if (Tok.is(tok::numeric_constant)) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001738 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
Eli Friedman68be1642012-10-04 02:36:51 +00001739 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001740
1741 PP.Lex(Tok);
1742 } else if (Tok.is(tok::identifier)) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001743 SlotLabel = Tok.getIdentifierInfo()->getName();
Daniel Dunbar921b9682008-10-04 19:21:03 +00001744 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001745
Daniel Dunbar921b9682008-10-04 19:21:03 +00001746 if (Tok.is(tok::comma)) {
1747 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001748
Daniel Dunbar921b9682008-10-04 19:21:03 +00001749 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001750 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001751 return;
1752 }
Mike Stump11289f42009-09-09 15:08:12 +00001753
Denis Zobnin10c4f452016-04-29 18:17:40 +00001754 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
Eli Friedman68be1642012-10-04 02:36:51 +00001755 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001756
1757 PP.Lex(Tok);
1758 }
1759 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001760 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001761 return;
1762 }
1763 }
1764 }
David Blaikiebbafb8a2012-03-11 07:00:24 +00001765 } else if (PP.getLangOpts().ApplePragmaPack) {
Eli Friedman055c9702011-11-02 01:53:16 +00001766 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
1767 // the push/pop stack.
1768 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
Denis Zobnin10c4f452016-04-29 18:17:40 +00001769 Action = Sema::PSK_Pop;
Sebastian Redl17f2c7d2008-12-09 13:15:23 +00001770 }
Daniel Dunbar921b9682008-10-04 19:21:03 +00001771
1772 if (Tok.isNot(tok::r_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001773 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001774 return;
1775 }
1776
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001777 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001778 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001779 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001780 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
1781 return;
1782 }
1783
David Blaikie2eabcc92016-02-09 18:52:09 +00001784 PragmaPackInfo *Info =
1785 PP.getPreprocessorAllocator().Allocate<PragmaPackInfo>(1);
Denis Zobnin10c4f452016-04-29 18:17:40 +00001786 Info->Action = Action;
1787 Info->SlotLabel = SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +00001788 Info->Alignment = Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +00001789
David Blaikie2eabcc92016-02-09 18:52:09 +00001790 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1791 1);
Eli Friedmanec52f922012-02-23 23:47:16 +00001792 Toks[0].startToken();
1793 Toks[0].setKind(tok::annot_pragma_pack);
1794 Toks[0].setLocation(PackLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001795 Toks[0].setAnnotationEndLoc(RParenLoc);
Eli Friedmanec52f922012-02-23 23:47:16 +00001796 Toks[0].setAnnotationValue(static_cast<void*>(Info));
Ilya Biryukov929af672019-05-17 09:32:05 +00001797 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
1798 /*IsReinject=*/false);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001799}
1800
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001801// #pragma ms_struct on
1802// #pragma ms_struct off
Fangrui Song6907ce22018-07-30 19:24:48 +00001803void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00001804 PragmaIntroducer Introducer,
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001805 Token &MSStructTok) {
Nico Weber779355f2016-03-02 23:22:00 +00001806 PragmaMSStructKind Kind = PMSST_OFF;
1807
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001808 Token Tok;
1809 PP.Lex(Tok);
1810 if (Tok.isNot(tok::identifier)) {
1811 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1812 return;
1813 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00001814 SourceLocation EndLoc = Tok.getLocation();
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001815 const IdentifierInfo *II = Tok.getIdentifierInfo();
1816 if (II->isStr("on")) {
Nico Weber779355f2016-03-02 23:22:00 +00001817 Kind = PMSST_ON;
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001818 PP.Lex(Tok);
1819 }
1820 else if (II->isStr("off") || II->isStr("reset"))
1821 PP.Lex(Tok);
1822 else {
1823 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1824 return;
1825 }
Fangrui Song6907ce22018-07-30 19:24:48 +00001826
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001827 if (Tok.isNot(tok::eod)) {
Daniel Dunbar340cf242012-02-29 01:38:22 +00001828 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1829 << "ms_struct";
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001830 return;
1831 }
Eli Friedman68be1642012-10-04 02:36:51 +00001832
David Blaikie2eabcc92016-02-09 18:52:09 +00001833 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1834 1);
Eli Friedman68be1642012-10-04 02:36:51 +00001835 Toks[0].startToken();
1836 Toks[0].setKind(tok::annot_pragma_msstruct);
1837 Toks[0].setLocation(MSStructTok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001838 Toks[0].setAnnotationEndLoc(EndLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001839 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1840 static_cast<uintptr_t>(Kind)));
Ilya Biryukov929af672019-05-17 09:32:05 +00001841 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
1842 /*IsReinject=*/false);
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001843}
1844
Dmitry Mikulinf14642f2019-10-15 18:31:10 +00001845// #pragma clang section bss="abc" data="" rodata="def" text="" relro=""
Javed Absar2a67c9e2017-06-05 10:11:57 +00001846void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00001847 PragmaIntroducer Introducer,
1848 Token &FirstToken) {
Javed Absar2a67c9e2017-06-05 10:11:57 +00001849
1850 Token Tok;
1851 auto SecKind = Sema::PragmaClangSectionKind::PCSK_Invalid;
1852
1853 PP.Lex(Tok); // eat 'section'
1854 while (Tok.isNot(tok::eod)) {
1855 if (Tok.isNot(tok::identifier)) {
1856 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
1857 return;
1858 }
1859
1860 const IdentifierInfo *SecType = Tok.getIdentifierInfo();
1861 if (SecType->isStr("bss"))
1862 SecKind = Sema::PragmaClangSectionKind::PCSK_BSS;
1863 else if (SecType->isStr("data"))
1864 SecKind = Sema::PragmaClangSectionKind::PCSK_Data;
1865 else if (SecType->isStr("rodata"))
1866 SecKind = Sema::PragmaClangSectionKind::PCSK_Rodata;
Dmitry Mikulinf14642f2019-10-15 18:31:10 +00001867 else if (SecType->isStr("relro"))
1868 SecKind = Sema::PragmaClangSectionKind::PCSK_Relro;
Javed Absar2a67c9e2017-06-05 10:11:57 +00001869 else if (SecType->isStr("text"))
1870 SecKind = Sema::PragmaClangSectionKind::PCSK_Text;
1871 else {
1872 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
1873 return;
1874 }
1875
Lucas Prates0dac6392020-04-16 13:55:18 +01001876 SourceLocation PragmaLocation = Tok.getLocation();
Javed Absar2a67c9e2017-06-05 10:11:57 +00001877 PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text']
1878 if (Tok.isNot(tok::equal)) {
1879 PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind;
1880 return;
1881 }
1882
1883 std::string SecName;
1884 if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false))
1885 return;
1886
Lucas Prates0dac6392020-04-16 13:55:18 +01001887 Actions.ActOnPragmaClangSection(
1888 PragmaLocation,
1889 (SecName.size() ? Sema::PragmaClangSectionAction::PCSA_Set
1890 : Sema::PragmaClangSectionAction::PCSA_Clear),
1891 SecKind, SecName);
Javed Absar2a67c9e2017-06-05 10:11:57 +00001892 }
1893}
1894
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001895// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
1896// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
Eli Friedman68be1642012-10-04 02:36:51 +00001897static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001898 bool IsOptions) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001899 Token Tok;
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001900
1901 if (IsOptions) {
1902 PP.Lex(Tok);
1903 if (Tok.isNot(tok::identifier) ||
1904 !Tok.getIdentifierInfo()->isStr("align")) {
1905 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
1906 return;
1907 }
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001908 }
Daniel Dunbar663e8092010-05-27 18:42:09 +00001909
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001910 PP.Lex(Tok);
1911 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001912 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
1913 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001914 return;
1915 }
1916
1917 PP.Lex(Tok);
1918 if (Tok.isNot(tok::identifier)) {
1919 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001920 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001921 return;
1922 }
1923
John McCallfaf5fb42010-08-26 23:41:50 +00001924 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001925 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar663e8092010-05-27 18:42:09 +00001926 if (II->isStr("native"))
John McCallfaf5fb42010-08-26 23:41:50 +00001927 Kind = Sema::POAK_Native;
Daniel Dunbar663e8092010-05-27 18:42:09 +00001928 else if (II->isStr("natural"))
John McCallfaf5fb42010-08-26 23:41:50 +00001929 Kind = Sema::POAK_Natural;
Daniel Dunbar9c84d4a2010-05-27 18:42:17 +00001930 else if (II->isStr("packed"))
John McCallfaf5fb42010-08-26 23:41:50 +00001931 Kind = Sema::POAK_Packed;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001932 else if (II->isStr("power"))
John McCallfaf5fb42010-08-26 23:41:50 +00001933 Kind = Sema::POAK_Power;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001934 else if (II->isStr("mac68k"))
John McCallfaf5fb42010-08-26 23:41:50 +00001935 Kind = Sema::POAK_Mac68k;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001936 else if (II->isStr("reset"))
John McCallfaf5fb42010-08-26 23:41:50 +00001937 Kind = Sema::POAK_Reset;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001938 else {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001939 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
1940 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001941 return;
1942 }
1943
David Majnemera8f2f1d2015-03-19 00:10:23 +00001944 SourceLocation EndLoc = Tok.getLocation();
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001945 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001946 if (Tok.isNot(tok::eod)) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001947 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001948 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001949 return;
1950 }
1951
David Blaikie2eabcc92016-02-09 18:52:09 +00001952 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1953 1);
Eli Friedman68be1642012-10-04 02:36:51 +00001954 Toks[0].startToken();
1955 Toks[0].setKind(tok::annot_pragma_align);
1956 Toks[0].setLocation(FirstTok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001957 Toks[0].setAnnotationEndLoc(EndLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001958 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1959 static_cast<uintptr_t>(Kind)));
Ilya Biryukov929af672019-05-17 09:32:05 +00001960 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
1961 /*IsReinject=*/false);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001962}
1963
Fangrui Song6907ce22018-07-30 19:24:48 +00001964void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00001965 PragmaIntroducer Introducer,
Douglas Gregorc7d65762010-09-09 22:45:38 +00001966 Token &AlignTok) {
Eli Friedman68be1642012-10-04 02:36:51 +00001967 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001968}
1969
Fangrui Song6907ce22018-07-30 19:24:48 +00001970void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00001971 PragmaIntroducer Introducer,
Douglas Gregorc7d65762010-09-09 22:45:38 +00001972 Token &OptionsTok) {
Eli Friedman68be1642012-10-04 02:36:51 +00001973 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001974}
1975
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001976// #pragma unused(identifier)
Fangrui Song6907ce22018-07-30 19:24:48 +00001977void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00001978 PragmaIntroducer Introducer,
Douglas Gregorc7d65762010-09-09 22:45:38 +00001979 Token &UnusedTok) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001980 // FIXME: Should we be expanding macros here? My guess is no.
1981 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump11289f42009-09-09 15:08:12 +00001982
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001983 // Lex the left '('.
1984 Token Tok;
1985 PP.Lex(Tok);
1986 if (Tok.isNot(tok::l_paren)) {
1987 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
1988 return;
1989 }
Mike Stump11289f42009-09-09 15:08:12 +00001990
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001991 // Lex the declaration reference(s).
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001992 SmallVector<Token, 5> Identifiers;
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001993 SourceLocation RParenLoc;
1994 bool LexID = true;
Mike Stump11289f42009-09-09 15:08:12 +00001995
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001996 while (true) {
1997 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001998
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001999 if (LexID) {
Mike Stump11289f42009-09-09 15:08:12 +00002000 if (Tok.is(tok::identifier)) {
Ted Kremenekfb50bf52009-08-03 23:24:57 +00002001 Identifiers.push_back(Tok);
Ted Kremenekfd14fad2009-03-23 22:28:25 +00002002 LexID = false;
2003 continue;
2004 }
2005
Ted Kremenekfb50bf52009-08-03 23:24:57 +00002006 // Illegal token!
Ted Kremenekfd14fad2009-03-23 22:28:25 +00002007 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
2008 return;
2009 }
Mike Stump11289f42009-09-09 15:08:12 +00002010
Ted Kremenekfd14fad2009-03-23 22:28:25 +00002011 // We are execting a ')' or a ','.
2012 if (Tok.is(tok::comma)) {
2013 LexID = true;
2014 continue;
2015 }
Mike Stump11289f42009-09-09 15:08:12 +00002016
Ted Kremenekfd14fad2009-03-23 22:28:25 +00002017 if (Tok.is(tok::r_paren)) {
2018 RParenLoc = Tok.getLocation();
2019 break;
2020 }
Mike Stump11289f42009-09-09 15:08:12 +00002021
Ted Kremenekfb50bf52009-08-03 23:24:57 +00002022 // Illegal token!
David Majnemer88969812014-02-10 19:06:37 +00002023 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
Ted Kremenekfd14fad2009-03-23 22:28:25 +00002024 return;
2025 }
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002026
2027 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00002028 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002029 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2030 "unused";
2031 return;
2032 }
2033
Ted Kremenekfd14fad2009-03-23 22:28:25 +00002034 // Verify that we have a location for the right parenthesis.
2035 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenekfb50bf52009-08-03 23:24:57 +00002036 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenekfd14fad2009-03-23 22:28:25 +00002037
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +00002038 // For each identifier token, insert into the token stream a
2039 // annot_pragma_unused token followed by the identifier token.
2040 // This allows us to cache a "#pragma unused" that occurs inside an inline
2041 // C++ member function.
2042
David Blaikie2eabcc92016-02-09 18:52:09 +00002043 MutableArrayRef<Token> Toks(
2044 PP.getPreprocessorAllocator().Allocate<Token>(2 * Identifiers.size()),
2045 2 * Identifiers.size());
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +00002046 for (unsigned i=0; i != Identifiers.size(); i++) {
2047 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
2048 pragmaUnusedTok.startToken();
2049 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
2050 pragmaUnusedTok.setLocation(UnusedLoc);
2051 idTok = Identifiers[i];
2052 }
Ilya Biryukov929af672019-05-17 09:32:05 +00002053 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2054 /*IsReinject=*/false);
Ted Kremenekfd14fad2009-03-23 22:28:25 +00002055}
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002056
2057// #pragma weak identifier
2058// #pragma weak identifier '=' identifier
Fangrui Song6907ce22018-07-30 19:24:48 +00002059void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002060 PragmaIntroducer Introducer,
Douglas Gregorc7d65762010-09-09 22:45:38 +00002061 Token &WeakTok) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002062 SourceLocation WeakLoc = WeakTok.getLocation();
2063
2064 Token Tok;
2065 PP.Lex(Tok);
2066 if (Tok.isNot(tok::identifier)) {
2067 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
2068 return;
2069 }
2070
Eli Friedman68be1642012-10-04 02:36:51 +00002071 Token WeakName = Tok;
2072 bool HasAlias = false;
2073 Token AliasName;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002074
2075 PP.Lex(Tok);
2076 if (Tok.is(tok::equal)) {
Eli Friedman68be1642012-10-04 02:36:51 +00002077 HasAlias = true;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002078 PP.Lex(Tok);
2079 if (Tok.isNot(tok::identifier)) {
Mike Stump11289f42009-09-09 15:08:12 +00002080 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002081 << "weak";
2082 return;
2083 }
Eli Friedman68be1642012-10-04 02:36:51 +00002084 AliasName = Tok;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002085 PP.Lex(Tok);
2086 }
2087
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00002088 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002089 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
2090 return;
2091 }
2092
Eli Friedman68be1642012-10-04 02:36:51 +00002093 if (HasAlias) {
David Blaikie2eabcc92016-02-09 18:52:09 +00002094 MutableArrayRef<Token> Toks(
2095 PP.getPreprocessorAllocator().Allocate<Token>(3), 3);
Eli Friedman68be1642012-10-04 02:36:51 +00002096 Token &pragmaUnusedTok = Toks[0];
2097 pragmaUnusedTok.startToken();
2098 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
2099 pragmaUnusedTok.setLocation(WeakLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002100 pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00002101 Toks[1] = WeakName;
2102 Toks[2] = AliasName;
Ilya Biryukov929af672019-05-17 09:32:05 +00002103 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2104 /*IsReinject=*/false);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002105 } else {
David Blaikie2eabcc92016-02-09 18:52:09 +00002106 MutableArrayRef<Token> Toks(
2107 PP.getPreprocessorAllocator().Allocate<Token>(2), 2);
Eli Friedman68be1642012-10-04 02:36:51 +00002108 Token &pragmaUnusedTok = Toks[0];
2109 pragmaUnusedTok.startToken();
2110 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
2111 pragmaUnusedTok.setLocation(WeakLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002112 pragmaUnusedTok.setAnnotationEndLoc(WeakLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00002113 Toks[1] = WeakName;
Ilya Biryukov929af672019-05-17 09:32:05 +00002114 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2115 /*IsReinject=*/false);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002116 }
2117}
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00002118
David Chisnall0867d9c2012-02-18 16:12:34 +00002119// #pragma redefine_extname identifier identifier
Fangrui Song6907ce22018-07-30 19:24:48 +00002120void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002121 PragmaIntroducer Introducer,
David Chisnall0867d9c2012-02-18 16:12:34 +00002122 Token &RedefToken) {
2123 SourceLocation RedefLoc = RedefToken.getLocation();
2124
2125 Token Tok;
2126 PP.Lex(Tok);
2127 if (Tok.isNot(tok::identifier)) {
2128 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
2129 "redefine_extname";
2130 return;
2131 }
2132
Eli Friedman68be1642012-10-04 02:36:51 +00002133 Token RedefName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00002134 PP.Lex(Tok);
Eli Friedman68be1642012-10-04 02:36:51 +00002135
David Chisnall0867d9c2012-02-18 16:12:34 +00002136 if (Tok.isNot(tok::identifier)) {
2137 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2138 << "redefine_extname";
2139 return;
2140 }
Eli Friedman68be1642012-10-04 02:36:51 +00002141
2142 Token AliasName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00002143 PP.Lex(Tok);
2144
2145 if (Tok.isNot(tok::eod)) {
2146 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2147 "redefine_extname";
2148 return;
2149 }
2150
David Blaikie2eabcc92016-02-09 18:52:09 +00002151 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(3),
2152 3);
Eli Friedman68be1642012-10-04 02:36:51 +00002153 Token &pragmaRedefTok = Toks[0];
2154 pragmaRedefTok.startToken();
2155 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
2156 pragmaRedefTok.setLocation(RedefLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002157 pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00002158 Toks[1] = RedefName;
2159 Toks[2] = AliasName;
Ilya Biryukov929af672019-05-17 09:32:05 +00002160 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2161 /*IsReinject=*/false);
David Chisnall0867d9c2012-02-18 16:12:34 +00002162}
2163
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002164void PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
2165 PragmaIntroducer Introducer,
2166 Token &Tok) {
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00002167 tok::OnOffSwitch OOS;
2168 if (PP.LexOnOffSwitch(OOS))
2169 return;
2170
David Blaikie2eabcc92016-02-09 18:52:09 +00002171 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2172 1);
Eli Friedman68be1642012-10-04 02:36:51 +00002173 Toks[0].startToken();
2174 Toks[0].setKind(tok::annot_pragma_fp_contract);
2175 Toks[0].setLocation(Tok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002176 Toks[0].setAnnotationEndLoc(Tok.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00002177 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
2178 static_cast<uintptr_t>(OOS)));
Ilya Biryukov929af672019-05-17 09:32:05 +00002179 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2180 /*IsReinject=*/false);
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00002181}
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002182
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002183void PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
2184 PragmaIntroducer Introducer,
2185 Token &Tok) {
Tanya Lattneree840b82011-04-14 23:35:31 +00002186 PP.LexUnexpandedToken(Tok);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002187 if (Tok.isNot(tok::identifier)) {
2188 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
2189 "OPENCL";
2190 return;
2191 }
Yaxun Liu5b746652016-12-18 05:18:55 +00002192 IdentifierInfo *Ext = Tok.getIdentifierInfo();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002193 SourceLocation NameLoc = Tok.getLocation();
2194
2195 PP.Lex(Tok);
2196 if (Tok.isNot(tok::colon)) {
Yaxun Liu5b746652016-12-18 05:18:55 +00002197 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext;
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002198 return;
2199 }
2200
2201 PP.Lex(Tok);
2202 if (Tok.isNot(tok::identifier)) {
Yaxun Liu5b746652016-12-18 05:18:55 +00002203 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0;
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002204 return;
2205 }
Yaxun Liu5b746652016-12-18 05:18:55 +00002206 IdentifierInfo *Pred = Tok.getIdentifierInfo();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002207
Yaxun Liu5b746652016-12-18 05:18:55 +00002208 OpenCLExtState State;
2209 if (Pred->isStr("enable")) {
2210 State = Enable;
2211 } else if (Pred->isStr("disable")) {
2212 State = Disable;
2213 } else if (Pred->isStr("begin"))
2214 State = Begin;
2215 else if (Pred->isStr("end"))
2216 State = End;
2217 else {
2218 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate)
2219 << Ext->isStr("all");
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002220 return;
2221 }
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00002222 SourceLocation StateLoc = Tok.getLocation();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002223
Eli Friedman68be1642012-10-04 02:36:51 +00002224 PP.Lex(Tok);
2225 if (Tok.isNot(tok::eod)) {
2226 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2227 "OPENCL EXTENSION";
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002228 return;
2229 }
Eli Friedman68be1642012-10-04 02:36:51 +00002230
Yaxun Liu5b746652016-12-18 05:18:55 +00002231 auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1);
2232 Info->first = Ext;
2233 Info->second = State;
David Blaikie2eabcc92016-02-09 18:52:09 +00002234 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2235 1);
Eli Friedman68be1642012-10-04 02:36:51 +00002236 Toks[0].startToken();
2237 Toks[0].setKind(tok::annot_pragma_opencl_extension);
2238 Toks[0].setLocation(NameLoc);
Yaxun Liu5b746652016-12-18 05:18:55 +00002239 Toks[0].setAnnotationValue(static_cast<void*>(Info));
David Majnemera8f2f1d2015-03-19 00:10:23 +00002240 Toks[0].setAnnotationEndLoc(StateLoc);
Ilya Biryukov929af672019-05-17 09:32:05 +00002241 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2242 /*IsReinject=*/false);
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00002243
2244 if (PP.getPPCallbacks())
Fangrui Song6907ce22018-07-30 19:24:48 +00002245 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext,
Yaxun Liu5b746652016-12-18 05:18:55 +00002246 StateLoc, State);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002247}
2248
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002249/// Handle '#pragma omp ...' when OpenMP is disabled.
Alexey Bataeva769e072013-03-22 06:34:35 +00002250///
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002251void PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
2252 PragmaIntroducer Introducer,
2253 Token &FirstTok) {
Alp Tokerd4a3f0e2014-06-15 23:30:39 +00002254 if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
2255 FirstTok.getLocation())) {
Alexey Bataeva769e072013-03-22 06:34:35 +00002256 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
Alp Tokerd576e002014-06-12 11:13:52 +00002257 PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
2258 diag::Severity::Ignored, SourceLocation());
Alexey Bataeva769e072013-03-22 06:34:35 +00002259 }
2260 PP.DiscardUntilEndOfDirective();
2261}
2262
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002263/// Handle '#pragma omp ...' when OpenMP is enabled.
Alexey Bataeva769e072013-03-22 06:34:35 +00002264///
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002265void PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
2266 PragmaIntroducer Introducer,
2267 Token &FirstTok) {
Alexey Bataeva769e072013-03-22 06:34:35 +00002268 SmallVector<Token, 16> Pragma;
2269 Token Tok;
2270 Tok.startToken();
2271 Tok.setKind(tok::annot_pragma_openmp);
Joel E. Denny91f80662019-05-28 19:27:19 +00002272 Tok.setLocation(Introducer.Loc);
Alexey Bataeva769e072013-03-22 06:34:35 +00002273
Alexey Bataev96dae812018-02-16 18:36:44 +00002274 while (Tok.isNot(tok::eod) && Tok.isNot(tok::eof)) {
Alexey Bataeva769e072013-03-22 06:34:35 +00002275 Pragma.push_back(Tok);
2276 PP.Lex(Tok);
Alexey Bataev96dae812018-02-16 18:36:44 +00002277 if (Tok.is(tok::annot_pragma_openmp)) {
2278 PP.Diag(Tok, diag::err_omp_unexpected_directive) << 0;
2279 unsigned InnerPragmaCnt = 1;
2280 while (InnerPragmaCnt != 0) {
2281 PP.Lex(Tok);
2282 if (Tok.is(tok::annot_pragma_openmp))
2283 ++InnerPragmaCnt;
2284 else if (Tok.is(tok::annot_pragma_openmp_end))
2285 --InnerPragmaCnt;
2286 }
2287 PP.Lex(Tok);
2288 }
Alexey Bataeva769e072013-03-22 06:34:35 +00002289 }
2290 SourceLocation EodLoc = Tok.getLocation();
2291 Tok.startToken();
2292 Tok.setKind(tok::annot_pragma_openmp_end);
2293 Tok.setLocation(EodLoc);
2294 Pragma.push_back(Tok);
2295
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +00002296 auto Toks = std::make_unique<Token[]>(Pragma.size());
David Blaikie2eabcc92016-02-09 18:52:09 +00002297 std::copy(Pragma.begin(), Pragma.end(), Toks.get());
2298 PP.EnterTokenStream(std::move(Toks), Pragma.size(),
Ilya Biryukov929af672019-05-17 09:32:05 +00002299 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
Alexey Bataeva769e072013-03-22 06:34:35 +00002300}
Reid Kleckner002562a2013-05-06 21:02:12 +00002301
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002302/// Handle '#pragma pointers_to_members'
David Majnemer4bb09802014-02-10 19:50:15 +00002303// The grammar for this pragma is as follows:
2304//
2305// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
2306//
2307// #pragma pointers_to_members '(' 'best_case' ')'
2308// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
2309// #pragma pointers_to_members '(' inheritance-model ')'
2310void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002311 PragmaIntroducer Introducer,
David Majnemer4bb09802014-02-10 19:50:15 +00002312 Token &Tok) {
2313 SourceLocation PointersToMembersLoc = Tok.getLocation();
2314 PP.Lex(Tok);
2315 if (Tok.isNot(tok::l_paren)) {
2316 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
2317 << "pointers_to_members";
2318 return;
2319 }
2320 PP.Lex(Tok);
2321 const IdentifierInfo *Arg = Tok.getIdentifierInfo();
2322 if (!Arg) {
2323 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2324 << "pointers_to_members";
2325 return;
2326 }
2327 PP.Lex(Tok);
2328
David Majnemer86c318f2014-02-11 21:05:00 +00002329 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
David Majnemer4bb09802014-02-10 19:50:15 +00002330 if (Arg->isStr("best_case")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002331 RepresentationMethod = LangOptions::PPTMK_BestCase;
David Majnemer4bb09802014-02-10 19:50:15 +00002332 } else {
2333 if (Arg->isStr("full_generality")) {
2334 if (Tok.is(tok::comma)) {
2335 PP.Lex(Tok);
2336
2337 Arg = Tok.getIdentifierInfo();
2338 if (!Arg) {
2339 PP.Diag(Tok.getLocation(),
2340 diag::err_pragma_pointers_to_members_unknown_kind)
2341 << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
2342 return;
2343 }
2344 PP.Lex(Tok);
2345 } else if (Tok.is(tok::r_paren)) {
2346 // #pragma pointers_to_members(full_generality) implicitly specifies
2347 // virtual_inheritance.
Craig Topper161e4db2014-05-21 06:02:52 +00002348 Arg = nullptr;
David Majnemer86c318f2014-02-11 21:05:00 +00002349 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002350 } else {
2351 PP.Diag(Tok.getLocation(), diag::err_expected_punc)
2352 << "full_generality";
2353 return;
2354 }
2355 }
2356
2357 if (Arg) {
2358 if (Arg->isStr("single_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002359 RepresentationMethod =
2360 LangOptions::PPTMK_FullGeneralitySingleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002361 } else if (Arg->isStr("multiple_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002362 RepresentationMethod =
2363 LangOptions::PPTMK_FullGeneralityMultipleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002364 } else if (Arg->isStr("virtual_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002365 RepresentationMethod =
2366 LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002367 } else {
2368 PP.Diag(Tok.getLocation(),
2369 diag::err_pragma_pointers_to_members_unknown_kind)
2370 << Arg << /*HasPointerDeclaration*/ 1;
2371 return;
2372 }
2373 }
2374 }
2375
2376 if (Tok.isNot(tok::r_paren)) {
2377 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
2378 << (Arg ? Arg->getName() : "full_generality");
2379 return;
2380 }
2381
David Majnemera8f2f1d2015-03-19 00:10:23 +00002382 SourceLocation EndLoc = Tok.getLocation();
David Majnemer4bb09802014-02-10 19:50:15 +00002383 PP.Lex(Tok);
2384 if (Tok.isNot(tok::eod)) {
2385 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2386 << "pointers_to_members";
2387 return;
2388 }
2389
2390 Token AnnotTok;
2391 AnnotTok.startToken();
2392 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
2393 AnnotTok.setLocation(PointersToMembersLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002394 AnnotTok.setAnnotationEndLoc(EndLoc);
David Majnemer4bb09802014-02-10 19:50:15 +00002395 AnnotTok.setAnnotationValue(
2396 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
Ilya Biryukov929af672019-05-17 09:32:05 +00002397 PP.EnterToken(AnnotTok, /*IsReinject=*/true);
David Majnemer4bb09802014-02-10 19:50:15 +00002398}
2399
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002400/// Handle '#pragma vtordisp'
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002401// The grammar for this pragma is as follows:
2402//
2403// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
2404//
2405// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
2406// #pragma vtordisp '(' 'pop' ')'
2407// #pragma vtordisp '(' ')'
2408void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002409 PragmaIntroducer Introducer, Token &Tok) {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002410 SourceLocation VtorDispLoc = Tok.getLocation();
2411 PP.Lex(Tok);
2412 if (Tok.isNot(tok::l_paren)) {
2413 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
2414 return;
2415 }
2416 PP.Lex(Tok);
2417
Denis Zobnin2290dac2016-04-29 11:27:00 +00002418 Sema::PragmaMsStackAction Action = Sema::PSK_Set;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002419 const IdentifierInfo *II = Tok.getIdentifierInfo();
2420 if (II) {
2421 if (II->isStr("push")) {
2422 // #pragma vtordisp(push, mode)
2423 PP.Lex(Tok);
2424 if (Tok.isNot(tok::comma)) {
2425 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
2426 return;
2427 }
2428 PP.Lex(Tok);
Denis Zobnin2290dac2016-04-29 11:27:00 +00002429 Action = Sema::PSK_Push_Set;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002430 // not push, could be on/off
2431 } else if (II->isStr("pop")) {
2432 // #pragma vtordisp(pop)
2433 PP.Lex(Tok);
Denis Zobnin2290dac2016-04-29 11:27:00 +00002434 Action = Sema::PSK_Pop;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002435 }
2436 // not push or pop, could be on/off
2437 } else {
2438 if (Tok.is(tok::r_paren)) {
2439 // #pragma vtordisp()
Denis Zobnin2290dac2016-04-29 11:27:00 +00002440 Action = Sema::PSK_Reset;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002441 }
2442 }
2443
2444
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00002445 uint64_t Value = 0;
Denis Zobnin2290dac2016-04-29 11:27:00 +00002446 if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002447 const IdentifierInfo *II = Tok.getIdentifierInfo();
2448 if (II && II->isStr("off")) {
2449 PP.Lex(Tok);
2450 Value = 0;
2451 } else if (II && II->isStr("on")) {
2452 PP.Lex(Tok);
2453 Value = 1;
2454 } else if (Tok.is(tok::numeric_constant) &&
2455 PP.parseSimpleIntegerLiteral(Tok, Value)) {
2456 if (Value > 2) {
2457 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
2458 << 0 << 2 << "vtordisp";
2459 return;
2460 }
2461 } else {
2462 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
2463 << "vtordisp";
2464 return;
2465 }
2466 }
2467
2468 // Finish the pragma: ')' $
2469 if (Tok.isNot(tok::r_paren)) {
2470 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
2471 return;
2472 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00002473 SourceLocation EndLoc = Tok.getLocation();
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002474 PP.Lex(Tok);
2475 if (Tok.isNot(tok::eod)) {
2476 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2477 << "vtordisp";
2478 return;
2479 }
2480
2481 // Enter the annotation.
2482 Token AnnotTok;
2483 AnnotTok.startToken();
2484 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
2485 AnnotTok.setLocation(VtorDispLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002486 AnnotTok.setAnnotationEndLoc(EndLoc);
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00002487 AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
Denis Zobnin2290dac2016-04-29 11:27:00 +00002488 static_cast<uintptr_t>((Action << 16) | (Value & 0xFFFF))));
Ilya Biryukov929af672019-05-17 09:32:05 +00002489 PP.EnterToken(AnnotTok, /*IsReinject=*/false);
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002490}
2491
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002492/// Handle all MS pragmas. Simply forwards the tokens after inserting
Warren Huntc3b18962014-04-08 22:30:47 +00002493/// an annotation token.
2494void PragmaMSPragma::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002495 PragmaIntroducer Introducer, Token &Tok) {
Warren Huntc3b18962014-04-08 22:30:47 +00002496 Token EoF, AnnotTok;
2497 EoF.startToken();
2498 EoF.setKind(tok::eof);
2499 AnnotTok.startToken();
2500 AnnotTok.setKind(tok::annot_pragma_ms_pragma);
2501 AnnotTok.setLocation(Tok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002502 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
Warren Huntc3b18962014-04-08 22:30:47 +00002503 SmallVector<Token, 8> TokenVector;
2504 // Suck up all of the tokens before the eod.
David Majnemera8f2f1d2015-03-19 00:10:23 +00002505 for (; Tok.isNot(tok::eod); PP.Lex(Tok)) {
Warren Huntc3b18962014-04-08 22:30:47 +00002506 TokenVector.push_back(Tok);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002507 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
2508 }
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00002509 // Add a sentinel EoF token to the end of the list.
Warren Huntc3b18962014-04-08 22:30:47 +00002510 TokenVector.push_back(EoF);
2511 // We must allocate this array with new because EnterTokenStream is going to
2512 // delete it later.
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +00002513 auto TokenArray = std::make_unique<Token[]>(TokenVector.size());
David Blaikie2eabcc92016-02-09 18:52:09 +00002514 std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get());
Warren Huntc3b18962014-04-08 22:30:47 +00002515 auto Value = new (PP.getPreprocessorAllocator())
David Blaikie2eabcc92016-02-09 18:52:09 +00002516 std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray),
2517 TokenVector.size());
Warren Huntc3b18962014-04-08 22:30:47 +00002518 AnnotTok.setAnnotationValue(Value);
Ilya Biryukov929af672019-05-17 09:32:05 +00002519 PP.EnterToken(AnnotTok, /*IsReinject*/ false);
Reid Klecknerd3923aa2014-04-03 19:04:24 +00002520}
2521
Melanie Blowerf5360d42020-05-01 10:32:06 -07002522/// Handle the \#pragma float_control extension.
2523///
2524/// The syntax is:
2525/// \code
2526/// #pragma float_control(keyword[, setting] [,push])
2527/// \endcode
2528/// Where 'keyword' and 'setting' are identifiers.
2529// 'keyword' can be: precise, except, push, pop
2530// 'setting' can be: on, off
2531/// The optional arguments 'setting' and 'push' are supported only
2532/// when the keyword is 'precise' or 'except'.
2533void PragmaFloatControlHandler::HandlePragma(Preprocessor &PP,
2534 PragmaIntroducer Introducer,
2535 Token &Tok) {
2536 Sema::PragmaMsStackAction Action = Sema::PSK_Set;
2537 SourceLocation FloatControlLoc = Tok.getLocation();
2538 PP.Lex(Tok);
2539 if (Tok.isNot(tok::l_paren)) {
2540 PP.Diag(FloatControlLoc, diag::err_expected) << tok::l_paren;
2541 return;
2542 }
2543
2544 // Read the identifier.
2545 PP.Lex(Tok);
2546 if (Tok.isNot(tok::identifier)) {
2547 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2548 return;
2549 }
2550
2551 // Verify that this is one of the float control options.
2552 IdentifierInfo *II = Tok.getIdentifierInfo();
2553 PragmaFloatControlKind Kind =
2554 llvm::StringSwitch<PragmaFloatControlKind>(II->getName())
2555 .Case("precise", PFC_Precise)
2556 .Case("except", PFC_Except)
2557 .Case("push", PFC_Push)
2558 .Case("pop", PFC_Pop)
2559 .Default(PFC_Unknown);
2560 PP.Lex(Tok); // the identifier
2561 if (Kind == PFC_Unknown) {
2562 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2563 return;
2564 } else if (Kind == PFC_Push || Kind == PFC_Pop) {
2565 if (Tok.isNot(tok::r_paren)) {
2566 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2567 return;
2568 }
2569 PP.Lex(Tok); // Eat the r_paren
2570 Action = (Kind == PFC_Pop) ? Sema::PSK_Pop : Sema::PSK_Push;
2571 } else {
2572 if (Tok.is(tok::r_paren))
2573 // Selecting Precise or Except
2574 PP.Lex(Tok); // the r_paren
2575 else if (Tok.isNot(tok::comma)) {
2576 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2577 return;
2578 } else {
2579 PP.Lex(Tok); // ,
2580 if (!Tok.isAnyIdentifier()) {
2581 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2582 return;
2583 }
2584 StringRef PushOnOff = Tok.getIdentifierInfo()->getName();
2585 if (PushOnOff == "on")
2586 // Kind is set correctly
2587 ;
2588 else if (PushOnOff == "off") {
2589 if (Kind == PFC_Precise)
2590 Kind = PFC_NoPrecise;
2591 if (Kind == PFC_Except)
2592 Kind = PFC_NoExcept;
2593 } else if (PushOnOff == "push") {
2594 Action = Sema::PSK_Push_Set;
2595 } else {
2596 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2597 return;
2598 }
2599 PP.Lex(Tok); // the identifier
2600 if (Tok.is(tok::comma)) {
2601 PP.Lex(Tok); // ,
2602 if (!Tok.isAnyIdentifier()) {
2603 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2604 return;
2605 }
2606 StringRef ExpectedPush = Tok.getIdentifierInfo()->getName();
2607 if (ExpectedPush == "push") {
2608 Action = Sema::PSK_Push_Set;
2609 } else {
2610 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2611 return;
2612 }
2613 PP.Lex(Tok); // the push identifier
2614 }
2615 if (Tok.isNot(tok::r_paren)) {
2616 PP.Diag(Tok.getLocation(), diag::err_pragma_float_control_malformed);
2617 return;
2618 }
2619 PP.Lex(Tok); // the r_paren
2620 }
2621 }
2622 SourceLocation EndLoc = Tok.getLocation();
2623 if (Tok.isNot(tok::eod)) {
2624 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2625 << "float_control";
2626 return;
2627 }
2628
2629 // Note: there is no accomodation for PP callback for this pragma.
2630
2631 // Enter the annotation.
2632 auto TokenArray = std::make_unique<Token[]>(1);
2633 TokenArray[0].startToken();
2634 TokenArray[0].setKind(tok::annot_pragma_float_control);
2635 TokenArray[0].setLocation(FloatControlLoc);
2636 TokenArray[0].setAnnotationEndLoc(EndLoc);
2637 // Create an encoding of Action and Value by shifting the Action into
2638 // the high 16 bits then union with the Kind.
2639 TokenArray[0].setAnnotationValue(reinterpret_cast<void *>(
2640 static_cast<uintptr_t>((Action << 16) | (Kind & 0xFFFF))));
2641 PP.EnterTokenStream(std::move(TokenArray), 1,
2642 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
2643}
2644
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002645/// Handle the Microsoft \#pragma detect_mismatch extension.
Aaron Ballman5d041be2013-06-04 02:07:14 +00002646///
2647/// The syntax is:
2648/// \code
2649/// #pragma detect_mismatch("name", "value")
2650/// \endcode
2651/// Where 'name' and 'value' are quoted strings. The values are embedded in
2652/// the object file and passed along to the linker. If the linker detects a
2653/// mismatch in the object file's values for the given name, a LNK2038 error
2654/// is emitted. See MSDN for more details.
2655void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002656 PragmaIntroducer Introducer,
Aaron Ballman5d041be2013-06-04 02:07:14 +00002657 Token &Tok) {
Nico Webercbbaeb12016-03-02 19:28:54 +00002658 SourceLocation DetectMismatchLoc = Tok.getLocation();
Aaron Ballman5d041be2013-06-04 02:07:14 +00002659 PP.Lex(Tok);
2660 if (Tok.isNot(tok::l_paren)) {
Nico Webercbbaeb12016-03-02 19:28:54 +00002661 PP.Diag(DetectMismatchLoc, diag::err_expected) << tok::l_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00002662 return;
2663 }
2664
2665 // Read the name to embed, which must be a string literal.
2666 std::string NameString;
2667 if (!PP.LexStringLiteral(Tok, NameString,
2668 "pragma detect_mismatch",
Rui Ueyama49a3ad22019-07-16 04:46:31 +00002669 /*AllowMacroExpansion=*/true))
Aaron Ballman5d041be2013-06-04 02:07:14 +00002670 return;
2671
2672 // Read the comma followed by a second string literal.
2673 std::string ValueString;
2674 if (Tok.isNot(tok::comma)) {
2675 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
2676 return;
2677 }
2678
2679 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
Rui Ueyama49a3ad22019-07-16 04:46:31 +00002680 /*AllowMacroExpansion=*/true))
Aaron Ballman5d041be2013-06-04 02:07:14 +00002681 return;
2682
2683 if (Tok.isNot(tok::r_paren)) {
Alp Tokerec543272013-12-24 09:48:30 +00002684 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00002685 return;
2686 }
2687 PP.Lex(Tok); // Eat the r_paren.
2688
2689 if (Tok.isNot(tok::eod)) {
2690 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
2691 return;
2692 }
2693
Reid Kleckner71966c92014-02-20 23:37:45 +00002694 // If the pragma is lexically sound, notify any interested PPCallbacks.
2695 if (PP.getPPCallbacks())
Nico Webercbbaeb12016-03-02 19:28:54 +00002696 PP.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc, NameString,
Reid Kleckner71966c92014-02-20 23:37:45 +00002697 ValueString);
2698
Nico Webercbbaeb12016-03-02 19:28:54 +00002699 Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString);
Aaron Ballman5d041be2013-06-04 02:07:14 +00002700}
2701
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002702/// Handle the microsoft \#pragma comment extension.
Reid Kleckner002562a2013-05-06 21:02:12 +00002703///
2704/// The syntax is:
2705/// \code
2706/// #pragma comment(linker, "foo")
2707/// \endcode
2708/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
2709/// "foo" is a string, which is fully macro expanded, and permits string
2710/// concatenation, embedded escape characters etc. See MSDN for more details.
2711void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002712 PragmaIntroducer Introducer,
Reid Kleckner002562a2013-05-06 21:02:12 +00002713 Token &Tok) {
2714 SourceLocation CommentLoc = Tok.getLocation();
2715 PP.Lex(Tok);
2716 if (Tok.isNot(tok::l_paren)) {
2717 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
2718 return;
2719 }
2720
2721 // Read the identifier.
2722 PP.Lex(Tok);
2723 if (Tok.isNot(tok::identifier)) {
2724 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
2725 return;
2726 }
2727
Eric Christopher1f593f42020-06-20 01:14:57 -07002728 // Verify that this is one of the 5 explicitly listed options.
Reid Klecknere43f0fe2013-05-08 13:44:39 +00002729 IdentifierInfo *II = Tok.getIdentifierInfo();
Nico Weber66220292016-03-02 17:28:48 +00002730 PragmaMSCommentKind Kind =
2731 llvm::StringSwitch<PragmaMSCommentKind>(II->getName())
2732 .Case("linker", PCK_Linker)
2733 .Case("lib", PCK_Lib)
2734 .Case("compiler", PCK_Compiler)
2735 .Case("exestr", PCK_ExeStr)
2736 .Case("user", PCK_User)
2737 .Default(PCK_Unknown);
2738 if (Kind == PCK_Unknown) {
Reid Kleckner002562a2013-05-06 21:02:12 +00002739 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
2740 return;
2741 }
2742
Saleem Abdulrasoolfd4db532018-02-07 01:46:46 +00002743 if (PP.getTargetInfo().getTriple().isOSBinFormatELF() && Kind != PCK_Lib) {
2744 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
2745 << II->getName();
2746 return;
2747 }
2748
Yunzhong Gao99efc032015-03-23 20:41:42 +00002749 // On PS4, issue a warning about any pragma comments other than
2750 // #pragma comment lib.
Nico Weber66220292016-03-02 17:28:48 +00002751 if (PP.getTargetInfo().getTriple().isPS4() && Kind != PCK_Lib) {
Yunzhong Gao99efc032015-03-23 20:41:42 +00002752 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
2753 << II->getName();
2754 return;
2755 }
2756
Reid Kleckner002562a2013-05-06 21:02:12 +00002757 // Read the optional string if present.
2758 PP.Lex(Tok);
2759 std::string ArgumentString;
2760 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
2761 "pragma comment",
Rui Ueyama49a3ad22019-07-16 04:46:31 +00002762 /*AllowMacroExpansion=*/true))
Reid Kleckner002562a2013-05-06 21:02:12 +00002763 return;
2764
Reid Klecknere43f0fe2013-05-08 13:44:39 +00002765 // FIXME: warn that 'exestr' is deprecated.
Reid Kleckner002562a2013-05-06 21:02:12 +00002766 // FIXME: If the kind is "compiler" warn if the string is present (it is
2767 // ignored).
Reid Klecknere43f0fe2013-05-08 13:44:39 +00002768 // The MSDN docs say that "lib" and "linker" require a string and have a short
Eric Christopher1f593f42020-06-20 01:14:57 -07002769 // list of linker options they support, but in practice MSVC doesn't
Reid Klecknere43f0fe2013-05-08 13:44:39 +00002770 // issue a diagnostic. Therefore neither does clang.
Reid Kleckner002562a2013-05-06 21:02:12 +00002771
2772 if (Tok.isNot(tok::r_paren)) {
2773 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
2774 return;
2775 }
2776 PP.Lex(Tok); // eat the r_paren.
2777
2778 if (Tok.isNot(tok::eod)) {
2779 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
2780 return;
2781 }
2782
Reid Kleckner71966c92014-02-20 23:37:45 +00002783 // If the pragma is lexically sound, notify any interested PPCallbacks.
2784 if (PP.getPPCallbacks())
2785 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
2786
Nico Weber66220292016-03-02 17:28:48 +00002787 Actions.ActOnPragmaMSComment(CommentLoc, Kind, ArgumentString);
Reid Kleckner002562a2013-05-06 21:02:12 +00002788}
Dario Domizioli13a0a382014-05-23 12:13:25 +00002789
2790// #pragma clang optimize off
2791// #pragma clang optimize on
Fangrui Song6907ce22018-07-30 19:24:48 +00002792void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002793 PragmaIntroducer Introducer,
2794 Token &FirstToken) {
Dario Domizioli13a0a382014-05-23 12:13:25 +00002795 Token Tok;
2796 PP.Lex(Tok);
2797 if (Tok.is(tok::eod)) {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002798 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
Mark Heffernan450c2382014-07-23 17:31:31 +00002799 << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
Dario Domizioli13a0a382014-05-23 12:13:25 +00002800 return;
2801 }
2802 if (Tok.isNot(tok::identifier)) {
2803 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
2804 << PP.getSpelling(Tok);
2805 return;
2806 }
2807 const IdentifierInfo *II = Tok.getIdentifierInfo();
2808 // The only accepted values are 'on' or 'off'.
2809 bool IsOn = false;
2810 if (II->isStr("on")) {
2811 IsOn = true;
2812 } else if (!II->isStr("off")) {
2813 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
2814 << PP.getSpelling(Tok);
2815 return;
2816 }
2817 PP.Lex(Tok);
Fangrui Song6907ce22018-07-30 19:24:48 +00002818
Dario Domizioli13a0a382014-05-23 12:13:25 +00002819 if (Tok.isNot(tok::eod)) {
2820 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
2821 << PP.getSpelling(Tok);
2822 return;
2823 }
Eli Bendersky06a40422014-06-06 20:31:48 +00002824
2825 Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
2826}
2827
Adam Nemet60d32642017-04-04 21:18:36 +00002828namespace {
2829/// Used as the annotation value for tok::annot_pragma_fp.
2830struct TokFPAnnotValue {
Melanie Blowerc355bec2020-05-04 10:48:12 -07002831 enum FlagKinds { Contract, Reassociate };
Adam Nemet60d32642017-04-04 21:18:36 +00002832 enum FlagValues { On, Off, Fast };
2833
2834 FlagKinds FlagKind;
2835 FlagValues FlagValue;
2836};
2837} // end anonymous namespace
2838
2839void PragmaFPHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002840 PragmaIntroducer Introducer, Token &Tok) {
Adam Nemet60d32642017-04-04 21:18:36 +00002841 // fp
2842 Token PragmaName = Tok;
2843 SmallVector<Token, 1> TokenList;
2844
2845 PP.Lex(Tok);
2846 if (Tok.isNot(tok::identifier)) {
2847 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
2848 << /*MissingOption=*/true << "";
2849 return;
2850 }
2851
2852 while (Tok.is(tok::identifier)) {
2853 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
2854
2855 auto FlagKind =
2856 llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagKinds>>(
2857 OptionInfo->getName())
2858 .Case("contract", TokFPAnnotValue::Contract)
Melanie Blowerc355bec2020-05-04 10:48:12 -07002859 .Case("reassociate", TokFPAnnotValue::Reassociate)
Adam Nemet60d32642017-04-04 21:18:36 +00002860 .Default(None);
2861 if (!FlagKind) {
2862 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
2863 << /*MissingOption=*/false << OptionInfo;
2864 return;
2865 }
2866 PP.Lex(Tok);
2867
2868 // Read '('
2869 if (Tok.isNot(tok::l_paren)) {
2870 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
2871 return;
2872 }
2873 PP.Lex(Tok);
2874
2875 if (Tok.isNot(tok::identifier)) {
2876 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
Melanie Blowerc355bec2020-05-04 10:48:12 -07002877 << PP.getSpelling(Tok) << OptionInfo->getName()
2878 << (FlagKind == TokFPAnnotValue::Reassociate);
Adam Nemet60d32642017-04-04 21:18:36 +00002879 return;
2880 }
2881 const IdentifierInfo *II = Tok.getIdentifierInfo();
2882
2883 auto FlagValue =
2884 llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagValues>>(
2885 II->getName())
2886 .Case("on", TokFPAnnotValue::On)
2887 .Case("off", TokFPAnnotValue::Off)
2888 .Case("fast", TokFPAnnotValue::Fast)
2889 .Default(llvm::None);
2890
Melanie Blowerc355bec2020-05-04 10:48:12 -07002891 if (!FlagValue || (FlagKind == TokFPAnnotValue::Reassociate &&
2892 FlagValue == TokFPAnnotValue::Fast)) {
Adam Nemet60d32642017-04-04 21:18:36 +00002893 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
Melanie Blowerc355bec2020-05-04 10:48:12 -07002894 << PP.getSpelling(Tok) << OptionInfo->getName()
2895 << (FlagKind == TokFPAnnotValue::Reassociate);
Adam Nemet60d32642017-04-04 21:18:36 +00002896 return;
2897 }
2898 PP.Lex(Tok);
2899
2900 // Read ')'
2901 if (Tok.isNot(tok::r_paren)) {
2902 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
2903 return;
2904 }
2905 PP.Lex(Tok);
2906
2907 auto *AnnotValue = new (PP.getPreprocessorAllocator())
2908 TokFPAnnotValue{*FlagKind, *FlagValue};
Melanie Blowerf5360d42020-05-01 10:32:06 -07002909 // Generate the fp annotation token.
Adam Nemet60d32642017-04-04 21:18:36 +00002910 Token FPTok;
2911 FPTok.startToken();
2912 FPTok.setKind(tok::annot_pragma_fp);
2913 FPTok.setLocation(PragmaName.getLocation());
2914 FPTok.setAnnotationEndLoc(PragmaName.getLocation());
2915 FPTok.setAnnotationValue(reinterpret_cast<void *>(AnnotValue));
2916 TokenList.push_back(FPTok);
2917 }
2918
2919 if (Tok.isNot(tok::eod)) {
2920 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2921 << "clang fp";
2922 return;
2923 }
2924
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +00002925 auto TokenArray = std::make_unique<Token[]>(TokenList.size());
Adam Nemet60d32642017-04-04 21:18:36 +00002926 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
2927
2928 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
Ilya Biryukov929af672019-05-17 09:32:05 +00002929 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
Adam Nemet60d32642017-04-04 21:18:36 +00002930}
2931
2932void Parser::HandlePragmaFP() {
2933 assert(Tok.is(tok::annot_pragma_fp));
2934 auto *AnnotValue =
2935 reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue());
2936
Melanie Blowerc355bec2020-05-04 10:48:12 -07002937 if (AnnotValue->FlagKind == TokFPAnnotValue::Reassociate)
Melanie Blowerf4aaed32020-06-26 09:23:45 -07002938 Actions.ActOnPragmaFPReassociate(
2939 Tok.getLocation(), AnnotValue->FlagValue == TokFPAnnotValue::On);
Melanie Blowerc355bec2020-05-04 10:48:12 -07002940 else {
2941 LangOptions::FPModeKind FPC;
2942 switch (AnnotValue->FlagValue) {
2943 case TokFPAnnotValue::Off:
2944 FPC = LangOptions::FPM_Off;
2945 break;
2946 case TokFPAnnotValue::On:
2947 FPC = LangOptions::FPM_On;
2948 break;
2949 case TokFPAnnotValue::Fast:
2950 FPC = LangOptions::FPM_Fast;
2951 break;
2952 }
Melanie Blowerf4aaed32020-06-26 09:23:45 -07002953 Actions.ActOnPragmaFPContract(Tok.getLocation(), FPC);
Adam Nemet60d32642017-04-04 21:18:36 +00002954 }
Richard Smithaf3b3252017-05-18 19:21:48 +00002955 ConsumeAnnotationToken();
Adam Nemet60d32642017-04-04 21:18:36 +00002956}
2957
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002958/// Parses loop or unroll pragma hint value and fills in Info.
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002959static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
2960 Token Option, bool ValueInParens,
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002961 PragmaLoopHintInfo &Info) {
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002962 SmallVector<Token, 1> ValueList;
2963 int OpenParens = ValueInParens ? 1 : 0;
2964 // Read constant expression.
2965 while (Tok.isNot(tok::eod)) {
2966 if (Tok.is(tok::l_paren))
2967 OpenParens++;
2968 else if (Tok.is(tok::r_paren)) {
2969 OpenParens--;
2970 if (OpenParens == 0 && ValueInParens)
2971 break;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002972 }
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002973
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002974 ValueList.push_back(Tok);
2975 PP.Lex(Tok);
2976 }
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002977
2978 if (ValueInParens) {
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002979 // Read ')'
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002980 if (Tok.isNot(tok::r_paren)) {
2981 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
2982 return true;
2983 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002984 PP.Lex(Tok);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002985 }
2986
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002987 Token EOFTok;
2988 EOFTok.startToken();
2989 EOFTok.setKind(tok::eof);
2990 EOFTok.setLocation(Tok.getLocation());
2991 ValueList.push_back(EOFTok); // Terminates expression for parsing.
2992
Benjamin Kramerfa7f8552015-08-05 09:39:57 +00002993 Info.Toks = llvm::makeArrayRef(ValueList).copy(PP.getPreprocessorAllocator());
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002994
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002995 Info.PragmaName = PragmaName;
2996 Info.Option = Option;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002997 return false;
2998}
2999
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003000/// Handle the \#pragma clang loop directive.
Eli Bendersky06a40422014-06-06 20:31:48 +00003001/// #pragma clang 'loop' loop-hints
3002///
3003/// loop-hints:
3004/// loop-hint loop-hints[opt]
3005///
3006/// loop-hint:
3007/// 'vectorize' '(' loop-hint-keyword ')'
3008/// 'interleave' '(' loop-hint-keyword ')'
Mark Heffernan450c2382014-07-23 17:31:31 +00003009/// 'unroll' '(' unroll-hint-keyword ')'
Sjoerd Meijera48f58c2019-07-25 07:33:13 +00003010/// 'vectorize_predicate' '(' loop-hint-keyword ')'
Eli Bendersky06a40422014-06-06 20:31:48 +00003011/// 'vectorize_width' '(' loop-hint-value ')'
3012/// 'interleave_count' '(' loop-hint-value ')'
Eli Bendersky86483b32014-06-11 17:56:26 +00003013/// 'unroll_count' '(' loop-hint-value ')'
Aaron Ballman9bdf5152019-01-04 17:20:00 +00003014/// 'pipeline' '(' disable ')'
3015/// 'pipeline_initiation_interval' '(' loop-hint-value ')'
Eli Bendersky06a40422014-06-06 20:31:48 +00003016///
3017/// loop-hint-keyword:
3018/// 'enable'
3019/// 'disable'
Tyler Nowicki9d268e12015-06-11 23:23:17 +00003020/// 'assume_safety'
Eli Bendersky06a40422014-06-06 20:31:48 +00003021///
Mark Heffernan450c2382014-07-23 17:31:31 +00003022/// unroll-hint-keyword:
Mark Heffernan397a98d2015-08-10 17:29:39 +00003023/// 'enable'
Mark Heffernan450c2382014-07-23 17:31:31 +00003024/// 'disable'
Mark Heffernan397a98d2015-08-10 17:29:39 +00003025/// 'full'
Mark Heffernan450c2382014-07-23 17:31:31 +00003026///
Eli Bendersky06a40422014-06-06 20:31:48 +00003027/// loop-hint-value:
3028/// constant-expression
3029///
3030/// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
3031/// try vectorizing the instructions of the loop it precedes. Specifying
3032/// interleave(enable) or interleave_count(_value_) instructs llvm to try
3033/// interleaving multiple iterations of the loop it precedes. The width of the
3034/// vector instructions is specified by vectorize_width() and the number of
3035/// interleaved loop iterations is specified by interleave_count(). Specifying a
3036/// value of 1 effectively disables vectorization/interleaving, even if it is
3037/// possible and profitable, and 0 is invalid. The loop vectorizer currently
3038/// only works on inner loops.
3039///
Eli Bendersky86483b32014-06-11 17:56:26 +00003040/// The unroll and unroll_count directives control the concatenation
Mark Heffernan397a98d2015-08-10 17:29:39 +00003041/// unroller. Specifying unroll(enable) instructs llvm to unroll the loop
3042/// completely if the trip count is known at compile time and unroll partially
3043/// if the trip count is not known. Specifying unroll(full) is similar to
3044/// unroll(enable) but will unroll the loop only if the trip count is known at
3045/// compile time. Specifying unroll(disable) disables unrolling for the
3046/// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the
3047/// loop the number of times indicated by the value.
Eli Bendersky06a40422014-06-06 20:31:48 +00003048void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00003049 PragmaIntroducer Introducer,
Eli Bendersky06a40422014-06-06 20:31:48 +00003050 Token &Tok) {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003051 // Incoming token is "loop" from "#pragma clang loop".
3052 Token PragmaName = Tok;
Eli Bendersky06a40422014-06-06 20:31:48 +00003053 SmallVector<Token, 1> TokenList;
3054
3055 // Lex the optimization option and verify it is an identifier.
3056 PP.Lex(Tok);
3057 if (Tok.isNot(tok::identifier)) {
3058 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
3059 << /*MissingOption=*/true << "";
3060 return;
3061 }
3062
3063 while (Tok.is(tok::identifier)) {
3064 Token Option = Tok;
3065 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
3066
Eli Bendersky86483b32014-06-11 17:56:26 +00003067 bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003068 .Case("vectorize", true)
3069 .Case("interleave", true)
3070 .Case("unroll", true)
Adam Nemet2de463e2016-06-14 12:04:26 +00003071 .Case("distribute", true)
Sjoerd Meijera48f58c2019-07-25 07:33:13 +00003072 .Case("vectorize_predicate", true)
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003073 .Case("vectorize_width", true)
3074 .Case("interleave_count", true)
3075 .Case("unroll_count", true)
Aaron Ballman9bdf5152019-01-04 17:20:00 +00003076 .Case("pipeline", true)
3077 .Case("pipeline_initiation_interval", true)
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003078 .Default(false);
Eli Bendersky86483b32014-06-11 17:56:26 +00003079 if (!OptionValid) {
Eli Bendersky06a40422014-06-06 20:31:48 +00003080 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
3081 << /*MissingOption=*/false << OptionInfo;
3082 return;
3083 }
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00003084 PP.Lex(Tok);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003085
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00003086 // Read '('
3087 if (Tok.isNot(tok::l_paren)) {
3088 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00003089 return;
3090 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00003091 PP.Lex(Tok);
3092
3093 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
3094 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
3095 *Info))
3096 return;
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00003097
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003098 // Generate the loop hint token.
Eli Bendersky06a40422014-06-06 20:31:48 +00003099 Token LoopHintTok;
3100 LoopHintTok.startToken();
3101 LoopHintTok.setKind(tok::annot_pragma_loop_hint);
Yuanfang Chen9c2e7702020-05-31 19:51:15 -07003102 LoopHintTok.setLocation(Introducer.Loc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00003103 LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());
Eli Bendersky06a40422014-06-06 20:31:48 +00003104 LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
3105 TokenList.push_back(LoopHintTok);
3106 }
3107
3108 if (Tok.isNot(tok::eod)) {
3109 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3110 << "clang loop";
3111 return;
3112 }
3113
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +00003114 auto TokenArray = std::make_unique<Token[]>(TokenList.size());
David Blaikie2eabcc92016-02-09 18:52:09 +00003115 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
Eli Bendersky06a40422014-06-06 20:31:48 +00003116
David Blaikie2eabcc92016-02-09 18:52:09 +00003117 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
Ilya Biryukov929af672019-05-17 09:32:05 +00003118 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
Eli Bendersky06a40422014-06-06 20:31:48 +00003119}
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003120
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003121/// Handle the loop unroll optimization pragmas.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003122/// #pragma unroll
3123/// #pragma unroll unroll-hint-value
3124/// #pragma unroll '(' unroll-hint-value ')'
Mark Heffernanc888e412014-07-24 18:09:38 +00003125/// #pragma nounroll
David Greenc8e39242018-08-01 14:36:12 +00003126/// #pragma unroll_and_jam
3127/// #pragma unroll_and_jam unroll-hint-value
3128/// #pragma unroll_and_jam '(' unroll-hint-value ')'
3129/// #pragma nounroll_and_jam
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003130///
3131/// unroll-hint-value:
3132/// constant-expression
3133///
Mark Heffernanc888e412014-07-24 18:09:38 +00003134/// Loop unrolling hints can be specified with '#pragma unroll' or
3135/// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
3136/// contained in parentheses. With no argument the directive instructs llvm to
3137/// try to unroll the loop completely. A positive integer argument can be
3138/// specified to indicate the number of times the loop should be unrolled. To
3139/// maximize compatibility with other compilers the unroll count argument can be
3140/// specified with or without parentheses. Specifying, '#pragma nounroll'
3141/// disables unrolling of the loop.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003142void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00003143 PragmaIntroducer Introducer,
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003144 Token &Tok) {
Mark Heffernanc888e412014-07-24 18:09:38 +00003145 // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
3146 // "#pragma nounroll".
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003147 Token PragmaName = Tok;
3148 PP.Lex(Tok);
3149 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
3150 if (Tok.is(tok::eod)) {
Mark Heffernanc888e412014-07-24 18:09:38 +00003151 // nounroll or unroll pragma without an argument.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003152 Info->PragmaName = PragmaName;
Aaron Ballmand6807da2014-08-01 12:41:37 +00003153 Info->Option.startToken();
David Greenc8e39242018-08-01 14:36:12 +00003154 } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll" ||
3155 PragmaName.getIdentifierInfo()->getName() == "nounroll_and_jam") {
Mark Heffernanc888e412014-07-24 18:09:38 +00003156 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
David Greenc8e39242018-08-01 14:36:12 +00003157 << PragmaName.getIdentifierInfo()->getName();
Mark Heffernanc888e412014-07-24 18:09:38 +00003158 return;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003159 } else {
3160 // Unroll pragma with an argument: "#pragma unroll N" or
3161 // "#pragma unroll(N)".
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00003162 // Read '(' if it exists.
3163 bool ValueInParens = Tok.is(tok::l_paren);
3164 if (ValueInParens)
3165 PP.Lex(Tok);
3166
Aaron Ballmand0b090d2014-08-01 12:20:20 +00003167 Token Option;
3168 Option.startToken();
3169 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003170 return;
3171
3172 // In CUDA, the argument to '#pragma unroll' should not be contained in
3173 // parentheses.
3174 if (PP.getLangOpts().CUDA && ValueInParens)
Tyler Nowickic724a83e2014-10-12 20:46:07 +00003175 PP.Diag(Info->Toks[0].getLocation(),
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003176 diag::warn_pragma_unroll_cuda_value_in_parens);
3177
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003178 if (Tok.isNot(tok::eod)) {
3179 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3180 << "unroll";
3181 return;
3182 }
3183 }
3184
3185 // Generate the hint token.
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +00003186 auto TokenArray = std::make_unique<Token[]>(1);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003187 TokenArray[0].startToken();
3188 TokenArray[0].setKind(tok::annot_pragma_loop_hint);
Yuanfang Chen9c2e7702020-05-31 19:51:15 -07003189 TokenArray[0].setLocation(Introducer.Loc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00003190 TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003191 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
David Blaikie2eabcc92016-02-09 18:52:09 +00003192 PP.EnterTokenStream(std::move(TokenArray), 1,
Ilya Biryukov929af672019-05-17 09:32:05 +00003193 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003194}
Reid Kleckner3f1ec622016-09-07 16:38:32 +00003195
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003196/// Handle the Microsoft \#pragma intrinsic extension.
Reid Kleckner3f1ec622016-09-07 16:38:32 +00003197///
3198/// The syntax is:
3199/// \code
3200/// #pragma intrinsic(memset)
3201/// #pragma intrinsic(strlen, memcpy)
3202/// \endcode
3203///
3204/// Pragma intrisic tells the compiler to use a builtin version of the
3205/// function. Clang does it anyway, so the pragma doesn't really do anything.
3206/// Anyway, we emit a warning if the function specified in \#pragma intrinsic
3207/// isn't an intrinsic in clang and suggest to include intrin.h.
3208void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00003209 PragmaIntroducer Introducer,
Reid Kleckner3f1ec622016-09-07 16:38:32 +00003210 Token &Tok) {
3211 PP.Lex(Tok);
3212
3213 if (Tok.isNot(tok::l_paren)) {
3214 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
3215 << "intrinsic";
3216 return;
3217 }
3218 PP.Lex(Tok);
3219
3220 bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
3221
3222 while (Tok.is(tok::identifier)) {
3223 IdentifierInfo *II = Tok.getIdentifierInfo();
3224 if (!II->getBuiltinID())
3225 PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
3226 << II << SuggestIntrinH;
3227
3228 PP.Lex(Tok);
3229 if (Tok.isNot(tok::comma))
3230 break;
3231 PP.Lex(Tok);
3232 }
3233
3234 if (Tok.isNot(tok::r_paren)) {
3235 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
3236 << "intrinsic";
3237 return;
3238 }
3239 PP.Lex(Tok);
3240
3241 if (Tok.isNot(tok::eod))
3242 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3243 << "intrinsic";
3244}
Hans Wennborg1bbe00e2018-03-20 08:53:11 +00003245
3246// #pragma optimize("gsty", on|off)
3247void PragmaMSOptimizeHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00003248 PragmaIntroducer Introducer,
Hans Wennborg1bbe00e2018-03-20 08:53:11 +00003249 Token &Tok) {
3250 SourceLocation StartLoc = Tok.getLocation();
3251 PP.Lex(Tok);
3252
3253 if (Tok.isNot(tok::l_paren)) {
3254 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "optimize";
3255 return;
3256 }
3257 PP.Lex(Tok);
3258
3259 if (Tok.isNot(tok::string_literal)) {
3260 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_string) << "optimize";
3261 return;
3262 }
3263 // We could syntax check the string but it's probably not worth the effort.
3264 PP.Lex(Tok);
3265
3266 if (Tok.isNot(tok::comma)) {
3267 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_comma) << "optimize";
3268 return;
3269 }
3270 PP.Lex(Tok);
3271
3272 if (Tok.is(tok::eod) || Tok.is(tok::r_paren)) {
3273 PP.Diag(Tok.getLocation(), diag::warn_pragma_missing_argument)
3274 << "optimize" << /*Expected=*/true << "'on' or 'off'";
3275 return;
3276 }
3277 IdentifierInfo *II = Tok.getIdentifierInfo();
3278 if (!II || (!II->isStr("on") && !II->isStr("off"))) {
3279 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)
3280 << PP.getSpelling(Tok) << "optimize" << /*Expected=*/true
3281 << "'on' or 'off'";
3282 return;
3283 }
3284 PP.Lex(Tok);
3285
3286 if (Tok.isNot(tok::r_paren)) {
3287 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "optimize";
3288 return;
3289 }
3290 PP.Lex(Tok);
3291
3292 if (Tok.isNot(tok::eod)) {
3293 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3294 << "optimize";
3295 return;
3296 }
3297 PP.Diag(StartLoc, diag::warn_pragma_optimize);
3298}
3299
Justin Lebar67a78a62016-10-08 22:15:58 +00003300void PragmaForceCUDAHostDeviceHandler::HandlePragma(
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00003301 Preprocessor &PP, PragmaIntroducer Introducer, Token &Tok) {
Justin Lebar67a78a62016-10-08 22:15:58 +00003302 Token FirstTok = Tok;
3303
3304 PP.Lex(Tok);
3305 IdentifierInfo *Info = Tok.getIdentifierInfo();
3306 if (!Info || (!Info->isStr("begin") && !Info->isStr("end"))) {
3307 PP.Diag(FirstTok.getLocation(),
3308 diag::warn_pragma_force_cuda_host_device_bad_arg);
3309 return;
3310 }
3311
3312 if (Info->isStr("begin"))
3313 Actions.PushForceCUDAHostDevice();
3314 else if (!Actions.PopForceCUDAHostDevice())
3315 PP.Diag(FirstTok.getLocation(),
3316 diag::err_pragma_cannot_end_force_cuda_host_device);
3317
3318 PP.Lex(Tok);
3319 if (!Tok.is(tok::eod))
3320 PP.Diag(FirstTok.getLocation(),
3321 diag::warn_pragma_force_cuda_host_device_bad_arg);
3322}
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003323
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003324/// Handle the #pragma clang attribute directive.
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003325///
3326/// The syntax is:
3327/// \code
Erik Pilkington0876cae2018-12-20 22:32:04 +00003328/// #pragma clang attribute push (attribute, subject-set)
Erik Pilkington7d180942018-10-29 17:38:42 +00003329/// #pragma clang attribute push
3330/// #pragma clang attribute (attribute, subject-set)
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003331/// #pragma clang attribute pop
3332/// \endcode
3333///
Erik Pilkington0876cae2018-12-20 22:32:04 +00003334/// There are also 'namespace' variants of push and pop directives. The bare
3335/// '#pragma clang attribute (attribute, subject-set)' version doesn't require a
3336/// namespace, since it always applies attributes to the most recently pushed
3337/// group, regardless of namespace.
3338/// \code
3339/// #pragma clang attribute namespace.push (attribute, subject-set)
3340/// #pragma clang attribute namespace.push
3341/// #pragma clang attribute namespace.pop
3342/// \endcode
3343///
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003344/// The subject-set clause defines the set of declarations which receive the
3345/// attribute. Its exact syntax is described in the LanguageExtensions document
3346/// in Clang's documentation.
3347///
3348/// This directive instructs the compiler to begin/finish applying the specified
3349/// attribute to the set of attribute-specific declarations in the active range
3350/// of the pragma.
3351void PragmaAttributeHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00003352 PragmaIntroducer Introducer,
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003353 Token &FirstToken) {
3354 Token Tok;
3355 PP.Lex(Tok);
3356 auto *Info = new (PP.getPreprocessorAllocator())
3357 PragmaAttributeInfo(AttributesForPragmaAttribute);
3358
Erik Pilkington0876cae2018-12-20 22:32:04 +00003359 // Parse the optional namespace followed by a period.
3360 if (Tok.is(tok::identifier)) {
3361 IdentifierInfo *II = Tok.getIdentifierInfo();
3362 if (!II->isStr("push") && !II->isStr("pop")) {
3363 Info->Namespace = II;
3364 PP.Lex(Tok);
3365
3366 if (!Tok.is(tok::period)) {
3367 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_period)
3368 << II;
3369 return;
3370 }
3371 PP.Lex(Tok);
3372 }
3373 }
3374
Erik Pilkington7d180942018-10-29 17:38:42 +00003375 if (!Tok.isOneOf(tok::identifier, tok::l_paren)) {
3376 PP.Diag(Tok.getLocation(),
3377 diag::err_pragma_attribute_expected_push_pop_paren);
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003378 return;
3379 }
Erik Pilkington7d180942018-10-29 17:38:42 +00003380
3381 // Determine what action this pragma clang attribute represents.
Erik Pilkington0876cae2018-12-20 22:32:04 +00003382 if (Tok.is(tok::l_paren)) {
3383 if (Info->Namespace) {
3384 PP.Diag(Tok.getLocation(),
3385 diag::err_pragma_attribute_namespace_on_attribute);
3386 PP.Diag(Tok.getLocation(),
3387 diag::note_pragma_attribute_namespace_on_attribute);
3388 return;
3389 }
Erik Pilkington7d180942018-10-29 17:38:42 +00003390 Info->Action = PragmaAttributeInfo::Attribute;
Erik Pilkington0876cae2018-12-20 22:32:04 +00003391 } else {
Erik Pilkington7d180942018-10-29 17:38:42 +00003392 const IdentifierInfo *II = Tok.getIdentifierInfo();
3393 if (II->isStr("push"))
3394 Info->Action = PragmaAttributeInfo::Push;
3395 else if (II->isStr("pop"))
3396 Info->Action = PragmaAttributeInfo::Pop;
3397 else {
3398 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument)
3399 << PP.getSpelling(Tok);
3400 return;
3401 }
3402
3403 PP.Lex(Tok);
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003404 }
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003405
3406 // Parse the actual attribute.
Erik Pilkington7d180942018-10-29 17:38:42 +00003407 if ((Info->Action == PragmaAttributeInfo::Push && Tok.isNot(tok::eod)) ||
3408 Info->Action == PragmaAttributeInfo::Attribute) {
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003409 if (Tok.isNot(tok::l_paren)) {
3410 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
3411 return;
3412 }
3413 PP.Lex(Tok);
3414
3415 // Lex the attribute tokens.
3416 SmallVector<Token, 16> AttributeTokens;
3417 int OpenParens = 1;
3418 while (Tok.isNot(tok::eod)) {
3419 if (Tok.is(tok::l_paren))
3420 OpenParens++;
3421 else if (Tok.is(tok::r_paren)) {
3422 OpenParens--;
3423 if (OpenParens == 0)
3424 break;
3425 }
3426
3427 AttributeTokens.push_back(Tok);
3428 PP.Lex(Tok);
3429 }
3430
3431 if (AttributeTokens.empty()) {
3432 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_attribute);
3433 return;
3434 }
3435 if (Tok.isNot(tok::r_paren)) {
3436 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3437 return;
3438 }
3439 SourceLocation EndLoc = Tok.getLocation();
3440 PP.Lex(Tok);
3441
3442 // Terminate the attribute for parsing.
3443 Token EOFTok;
3444 EOFTok.startToken();
3445 EOFTok.setKind(tok::eof);
3446 EOFTok.setLocation(EndLoc);
3447 AttributeTokens.push_back(EOFTok);
3448
3449 Info->Tokens =
3450 llvm::makeArrayRef(AttributeTokens).copy(PP.getPreprocessorAllocator());
3451 }
3452
3453 if (Tok.isNot(tok::eod))
3454 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3455 << "clang attribute";
3456
3457 // Generate the annotated pragma token.
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +00003458 auto TokenArray = std::make_unique<Token[]>(1);
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003459 TokenArray[0].startToken();
3460 TokenArray[0].setKind(tok::annot_pragma_attribute);
3461 TokenArray[0].setLocation(FirstToken.getLocation());
3462 TokenArray[0].setAnnotationEndLoc(FirstToken.getLocation());
3463 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
3464 PP.EnterTokenStream(std::move(TokenArray), 1,
Ilya Biryukov929af672019-05-17 09:32:05 +00003465 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003466}
Hans Wennborg739b4102019-10-09 15:22:38 +02003467
3468// Handle '#pragma clang max_tokens 12345'.
3469void PragmaMaxTokensHereHandler::HandlePragma(Preprocessor &PP,
3470 PragmaIntroducer Introducer,
3471 Token &Tok) {
3472 PP.Lex(Tok);
3473 if (Tok.is(tok::eod)) {
3474 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
3475 << "clang max_tokens_here" << /*Expected=*/true << "integer";
3476 return;
3477 }
3478
3479 SourceLocation Loc = Tok.getLocation();
3480 uint64_t MaxTokens;
3481 if (Tok.isNot(tok::numeric_constant) ||
3482 !PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) {
3483 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer)
3484 << "clang max_tokens_here";
3485 return;
3486 }
3487
3488 if (Tok.isNot(tok::eod)) {
3489 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3490 << "clang max_tokens_here";
3491 return;
3492 }
3493
3494 if (PP.getTokenCount() > MaxTokens) {
3495 PP.Diag(Loc, diag::warn_max_tokens)
3496 << PP.getTokenCount() << (unsigned)MaxTokens;
3497 }
3498}
3499
Hans Wennborg74734e82020-02-07 11:32:24 +01003500// Handle '#pragma clang max_tokens_total 12345'.
Hans Wennborg739b4102019-10-09 15:22:38 +02003501void PragmaMaxTokensTotalHandler::HandlePragma(Preprocessor &PP,
3502 PragmaIntroducer Introducer,
3503 Token &Tok) {
3504 PP.Lex(Tok);
3505 if (Tok.is(tok::eod)) {
3506 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
3507 << "clang max_tokens_total" << /*Expected=*/true << "integer";
3508 return;
3509 }
3510
3511 SourceLocation Loc = Tok.getLocation();
3512 uint64_t MaxTokens;
3513 if (Tok.isNot(tok::numeric_constant) ||
3514 !PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) {
3515 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer)
3516 << "clang max_tokens_total";
3517 return;
3518 }
3519
3520 if (Tok.isNot(tok::eod)) {
3521 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3522 << "clang max_tokens_total";
3523 return;
3524 }
3525
3526 PP.overrideMaxTokens(MaxTokens, Loc);
3527}