blob: 34232437528bb0f80c1ca0d1f41b5875389cf8d2 [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);
Kevin P. Neal2c0bc8b2018-08-14 17:06:56 +0000111 }
112
113 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
114 1);
115 Toks[0].startToken();
116 Toks[0].setKind(tok::annot_pragma_fenv_access);
117 Toks[0].setLocation(Tok.getLocation());
118 Toks[0].setAnnotationEndLoc(Tok.getLocation());
119 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
120 static_cast<uintptr_t>(OOS)));
Ilya Biryukov929af672019-05-17 09:32:05 +0000121 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
122 /*IsReinject=*/false);
Steven Wub96a3a42018-01-05 22:45:03 +0000123 }
124};
125
126/// PragmaSTDC_CX_LIMITED_RANGEHandler - "\#pragma STDC CX_LIMITED_RANGE ...".
127struct PragmaSTDC_CX_LIMITED_RANGEHandler : public PragmaHandler {
128 PragmaSTDC_CX_LIMITED_RANGEHandler() : PragmaHandler("CX_LIMITED_RANGE") {}
129
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000130 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Steven Wub96a3a42018-01-05 22:45:03 +0000131 Token &Tok) override {
132 tok::OnOffSwitch OOS;
133 PP.LexOnOffSwitch(OOS);
134 }
135};
136
137/// PragmaSTDC_UnknownHandler - "\#pragma STDC ...".
138struct PragmaSTDC_UnknownHandler : public PragmaHandler {
139 PragmaSTDC_UnknownHandler() = default;
140
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000141 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Steven Wub96a3a42018-01-05 22:45:03 +0000142 Token &UnknownTok) override {
143 // C99 6.10.6p2, unknown forms are not allowed.
144 PP.Diag(UnknownTok, diag::ext_stdc_pragma_ignored);
145 }
146};
147
Adam Nemet60d32642017-04-04 21:18:36 +0000148struct PragmaFPHandler : public PragmaHandler {
149 PragmaFPHandler() : PragmaHandler("fp") {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000150 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Adam Nemet60d32642017-04-04 21:18:36 +0000151 Token &FirstToken) override;
152};
153
Reid Kleckner5b086462014-02-20 22:52:09 +0000154struct PragmaNoOpenMPHandler : public PragmaHandler {
155 PragmaNoOpenMPHandler() : PragmaHandler("omp") { }
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000156 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Craig Topper2b07f022014-03-12 05:09:18 +0000157 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000158};
159
160struct PragmaOpenMPHandler : public PragmaHandler {
161 PragmaOpenMPHandler() : PragmaHandler("omp") { }
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000162 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Craig Topper2b07f022014-03-12 05:09:18 +0000163 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000164};
165
166/// PragmaCommentHandler - "\#pragma comment ...".
167struct PragmaCommentHandler : public PragmaHandler {
168 PragmaCommentHandler(Sema &Actions)
169 : PragmaHandler("comment"), Actions(Actions) {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000170 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Craig Topper2b07f022014-03-12 05:09:18 +0000171 Token &FirstToken) override;
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000172
Reid Kleckner5b086462014-02-20 22:52:09 +0000173private:
174 Sema &Actions;
175};
176
177struct PragmaDetectMismatchHandler : public PragmaHandler {
178 PragmaDetectMismatchHandler(Sema &Actions)
179 : PragmaHandler("detect_mismatch"), Actions(Actions) {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000180 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Craig Topper2b07f022014-03-12 05:09:18 +0000181 Token &FirstToken) override;
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000182
Reid Kleckner5b086462014-02-20 22:52:09 +0000183private:
184 Sema &Actions;
185};
186
187struct PragmaMSPointersToMembers : public PragmaHandler {
188 explicit PragmaMSPointersToMembers() : PragmaHandler("pointers_to_members") {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000189 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Craig Topper2b07f022014-03-12 05:09:18 +0000190 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000191};
192
193struct PragmaMSVtorDisp : public PragmaHandler {
194 explicit PragmaMSVtorDisp() : PragmaHandler("vtordisp") {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000195 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Craig Topper2b07f022014-03-12 05:09:18 +0000196 Token &FirstToken) override;
Reid Kleckner5b086462014-02-20 22:52:09 +0000197};
198
Warren Huntc3b18962014-04-08 22:30:47 +0000199struct PragmaMSPragma : public PragmaHandler {
200 explicit PragmaMSPragma(const char *name) : PragmaHandler(name) {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000201 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000202 Token &FirstToken) override;
203};
204
Dario Domizioli13a0a382014-05-23 12:13:25 +0000205/// PragmaOptimizeHandler - "\#pragma clang optimize on/off".
206struct PragmaOptimizeHandler : public PragmaHandler {
207 PragmaOptimizeHandler(Sema &S)
208 : PragmaHandler("optimize"), Actions(S) {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000209 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Dario Domizioli13a0a382014-05-23 12:13:25 +0000210 Token &FirstToken) override;
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000211
Dario Domizioli13a0a382014-05-23 12:13:25 +0000212private:
Eli Bendersky06a40422014-06-06 20:31:48 +0000213 Sema &Actions;
214};
215
216struct PragmaLoopHintHandler : public PragmaHandler {
217 PragmaLoopHintHandler() : PragmaHandler("loop") {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000218 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Eli Bendersky06a40422014-06-06 20:31:48 +0000219 Token &FirstToken) override;
220};
221
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000222struct PragmaUnrollHintHandler : public PragmaHandler {
223 PragmaUnrollHintHandler(const char *name) : PragmaHandler(name) {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000224 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000225 Token &FirstToken) override;
226};
227
Hans Wennborg7357bbc2015-10-12 20:47:58 +0000228struct PragmaMSRuntimeChecksHandler : public EmptyPragmaHandler {
229 PragmaMSRuntimeChecksHandler() : EmptyPragmaHandler("runtime_checks") {}
230};
231
Reid Kleckner3f1ec622016-09-07 16:38:32 +0000232struct PragmaMSIntrinsicHandler : public PragmaHandler {
233 PragmaMSIntrinsicHandler() : PragmaHandler("intrinsic") {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000234 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Reid Kleckner3f1ec622016-09-07 16:38:32 +0000235 Token &FirstToken) override;
236};
237
Hans Wennborg1bbe00e2018-03-20 08:53:11 +0000238struct PragmaMSOptimizeHandler : public PragmaHandler {
239 PragmaMSOptimizeHandler() : PragmaHandler("optimize") {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000240 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Hans Wennborg1bbe00e2018-03-20 08:53:11 +0000241 Token &FirstToken) override;
242};
243
Justin Lebar67a78a62016-10-08 22:15:58 +0000244struct PragmaForceCUDAHostDeviceHandler : public PragmaHandler {
245 PragmaForceCUDAHostDeviceHandler(Sema &Actions)
246 : PragmaHandler("force_cuda_host_device"), Actions(Actions) {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000247 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Justin Lebar67a78a62016-10-08 22:15:58 +0000248 Token &FirstToken) override;
249
250private:
251 Sema &Actions;
252};
253
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000254/// PragmaAttributeHandler - "\#pragma clang attribute ...".
255struct PragmaAttributeHandler : public PragmaHandler {
256 PragmaAttributeHandler(AttributeFactory &AttrFactory)
257 : PragmaHandler("attribute"), AttributesForPragmaAttribute(AttrFactory) {}
Joel E. Dennyddde0ec2019-05-21 23:51:38 +0000258 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000259 Token &FirstToken) override;
260
261 /// A pool of attributes that were parsed in \#pragma clang attribute.
262 ParsedAttributes AttributesForPragmaAttribute;
263};
264
Hans Wennborg739b4102019-10-09 15:22:38 +0200265struct PragmaMaxTokensHereHandler : public PragmaHandler {
266 PragmaMaxTokensHereHandler() : PragmaHandler("max_tokens_here") {}
267 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
268 Token &FirstToken) override;
269};
270
271struct PragmaMaxTokensTotalHandler : public PragmaHandler {
272 PragmaMaxTokensTotalHandler() : PragmaHandler("max_tokens_total") {}
273 void HandlePragma(Preprocessor &PP, PragmaIntroducer Introducer,
274 Token &FirstToken) override;
275};
276
Eli Bendersky06a40422014-06-06 20:31:48 +0000277} // end namespace
278
279void Parser::initializePragmaHandlers() {
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000280 AlignHandler = std::make_unique<PragmaAlignHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000281 PP.AddPragmaHandler(AlignHandler.get());
282
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000283 GCCVisibilityHandler = std::make_unique<PragmaGCCVisibilityHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000284 PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
285
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000286 OptionsHandler = std::make_unique<PragmaOptionsHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000287 PP.AddPragmaHandler(OptionsHandler.get());
288
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000289 PackHandler = std::make_unique<PragmaPackHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000290 PP.AddPragmaHandler(PackHandler.get());
291
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000292 MSStructHandler = std::make_unique<PragmaMSStructHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000293 PP.AddPragmaHandler(MSStructHandler.get());
294
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000295 UnusedHandler = std::make_unique<PragmaUnusedHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000296 PP.AddPragmaHandler(UnusedHandler.get());
297
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000298 WeakHandler = std::make_unique<PragmaWeakHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000299 PP.AddPragmaHandler(WeakHandler.get());
300
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000301 RedefineExtnameHandler = std::make_unique<PragmaRedefineExtnameHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000302 PP.AddPragmaHandler(RedefineExtnameHandler.get());
303
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000304 FPContractHandler = std::make_unique<PragmaFPContractHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000305 PP.AddPragmaHandler("STDC", FPContractHandler.get());
306
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000307 STDCFENVHandler = std::make_unique<PragmaSTDC_FENV_ACCESSHandler>();
Steven Wub96a3a42018-01-05 22:45:03 +0000308 PP.AddPragmaHandler("STDC", STDCFENVHandler.get());
309
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000310 STDCCXLIMITHandler = std::make_unique<PragmaSTDC_CX_LIMITED_RANGEHandler>();
Steven Wub96a3a42018-01-05 22:45:03 +0000311 PP.AddPragmaHandler("STDC", STDCCXLIMITHandler.get());
312
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000313 STDCUnknownHandler = std::make_unique<PragmaSTDC_UnknownHandler>();
Steven Wub96a3a42018-01-05 22:45:03 +0000314 PP.AddPragmaHandler("STDC", STDCUnknownHandler.get());
315
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000316 PCSectionHandler = std::make_unique<PragmaClangSectionHandler>(Actions);
Javed Absar2a67c9e2017-06-05 10:11:57 +0000317 PP.AddPragmaHandler("clang", PCSectionHandler.get());
318
Reid Kleckner5b086462014-02-20 22:52:09 +0000319 if (getLangOpts().OpenCL) {
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000320 OpenCLExtensionHandler = std::make_unique<PragmaOpenCLExtensionHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000321 PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
322
323 PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
324 }
325 if (getLangOpts().OpenMP)
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000326 OpenMPHandler = std::make_unique<PragmaOpenMPHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000327 else
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000328 OpenMPHandler = std::make_unique<PragmaNoOpenMPHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000329 PP.AddPragmaHandler(OpenMPHandler.get());
330
Saleem Abdulrasoolfd4db532018-02-07 01:46:46 +0000331 if (getLangOpts().MicrosoftExt ||
332 getTargetInfo().getTriple().isOSBinFormatELF()) {
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000333 MSCommentHandler = std::make_unique<PragmaCommentHandler>(Actions);
Reid Kleckner5b086462014-02-20 22:52:09 +0000334 PP.AddPragmaHandler(MSCommentHandler.get());
Yunzhong Gao99efc032015-03-23 20:41:42 +0000335 }
336
337 if (getLangOpts().MicrosoftExt) {
David Blaikiee0cfc042018-11-15 03:04:23 +0000338 MSDetectMismatchHandler =
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000339 std::make_unique<PragmaDetectMismatchHandler>(Actions);
Reid Kleckner5b086462014-02-20 22:52:09 +0000340 PP.AddPragmaHandler(MSDetectMismatchHandler.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000341 MSPointersToMembers = std::make_unique<PragmaMSPointersToMembers>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000342 PP.AddPragmaHandler(MSPointersToMembers.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000343 MSVtorDisp = std::make_unique<PragmaMSVtorDisp>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000344 PP.AddPragmaHandler(MSVtorDisp.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000345 MSInitSeg = std::make_unique<PragmaMSPragma>("init_seg");
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000346 PP.AddPragmaHandler(MSInitSeg.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000347 MSDataSeg = std::make_unique<PragmaMSPragma>("data_seg");
Warren Huntc3b18962014-04-08 22:30:47 +0000348 PP.AddPragmaHandler(MSDataSeg.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000349 MSBSSSeg = std::make_unique<PragmaMSPragma>("bss_seg");
Warren Huntc3b18962014-04-08 22:30:47 +0000350 PP.AddPragmaHandler(MSBSSSeg.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000351 MSConstSeg = std::make_unique<PragmaMSPragma>("const_seg");
Warren Huntc3b18962014-04-08 22:30:47 +0000352 PP.AddPragmaHandler(MSConstSeg.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000353 MSCodeSeg = std::make_unique<PragmaMSPragma>("code_seg");
Warren Huntc3b18962014-04-08 22:30:47 +0000354 PP.AddPragmaHandler(MSCodeSeg.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000355 MSSection = std::make_unique<PragmaMSPragma>("section");
Warren Huntc3b18962014-04-08 22:30:47 +0000356 PP.AddPragmaHandler(MSSection.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000357 MSRuntimeChecks = std::make_unique<PragmaMSRuntimeChecksHandler>();
Hans Wennborg7357bbc2015-10-12 20:47:58 +0000358 PP.AddPragmaHandler(MSRuntimeChecks.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000359 MSIntrinsic = std::make_unique<PragmaMSIntrinsicHandler>();
Reid Kleckner3f1ec622016-09-07 16:38:32 +0000360 PP.AddPragmaHandler(MSIntrinsic.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000361 MSOptimize = std::make_unique<PragmaMSOptimizeHandler>();
Hans Wennborg1bbe00e2018-03-20 08:53:11 +0000362 PP.AddPragmaHandler(MSOptimize.get());
Reid Kleckner5b086462014-02-20 22:52:09 +0000363 }
Eli Bendersky06a40422014-06-06 20:31:48 +0000364
Justin Lebar67a78a62016-10-08 22:15:58 +0000365 if (getLangOpts().CUDA) {
David Blaikiee0cfc042018-11-15 03:04:23 +0000366 CUDAForceHostDeviceHandler =
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000367 std::make_unique<PragmaForceCUDAHostDeviceHandler>(Actions);
Justin Lebar67a78a62016-10-08 22:15:58 +0000368 PP.AddPragmaHandler("clang", CUDAForceHostDeviceHandler.get());
369 }
370
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000371 OptimizeHandler = std::make_unique<PragmaOptimizeHandler>(Actions);
Eli Bendersky06a40422014-06-06 20:31:48 +0000372 PP.AddPragmaHandler("clang", OptimizeHandler.get());
373
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000374 LoopHintHandler = std::make_unique<PragmaLoopHintHandler>();
Eli Bendersky06a40422014-06-06 20:31:48 +0000375 PP.AddPragmaHandler("clang", LoopHintHandler.get());
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000376
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000377 UnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("unroll");
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000378 PP.AddPragmaHandler(UnrollHintHandler.get());
Mark Heffernanc888e412014-07-24 18:09:38 +0000379
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000380 NoUnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("nounroll");
Mark Heffernanc888e412014-07-24 18:09:38 +0000381 PP.AddPragmaHandler(NoUnrollHintHandler.get());
Adam Nemet60d32642017-04-04 21:18:36 +0000382
David Blaikiee0cfc042018-11-15 03:04:23 +0000383 UnrollAndJamHintHandler =
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000384 std::make_unique<PragmaUnrollHintHandler>("unroll_and_jam");
David Greenc8e39242018-08-01 14:36:12 +0000385 PP.AddPragmaHandler(UnrollAndJamHintHandler.get());
386
David Blaikiee0cfc042018-11-15 03:04:23 +0000387 NoUnrollAndJamHintHandler =
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000388 std::make_unique<PragmaUnrollHintHandler>("nounroll_and_jam");
David Greenc8e39242018-08-01 14:36:12 +0000389 PP.AddPragmaHandler(NoUnrollAndJamHintHandler.get());
390
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000391 FPHandler = std::make_unique<PragmaFPHandler>();
Adam Nemet60d32642017-04-04 21:18:36 +0000392 PP.AddPragmaHandler("clang", FPHandler.get());
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000393
David Blaikiee0cfc042018-11-15 03:04:23 +0000394 AttributePragmaHandler =
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000395 std::make_unique<PragmaAttributeHandler>(AttrFactory);
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000396 PP.AddPragmaHandler("clang", AttributePragmaHandler.get());
Hans Wennborg739b4102019-10-09 15:22:38 +0200397
398 MaxTokensHerePragmaHandler = std::make_unique<PragmaMaxTokensHereHandler>();
399 PP.AddPragmaHandler("clang", MaxTokensHerePragmaHandler.get());
400
401 MaxTokensTotalPragmaHandler = std::make_unique<PragmaMaxTokensTotalHandler>();
402 PP.AddPragmaHandler("clang", MaxTokensTotalPragmaHandler.get());
Eli Bendersky06a40422014-06-06 20:31:48 +0000403}
404
405void Parser::resetPragmaHandlers() {
Reid Kleckner5b086462014-02-20 22:52:09 +0000406 // Remove the pragma handlers we installed.
407 PP.RemovePragmaHandler(AlignHandler.get());
408 AlignHandler.reset();
409 PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
410 GCCVisibilityHandler.reset();
411 PP.RemovePragmaHandler(OptionsHandler.get());
412 OptionsHandler.reset();
413 PP.RemovePragmaHandler(PackHandler.get());
414 PackHandler.reset();
415 PP.RemovePragmaHandler(MSStructHandler.get());
416 MSStructHandler.reset();
417 PP.RemovePragmaHandler(UnusedHandler.get());
418 UnusedHandler.reset();
419 PP.RemovePragmaHandler(WeakHandler.get());
420 WeakHandler.reset();
421 PP.RemovePragmaHandler(RedefineExtnameHandler.get());
422 RedefineExtnameHandler.reset();
423
424 if (getLangOpts().OpenCL) {
425 PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
426 OpenCLExtensionHandler.reset();
427 PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
428 }
429 PP.RemovePragmaHandler(OpenMPHandler.get());
430 OpenMPHandler.reset();
431
Saleem Abdulrasoolfd4db532018-02-07 01:46:46 +0000432 if (getLangOpts().MicrosoftExt ||
433 getTargetInfo().getTriple().isOSBinFormatELF()) {
Reid Kleckner5b086462014-02-20 22:52:09 +0000434 PP.RemovePragmaHandler(MSCommentHandler.get());
435 MSCommentHandler.reset();
Yunzhong Gao99efc032015-03-23 20:41:42 +0000436 }
437
Javed Absar2a67c9e2017-06-05 10:11:57 +0000438 PP.RemovePragmaHandler("clang", PCSectionHandler.get());
439 PCSectionHandler.reset();
440
Yunzhong Gao99efc032015-03-23 20:41:42 +0000441 if (getLangOpts().MicrosoftExt) {
Reid Kleckner5b086462014-02-20 22:52:09 +0000442 PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
443 MSDetectMismatchHandler.reset();
444 PP.RemovePragmaHandler(MSPointersToMembers.get());
445 MSPointersToMembers.reset();
446 PP.RemovePragmaHandler(MSVtorDisp.get());
447 MSVtorDisp.reset();
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000448 PP.RemovePragmaHandler(MSInitSeg.get());
449 MSInitSeg.reset();
Warren Huntc3b18962014-04-08 22:30:47 +0000450 PP.RemovePragmaHandler(MSDataSeg.get());
451 MSDataSeg.reset();
452 PP.RemovePragmaHandler(MSBSSSeg.get());
453 MSBSSSeg.reset();
454 PP.RemovePragmaHandler(MSConstSeg.get());
455 MSConstSeg.reset();
456 PP.RemovePragmaHandler(MSCodeSeg.get());
457 MSCodeSeg.reset();
458 PP.RemovePragmaHandler(MSSection.get());
459 MSSection.reset();
Hans Wennborg7357bbc2015-10-12 20:47:58 +0000460 PP.RemovePragmaHandler(MSRuntimeChecks.get());
461 MSRuntimeChecks.reset();
Reid Kleckner3f1ec622016-09-07 16:38:32 +0000462 PP.RemovePragmaHandler(MSIntrinsic.get());
463 MSIntrinsic.reset();
Hans Wennborg1bbe00e2018-03-20 08:53:11 +0000464 PP.RemovePragmaHandler(MSOptimize.get());
465 MSOptimize.reset();
Reid Kleckner5b086462014-02-20 22:52:09 +0000466 }
467
Justin Lebar67a78a62016-10-08 22:15:58 +0000468 if (getLangOpts().CUDA) {
469 PP.RemovePragmaHandler("clang", CUDAForceHostDeviceHandler.get());
470 CUDAForceHostDeviceHandler.reset();
471 }
472
Reid Kleckner5b086462014-02-20 22:52:09 +0000473 PP.RemovePragmaHandler("STDC", FPContractHandler.get());
474 FPContractHandler.reset();
Eli Bendersky06a40422014-06-06 20:31:48 +0000475
Steven Wub96a3a42018-01-05 22:45:03 +0000476 PP.RemovePragmaHandler("STDC", STDCFENVHandler.get());
477 STDCFENVHandler.reset();
478
479 PP.RemovePragmaHandler("STDC", STDCCXLIMITHandler.get());
480 STDCCXLIMITHandler.reset();
481
482 PP.RemovePragmaHandler("STDC", STDCUnknownHandler.get());
483 STDCUnknownHandler.reset();
484
Eli Bendersky06a40422014-06-06 20:31:48 +0000485 PP.RemovePragmaHandler("clang", OptimizeHandler.get());
486 OptimizeHandler.reset();
487
488 PP.RemovePragmaHandler("clang", LoopHintHandler.get());
489 LoopHintHandler.reset();
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000490
491 PP.RemovePragmaHandler(UnrollHintHandler.get());
492 UnrollHintHandler.reset();
Mark Heffernanc888e412014-07-24 18:09:38 +0000493
494 PP.RemovePragmaHandler(NoUnrollHintHandler.get());
495 NoUnrollHintHandler.reset();
Adam Nemet60d32642017-04-04 21:18:36 +0000496
David Greenc8e39242018-08-01 14:36:12 +0000497 PP.RemovePragmaHandler(UnrollAndJamHintHandler.get());
498 UnrollAndJamHintHandler.reset();
499
500 PP.RemovePragmaHandler(NoUnrollAndJamHintHandler.get());
501 NoUnrollAndJamHintHandler.reset();
502
Adam Nemet60d32642017-04-04 21:18:36 +0000503 PP.RemovePragmaHandler("clang", FPHandler.get());
504 FPHandler.reset();
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000505
506 PP.RemovePragmaHandler("clang", AttributePragmaHandler.get());
507 AttributePragmaHandler.reset();
Hans Wennborg739b4102019-10-09 15:22:38 +0200508
509 PP.RemovePragmaHandler("clang", MaxTokensHerePragmaHandler.get());
510 MaxTokensHerePragmaHandler.reset();
511
512 PP.RemovePragmaHandler("clang", MaxTokensTotalPragmaHandler.get());
513 MaxTokensTotalPragmaHandler.reset();
Eli Bendersky06a40422014-06-06 20:31:48 +0000514}
515
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000516/// Handle the annotation token produced for #pragma unused(...)
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000517///
518/// Each annot_pragma_unused is followed by the argument token so e.g.
519/// "#pragma unused(x,y)" becomes:
520/// annot_pragma_unused 'x' annot_pragma_unused 'y'
521void Parser::HandlePragmaUnused() {
522 assert(Tok.is(tok::annot_pragma_unused));
Richard Smithaf3b3252017-05-18 19:21:48 +0000523 SourceLocation UnusedLoc = ConsumeAnnotationToken();
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000524 Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
525 ConsumeToken(); // The argument token.
526}
Eli Friedman570024a2010-08-05 06:57:20 +0000527
Rafael Espindola273fd772012-01-26 02:02:57 +0000528void Parser::HandlePragmaVisibility() {
529 assert(Tok.is(tok::annot_pragma_vis));
530 const IdentifierInfo *VisType =
531 static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
Richard Smithaf3b3252017-05-18 19:21:48 +0000532 SourceLocation VisLoc = ConsumeAnnotationToken();
Rafael Espindola273fd772012-01-26 02:02:57 +0000533 Actions.ActOnPragmaVisibility(VisType, VisLoc);
534}
535
Benjamin Kramere003ca22015-10-28 13:54:16 +0000536namespace {
Eli Friedmanec52f922012-02-23 23:47:16 +0000537struct PragmaPackInfo {
Denis Zobnin10c4f452016-04-29 18:17:40 +0000538 Sema::PragmaMsStackAction Action;
539 StringRef SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +0000540 Token Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +0000541};
Benjamin Kramere003ca22015-10-28 13:54:16 +0000542} // end anonymous namespace
Eli Friedmanec52f922012-02-23 23:47:16 +0000543
544void Parser::HandlePragmaPack() {
545 assert(Tok.is(tok::annot_pragma_pack));
546 PragmaPackInfo *Info =
547 static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
Alex Lorenz45b40142017-07-28 14:41:21 +0000548 SourceLocation PragmaLoc = Tok.getLocation();
Eli Friedman68be1642012-10-04 02:36:51 +0000549 ExprResult Alignment;
550 if (Info->Alignment.is(tok::numeric_constant)) {
551 Alignment = Actions.ActOnNumericConstant(Info->Alignment);
Alex Lorenz45b40142017-07-28 14:41:21 +0000552 if (Alignment.isInvalid()) {
553 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000554 return;
Alex Lorenz45b40142017-07-28 14:41:21 +0000555 }
Eli Friedman68be1642012-10-04 02:36:51 +0000556 }
Denis Zobnin10c4f452016-04-29 18:17:40 +0000557 Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel,
558 Alignment.get());
Alex Lorenz45b40142017-07-28 14:41:21 +0000559 // Consume the token after processing the pragma to enable pragma-specific
560 // #include warnings.
561 ConsumeAnnotationToken();
Eli Friedmanec52f922012-02-23 23:47:16 +0000562}
563
Eli Friedman68be1642012-10-04 02:36:51 +0000564void Parser::HandlePragmaMSStruct() {
565 assert(Tok.is(tok::annot_pragma_msstruct));
Nico Weber779355f2016-03-02 23:22:00 +0000566 PragmaMSStructKind Kind = static_cast<PragmaMSStructKind>(
567 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Eli Friedman68be1642012-10-04 02:36:51 +0000568 Actions.ActOnPragmaMSStruct(Kind);
Richard Smithaf3b3252017-05-18 19:21:48 +0000569 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000570}
571
572void Parser::HandlePragmaAlign() {
573 assert(Tok.is(tok::annot_pragma_align));
574 Sema::PragmaOptionsAlignKind Kind =
575 static_cast<Sema::PragmaOptionsAlignKind>(
576 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Alex Lorenz692821a2018-02-08 21:20:43 +0000577 Actions.ActOnPragmaOptionsAlign(Kind, Tok.getLocation());
578 // Consume the token after processing the pragma to enable pragma-specific
579 // #include warnings.
580 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000581}
582
Richard Smithba3a4f92016-01-12 21:59:26 +0000583void Parser::HandlePragmaDump() {
584 assert(Tok.is(tok::annot_pragma_dump));
585 IdentifierInfo *II =
586 reinterpret_cast<IdentifierInfo *>(Tok.getAnnotationValue());
587 Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II);
Richard Smithaf3b3252017-05-18 19:21:48 +0000588 ConsumeAnnotationToken();
Richard Smithba3a4f92016-01-12 21:59:26 +0000589}
590
Eli Friedman68be1642012-10-04 02:36:51 +0000591void Parser::HandlePragmaWeak() {
592 assert(Tok.is(tok::annot_pragma_weak));
Richard Smithaf3b3252017-05-18 19:21:48 +0000593 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000594 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
595 Tok.getLocation());
596 ConsumeToken(); // The weak name.
597}
598
599void Parser::HandlePragmaWeakAlias() {
600 assert(Tok.is(tok::annot_pragma_weakalias));
Richard Smithaf3b3252017-05-18 19:21:48 +0000601 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000602 IdentifierInfo *WeakName = Tok.getIdentifierInfo();
603 SourceLocation WeakNameLoc = Tok.getLocation();
604 ConsumeToken();
605 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
606 SourceLocation AliasNameLoc = Tok.getLocation();
607 ConsumeToken();
608 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
609 WeakNameLoc, AliasNameLoc);
610
611}
612
613void Parser::HandlePragmaRedefineExtname() {
614 assert(Tok.is(tok::annot_pragma_redefine_extname));
Richard Smithaf3b3252017-05-18 19:21:48 +0000615 SourceLocation RedefLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000616 IdentifierInfo *RedefName = Tok.getIdentifierInfo();
617 SourceLocation RedefNameLoc = Tok.getLocation();
618 ConsumeToken();
619 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
620 SourceLocation AliasNameLoc = Tok.getLocation();
621 ConsumeToken();
622 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
623 RedefNameLoc, AliasNameLoc);
624}
625
626void Parser::HandlePragmaFPContract() {
627 assert(Tok.is(tok::annot_pragma_fp_contract));
628 tok::OnOffSwitch OOS =
629 static_cast<tok::OnOffSwitch>(
630 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Adam Nemet60d32642017-04-04 21:18:36 +0000631
632 LangOptions::FPContractModeKind FPC;
633 switch (OOS) {
634 case tok::OOS_ON:
635 FPC = LangOptions::FPC_On;
636 break;
637 case tok::OOS_OFF:
638 FPC = LangOptions::FPC_Off;
639 break;
640 case tok::OOS_DEFAULT:
641 FPC = getLangOpts().getDefaultFPContractMode();
642 break;
643 }
644
645 Actions.ActOnPragmaFPContract(FPC);
Richard Smithaf3b3252017-05-18 19:21:48 +0000646 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000647}
648
Kevin P. Neal2c0bc8b2018-08-14 17:06:56 +0000649void Parser::HandlePragmaFEnvAccess() {
650 assert(Tok.is(tok::annot_pragma_fenv_access));
651 tok::OnOffSwitch OOS =
652 static_cast<tok::OnOffSwitch>(
653 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
654
655 LangOptions::FEnvAccessModeKind FPC;
656 switch (OOS) {
657 case tok::OOS_ON:
658 FPC = LangOptions::FEA_On;
659 break;
660 case tok::OOS_OFF:
661 FPC = LangOptions::FEA_Off;
662 break;
663 case tok::OOS_DEFAULT: // FIXME: Add this cli option when it makes sense.
664 FPC = LangOptions::FEA_Off;
665 break;
666 }
667
668 Actions.ActOnPragmaFEnvAccess(FPC);
669 ConsumeAnnotationToken();
670}
671
672
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000673StmtResult Parser::HandlePragmaCaptured()
674{
675 assert(Tok.is(tok::annot_pragma_captured));
Richard Smithaf3b3252017-05-18 19:21:48 +0000676 ConsumeAnnotationToken();
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000677
678 if (Tok.isNot(tok::l_brace)) {
Alp Tokerec543272013-12-24 09:48:30 +0000679 PP.Diag(Tok, diag::err_expected) << tok::l_brace;
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000680 return StmtError();
681 }
682
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000683 SourceLocation Loc = Tok.getLocation();
684
Momchil Velikov57c681f2017-08-10 15:43:06 +0000685 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope |
686 Scope::CompoundStmtScope);
Ben Langmuir37943a72013-05-03 19:00:33 +0000687 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
688 /*NumParams=*/1);
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000689
690 StmtResult R = ParseCompoundStatement();
691 CapturedRegionScope.Exit();
692
693 if (R.isInvalid()) {
694 Actions.ActOnCapturedRegionError();
695 return StmtError();
696 }
697
698 return Actions.ActOnCapturedRegionEnd(R.get());
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000699}
700
Eli Friedman68be1642012-10-04 02:36:51 +0000701namespace {
Yaxun Liu5b746652016-12-18 05:18:55 +0000702 enum OpenCLExtState : char {
703 Disable, Enable, Begin, End
704 };
705 typedef std::pair<const IdentifierInfo *, OpenCLExtState> OpenCLExtData;
Eli Friedman68be1642012-10-04 02:36:51 +0000706}
707
708void Parser::HandlePragmaOpenCLExtension() {
709 assert(Tok.is(tok::annot_pragma_opencl_extension));
Yaxun Liu5b746652016-12-18 05:18:55 +0000710 OpenCLExtData *Data = static_cast<OpenCLExtData*>(Tok.getAnnotationValue());
711 auto State = Data->second;
712 auto Ident = Data->first;
Eli Friedman68be1642012-10-04 02:36:51 +0000713 SourceLocation NameLoc = Tok.getLocation();
Richard Smithaf3b3252017-05-18 19:21:48 +0000714 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000715
Yaxun Liu5b746652016-12-18 05:18:55 +0000716 auto &Opt = Actions.getOpenCLOptions();
717 auto Name = Ident->getName();
Eli Friedman68be1642012-10-04 02:36:51 +0000718 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
719 // overriding all previously issued extension directives, but only if the
720 // behavior is set to disable."
Yaxun Liu5b746652016-12-18 05:18:55 +0000721 if (Name == "all") {
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000722 if (State == Disable) {
Yaxun Liu5b746652016-12-18 05:18:55 +0000723 Opt.disableAll();
Anastasia Stulovae88e2b92019-02-07 17:32:37 +0000724 Opt.enableSupportedCore(getLangOpts());
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000725 } else {
Yaxun Liu5b746652016-12-18 05:18:55 +0000726 PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1;
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000727 }
Yaxun Liu5b746652016-12-18 05:18:55 +0000728 } else if (State == Begin) {
Anastasia Stulovae88e2b92019-02-07 17:32:37 +0000729 if (!Opt.isKnown(Name) || !Opt.isSupported(Name, getLangOpts())) {
Yaxun Liu5b746652016-12-18 05:18:55 +0000730 Opt.support(Name);
731 }
732 Actions.setCurrentOpenCLExtension(Name);
733 } else if (State == End) {
734 if (Name != Actions.getCurrentOpenCLExtension())
735 PP.Diag(NameLoc, diag::warn_pragma_begin_end_mismatch);
736 Actions.setCurrentOpenCLExtension("");
737 } else if (!Opt.isKnown(Name))
738 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;
Anastasia Stulovae88e2b92019-02-07 17:32:37 +0000739 else if (Opt.isSupportedExtension(Name, getLangOpts()))
Yaxun Liu5b746652016-12-18 05:18:55 +0000740 Opt.enable(Name, State == Enable);
Anastasia Stulovae88e2b92019-02-07 17:32:37 +0000741 else if (Opt.isSupportedCore(Name, getLangOpts()))
Yaxun Liu5b746652016-12-18 05:18:55 +0000742 PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident;
743 else
744 PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident;
Eli Friedman68be1642012-10-04 02:36:51 +0000745}
746
David Majnemer4bb09802014-02-10 19:50:15 +0000747void Parser::HandlePragmaMSPointersToMembers() {
748 assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
David Majnemer86c318f2014-02-11 21:05:00 +0000749 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
750 static_cast<LangOptions::PragmaMSPointersToMembersKind>(
David Majnemer4bb09802014-02-10 19:50:15 +0000751 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Richard Smithaf3b3252017-05-18 19:21:48 +0000752 SourceLocation PragmaLoc = ConsumeAnnotationToken();
David Majnemer4bb09802014-02-10 19:50:15 +0000753 Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
754}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000755
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000756void Parser::HandlePragmaMSVtorDisp() {
757 assert(Tok.is(tok::annot_pragma_ms_vtordisp));
758 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
Denis Zobnin2290dac2016-04-29 11:27:00 +0000759 Sema::PragmaMsStackAction Action =
760 static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
Reid Kleckner2692eb02019-11-22 14:55:49 -0800761 MSVtorDispMode Mode = MSVtorDispMode(Value & 0xFFFF);
Richard Smithaf3b3252017-05-18 19:21:48 +0000762 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Denis Zobnin2290dac2016-04-29 11:27:00 +0000763 Actions.ActOnPragmaMSVtorDisp(Action, PragmaLoc, Mode);
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000764}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000765
Warren Huntc3b18962014-04-08 22:30:47 +0000766void Parser::HandlePragmaMSPragma() {
767 assert(Tok.is(tok::annot_pragma_ms_pragma));
768 // Grab the tokens out of the annotation and enter them into the stream.
David Blaikie2eabcc92016-02-09 18:52:09 +0000769 auto TheTokens =
770 (std::pair<std::unique_ptr<Token[]>, size_t> *)Tok.getAnnotationValue();
Ilya Biryukov929af672019-05-17 09:32:05 +0000771 PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true,
772 /*IsReinject=*/true);
Richard Smithaf3b3252017-05-18 19:21:48 +0000773 SourceLocation PragmaLocation = ConsumeAnnotationToken();
Warren Huntc3b18962014-04-08 22:30:47 +0000774 assert(Tok.isAnyIdentifier());
Reid Kleckner722b1df2014-07-18 00:13:16 +0000775 StringRef PragmaName = Tok.getIdentifierInfo()->getName();
Warren Huntc3b18962014-04-08 22:30:47 +0000776 PP.Lex(Tok); // pragma kind
Reid Kleckner722b1df2014-07-18 00:13:16 +0000777
Warren Huntc3b18962014-04-08 22:30:47 +0000778 // Figure out which #pragma we're dealing with. The switch has no default
779 // because lex shouldn't emit the annotation token for unrecognized pragmas.
Reid Kleckner722b1df2014-07-18 00:13:16 +0000780 typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
Warren Huntc3b18962014-04-08 22:30:47 +0000781 PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
782 .Case("data_seg", &Parser::HandlePragmaMSSegment)
783 .Case("bss_seg", &Parser::HandlePragmaMSSegment)
784 .Case("const_seg", &Parser::HandlePragmaMSSegment)
785 .Case("code_seg", &Parser::HandlePragmaMSSegment)
786 .Case("section", &Parser::HandlePragmaMSSection)
787 .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000788
789 if (!(this->*Handler)(PragmaName, PragmaLocation)) {
790 // Pragma handling failed, and has been diagnosed. Slurp up the tokens
791 // until eof (really end of line) to prevent follow-on errors.
Warren Huntc3b18962014-04-08 22:30:47 +0000792 while (Tok.isNot(tok::eof))
793 PP.Lex(Tok);
794 PP.Lex(Tok);
795 }
796}
797
Reid Kleckner722b1df2014-07-18 00:13:16 +0000798bool Parser::HandlePragmaMSSection(StringRef PragmaName,
799 SourceLocation PragmaLocation) {
800 if (Tok.isNot(tok::l_paren)) {
801 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
802 return false;
803 }
Warren Huntc3b18962014-04-08 22:30:47 +0000804 PP.Lex(Tok); // (
805 // Parsing code for pragma section
Reid Kleckner722b1df2014-07-18 00:13:16 +0000806 if (Tok.isNot(tok::string_literal)) {
807 PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
808 << PragmaName;
809 return false;
810 }
811 ExprResult StringResult = ParseStringLiteralExpression();
812 if (StringResult.isInvalid())
813 return false; // Already diagnosed.
814 StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
815 if (SegmentName->getCharByteWidth() != 1) {
816 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
817 << PragmaName;
818 return false;
819 }
David Majnemer48c28fa2014-10-22 21:08:43 +0000820 int SectionFlags = ASTContext::PSF_Read;
821 bool SectionFlagsAreDefault = true;
Warren Huntc3b18962014-04-08 22:30:47 +0000822 while (Tok.is(tok::comma)) {
823 PP.Lex(Tok); // ,
David Majnemer48c28fa2014-10-22 21:08:43 +0000824 // Ignore "long" and "short".
825 // They are undocumented, but widely used, section attributes which appear
826 // to do nothing.
827 if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) {
828 PP.Lex(Tok); // long/short
829 continue;
830 }
831
Reid Kleckner722b1df2014-07-18 00:13:16 +0000832 if (!Tok.isAnyIdentifier()) {
833 PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
834 << PragmaName;
835 return false;
836 }
Hans Wennborg899ded92014-10-16 20:52:46 +0000837 ASTContext::PragmaSectionFlag Flag =
838 llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
Warren Huntc3b18962014-04-08 22:30:47 +0000839 Tok.getIdentifierInfo()->getName())
Hans Wennborg899ded92014-10-16 20:52:46 +0000840 .Case("read", ASTContext::PSF_Read)
841 .Case("write", ASTContext::PSF_Write)
842 .Case("execute", ASTContext::PSF_Execute)
843 .Case("shared", ASTContext::PSF_Invalid)
844 .Case("nopage", ASTContext::PSF_Invalid)
845 .Case("nocache", ASTContext::PSF_Invalid)
846 .Case("discard", ASTContext::PSF_Invalid)
847 .Case("remove", ASTContext::PSF_Invalid)
848 .Default(ASTContext::PSF_None);
849 if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) {
850 PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
Reid Kleckner722b1df2014-07-18 00:13:16 +0000851 ? diag::warn_pragma_invalid_specific_action
852 : diag::warn_pragma_unsupported_action)
Warren Huntc3b18962014-04-08 22:30:47 +0000853 << PragmaName << Tok.getIdentifierInfo()->getName();
Reid Kleckner722b1df2014-07-18 00:13:16 +0000854 return false;
Warren Huntc3b18962014-04-08 22:30:47 +0000855 }
856 SectionFlags |= Flag;
David Majnemer48c28fa2014-10-22 21:08:43 +0000857 SectionFlagsAreDefault = false;
Warren Huntc3b18962014-04-08 22:30:47 +0000858 PP.Lex(Tok); // Identifier
859 }
David Majnemer48c28fa2014-10-22 21:08:43 +0000860 // If no section attributes are specified, the section will be marked as
861 // read/write.
862 if (SectionFlagsAreDefault)
863 SectionFlags |= ASTContext::PSF_Write;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000864 if (Tok.isNot(tok::r_paren)) {
865 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
866 return false;
867 }
Warren Huntc3b18962014-04-08 22:30:47 +0000868 PP.Lex(Tok); // )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000869 if (Tok.isNot(tok::eof)) {
870 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
871 << PragmaName;
872 return false;
873 }
Warren Huntc3b18962014-04-08 22:30:47 +0000874 PP.Lex(Tok); // eof
875 Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000876 return true;
Warren Huntc3b18962014-04-08 22:30:47 +0000877}
878
Reid Kleckner722b1df2014-07-18 00:13:16 +0000879bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
880 SourceLocation PragmaLocation) {
881 if (Tok.isNot(tok::l_paren)) {
882 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
883 return false;
884 }
Warren Huntc3b18962014-04-08 22:30:47 +0000885 PP.Lex(Tok); // (
886 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000887 StringRef SlotLabel;
Warren Huntc3b18962014-04-08 22:30:47 +0000888 if (Tok.isAnyIdentifier()) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000889 StringRef PushPop = Tok.getIdentifierInfo()->getName();
Warren Huntc3b18962014-04-08 22:30:47 +0000890 if (PushPop == "push")
891 Action = Sema::PSK_Push;
892 else if (PushPop == "pop")
893 Action = Sema::PSK_Pop;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000894 else {
895 PP.Diag(PragmaLocation,
896 diag::warn_pragma_expected_section_push_pop_or_name)
897 << PragmaName;
898 return false;
899 }
Warren Huntc3b18962014-04-08 22:30:47 +0000900 if (Action != Sema::PSK_Reset) {
901 PP.Lex(Tok); // push | pop
902 if (Tok.is(tok::comma)) {
903 PP.Lex(Tok); // ,
904 // If we've got a comma, we either need a label or a string.
905 if (Tok.isAnyIdentifier()) {
906 SlotLabel = Tok.getIdentifierInfo()->getName();
907 PP.Lex(Tok); // identifier
908 if (Tok.is(tok::comma))
909 PP.Lex(Tok);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000910 else if (Tok.isNot(tok::r_paren)) {
911 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
912 << PragmaName;
913 return false;
914 }
Warren Huntc3b18962014-04-08 22:30:47 +0000915 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000916 } else if (Tok.isNot(tok::r_paren)) {
917 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
918 return false;
919 }
Warren Huntc3b18962014-04-08 22:30:47 +0000920 }
921 }
922 // Grab the string literal for our section name.
923 StringLiteral *SegmentName = nullptr;
924 if (Tok.isNot(tok::r_paren)) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000925 if (Tok.isNot(tok::string_literal)) {
926 unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
Warren Huntc3b18962014-04-08 22:30:47 +0000927 diag::warn_pragma_expected_section_name :
928 diag::warn_pragma_expected_section_label_or_name :
929 diag::warn_pragma_expected_section_push_pop_or_name;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000930 PP.Diag(PragmaLocation, DiagID) << PragmaName;
931 return false;
932 }
933 ExprResult StringResult = ParseStringLiteralExpression();
934 if (StringResult.isInvalid())
935 return false; // Already diagnosed.
936 SegmentName = cast<StringLiteral>(StringResult.get());
937 if (SegmentName->getCharByteWidth() != 1) {
938 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
939 << PragmaName;
940 return false;
941 }
Warren Huntc3b18962014-04-08 22:30:47 +0000942 // Setting section "" has no effect
943 if (SegmentName->getLength())
944 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
945 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000946 if (Tok.isNot(tok::r_paren)) {
947 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
948 return false;
949 }
Warren Huntc3b18962014-04-08 22:30:47 +0000950 PP.Lex(Tok); // )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000951 if (Tok.isNot(tok::eof)) {
952 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
953 << PragmaName;
954 return false;
955 }
Warren Huntc3b18962014-04-08 22:30:47 +0000956 PP.Lex(Tok); // eof
957 Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
958 SegmentName, PragmaName);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000959 return true;
Warren Huntc3b18962014-04-08 22:30:47 +0000960}
961
Reid Kleckner1a711b12014-07-22 00:53:05 +0000962// #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000963bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
964 SourceLocation PragmaLocation) {
David Majnemerad2986e2014-08-14 06:35:08 +0000965 if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
966 PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
967 return false;
968 }
969
Reid Kleckner1a711b12014-07-22 00:53:05 +0000970 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
971 PragmaName))
972 return false;
973
974 // Parse either the known section names or the string section name.
975 StringLiteral *SegmentName = nullptr;
976 if (Tok.isAnyIdentifier()) {
977 auto *II = Tok.getIdentifierInfo();
978 StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
979 .Case("compiler", "\".CRT$XCC\"")
980 .Case("lib", "\".CRT$XCL\"")
981 .Case("user", "\".CRT$XCU\"")
982 .Default("");
983
984 if (!Section.empty()) {
985 // Pretend the user wrote the appropriate string literal here.
986 Token Toks[1];
987 Toks[0].startToken();
988 Toks[0].setKind(tok::string_literal);
989 Toks[0].setLocation(Tok.getLocation());
990 Toks[0].setLiteralData(Section.data());
991 Toks[0].setLength(Section.size());
992 SegmentName =
993 cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
994 PP.Lex(Tok);
995 }
996 } else if (Tok.is(tok::string_literal)) {
997 ExprResult StringResult = ParseStringLiteralExpression();
998 if (StringResult.isInvalid())
999 return false;
1000 SegmentName = cast<StringLiteral>(StringResult.get());
1001 if (SegmentName->getCharByteWidth() != 1) {
1002 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
1003 << PragmaName;
1004 return false;
1005 }
1006 // FIXME: Add support for the '[, func-name]' part of the pragma.
1007 }
1008
1009 if (!SegmentName) {
1010 PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
1011 return false;
1012 }
1013
1014 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
1015 PragmaName) ||
1016 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
1017 PragmaName))
1018 return false;
1019
1020 Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
1021 return true;
Eli Bendersky06a40422014-06-06 20:31:48 +00001022}
1023
Benjamin Kramere003ca22015-10-28 13:54:16 +00001024namespace {
Eli Bendersky06a40422014-06-06 20:31:48 +00001025struct PragmaLoopHintInfo {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001026 Token PragmaName;
Eli Bendersky06a40422014-06-06 20:31:48 +00001027 Token Option;
Benjamin Kramerfa7f8552015-08-05 09:39:57 +00001028 ArrayRef<Token> Toks;
Eli Bendersky06a40422014-06-06 20:31:48 +00001029};
Benjamin Kramere003ca22015-10-28 13:54:16 +00001030} // end anonymous namespace
Eli Bendersky06a40422014-06-06 20:31:48 +00001031
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001032static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
Sjoerd Meijer90374f72019-08-15 07:39:05 +00001033 StringRef Str = PragmaName.getIdentifierInfo()->getName();
1034 std::string ClangLoopStr = (llvm::Twine("clang loop ") + Str).str();
Benjamin Krameradcd0262020-01-28 20:23:46 +01001035 return std::string(llvm::StringSwitch<StringRef>(Str)
1036 .Case("loop", ClangLoopStr)
1037 .Case("unroll_and_jam", Str)
1038 .Case("unroll", Str)
1039 .Default(""));
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001040}
1041
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001042bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
Eli Bendersky06a40422014-06-06 20:31:48 +00001043 assert(Tok.is(tok::annot_pragma_loop_hint));
1044 PragmaLoopHintInfo *Info =
1045 static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
1046
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001047 IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
1048 Hint.PragmaNameLoc = IdentifierLoc::create(
1049 Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);
Eli Bendersky06a40422014-06-06 20:31:48 +00001050
Aaron Ballmanef940aa2014-07-31 21:24:32 +00001051 // It is possible that the loop hint has no option identifier, such as
1052 // #pragma unroll(4).
1053 IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
1054 ? Info->Option.getIdentifierInfo()
1055 : nullptr;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001056 Hint.OptionLoc = IdentifierLoc::create(
1057 Actions.Context, Info->Option.getLocation(), OptionInfo);
1058
David Blaikie2eabcc92016-02-09 18:52:09 +00001059 llvm::ArrayRef<Token> Toks = Info->Toks;
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001060
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001061 // Return a valid hint if pragma unroll or nounroll were specified
1062 // without an argument.
Sjoerd Meijer90374f72019-08-15 07:39:05 +00001063 auto IsLoopHint = llvm::StringSwitch<bool>(PragmaNameInfo->getName())
1064 .Cases("unroll", "nounroll", "unroll_and_jam",
1065 "nounroll_and_jam", true)
1066 .Default(false);
1067
1068 if (Toks.empty() && IsLoopHint) {
Richard Smithaf3b3252017-05-18 19:21:48 +00001069 ConsumeAnnotationToken();
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001070 Hint.Range = Info->PragmaName.getLocation();
1071 return true;
1072 }
1073
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001074 // The constant expression is always followed by an eof token, which increases
1075 // the TokSize by 1.
David Blaikie2eabcc92016-02-09 18:52:09 +00001076 assert(!Toks.empty() &&
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001077 "PragmaLoopHintInfo::Toks must contain at least one token.");
1078
1079 // If no option is specified the argument is assumed to be a constant expr.
Tyler Nowicki24853c12015-06-08 23:13:43 +00001080 bool OptionUnroll = false;
David Greenc8e39242018-08-01 14:36:12 +00001081 bool OptionUnrollAndJam = false;
Adam Nemet2de463e2016-06-14 12:04:26 +00001082 bool OptionDistribute = false;
Aaron Ballman9bdf5152019-01-04 17:20:00 +00001083 bool OptionPipelineDisabled = false;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001084 bool StateOption = false;
Tyler Nowicki24853c12015-06-08 23:13:43 +00001085 if (OptionInfo) { // Pragma Unroll does not specify an option.
1086 OptionUnroll = OptionInfo->isStr("unroll");
David Greenc8e39242018-08-01 14:36:12 +00001087 OptionUnrollAndJam = OptionInfo->isStr("unroll_and_jam");
Adam Nemet2de463e2016-06-14 12:04:26 +00001088 OptionDistribute = OptionInfo->isStr("distribute");
Aaron Ballman9bdf5152019-01-04 17:20:00 +00001089 OptionPipelineDisabled = OptionInfo->isStr("pipeline");
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001090 StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
1091 .Case("vectorize", true)
1092 .Case("interleave", true)
Sjoerd Meijera48f58c2019-07-25 07:33:13 +00001093 .Case("vectorize_predicate", true)
Adam Nemet2de463e2016-06-14 12:04:26 +00001094 .Default(false) ||
Aaron Ballman9bdf5152019-01-04 17:20:00 +00001095 OptionUnroll || OptionUnrollAndJam || OptionDistribute ||
1096 OptionPipelineDisabled;
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001097 }
1098
Aaron Ballman9bdf5152019-01-04 17:20:00 +00001099 bool AssumeSafetyArg = !OptionUnroll && !OptionUnrollAndJam &&
1100 !OptionDistribute && !OptionPipelineDisabled;
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001101 // Verify loop hint has an argument.
1102 if (Toks[0].is(tok::eof)) {
Richard Smithaf3b3252017-05-18 19:21:48 +00001103 ConsumeAnnotationToken();
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001104 Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
David Greenc8e39242018-08-01 14:36:12 +00001105 << /*StateArgument=*/StateOption
1106 << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
Adam Nemet2de463e2016-06-14 12:04:26 +00001107 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001108 return false;
1109 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001110
1111 // Validate the argument.
1112 if (StateOption) {
Richard Smithaf3b3252017-05-18 19:21:48 +00001113 ConsumeAnnotationToken();
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001114 SourceLocation StateLoc = Toks[0].getLocation();
1115 IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
Adam Nemet50de4e82016-04-19 22:17:45 +00001116
Aaron Ballman9bdf5152019-01-04 17:20:00 +00001117 bool Valid = StateInfo &&
1118 llvm::StringSwitch<bool>(StateInfo->getName())
1119 .Case("disable", true)
1120 .Case("enable", !OptionPipelineDisabled)
1121 .Case("full", OptionUnroll || OptionUnrollAndJam)
1122 .Case("assume_safety", AssumeSafetyArg)
1123 .Default(false);
Adam Nemet50de4e82016-04-19 22:17:45 +00001124 if (!Valid) {
Aaron Ballman9bdf5152019-01-04 17:20:00 +00001125 if (OptionPipelineDisabled) {
1126 Diag(Toks[0].getLocation(), diag::err_pragma_pipeline_invalid_keyword);
1127 } else {
1128 Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
1129 << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
1130 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
1131 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001132 return false;
1133 }
David Blaikie2eabcc92016-02-09 18:52:09 +00001134 if (Toks.size() > 2)
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001135 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1136 << PragmaLoopHintString(Info->PragmaName, Info->Option);
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001137 Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
1138 } else {
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001139 // Enter constant expression including eof terminator into token stream.
Ilya Biryukov929af672019-05-17 09:32:05 +00001140 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false,
1141 /*IsReinject=*/false);
Richard Smithaf3b3252017-05-18 19:21:48 +00001142 ConsumeAnnotationToken();
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001143
1144 ExprResult R = ParseConstantExpression();
1145
1146 // Tokens following an error in an ill-formed constant expression will
1147 // remain in the token stream and must be removed.
1148 if (Tok.isNot(tok::eof)) {
1149 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1150 << PragmaLoopHintString(Info->PragmaName, Info->Option);
1151 while (Tok.isNot(tok::eof))
1152 ConsumeAnyToken();
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001153 }
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001154
1155 ConsumeToken(); // Consume the constant expression eof terminator.
1156
1157 if (R.isInvalid() ||
1158 Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
1159 return false;
1160
1161 // Argument is a constant expression with an integer type.
1162 Hint.ValueExpr = R.get();
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001163 }
Eli Bendersky06a40422014-06-06 20:31:48 +00001164
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001165 Hint.Range = SourceRange(Info->PragmaName.getLocation(),
David Blaikie2eabcc92016-02-09 18:52:09 +00001166 Info->Toks.back().getLocation());
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001167 return true;
Eli Bendersky06a40422014-06-06 20:31:48 +00001168}
1169
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001170namespace {
1171struct PragmaAttributeInfo {
Erik Pilkington7d180942018-10-29 17:38:42 +00001172 enum ActionType { Push, Pop, Attribute };
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001173 ParsedAttributes &Attributes;
1174 ActionType Action;
Erik Pilkington0876cae2018-12-20 22:32:04 +00001175 const IdentifierInfo *Namespace = nullptr;
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001176 ArrayRef<Token> Tokens;
1177
1178 PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {}
1179};
1180
1181#include "clang/Parse/AttrSubMatchRulesParserStringSwitches.inc"
1182
1183} // end anonymous namespace
1184
1185static StringRef getIdentifier(const Token &Tok) {
1186 if (Tok.is(tok::identifier))
1187 return Tok.getIdentifierInfo()->getName();
1188 const char *S = tok::getKeywordSpelling(Tok.getKind());
1189 if (!S)
1190 return "";
1191 return S;
1192}
1193
1194static bool isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule) {
1195 using namespace attr;
1196 switch (Rule) {
1197#define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) \
1198 case Value: \
1199 return IsAbstract;
1200#include "clang/Basic/AttrSubMatchRulesList.inc"
1201 }
1202 llvm_unreachable("Invalid attribute subject match rule");
1203 return false;
1204}
1205
1206static void diagnoseExpectedAttributeSubjectSubRule(
1207 Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1208 SourceLocation SubRuleLoc) {
1209 auto Diagnostic =
1210 PRef.Diag(SubRuleLoc,
1211 diag::err_pragma_attribute_expected_subject_sub_identifier)
1212 << PrimaryRuleName;
1213 if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1214 Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1215 else
1216 Diagnostic << /*SubRulesSupported=*/0;
1217}
1218
1219static void diagnoseUnknownAttributeSubjectSubRule(
1220 Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1221 StringRef SubRuleName, SourceLocation SubRuleLoc) {
1222
1223 auto Diagnostic =
1224 PRef.Diag(SubRuleLoc, diag::err_pragma_attribute_unknown_subject_sub_rule)
1225 << SubRuleName << PrimaryRuleName;
1226 if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1227 Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1228 else
1229 Diagnostic << /*SubRulesSupported=*/0;
1230}
1231
1232bool Parser::ParsePragmaAttributeSubjectMatchRuleSet(
1233 attr::ParsedSubjectMatchRuleSet &SubjectMatchRules, SourceLocation &AnyLoc,
1234 SourceLocation &LastMatchRuleEndLoc) {
1235 bool IsAny = false;
1236 BalancedDelimiterTracker AnyParens(*this, tok::l_paren);
1237 if (getIdentifier(Tok) == "any") {
1238 AnyLoc = ConsumeToken();
1239 IsAny = true;
1240 if (AnyParens.expectAndConsume())
1241 return true;
1242 }
1243
1244 do {
1245 // Parse the subject matcher rule.
1246 StringRef Name = getIdentifier(Tok);
1247 if (Name.empty()) {
1248 Diag(Tok, diag::err_pragma_attribute_expected_subject_identifier);
1249 return true;
1250 }
1251 std::pair<Optional<attr::SubjectMatchRule>,
1252 Optional<attr::SubjectMatchRule> (*)(StringRef, bool)>
1253 Rule = isAttributeSubjectMatchRule(Name);
1254 if (!Rule.first) {
1255 Diag(Tok, diag::err_pragma_attribute_unknown_subject_rule) << Name;
1256 return true;
1257 }
1258 attr::SubjectMatchRule PrimaryRule = *Rule.first;
1259 SourceLocation RuleLoc = ConsumeToken();
1260
1261 BalancedDelimiterTracker Parens(*this, tok::l_paren);
1262 if (isAbstractAttrMatcherRule(PrimaryRule)) {
1263 if (Parens.expectAndConsume())
1264 return true;
1265 } else if (Parens.consumeOpen()) {
1266 if (!SubjectMatchRules
1267 .insert(
1268 std::make_pair(PrimaryRule, SourceRange(RuleLoc, RuleLoc)))
1269 .second)
1270 Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1271 << Name
1272 << FixItHint::CreateRemoval(SourceRange(
1273 RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleLoc));
1274 LastMatchRuleEndLoc = RuleLoc;
1275 continue;
1276 }
1277
1278 // Parse the sub-rules.
1279 StringRef SubRuleName = getIdentifier(Tok);
1280 if (SubRuleName.empty()) {
1281 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1282 Tok.getLocation());
1283 return true;
1284 }
1285 attr::SubjectMatchRule SubRule;
1286 if (SubRuleName == "unless") {
1287 SourceLocation SubRuleLoc = ConsumeToken();
1288 BalancedDelimiterTracker Parens(*this, tok::l_paren);
1289 if (Parens.expectAndConsume())
1290 return true;
1291 SubRuleName = getIdentifier(Tok);
1292 if (SubRuleName.empty()) {
1293 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1294 SubRuleLoc);
1295 return true;
1296 }
1297 auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/true);
1298 if (!SubRuleOrNone) {
1299 std::string SubRuleUnlessName = "unless(" + SubRuleName.str() + ")";
1300 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1301 SubRuleUnlessName, SubRuleLoc);
1302 return true;
1303 }
1304 SubRule = *SubRuleOrNone;
1305 ConsumeToken();
1306 if (Parens.consumeClose())
1307 return true;
1308 } else {
1309 auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/false);
1310 if (!SubRuleOrNone) {
1311 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1312 SubRuleName, Tok.getLocation());
1313 return true;
1314 }
1315 SubRule = *SubRuleOrNone;
1316 ConsumeToken();
1317 }
1318 SourceLocation RuleEndLoc = Tok.getLocation();
1319 LastMatchRuleEndLoc = RuleEndLoc;
1320 if (Parens.consumeClose())
1321 return true;
1322 if (!SubjectMatchRules
1323 .insert(std::make_pair(SubRule, SourceRange(RuleLoc, RuleEndLoc)))
1324 .second) {
1325 Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1326 << attr::getSubjectMatchRuleSpelling(SubRule)
1327 << FixItHint::CreateRemoval(SourceRange(
1328 RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleEndLoc));
1329 continue;
1330 }
1331 } while (IsAny && TryConsumeToken(tok::comma));
1332
1333 if (IsAny)
1334 if (AnyParens.consumeClose())
1335 return true;
1336
1337 return false;
1338}
1339
1340namespace {
1341
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00001342/// Describes the stage at which attribute subject rule parsing was interrupted.
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001343enum class MissingAttributeSubjectRulesRecoveryPoint {
1344 Comma,
1345 ApplyTo,
1346 Equals,
1347 Any,
1348 None,
1349};
1350
1351MissingAttributeSubjectRulesRecoveryPoint
1352getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) {
1353 if (const auto *II = Tok.getIdentifierInfo()) {
1354 if (II->isStr("apply_to"))
1355 return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo;
1356 if (II->isStr("any"))
1357 return MissingAttributeSubjectRulesRecoveryPoint::Any;
1358 }
1359 if (Tok.is(tok::equal))
1360 return MissingAttributeSubjectRulesRecoveryPoint::Equals;
1361 return MissingAttributeSubjectRulesRecoveryPoint::None;
1362}
1363
1364/// Creates a diagnostic for the attribute subject rule parsing diagnostic that
1365/// suggests the possible attribute subject rules in a fix-it together with
1366/// any other missing tokens.
1367DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic(
Erich Keanee891aa92018-07-13 15:07:47 +00001368 unsigned DiagID, ParsedAttr &Attribute,
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001369 MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) {
1370 SourceLocation Loc = PRef.getEndOfPreviousToken();
1371 if (Loc.isInvalid())
1372 Loc = PRef.getCurToken().getLocation();
1373 auto Diagnostic = PRef.Diag(Loc, DiagID);
1374 std::string FixIt;
1375 MissingAttributeSubjectRulesRecoveryPoint EndPoint =
1376 getAttributeSubjectRulesRecoveryPointForToken(PRef.getCurToken());
1377 if (Point == MissingAttributeSubjectRulesRecoveryPoint::Comma)
1378 FixIt = ", ";
1379 if (Point <= MissingAttributeSubjectRulesRecoveryPoint::ApplyTo &&
1380 EndPoint > MissingAttributeSubjectRulesRecoveryPoint::ApplyTo)
1381 FixIt += "apply_to";
1382 if (Point <= MissingAttributeSubjectRulesRecoveryPoint::Equals &&
1383 EndPoint > MissingAttributeSubjectRulesRecoveryPoint::Equals)
1384 FixIt += " = ";
1385 SourceRange FixItRange(Loc);
1386 if (EndPoint == MissingAttributeSubjectRulesRecoveryPoint::None) {
1387 // Gather the subject match rules that are supported by the attribute.
1388 SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> SubjectMatchRuleSet;
1389 Attribute.getMatchRules(PRef.getLangOpts(), SubjectMatchRuleSet);
1390 if (SubjectMatchRuleSet.empty()) {
1391 // FIXME: We can emit a "fix-it" with a subject list placeholder when
1392 // placeholders will be supported by the fix-its.
1393 return Diagnostic;
1394 }
1395 FixIt += "any(";
1396 bool NeedsComma = false;
1397 for (const auto &I : SubjectMatchRuleSet) {
1398 // Ensure that the missing rule is reported in the fix-it only when it's
1399 // supported in the current language mode.
1400 if (!I.second)
1401 continue;
1402 if (NeedsComma)
1403 FixIt += ", ";
1404 else
1405 NeedsComma = true;
1406 FixIt += attr::getSubjectMatchRuleSpelling(I.first);
1407 }
1408 FixIt += ")";
1409 // Check if we need to remove the range
1410 PRef.SkipUntil(tok::eof, Parser::StopBeforeMatch);
1411 FixItRange.setEnd(PRef.getCurToken().getLocation());
1412 }
1413 if (FixItRange.getBegin() == FixItRange.getEnd())
1414 Diagnostic << FixItHint::CreateInsertion(FixItRange.getBegin(), FixIt);
1415 else
1416 Diagnostic << FixItHint::CreateReplacement(
1417 CharSourceRange::getCharRange(FixItRange), FixIt);
1418 return Diagnostic;
1419}
1420
1421} // end anonymous namespace
1422
1423void Parser::HandlePragmaAttribute() {
1424 assert(Tok.is(tok::annot_pragma_attribute) &&
1425 "Expected #pragma attribute annotation token");
1426 SourceLocation PragmaLoc = Tok.getLocation();
1427 auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue());
1428 if (Info->Action == PragmaAttributeInfo::Pop) {
Richard Smithaf3b3252017-05-18 19:21:48 +00001429 ConsumeAnnotationToken();
Erik Pilkington0876cae2018-12-20 22:32:04 +00001430 Actions.ActOnPragmaAttributePop(PragmaLoc, Info->Namespace);
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001431 return;
1432 }
1433 // Parse the actual attribute with its arguments.
Erik Pilkington7d180942018-10-29 17:38:42 +00001434 assert((Info->Action == PragmaAttributeInfo::Push ||
1435 Info->Action == PragmaAttributeInfo::Attribute) &&
Erik Pilkingtonb287a012018-10-29 03:24:16 +00001436 "Unexpected #pragma attribute command");
Erik Pilkington7d180942018-10-29 17:38:42 +00001437
1438 if (Info->Action == PragmaAttributeInfo::Push && Info->Tokens.empty()) {
1439 ConsumeAnnotationToken();
Erik Pilkington0876cae2018-12-20 22:32:04 +00001440 Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
Erik Pilkington7d180942018-10-29 17:38:42 +00001441 return;
1442 }
1443
Ilya Biryukov929af672019-05-17 09:32:05 +00001444 PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false,
1445 /*IsReinject=*/false);
Richard Smithaf3b3252017-05-18 19:21:48 +00001446 ConsumeAnnotationToken();
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001447
1448 ParsedAttributes &Attrs = Info->Attributes;
1449 Attrs.clearListOnly();
1450
1451 auto SkipToEnd = [this]() {
1452 SkipUntil(tok::eof, StopBeforeMatch);
1453 ConsumeToken();
1454 };
1455
1456 if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) {
1457 // Parse the CXX11 style attribute.
1458 ParseCXX11AttributeSpecifier(Attrs);
1459 } else if (Tok.is(tok::kw___attribute)) {
1460 ConsumeToken();
1461 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
1462 "attribute"))
1463 return SkipToEnd();
1464 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "("))
1465 return SkipToEnd();
1466
1467 if (Tok.isNot(tok::identifier)) {
1468 Diag(Tok, diag::err_pragma_attribute_expected_attribute_name);
1469 SkipToEnd();
1470 return;
1471 }
1472 IdentifierInfo *AttrName = Tok.getIdentifierInfo();
1473 SourceLocation AttrNameLoc = ConsumeToken();
1474
1475 if (Tok.isNot(tok::l_paren))
1476 Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
Erich Keanee891aa92018-07-13 15:07:47 +00001477 ParsedAttr::AS_GNU);
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001478 else
1479 ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr,
1480 /*ScopeName=*/nullptr,
Erich Keanee891aa92018-07-13 15:07:47 +00001481 /*ScopeLoc=*/SourceLocation(), ParsedAttr::AS_GNU,
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001482 /*Declarator=*/nullptr);
1483
1484 if (ExpectAndConsume(tok::r_paren))
1485 return SkipToEnd();
1486 if (ExpectAndConsume(tok::r_paren))
1487 return SkipToEnd();
1488 } else if (Tok.is(tok::kw___declspec)) {
1489 ParseMicrosoftDeclSpecs(Attrs);
1490 } else {
1491 Diag(Tok, diag::err_pragma_attribute_expected_attribute_syntax);
1492 if (Tok.getIdentifierInfo()) {
1493 // If we suspect that this is an attribute suggest the use of
1494 // '__attribute__'.
Erich Keane6a24e802019-09-13 17:39:31 +00001495 if (ParsedAttr::getParsedKind(
1496 Tok.getIdentifierInfo(), /*ScopeName=*/nullptr,
1497 ParsedAttr::AS_GNU) != ParsedAttr::UnknownAttribute) {
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001498 SourceLocation InsertStartLoc = Tok.getLocation();
1499 ConsumeToken();
1500 if (Tok.is(tok::l_paren)) {
1501 ConsumeAnyToken();
1502 SkipUntil(tok::r_paren, StopBeforeMatch);
1503 if (Tok.isNot(tok::r_paren))
1504 return SkipToEnd();
1505 }
1506 Diag(Tok, diag::note_pragma_attribute_use_attribute_kw)
1507 << FixItHint::CreateInsertion(InsertStartLoc, "__attribute__((")
1508 << FixItHint::CreateInsertion(Tok.getEndLoc(), "))");
1509 }
1510 }
1511 SkipToEnd();
1512 return;
1513 }
1514
Erich Keanec480f302018-07-12 21:09:05 +00001515 if (Attrs.empty() || Attrs.begin()->isInvalid()) {
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001516 SkipToEnd();
1517 return;
1518 }
1519
1520 // Ensure that we don't have more than one attribute.
Erich Keanec480f302018-07-12 21:09:05 +00001521 if (Attrs.size() > 1) {
1522 SourceLocation Loc = Attrs[1].getLoc();
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001523 Diag(Loc, diag::err_pragma_attribute_multiple_attributes);
1524 SkipToEnd();
1525 return;
1526 }
1527
Erich Keanee891aa92018-07-13 15:07:47 +00001528 ParsedAttr &Attribute = *Attrs.begin();
Erich Keanec480f302018-07-12 21:09:05 +00001529 if (!Attribute.isSupportedByPragmaAttribute()) {
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001530 Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute)
Erich Keane6a24e802019-09-13 17:39:31 +00001531 << Attribute;
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001532 SkipToEnd();
1533 return;
1534 }
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001535
1536 // Parse the subject-list.
1537 if (!TryConsumeToken(tok::comma)) {
1538 createExpectedAttributeSubjectRulesTokenDiagnostic(
1539 diag::err_expected, Attribute,
1540 MissingAttributeSubjectRulesRecoveryPoint::Comma, *this)
1541 << tok::comma;
1542 SkipToEnd();
1543 return;
1544 }
1545
1546 if (Tok.isNot(tok::identifier)) {
1547 createExpectedAttributeSubjectRulesTokenDiagnostic(
1548 diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute,
1549 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1550 SkipToEnd();
1551 return;
1552 }
1553 const IdentifierInfo *II = Tok.getIdentifierInfo();
1554 if (!II->isStr("apply_to")) {
1555 createExpectedAttributeSubjectRulesTokenDiagnostic(
1556 diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute,
1557 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1558 SkipToEnd();
1559 return;
1560 }
1561 ConsumeToken();
1562
1563 if (!TryConsumeToken(tok::equal)) {
1564 createExpectedAttributeSubjectRulesTokenDiagnostic(
1565 diag::err_expected, Attribute,
1566 MissingAttributeSubjectRulesRecoveryPoint::Equals, *this)
1567 << tok::equal;
1568 SkipToEnd();
1569 return;
1570 }
1571
1572 attr::ParsedSubjectMatchRuleSet SubjectMatchRules;
1573 SourceLocation AnyLoc, LastMatchRuleEndLoc;
1574 if (ParsePragmaAttributeSubjectMatchRuleSet(SubjectMatchRules, AnyLoc,
1575 LastMatchRuleEndLoc)) {
1576 SkipToEnd();
1577 return;
1578 }
1579
1580 // Tokens following an ill-formed attribute will remain in the token stream
1581 // and must be removed.
1582 if (Tok.isNot(tok::eof)) {
1583 Diag(Tok, diag::err_pragma_attribute_extra_tokens_after_attribute);
1584 SkipToEnd();
1585 return;
1586 }
1587
1588 // Consume the eof terminator token.
1589 ConsumeToken();
1590
Erik Pilkington7d180942018-10-29 17:38:42 +00001591 // Handle a mixed push/attribute by desurging to a push, then an attribute.
1592 if (Info->Action == PragmaAttributeInfo::Push)
Erik Pilkington0876cae2018-12-20 22:32:04 +00001593 Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
Erik Pilkington7d180942018-10-29 17:38:42 +00001594
1595 Actions.ActOnPragmaAttributeAttribute(Attribute, PragmaLoc,
1596 std::move(SubjectMatchRules));
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001597}
1598
Eli Bendersky06a40422014-06-06 20:31:48 +00001599// #pragma GCC visibility comes in two variants:
1600// 'push' '(' [visibility] ')'
1601// 'pop'
Fangrui Song6907ce22018-07-30 19:24:48 +00001602void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00001603 PragmaIntroducer Introducer,
Douglas Gregorc7d65762010-09-09 22:45:38 +00001604 Token &VisTok) {
Eli Friedman570024a2010-08-05 06:57:20 +00001605 SourceLocation VisLoc = VisTok.getLocation();
1606
1607 Token Tok;
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001608 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001609
1610 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
1611
Eli Friedman570024a2010-08-05 06:57:20 +00001612 const IdentifierInfo *VisType;
1613 if (PushPop && PushPop->isStr("pop")) {
Craig Topper161e4db2014-05-21 06:02:52 +00001614 VisType = nullptr;
Eli Friedman570024a2010-08-05 06:57:20 +00001615 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001616 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001617 if (Tok.isNot(tok::l_paren)) {
1618 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
1619 << "visibility";
1620 return;
1621 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001622 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001623 VisType = Tok.getIdentifierInfo();
1624 if (!VisType) {
1625 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1626 << "visibility";
1627 return;
1628 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001629 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001630 if (Tok.isNot(tok::r_paren)) {
1631 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
1632 << "visibility";
1633 return;
1634 }
1635 } else {
1636 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1637 << "visibility";
1638 return;
1639 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00001640 SourceLocation EndLoc = Tok.getLocation();
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001641 PP.LexUnexpandedToken(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001642 if (Tok.isNot(tok::eod)) {
Eli Friedman570024a2010-08-05 06:57:20 +00001643 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1644 << "visibility";
1645 return;
1646 }
1647
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +00001648 auto Toks = std::make_unique<Token[]>(1);
Rafael Espindola273fd772012-01-26 02:02:57 +00001649 Toks[0].startToken();
1650 Toks[0].setKind(tok::annot_pragma_vis);
1651 Toks[0].setLocation(VisLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001652 Toks[0].setAnnotationEndLoc(EndLoc);
Rafael Espindola273fd772012-01-26 02:02:57 +00001653 Toks[0].setAnnotationValue(
Ilya Biryukov929af672019-05-17 09:32:05 +00001654 const_cast<void *>(static_cast<const void *>(VisType)));
1655 PP.EnterTokenStream(std::move(Toks), 1, /*DisableMacroExpansion=*/true,
1656 /*IsReinject=*/false);
Eli Friedman570024a2010-08-05 06:57:20 +00001657}
1658
Daniel Dunbar921b9682008-10-04 19:21:03 +00001659// #pragma pack(...) comes in the following delicious flavors:
1660// pack '(' [integer] ')'
1661// pack '(' 'show' ')'
1662// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Fangrui Song6907ce22018-07-30 19:24:48 +00001663void PragmaPackHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00001664 PragmaIntroducer Introducer,
Douglas Gregorc7d65762010-09-09 22:45:38 +00001665 Token &PackTok) {
Daniel Dunbar921b9682008-10-04 19:21:03 +00001666 SourceLocation PackLoc = PackTok.getLocation();
1667
1668 Token Tok;
1669 PP.Lex(Tok);
1670 if (Tok.isNot(tok::l_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001671 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001672 return;
1673 }
1674
Denis Zobnin10c4f452016-04-29 18:17:40 +00001675 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
1676 StringRef SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +00001677 Token Alignment;
1678 Alignment.startToken();
Mike Stump11289f42009-09-09 15:08:12 +00001679 PP.Lex(Tok);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001680 if (Tok.is(tok::numeric_constant)) {
Eli Friedman68be1642012-10-04 02:36:51 +00001681 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001682
1683 PP.Lex(Tok);
Eli Friedman055c9702011-11-02 01:53:16 +00001684
1685 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
1686 // the push/pop stack.
1687 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
Denis Zobnin10c4f452016-04-29 18:17:40 +00001688 Action =
1689 PP.getLangOpts().ApplePragmaPack ? Sema::PSK_Push_Set : Sema::PSK_Set;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001690 } else if (Tok.is(tok::identifier)) {
1691 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattnere3d20d92008-11-23 21:45:46 +00001692 if (II->isStr("show")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001693 Action = Sema::PSK_Show;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001694 PP.Lex(Tok);
1695 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001696 if (II->isStr("push")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001697 Action = Sema::PSK_Push;
Chris Lattnere3d20d92008-11-23 21:45:46 +00001698 } else if (II->isStr("pop")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001699 Action = Sema::PSK_Pop;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001700 } else {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001701 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001702 return;
Mike Stump11289f42009-09-09 15:08:12 +00001703 }
Daniel Dunbar921b9682008-10-04 19:21:03 +00001704 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001705
Daniel Dunbar921b9682008-10-04 19:21:03 +00001706 if (Tok.is(tok::comma)) {
1707 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001708
Daniel Dunbar921b9682008-10-04 19:21:03 +00001709 if (Tok.is(tok::numeric_constant)) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001710 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
Eli Friedman68be1642012-10-04 02:36:51 +00001711 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001712
1713 PP.Lex(Tok);
1714 } else if (Tok.is(tok::identifier)) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001715 SlotLabel = Tok.getIdentifierInfo()->getName();
Daniel Dunbar921b9682008-10-04 19:21:03 +00001716 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001717
Daniel Dunbar921b9682008-10-04 19:21:03 +00001718 if (Tok.is(tok::comma)) {
1719 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001720
Daniel Dunbar921b9682008-10-04 19:21:03 +00001721 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001722 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001723 return;
1724 }
Mike Stump11289f42009-09-09 15:08:12 +00001725
Denis Zobnin10c4f452016-04-29 18:17:40 +00001726 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
Eli Friedman68be1642012-10-04 02:36:51 +00001727 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001728
1729 PP.Lex(Tok);
1730 }
1731 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001732 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001733 return;
1734 }
1735 }
1736 }
David Blaikiebbafb8a2012-03-11 07:00:24 +00001737 } else if (PP.getLangOpts().ApplePragmaPack) {
Eli Friedman055c9702011-11-02 01:53:16 +00001738 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
1739 // the push/pop stack.
1740 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
Denis Zobnin10c4f452016-04-29 18:17:40 +00001741 Action = Sema::PSK_Pop;
Sebastian Redl17f2c7d2008-12-09 13:15:23 +00001742 }
Daniel Dunbar921b9682008-10-04 19:21:03 +00001743
1744 if (Tok.isNot(tok::r_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001745 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001746 return;
1747 }
1748
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001749 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001750 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001751 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001752 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
1753 return;
1754 }
1755
David Blaikie2eabcc92016-02-09 18:52:09 +00001756 PragmaPackInfo *Info =
1757 PP.getPreprocessorAllocator().Allocate<PragmaPackInfo>(1);
Denis Zobnin10c4f452016-04-29 18:17:40 +00001758 Info->Action = Action;
1759 Info->SlotLabel = SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +00001760 Info->Alignment = Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +00001761
David Blaikie2eabcc92016-02-09 18:52:09 +00001762 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1763 1);
Eli Friedmanec52f922012-02-23 23:47:16 +00001764 Toks[0].startToken();
1765 Toks[0].setKind(tok::annot_pragma_pack);
1766 Toks[0].setLocation(PackLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001767 Toks[0].setAnnotationEndLoc(RParenLoc);
Eli Friedmanec52f922012-02-23 23:47:16 +00001768 Toks[0].setAnnotationValue(static_cast<void*>(Info));
Ilya Biryukov929af672019-05-17 09:32:05 +00001769 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
1770 /*IsReinject=*/false);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001771}
1772
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001773// #pragma ms_struct on
1774// #pragma ms_struct off
Fangrui Song6907ce22018-07-30 19:24:48 +00001775void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00001776 PragmaIntroducer Introducer,
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001777 Token &MSStructTok) {
Nico Weber779355f2016-03-02 23:22:00 +00001778 PragmaMSStructKind Kind = PMSST_OFF;
1779
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001780 Token Tok;
1781 PP.Lex(Tok);
1782 if (Tok.isNot(tok::identifier)) {
1783 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1784 return;
1785 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00001786 SourceLocation EndLoc = Tok.getLocation();
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001787 const IdentifierInfo *II = Tok.getIdentifierInfo();
1788 if (II->isStr("on")) {
Nico Weber779355f2016-03-02 23:22:00 +00001789 Kind = PMSST_ON;
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001790 PP.Lex(Tok);
1791 }
1792 else if (II->isStr("off") || II->isStr("reset"))
1793 PP.Lex(Tok);
1794 else {
1795 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1796 return;
1797 }
Fangrui Song6907ce22018-07-30 19:24:48 +00001798
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001799 if (Tok.isNot(tok::eod)) {
Daniel Dunbar340cf242012-02-29 01:38:22 +00001800 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1801 << "ms_struct";
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001802 return;
1803 }
Eli Friedman68be1642012-10-04 02:36:51 +00001804
David Blaikie2eabcc92016-02-09 18:52:09 +00001805 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1806 1);
Eli Friedman68be1642012-10-04 02:36:51 +00001807 Toks[0].startToken();
1808 Toks[0].setKind(tok::annot_pragma_msstruct);
1809 Toks[0].setLocation(MSStructTok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001810 Toks[0].setAnnotationEndLoc(EndLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001811 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1812 static_cast<uintptr_t>(Kind)));
Ilya Biryukov929af672019-05-17 09:32:05 +00001813 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
1814 /*IsReinject=*/false);
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001815}
1816
Dmitry Mikulinf14642f2019-10-15 18:31:10 +00001817// #pragma clang section bss="abc" data="" rodata="def" text="" relro=""
Javed Absar2a67c9e2017-06-05 10:11:57 +00001818void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00001819 PragmaIntroducer Introducer,
1820 Token &FirstToken) {
Javed Absar2a67c9e2017-06-05 10:11:57 +00001821
1822 Token Tok;
1823 auto SecKind = Sema::PragmaClangSectionKind::PCSK_Invalid;
1824
1825 PP.Lex(Tok); // eat 'section'
1826 while (Tok.isNot(tok::eod)) {
1827 if (Tok.isNot(tok::identifier)) {
1828 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
1829 return;
1830 }
1831
1832 const IdentifierInfo *SecType = Tok.getIdentifierInfo();
1833 if (SecType->isStr("bss"))
1834 SecKind = Sema::PragmaClangSectionKind::PCSK_BSS;
1835 else if (SecType->isStr("data"))
1836 SecKind = Sema::PragmaClangSectionKind::PCSK_Data;
1837 else if (SecType->isStr("rodata"))
1838 SecKind = Sema::PragmaClangSectionKind::PCSK_Rodata;
Dmitry Mikulinf14642f2019-10-15 18:31:10 +00001839 else if (SecType->isStr("relro"))
1840 SecKind = Sema::PragmaClangSectionKind::PCSK_Relro;
Javed Absar2a67c9e2017-06-05 10:11:57 +00001841 else if (SecType->isStr("text"))
1842 SecKind = Sema::PragmaClangSectionKind::PCSK_Text;
1843 else {
1844 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
1845 return;
1846 }
1847
1848 PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text']
1849 if (Tok.isNot(tok::equal)) {
1850 PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind;
1851 return;
1852 }
1853
1854 std::string SecName;
1855 if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false))
1856 return;
1857
1858 Actions.ActOnPragmaClangSection(Tok.getLocation(),
1859 (SecName.size()? Sema::PragmaClangSectionAction::PCSA_Set :
1860 Sema::PragmaClangSectionAction::PCSA_Clear),
1861 SecKind, SecName);
1862 }
1863}
1864
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001865// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
1866// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
Eli Friedman68be1642012-10-04 02:36:51 +00001867static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001868 bool IsOptions) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001869 Token Tok;
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001870
1871 if (IsOptions) {
1872 PP.Lex(Tok);
1873 if (Tok.isNot(tok::identifier) ||
1874 !Tok.getIdentifierInfo()->isStr("align")) {
1875 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
1876 return;
1877 }
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001878 }
Daniel Dunbar663e8092010-05-27 18:42:09 +00001879
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001880 PP.Lex(Tok);
1881 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001882 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
1883 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001884 return;
1885 }
1886
1887 PP.Lex(Tok);
1888 if (Tok.isNot(tok::identifier)) {
1889 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001890 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001891 return;
1892 }
1893
John McCallfaf5fb42010-08-26 23:41:50 +00001894 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001895 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar663e8092010-05-27 18:42:09 +00001896 if (II->isStr("native"))
John McCallfaf5fb42010-08-26 23:41:50 +00001897 Kind = Sema::POAK_Native;
Daniel Dunbar663e8092010-05-27 18:42:09 +00001898 else if (II->isStr("natural"))
John McCallfaf5fb42010-08-26 23:41:50 +00001899 Kind = Sema::POAK_Natural;
Daniel Dunbar9c84d4a2010-05-27 18:42:17 +00001900 else if (II->isStr("packed"))
John McCallfaf5fb42010-08-26 23:41:50 +00001901 Kind = Sema::POAK_Packed;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001902 else if (II->isStr("power"))
John McCallfaf5fb42010-08-26 23:41:50 +00001903 Kind = Sema::POAK_Power;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001904 else if (II->isStr("mac68k"))
John McCallfaf5fb42010-08-26 23:41:50 +00001905 Kind = Sema::POAK_Mac68k;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001906 else if (II->isStr("reset"))
John McCallfaf5fb42010-08-26 23:41:50 +00001907 Kind = Sema::POAK_Reset;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001908 else {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001909 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
1910 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001911 return;
1912 }
1913
David Majnemera8f2f1d2015-03-19 00:10:23 +00001914 SourceLocation EndLoc = Tok.getLocation();
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001915 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001916 if (Tok.isNot(tok::eod)) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001917 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001918 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001919 return;
1920 }
1921
David Blaikie2eabcc92016-02-09 18:52:09 +00001922 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1923 1);
Eli Friedman68be1642012-10-04 02:36:51 +00001924 Toks[0].startToken();
1925 Toks[0].setKind(tok::annot_pragma_align);
1926 Toks[0].setLocation(FirstTok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001927 Toks[0].setAnnotationEndLoc(EndLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001928 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1929 static_cast<uintptr_t>(Kind)));
Ilya Biryukov929af672019-05-17 09:32:05 +00001930 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
1931 /*IsReinject=*/false);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001932}
1933
Fangrui Song6907ce22018-07-30 19:24:48 +00001934void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00001935 PragmaIntroducer Introducer,
Douglas Gregorc7d65762010-09-09 22:45:38 +00001936 Token &AlignTok) {
Eli Friedman68be1642012-10-04 02:36:51 +00001937 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001938}
1939
Fangrui Song6907ce22018-07-30 19:24:48 +00001940void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00001941 PragmaIntroducer Introducer,
Douglas Gregorc7d65762010-09-09 22:45:38 +00001942 Token &OptionsTok) {
Eli Friedman68be1642012-10-04 02:36:51 +00001943 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001944}
1945
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001946// #pragma unused(identifier)
Fangrui Song6907ce22018-07-30 19:24:48 +00001947void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00001948 PragmaIntroducer Introducer,
Douglas Gregorc7d65762010-09-09 22:45:38 +00001949 Token &UnusedTok) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001950 // FIXME: Should we be expanding macros here? My guess is no.
1951 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump11289f42009-09-09 15:08:12 +00001952
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001953 // Lex the left '('.
1954 Token Tok;
1955 PP.Lex(Tok);
1956 if (Tok.isNot(tok::l_paren)) {
1957 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
1958 return;
1959 }
Mike Stump11289f42009-09-09 15:08:12 +00001960
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001961 // Lex the declaration reference(s).
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001962 SmallVector<Token, 5> Identifiers;
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001963 SourceLocation RParenLoc;
1964 bool LexID = true;
Mike Stump11289f42009-09-09 15:08:12 +00001965
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001966 while (true) {
1967 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001968
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001969 if (LexID) {
Mike Stump11289f42009-09-09 15:08:12 +00001970 if (Tok.is(tok::identifier)) {
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001971 Identifiers.push_back(Tok);
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001972 LexID = false;
1973 continue;
1974 }
1975
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001976 // Illegal token!
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001977 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
1978 return;
1979 }
Mike Stump11289f42009-09-09 15:08:12 +00001980
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001981 // We are execting a ')' or a ','.
1982 if (Tok.is(tok::comma)) {
1983 LexID = true;
1984 continue;
1985 }
Mike Stump11289f42009-09-09 15:08:12 +00001986
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001987 if (Tok.is(tok::r_paren)) {
1988 RParenLoc = Tok.getLocation();
1989 break;
1990 }
Mike Stump11289f42009-09-09 15:08:12 +00001991
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001992 // Illegal token!
David Majnemer88969812014-02-10 19:06:37 +00001993 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001994 return;
1995 }
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001996
1997 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001998 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001999 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2000 "unused";
2001 return;
2002 }
2003
Ted Kremenekfd14fad2009-03-23 22:28:25 +00002004 // Verify that we have a location for the right parenthesis.
2005 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenekfb50bf52009-08-03 23:24:57 +00002006 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenekfd14fad2009-03-23 22:28:25 +00002007
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +00002008 // For each identifier token, insert into the token stream a
2009 // annot_pragma_unused token followed by the identifier token.
2010 // This allows us to cache a "#pragma unused" that occurs inside an inline
2011 // C++ member function.
2012
David Blaikie2eabcc92016-02-09 18:52:09 +00002013 MutableArrayRef<Token> Toks(
2014 PP.getPreprocessorAllocator().Allocate<Token>(2 * Identifiers.size()),
2015 2 * Identifiers.size());
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +00002016 for (unsigned i=0; i != Identifiers.size(); i++) {
2017 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
2018 pragmaUnusedTok.startToken();
2019 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
2020 pragmaUnusedTok.setLocation(UnusedLoc);
2021 idTok = Identifiers[i];
2022 }
Ilya Biryukov929af672019-05-17 09:32:05 +00002023 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2024 /*IsReinject=*/false);
Ted Kremenekfd14fad2009-03-23 22:28:25 +00002025}
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002026
2027// #pragma weak identifier
2028// #pragma weak identifier '=' identifier
Fangrui Song6907ce22018-07-30 19:24:48 +00002029void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002030 PragmaIntroducer Introducer,
Douglas Gregorc7d65762010-09-09 22:45:38 +00002031 Token &WeakTok) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002032 SourceLocation WeakLoc = WeakTok.getLocation();
2033
2034 Token Tok;
2035 PP.Lex(Tok);
2036 if (Tok.isNot(tok::identifier)) {
2037 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
2038 return;
2039 }
2040
Eli Friedman68be1642012-10-04 02:36:51 +00002041 Token WeakName = Tok;
2042 bool HasAlias = false;
2043 Token AliasName;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002044
2045 PP.Lex(Tok);
2046 if (Tok.is(tok::equal)) {
Eli Friedman68be1642012-10-04 02:36:51 +00002047 HasAlias = true;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002048 PP.Lex(Tok);
2049 if (Tok.isNot(tok::identifier)) {
Mike Stump11289f42009-09-09 15:08:12 +00002050 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002051 << "weak";
2052 return;
2053 }
Eli Friedman68be1642012-10-04 02:36:51 +00002054 AliasName = Tok;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002055 PP.Lex(Tok);
2056 }
2057
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00002058 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002059 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
2060 return;
2061 }
2062
Eli Friedman68be1642012-10-04 02:36:51 +00002063 if (HasAlias) {
David Blaikie2eabcc92016-02-09 18:52:09 +00002064 MutableArrayRef<Token> Toks(
2065 PP.getPreprocessorAllocator().Allocate<Token>(3), 3);
Eli Friedman68be1642012-10-04 02:36:51 +00002066 Token &pragmaUnusedTok = Toks[0];
2067 pragmaUnusedTok.startToken();
2068 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
2069 pragmaUnusedTok.setLocation(WeakLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002070 pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00002071 Toks[1] = WeakName;
2072 Toks[2] = AliasName;
Ilya Biryukov929af672019-05-17 09:32:05 +00002073 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2074 /*IsReinject=*/false);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002075 } else {
David Blaikie2eabcc92016-02-09 18:52:09 +00002076 MutableArrayRef<Token> Toks(
2077 PP.getPreprocessorAllocator().Allocate<Token>(2), 2);
Eli Friedman68be1642012-10-04 02:36:51 +00002078 Token &pragmaUnusedTok = Toks[0];
2079 pragmaUnusedTok.startToken();
2080 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
2081 pragmaUnusedTok.setLocation(WeakLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002082 pragmaUnusedTok.setAnnotationEndLoc(WeakLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00002083 Toks[1] = WeakName;
Ilya Biryukov929af672019-05-17 09:32:05 +00002084 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2085 /*IsReinject=*/false);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002086 }
2087}
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00002088
David Chisnall0867d9c2012-02-18 16:12:34 +00002089// #pragma redefine_extname identifier identifier
Fangrui Song6907ce22018-07-30 19:24:48 +00002090void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002091 PragmaIntroducer Introducer,
David Chisnall0867d9c2012-02-18 16:12:34 +00002092 Token &RedefToken) {
2093 SourceLocation RedefLoc = RedefToken.getLocation();
2094
2095 Token Tok;
2096 PP.Lex(Tok);
2097 if (Tok.isNot(tok::identifier)) {
2098 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
2099 "redefine_extname";
2100 return;
2101 }
2102
Eli Friedman68be1642012-10-04 02:36:51 +00002103 Token RedefName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00002104 PP.Lex(Tok);
Eli Friedman68be1642012-10-04 02:36:51 +00002105
David Chisnall0867d9c2012-02-18 16:12:34 +00002106 if (Tok.isNot(tok::identifier)) {
2107 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2108 << "redefine_extname";
2109 return;
2110 }
Eli Friedman68be1642012-10-04 02:36:51 +00002111
2112 Token AliasName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00002113 PP.Lex(Tok);
2114
2115 if (Tok.isNot(tok::eod)) {
2116 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2117 "redefine_extname";
2118 return;
2119 }
2120
David Blaikie2eabcc92016-02-09 18:52:09 +00002121 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(3),
2122 3);
Eli Friedman68be1642012-10-04 02:36:51 +00002123 Token &pragmaRedefTok = Toks[0];
2124 pragmaRedefTok.startToken();
2125 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
2126 pragmaRedefTok.setLocation(RedefLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002127 pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00002128 Toks[1] = RedefName;
2129 Toks[2] = AliasName;
Ilya Biryukov929af672019-05-17 09:32:05 +00002130 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2131 /*IsReinject=*/false);
David Chisnall0867d9c2012-02-18 16:12:34 +00002132}
2133
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002134void PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
2135 PragmaIntroducer Introducer,
2136 Token &Tok) {
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00002137 tok::OnOffSwitch OOS;
2138 if (PP.LexOnOffSwitch(OOS))
2139 return;
2140
David Blaikie2eabcc92016-02-09 18:52:09 +00002141 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2142 1);
Eli Friedman68be1642012-10-04 02:36:51 +00002143 Toks[0].startToken();
2144 Toks[0].setKind(tok::annot_pragma_fp_contract);
2145 Toks[0].setLocation(Tok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002146 Toks[0].setAnnotationEndLoc(Tok.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00002147 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
2148 static_cast<uintptr_t>(OOS)));
Ilya Biryukov929af672019-05-17 09:32:05 +00002149 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2150 /*IsReinject=*/false);
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00002151}
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002152
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002153void PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
2154 PragmaIntroducer Introducer,
2155 Token &Tok) {
Tanya Lattneree840b82011-04-14 23:35:31 +00002156 PP.LexUnexpandedToken(Tok);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002157 if (Tok.isNot(tok::identifier)) {
2158 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
2159 "OPENCL";
2160 return;
2161 }
Yaxun Liu5b746652016-12-18 05:18:55 +00002162 IdentifierInfo *Ext = Tok.getIdentifierInfo();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002163 SourceLocation NameLoc = Tok.getLocation();
2164
2165 PP.Lex(Tok);
2166 if (Tok.isNot(tok::colon)) {
Yaxun Liu5b746652016-12-18 05:18:55 +00002167 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext;
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002168 return;
2169 }
2170
2171 PP.Lex(Tok);
2172 if (Tok.isNot(tok::identifier)) {
Yaxun Liu5b746652016-12-18 05:18:55 +00002173 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0;
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002174 return;
2175 }
Yaxun Liu5b746652016-12-18 05:18:55 +00002176 IdentifierInfo *Pred = Tok.getIdentifierInfo();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002177
Yaxun Liu5b746652016-12-18 05:18:55 +00002178 OpenCLExtState State;
2179 if (Pred->isStr("enable")) {
2180 State = Enable;
2181 } else if (Pred->isStr("disable")) {
2182 State = Disable;
2183 } else if (Pred->isStr("begin"))
2184 State = Begin;
2185 else if (Pred->isStr("end"))
2186 State = End;
2187 else {
2188 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate)
2189 << Ext->isStr("all");
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002190 return;
2191 }
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00002192 SourceLocation StateLoc = Tok.getLocation();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002193
Eli Friedman68be1642012-10-04 02:36:51 +00002194 PP.Lex(Tok);
2195 if (Tok.isNot(tok::eod)) {
2196 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2197 "OPENCL EXTENSION";
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002198 return;
2199 }
Eli Friedman68be1642012-10-04 02:36:51 +00002200
Yaxun Liu5b746652016-12-18 05:18:55 +00002201 auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1);
2202 Info->first = Ext;
2203 Info->second = State;
David Blaikie2eabcc92016-02-09 18:52:09 +00002204 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2205 1);
Eli Friedman68be1642012-10-04 02:36:51 +00002206 Toks[0].startToken();
2207 Toks[0].setKind(tok::annot_pragma_opencl_extension);
2208 Toks[0].setLocation(NameLoc);
Yaxun Liu5b746652016-12-18 05:18:55 +00002209 Toks[0].setAnnotationValue(static_cast<void*>(Info));
David Majnemera8f2f1d2015-03-19 00:10:23 +00002210 Toks[0].setAnnotationEndLoc(StateLoc);
Ilya Biryukov929af672019-05-17 09:32:05 +00002211 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2212 /*IsReinject=*/false);
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00002213
2214 if (PP.getPPCallbacks())
Fangrui Song6907ce22018-07-30 19:24:48 +00002215 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext,
Yaxun Liu5b746652016-12-18 05:18:55 +00002216 StateLoc, State);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002217}
2218
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002219/// Handle '#pragma omp ...' when OpenMP is disabled.
Alexey Bataeva769e072013-03-22 06:34:35 +00002220///
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002221void PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
2222 PragmaIntroducer Introducer,
2223 Token &FirstTok) {
Alp Tokerd4a3f0e2014-06-15 23:30:39 +00002224 if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
2225 FirstTok.getLocation())) {
Alexey Bataeva769e072013-03-22 06:34:35 +00002226 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
Alp Tokerd576e002014-06-12 11:13:52 +00002227 PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
2228 diag::Severity::Ignored, SourceLocation());
Alexey Bataeva769e072013-03-22 06:34:35 +00002229 }
2230 PP.DiscardUntilEndOfDirective();
2231}
2232
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002233/// Handle '#pragma omp ...' when OpenMP is enabled.
Alexey Bataeva769e072013-03-22 06:34:35 +00002234///
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002235void PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
2236 PragmaIntroducer Introducer,
2237 Token &FirstTok) {
Alexey Bataeva769e072013-03-22 06:34:35 +00002238 SmallVector<Token, 16> Pragma;
2239 Token Tok;
2240 Tok.startToken();
2241 Tok.setKind(tok::annot_pragma_openmp);
Joel E. Denny91f80662019-05-28 19:27:19 +00002242 Tok.setLocation(Introducer.Loc);
Alexey Bataeva769e072013-03-22 06:34:35 +00002243
Alexey Bataev96dae812018-02-16 18:36:44 +00002244 while (Tok.isNot(tok::eod) && Tok.isNot(tok::eof)) {
Alexey Bataeva769e072013-03-22 06:34:35 +00002245 Pragma.push_back(Tok);
2246 PP.Lex(Tok);
Alexey Bataev96dae812018-02-16 18:36:44 +00002247 if (Tok.is(tok::annot_pragma_openmp)) {
2248 PP.Diag(Tok, diag::err_omp_unexpected_directive) << 0;
2249 unsigned InnerPragmaCnt = 1;
2250 while (InnerPragmaCnt != 0) {
2251 PP.Lex(Tok);
2252 if (Tok.is(tok::annot_pragma_openmp))
2253 ++InnerPragmaCnt;
2254 else if (Tok.is(tok::annot_pragma_openmp_end))
2255 --InnerPragmaCnt;
2256 }
2257 PP.Lex(Tok);
2258 }
Alexey Bataeva769e072013-03-22 06:34:35 +00002259 }
2260 SourceLocation EodLoc = Tok.getLocation();
2261 Tok.startToken();
2262 Tok.setKind(tok::annot_pragma_openmp_end);
2263 Tok.setLocation(EodLoc);
2264 Pragma.push_back(Tok);
2265
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +00002266 auto Toks = std::make_unique<Token[]>(Pragma.size());
David Blaikie2eabcc92016-02-09 18:52:09 +00002267 std::copy(Pragma.begin(), Pragma.end(), Toks.get());
2268 PP.EnterTokenStream(std::move(Toks), Pragma.size(),
Ilya Biryukov929af672019-05-17 09:32:05 +00002269 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
Alexey Bataeva769e072013-03-22 06:34:35 +00002270}
Reid Kleckner002562a2013-05-06 21:02:12 +00002271
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002272/// Handle '#pragma pointers_to_members'
David Majnemer4bb09802014-02-10 19:50:15 +00002273// The grammar for this pragma is as follows:
2274//
2275// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
2276//
2277// #pragma pointers_to_members '(' 'best_case' ')'
2278// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
2279// #pragma pointers_to_members '(' inheritance-model ')'
2280void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002281 PragmaIntroducer Introducer,
David Majnemer4bb09802014-02-10 19:50:15 +00002282 Token &Tok) {
2283 SourceLocation PointersToMembersLoc = Tok.getLocation();
2284 PP.Lex(Tok);
2285 if (Tok.isNot(tok::l_paren)) {
2286 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
2287 << "pointers_to_members";
2288 return;
2289 }
2290 PP.Lex(Tok);
2291 const IdentifierInfo *Arg = Tok.getIdentifierInfo();
2292 if (!Arg) {
2293 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2294 << "pointers_to_members";
2295 return;
2296 }
2297 PP.Lex(Tok);
2298
David Majnemer86c318f2014-02-11 21:05:00 +00002299 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
David Majnemer4bb09802014-02-10 19:50:15 +00002300 if (Arg->isStr("best_case")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002301 RepresentationMethod = LangOptions::PPTMK_BestCase;
David Majnemer4bb09802014-02-10 19:50:15 +00002302 } else {
2303 if (Arg->isStr("full_generality")) {
2304 if (Tok.is(tok::comma)) {
2305 PP.Lex(Tok);
2306
2307 Arg = Tok.getIdentifierInfo();
2308 if (!Arg) {
2309 PP.Diag(Tok.getLocation(),
2310 diag::err_pragma_pointers_to_members_unknown_kind)
2311 << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
2312 return;
2313 }
2314 PP.Lex(Tok);
2315 } else if (Tok.is(tok::r_paren)) {
2316 // #pragma pointers_to_members(full_generality) implicitly specifies
2317 // virtual_inheritance.
Craig Topper161e4db2014-05-21 06:02:52 +00002318 Arg = nullptr;
David Majnemer86c318f2014-02-11 21:05:00 +00002319 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002320 } else {
2321 PP.Diag(Tok.getLocation(), diag::err_expected_punc)
2322 << "full_generality";
2323 return;
2324 }
2325 }
2326
2327 if (Arg) {
2328 if (Arg->isStr("single_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002329 RepresentationMethod =
2330 LangOptions::PPTMK_FullGeneralitySingleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002331 } else if (Arg->isStr("multiple_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002332 RepresentationMethod =
2333 LangOptions::PPTMK_FullGeneralityMultipleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002334 } else if (Arg->isStr("virtual_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002335 RepresentationMethod =
2336 LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002337 } else {
2338 PP.Diag(Tok.getLocation(),
2339 diag::err_pragma_pointers_to_members_unknown_kind)
2340 << Arg << /*HasPointerDeclaration*/ 1;
2341 return;
2342 }
2343 }
2344 }
2345
2346 if (Tok.isNot(tok::r_paren)) {
2347 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
2348 << (Arg ? Arg->getName() : "full_generality");
2349 return;
2350 }
2351
David Majnemera8f2f1d2015-03-19 00:10:23 +00002352 SourceLocation EndLoc = Tok.getLocation();
David Majnemer4bb09802014-02-10 19:50:15 +00002353 PP.Lex(Tok);
2354 if (Tok.isNot(tok::eod)) {
2355 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2356 << "pointers_to_members";
2357 return;
2358 }
2359
2360 Token AnnotTok;
2361 AnnotTok.startToken();
2362 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
2363 AnnotTok.setLocation(PointersToMembersLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002364 AnnotTok.setAnnotationEndLoc(EndLoc);
David Majnemer4bb09802014-02-10 19:50:15 +00002365 AnnotTok.setAnnotationValue(
2366 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
Ilya Biryukov929af672019-05-17 09:32:05 +00002367 PP.EnterToken(AnnotTok, /*IsReinject=*/true);
David Majnemer4bb09802014-02-10 19:50:15 +00002368}
2369
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002370/// Handle '#pragma vtordisp'
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002371// The grammar for this pragma is as follows:
2372//
2373// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
2374//
2375// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
2376// #pragma vtordisp '(' 'pop' ')'
2377// #pragma vtordisp '(' ')'
2378void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002379 PragmaIntroducer Introducer, Token &Tok) {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002380 SourceLocation VtorDispLoc = Tok.getLocation();
2381 PP.Lex(Tok);
2382 if (Tok.isNot(tok::l_paren)) {
2383 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
2384 return;
2385 }
2386 PP.Lex(Tok);
2387
Denis Zobnin2290dac2016-04-29 11:27:00 +00002388 Sema::PragmaMsStackAction Action = Sema::PSK_Set;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002389 const IdentifierInfo *II = Tok.getIdentifierInfo();
2390 if (II) {
2391 if (II->isStr("push")) {
2392 // #pragma vtordisp(push, mode)
2393 PP.Lex(Tok);
2394 if (Tok.isNot(tok::comma)) {
2395 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
2396 return;
2397 }
2398 PP.Lex(Tok);
Denis Zobnin2290dac2016-04-29 11:27:00 +00002399 Action = Sema::PSK_Push_Set;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002400 // not push, could be on/off
2401 } else if (II->isStr("pop")) {
2402 // #pragma vtordisp(pop)
2403 PP.Lex(Tok);
Denis Zobnin2290dac2016-04-29 11:27:00 +00002404 Action = Sema::PSK_Pop;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002405 }
2406 // not push or pop, could be on/off
2407 } else {
2408 if (Tok.is(tok::r_paren)) {
2409 // #pragma vtordisp()
Denis Zobnin2290dac2016-04-29 11:27:00 +00002410 Action = Sema::PSK_Reset;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002411 }
2412 }
2413
2414
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00002415 uint64_t Value = 0;
Denis Zobnin2290dac2016-04-29 11:27:00 +00002416 if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002417 const IdentifierInfo *II = Tok.getIdentifierInfo();
2418 if (II && II->isStr("off")) {
2419 PP.Lex(Tok);
2420 Value = 0;
2421 } else if (II && II->isStr("on")) {
2422 PP.Lex(Tok);
2423 Value = 1;
2424 } else if (Tok.is(tok::numeric_constant) &&
2425 PP.parseSimpleIntegerLiteral(Tok, Value)) {
2426 if (Value > 2) {
2427 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
2428 << 0 << 2 << "vtordisp";
2429 return;
2430 }
2431 } else {
2432 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
2433 << "vtordisp";
2434 return;
2435 }
2436 }
2437
2438 // Finish the pragma: ')' $
2439 if (Tok.isNot(tok::r_paren)) {
2440 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
2441 return;
2442 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00002443 SourceLocation EndLoc = Tok.getLocation();
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002444 PP.Lex(Tok);
2445 if (Tok.isNot(tok::eod)) {
2446 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2447 << "vtordisp";
2448 return;
2449 }
2450
2451 // Enter the annotation.
2452 Token AnnotTok;
2453 AnnotTok.startToken();
2454 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
2455 AnnotTok.setLocation(VtorDispLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002456 AnnotTok.setAnnotationEndLoc(EndLoc);
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00002457 AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
Denis Zobnin2290dac2016-04-29 11:27:00 +00002458 static_cast<uintptr_t>((Action << 16) | (Value & 0xFFFF))));
Ilya Biryukov929af672019-05-17 09:32:05 +00002459 PP.EnterToken(AnnotTok, /*IsReinject=*/false);
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002460}
2461
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002462/// Handle all MS pragmas. Simply forwards the tokens after inserting
Warren Huntc3b18962014-04-08 22:30:47 +00002463/// an annotation token.
2464void PragmaMSPragma::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002465 PragmaIntroducer Introducer, Token &Tok) {
Warren Huntc3b18962014-04-08 22:30:47 +00002466 Token EoF, AnnotTok;
2467 EoF.startToken();
2468 EoF.setKind(tok::eof);
2469 AnnotTok.startToken();
2470 AnnotTok.setKind(tok::annot_pragma_ms_pragma);
2471 AnnotTok.setLocation(Tok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002472 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
Warren Huntc3b18962014-04-08 22:30:47 +00002473 SmallVector<Token, 8> TokenVector;
2474 // Suck up all of the tokens before the eod.
David Majnemera8f2f1d2015-03-19 00:10:23 +00002475 for (; Tok.isNot(tok::eod); PP.Lex(Tok)) {
Warren Huntc3b18962014-04-08 22:30:47 +00002476 TokenVector.push_back(Tok);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002477 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
2478 }
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00002479 // Add a sentinel EoF token to the end of the list.
Warren Huntc3b18962014-04-08 22:30:47 +00002480 TokenVector.push_back(EoF);
2481 // We must allocate this array with new because EnterTokenStream is going to
2482 // delete it later.
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +00002483 auto TokenArray = std::make_unique<Token[]>(TokenVector.size());
David Blaikie2eabcc92016-02-09 18:52:09 +00002484 std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get());
Warren Huntc3b18962014-04-08 22:30:47 +00002485 auto Value = new (PP.getPreprocessorAllocator())
David Blaikie2eabcc92016-02-09 18:52:09 +00002486 std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray),
2487 TokenVector.size());
Warren Huntc3b18962014-04-08 22:30:47 +00002488 AnnotTok.setAnnotationValue(Value);
Ilya Biryukov929af672019-05-17 09:32:05 +00002489 PP.EnterToken(AnnotTok, /*IsReinject*/ false);
Reid Klecknerd3923aa2014-04-03 19:04:24 +00002490}
2491
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002492/// Handle the Microsoft \#pragma detect_mismatch extension.
Aaron Ballman5d041be2013-06-04 02:07:14 +00002493///
2494/// The syntax is:
2495/// \code
2496/// #pragma detect_mismatch("name", "value")
2497/// \endcode
2498/// Where 'name' and 'value' are quoted strings. The values are embedded in
2499/// the object file and passed along to the linker. If the linker detects a
2500/// mismatch in the object file's values for the given name, a LNK2038 error
2501/// is emitted. See MSDN for more details.
2502void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002503 PragmaIntroducer Introducer,
Aaron Ballman5d041be2013-06-04 02:07:14 +00002504 Token &Tok) {
Nico Webercbbaeb12016-03-02 19:28:54 +00002505 SourceLocation DetectMismatchLoc = Tok.getLocation();
Aaron Ballman5d041be2013-06-04 02:07:14 +00002506 PP.Lex(Tok);
2507 if (Tok.isNot(tok::l_paren)) {
Nico Webercbbaeb12016-03-02 19:28:54 +00002508 PP.Diag(DetectMismatchLoc, diag::err_expected) << tok::l_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00002509 return;
2510 }
2511
2512 // Read the name to embed, which must be a string literal.
2513 std::string NameString;
2514 if (!PP.LexStringLiteral(Tok, NameString,
2515 "pragma detect_mismatch",
Rui Ueyama49a3ad22019-07-16 04:46:31 +00002516 /*AllowMacroExpansion=*/true))
Aaron Ballman5d041be2013-06-04 02:07:14 +00002517 return;
2518
2519 // Read the comma followed by a second string literal.
2520 std::string ValueString;
2521 if (Tok.isNot(tok::comma)) {
2522 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
2523 return;
2524 }
2525
2526 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
Rui Ueyama49a3ad22019-07-16 04:46:31 +00002527 /*AllowMacroExpansion=*/true))
Aaron Ballman5d041be2013-06-04 02:07:14 +00002528 return;
2529
2530 if (Tok.isNot(tok::r_paren)) {
Alp Tokerec543272013-12-24 09:48:30 +00002531 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00002532 return;
2533 }
2534 PP.Lex(Tok); // Eat the r_paren.
2535
2536 if (Tok.isNot(tok::eod)) {
2537 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
2538 return;
2539 }
2540
Reid Kleckner71966c92014-02-20 23:37:45 +00002541 // If the pragma is lexically sound, notify any interested PPCallbacks.
2542 if (PP.getPPCallbacks())
Nico Webercbbaeb12016-03-02 19:28:54 +00002543 PP.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc, NameString,
Reid Kleckner71966c92014-02-20 23:37:45 +00002544 ValueString);
2545
Nico Webercbbaeb12016-03-02 19:28:54 +00002546 Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString);
Aaron Ballman5d041be2013-06-04 02:07:14 +00002547}
2548
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002549/// Handle the microsoft \#pragma comment extension.
Reid Kleckner002562a2013-05-06 21:02:12 +00002550///
2551/// The syntax is:
2552/// \code
2553/// #pragma comment(linker, "foo")
2554/// \endcode
2555/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
2556/// "foo" is a string, which is fully macro expanded, and permits string
2557/// concatenation, embedded escape characters etc. See MSDN for more details.
2558void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002559 PragmaIntroducer Introducer,
Reid Kleckner002562a2013-05-06 21:02:12 +00002560 Token &Tok) {
2561 SourceLocation CommentLoc = Tok.getLocation();
2562 PP.Lex(Tok);
2563 if (Tok.isNot(tok::l_paren)) {
2564 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
2565 return;
2566 }
2567
2568 // Read the identifier.
2569 PP.Lex(Tok);
2570 if (Tok.isNot(tok::identifier)) {
2571 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
2572 return;
2573 }
2574
2575 // Verify that this is one of the 5 whitelisted options.
Reid Klecknere43f0fe2013-05-08 13:44:39 +00002576 IdentifierInfo *II = Tok.getIdentifierInfo();
Nico Weber66220292016-03-02 17:28:48 +00002577 PragmaMSCommentKind Kind =
2578 llvm::StringSwitch<PragmaMSCommentKind>(II->getName())
2579 .Case("linker", PCK_Linker)
2580 .Case("lib", PCK_Lib)
2581 .Case("compiler", PCK_Compiler)
2582 .Case("exestr", PCK_ExeStr)
2583 .Case("user", PCK_User)
2584 .Default(PCK_Unknown);
2585 if (Kind == PCK_Unknown) {
Reid Kleckner002562a2013-05-06 21:02:12 +00002586 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
2587 return;
2588 }
2589
Saleem Abdulrasoolfd4db532018-02-07 01:46:46 +00002590 if (PP.getTargetInfo().getTriple().isOSBinFormatELF() && Kind != PCK_Lib) {
2591 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
2592 << II->getName();
2593 return;
2594 }
2595
Yunzhong Gao99efc032015-03-23 20:41:42 +00002596 // On PS4, issue a warning about any pragma comments other than
2597 // #pragma comment lib.
Nico Weber66220292016-03-02 17:28:48 +00002598 if (PP.getTargetInfo().getTriple().isPS4() && Kind != PCK_Lib) {
Yunzhong Gao99efc032015-03-23 20:41:42 +00002599 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
2600 << II->getName();
2601 return;
2602 }
2603
Reid Kleckner002562a2013-05-06 21:02:12 +00002604 // Read the optional string if present.
2605 PP.Lex(Tok);
2606 std::string ArgumentString;
2607 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
2608 "pragma comment",
Rui Ueyama49a3ad22019-07-16 04:46:31 +00002609 /*AllowMacroExpansion=*/true))
Reid Kleckner002562a2013-05-06 21:02:12 +00002610 return;
2611
Reid Klecknere43f0fe2013-05-08 13:44:39 +00002612 // FIXME: warn that 'exestr' is deprecated.
Reid Kleckner002562a2013-05-06 21:02:12 +00002613 // FIXME: If the kind is "compiler" warn if the string is present (it is
2614 // ignored).
Reid Klecknere43f0fe2013-05-08 13:44:39 +00002615 // The MSDN docs say that "lib" and "linker" require a string and have a short
2616 // whitelist of linker options they support, but in practice MSVC doesn't
2617 // issue a diagnostic. Therefore neither does clang.
Reid Kleckner002562a2013-05-06 21:02:12 +00002618
2619 if (Tok.isNot(tok::r_paren)) {
2620 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
2621 return;
2622 }
2623 PP.Lex(Tok); // eat the r_paren.
2624
2625 if (Tok.isNot(tok::eod)) {
2626 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
2627 return;
2628 }
2629
Reid Kleckner71966c92014-02-20 23:37:45 +00002630 // If the pragma is lexically sound, notify any interested PPCallbacks.
2631 if (PP.getPPCallbacks())
2632 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
2633
Nico Weber66220292016-03-02 17:28:48 +00002634 Actions.ActOnPragmaMSComment(CommentLoc, Kind, ArgumentString);
Reid Kleckner002562a2013-05-06 21:02:12 +00002635}
Dario Domizioli13a0a382014-05-23 12:13:25 +00002636
2637// #pragma clang optimize off
2638// #pragma clang optimize on
Fangrui Song6907ce22018-07-30 19:24:48 +00002639void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002640 PragmaIntroducer Introducer,
2641 Token &FirstToken) {
Dario Domizioli13a0a382014-05-23 12:13:25 +00002642 Token Tok;
2643 PP.Lex(Tok);
2644 if (Tok.is(tok::eod)) {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002645 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
Mark Heffernan450c2382014-07-23 17:31:31 +00002646 << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
Dario Domizioli13a0a382014-05-23 12:13:25 +00002647 return;
2648 }
2649 if (Tok.isNot(tok::identifier)) {
2650 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
2651 << PP.getSpelling(Tok);
2652 return;
2653 }
2654 const IdentifierInfo *II = Tok.getIdentifierInfo();
2655 // The only accepted values are 'on' or 'off'.
2656 bool IsOn = false;
2657 if (II->isStr("on")) {
2658 IsOn = true;
2659 } else if (!II->isStr("off")) {
2660 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
2661 << PP.getSpelling(Tok);
2662 return;
2663 }
2664 PP.Lex(Tok);
Fangrui Song6907ce22018-07-30 19:24:48 +00002665
Dario Domizioli13a0a382014-05-23 12:13:25 +00002666 if (Tok.isNot(tok::eod)) {
2667 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
2668 << PP.getSpelling(Tok);
2669 return;
2670 }
Eli Bendersky06a40422014-06-06 20:31:48 +00002671
2672 Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
2673}
2674
Adam Nemet60d32642017-04-04 21:18:36 +00002675namespace {
2676/// Used as the annotation value for tok::annot_pragma_fp.
2677struct TokFPAnnotValue {
2678 enum FlagKinds { Contract };
2679 enum FlagValues { On, Off, Fast };
2680
2681 FlagKinds FlagKind;
2682 FlagValues FlagValue;
2683};
2684} // end anonymous namespace
2685
2686void PragmaFPHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002687 PragmaIntroducer Introducer, Token &Tok) {
Adam Nemet60d32642017-04-04 21:18:36 +00002688 // fp
2689 Token PragmaName = Tok;
2690 SmallVector<Token, 1> TokenList;
2691
2692 PP.Lex(Tok);
2693 if (Tok.isNot(tok::identifier)) {
2694 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
2695 << /*MissingOption=*/true << "";
2696 return;
2697 }
2698
2699 while (Tok.is(tok::identifier)) {
2700 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
2701
2702 auto FlagKind =
2703 llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagKinds>>(
2704 OptionInfo->getName())
2705 .Case("contract", TokFPAnnotValue::Contract)
2706 .Default(None);
2707 if (!FlagKind) {
2708 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
2709 << /*MissingOption=*/false << OptionInfo;
2710 return;
2711 }
2712 PP.Lex(Tok);
2713
2714 // Read '('
2715 if (Tok.isNot(tok::l_paren)) {
2716 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
2717 return;
2718 }
2719 PP.Lex(Tok);
2720
2721 if (Tok.isNot(tok::identifier)) {
2722 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
2723 << PP.getSpelling(Tok) << OptionInfo->getName();
2724 return;
2725 }
2726 const IdentifierInfo *II = Tok.getIdentifierInfo();
2727
2728 auto FlagValue =
2729 llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagValues>>(
2730 II->getName())
2731 .Case("on", TokFPAnnotValue::On)
2732 .Case("off", TokFPAnnotValue::Off)
2733 .Case("fast", TokFPAnnotValue::Fast)
2734 .Default(llvm::None);
2735
2736 if (!FlagValue) {
2737 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
2738 << PP.getSpelling(Tok) << OptionInfo->getName();
2739 return;
2740 }
2741 PP.Lex(Tok);
2742
2743 // Read ')'
2744 if (Tok.isNot(tok::r_paren)) {
2745 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
2746 return;
2747 }
2748 PP.Lex(Tok);
2749
2750 auto *AnnotValue = new (PP.getPreprocessorAllocator())
2751 TokFPAnnotValue{*FlagKind, *FlagValue};
2752 // Generate the loop hint token.
2753 Token FPTok;
2754 FPTok.startToken();
2755 FPTok.setKind(tok::annot_pragma_fp);
2756 FPTok.setLocation(PragmaName.getLocation());
2757 FPTok.setAnnotationEndLoc(PragmaName.getLocation());
2758 FPTok.setAnnotationValue(reinterpret_cast<void *>(AnnotValue));
2759 TokenList.push_back(FPTok);
2760 }
2761
2762 if (Tok.isNot(tok::eod)) {
2763 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2764 << "clang fp";
2765 return;
2766 }
2767
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +00002768 auto TokenArray = std::make_unique<Token[]>(TokenList.size());
Adam Nemet60d32642017-04-04 21:18:36 +00002769 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
2770
2771 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
Ilya Biryukov929af672019-05-17 09:32:05 +00002772 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
Adam Nemet60d32642017-04-04 21:18:36 +00002773}
2774
2775void Parser::HandlePragmaFP() {
2776 assert(Tok.is(tok::annot_pragma_fp));
2777 auto *AnnotValue =
2778 reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue());
2779
2780 LangOptions::FPContractModeKind FPC;
2781 switch (AnnotValue->FlagValue) {
2782 case TokFPAnnotValue::On:
2783 FPC = LangOptions::FPC_On;
2784 break;
2785 case TokFPAnnotValue::Fast:
2786 FPC = LangOptions::FPC_Fast;
2787 break;
2788 case TokFPAnnotValue::Off:
2789 FPC = LangOptions::FPC_Off;
2790 break;
2791 }
2792
2793 Actions.ActOnPragmaFPContract(FPC);
Richard Smithaf3b3252017-05-18 19:21:48 +00002794 ConsumeAnnotationToken();
Adam Nemet60d32642017-04-04 21:18:36 +00002795}
2796
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002797/// Parses loop or unroll pragma hint value and fills in Info.
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002798static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
2799 Token Option, bool ValueInParens,
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002800 PragmaLoopHintInfo &Info) {
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002801 SmallVector<Token, 1> ValueList;
2802 int OpenParens = ValueInParens ? 1 : 0;
2803 // Read constant expression.
2804 while (Tok.isNot(tok::eod)) {
2805 if (Tok.is(tok::l_paren))
2806 OpenParens++;
2807 else if (Tok.is(tok::r_paren)) {
2808 OpenParens--;
2809 if (OpenParens == 0 && ValueInParens)
2810 break;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002811 }
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002812
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002813 ValueList.push_back(Tok);
2814 PP.Lex(Tok);
2815 }
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002816
2817 if (ValueInParens) {
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002818 // Read ')'
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002819 if (Tok.isNot(tok::r_paren)) {
2820 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
2821 return true;
2822 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002823 PP.Lex(Tok);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002824 }
2825
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002826 Token EOFTok;
2827 EOFTok.startToken();
2828 EOFTok.setKind(tok::eof);
2829 EOFTok.setLocation(Tok.getLocation());
2830 ValueList.push_back(EOFTok); // Terminates expression for parsing.
2831
Benjamin Kramerfa7f8552015-08-05 09:39:57 +00002832 Info.Toks = llvm::makeArrayRef(ValueList).copy(PP.getPreprocessorAllocator());
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002833
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002834 Info.PragmaName = PragmaName;
2835 Info.Option = Option;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002836 return false;
2837}
2838
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002839/// Handle the \#pragma clang loop directive.
Eli Bendersky06a40422014-06-06 20:31:48 +00002840/// #pragma clang 'loop' loop-hints
2841///
2842/// loop-hints:
2843/// loop-hint loop-hints[opt]
2844///
2845/// loop-hint:
2846/// 'vectorize' '(' loop-hint-keyword ')'
2847/// 'interleave' '(' loop-hint-keyword ')'
Mark Heffernan450c2382014-07-23 17:31:31 +00002848/// 'unroll' '(' unroll-hint-keyword ')'
Sjoerd Meijera48f58c2019-07-25 07:33:13 +00002849/// 'vectorize_predicate' '(' loop-hint-keyword ')'
Eli Bendersky06a40422014-06-06 20:31:48 +00002850/// 'vectorize_width' '(' loop-hint-value ')'
2851/// 'interleave_count' '(' loop-hint-value ')'
Eli Bendersky86483b32014-06-11 17:56:26 +00002852/// 'unroll_count' '(' loop-hint-value ')'
Aaron Ballman9bdf5152019-01-04 17:20:00 +00002853/// 'pipeline' '(' disable ')'
2854/// 'pipeline_initiation_interval' '(' loop-hint-value ')'
Eli Bendersky06a40422014-06-06 20:31:48 +00002855///
2856/// loop-hint-keyword:
2857/// 'enable'
2858/// 'disable'
Tyler Nowicki9d268e12015-06-11 23:23:17 +00002859/// 'assume_safety'
Eli Bendersky06a40422014-06-06 20:31:48 +00002860///
Mark Heffernan450c2382014-07-23 17:31:31 +00002861/// unroll-hint-keyword:
Mark Heffernan397a98d2015-08-10 17:29:39 +00002862/// 'enable'
Mark Heffernan450c2382014-07-23 17:31:31 +00002863/// 'disable'
Mark Heffernan397a98d2015-08-10 17:29:39 +00002864/// 'full'
Mark Heffernan450c2382014-07-23 17:31:31 +00002865///
Eli Bendersky06a40422014-06-06 20:31:48 +00002866/// loop-hint-value:
2867/// constant-expression
2868///
2869/// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
2870/// try vectorizing the instructions of the loop it precedes. Specifying
2871/// interleave(enable) or interleave_count(_value_) instructs llvm to try
2872/// interleaving multiple iterations of the loop it precedes. The width of the
2873/// vector instructions is specified by vectorize_width() and the number of
2874/// interleaved loop iterations is specified by interleave_count(). Specifying a
2875/// value of 1 effectively disables vectorization/interleaving, even if it is
2876/// possible and profitable, and 0 is invalid. The loop vectorizer currently
2877/// only works on inner loops.
2878///
Eli Bendersky86483b32014-06-11 17:56:26 +00002879/// The unroll and unroll_count directives control the concatenation
Mark Heffernan397a98d2015-08-10 17:29:39 +00002880/// unroller. Specifying unroll(enable) instructs llvm to unroll the loop
2881/// completely if the trip count is known at compile time and unroll partially
2882/// if the trip count is not known. Specifying unroll(full) is similar to
2883/// unroll(enable) but will unroll the loop only if the trip count is known at
2884/// compile time. Specifying unroll(disable) disables unrolling for the
2885/// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the
2886/// loop the number of times indicated by the value.
Eli Bendersky06a40422014-06-06 20:31:48 +00002887void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002888 PragmaIntroducer Introducer,
Eli Bendersky06a40422014-06-06 20:31:48 +00002889 Token &Tok) {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002890 // Incoming token is "loop" from "#pragma clang loop".
2891 Token PragmaName = Tok;
Eli Bendersky06a40422014-06-06 20:31:48 +00002892 SmallVector<Token, 1> TokenList;
2893
2894 // Lex the optimization option and verify it is an identifier.
2895 PP.Lex(Tok);
2896 if (Tok.isNot(tok::identifier)) {
2897 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
2898 << /*MissingOption=*/true << "";
2899 return;
2900 }
2901
2902 while (Tok.is(tok::identifier)) {
2903 Token Option = Tok;
2904 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
2905
Eli Bendersky86483b32014-06-11 17:56:26 +00002906 bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002907 .Case("vectorize", true)
2908 .Case("interleave", true)
2909 .Case("unroll", true)
Adam Nemet2de463e2016-06-14 12:04:26 +00002910 .Case("distribute", true)
Sjoerd Meijera48f58c2019-07-25 07:33:13 +00002911 .Case("vectorize_predicate", true)
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002912 .Case("vectorize_width", true)
2913 .Case("interleave_count", true)
2914 .Case("unroll_count", true)
Aaron Ballman9bdf5152019-01-04 17:20:00 +00002915 .Case("pipeline", true)
2916 .Case("pipeline_initiation_interval", true)
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002917 .Default(false);
Eli Bendersky86483b32014-06-11 17:56:26 +00002918 if (!OptionValid) {
Eli Bendersky06a40422014-06-06 20:31:48 +00002919 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
2920 << /*MissingOption=*/false << OptionInfo;
2921 return;
2922 }
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002923 PP.Lex(Tok);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002924
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002925 // Read '('
2926 if (Tok.isNot(tok::l_paren)) {
2927 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002928 return;
2929 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002930 PP.Lex(Tok);
2931
2932 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2933 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
2934 *Info))
2935 return;
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002936
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002937 // Generate the loop hint token.
Eli Bendersky06a40422014-06-06 20:31:48 +00002938 Token LoopHintTok;
2939 LoopHintTok.startToken();
2940 LoopHintTok.setKind(tok::annot_pragma_loop_hint);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002941 LoopHintTok.setLocation(PragmaName.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002942 LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());
Eli Bendersky06a40422014-06-06 20:31:48 +00002943 LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
2944 TokenList.push_back(LoopHintTok);
2945 }
2946
2947 if (Tok.isNot(tok::eod)) {
2948 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2949 << "clang loop";
2950 return;
2951 }
2952
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +00002953 auto TokenArray = std::make_unique<Token[]>(TokenList.size());
David Blaikie2eabcc92016-02-09 18:52:09 +00002954 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
Eli Bendersky06a40422014-06-06 20:31:48 +00002955
David Blaikie2eabcc92016-02-09 18:52:09 +00002956 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
Ilya Biryukov929af672019-05-17 09:32:05 +00002957 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
Eli Bendersky06a40422014-06-06 20:31:48 +00002958}
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002959
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002960/// Handle the loop unroll optimization pragmas.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002961/// #pragma unroll
2962/// #pragma unroll unroll-hint-value
2963/// #pragma unroll '(' unroll-hint-value ')'
Mark Heffernanc888e412014-07-24 18:09:38 +00002964/// #pragma nounroll
David Greenc8e39242018-08-01 14:36:12 +00002965/// #pragma unroll_and_jam
2966/// #pragma unroll_and_jam unroll-hint-value
2967/// #pragma unroll_and_jam '(' unroll-hint-value ')'
2968/// #pragma nounroll_and_jam
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002969///
2970/// unroll-hint-value:
2971/// constant-expression
2972///
Mark Heffernanc888e412014-07-24 18:09:38 +00002973/// Loop unrolling hints can be specified with '#pragma unroll' or
2974/// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
2975/// contained in parentheses. With no argument the directive instructs llvm to
2976/// try to unroll the loop completely. A positive integer argument can be
2977/// specified to indicate the number of times the loop should be unrolled. To
2978/// maximize compatibility with other compilers the unroll count argument can be
2979/// specified with or without parentheses. Specifying, '#pragma nounroll'
2980/// disables unrolling of the loop.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002981void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002982 PragmaIntroducer Introducer,
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002983 Token &Tok) {
Mark Heffernanc888e412014-07-24 18:09:38 +00002984 // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
2985 // "#pragma nounroll".
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002986 Token PragmaName = Tok;
2987 PP.Lex(Tok);
2988 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2989 if (Tok.is(tok::eod)) {
Mark Heffernanc888e412014-07-24 18:09:38 +00002990 // nounroll or unroll pragma without an argument.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002991 Info->PragmaName = PragmaName;
Aaron Ballmand6807da2014-08-01 12:41:37 +00002992 Info->Option.startToken();
David Greenc8e39242018-08-01 14:36:12 +00002993 } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll" ||
2994 PragmaName.getIdentifierInfo()->getName() == "nounroll_and_jam") {
Mark Heffernanc888e412014-07-24 18:09:38 +00002995 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
David Greenc8e39242018-08-01 14:36:12 +00002996 << PragmaName.getIdentifierInfo()->getName();
Mark Heffernanc888e412014-07-24 18:09:38 +00002997 return;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002998 } else {
2999 // Unroll pragma with an argument: "#pragma unroll N" or
3000 // "#pragma unroll(N)".
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00003001 // Read '(' if it exists.
3002 bool ValueInParens = Tok.is(tok::l_paren);
3003 if (ValueInParens)
3004 PP.Lex(Tok);
3005
Aaron Ballmand0b090d2014-08-01 12:20:20 +00003006 Token Option;
3007 Option.startToken();
3008 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003009 return;
3010
3011 // In CUDA, the argument to '#pragma unroll' should not be contained in
3012 // parentheses.
3013 if (PP.getLangOpts().CUDA && ValueInParens)
Tyler Nowickic724a83e2014-10-12 20:46:07 +00003014 PP.Diag(Info->Toks[0].getLocation(),
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003015 diag::warn_pragma_unroll_cuda_value_in_parens);
3016
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003017 if (Tok.isNot(tok::eod)) {
3018 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3019 << "unroll";
3020 return;
3021 }
3022 }
3023
3024 // Generate the hint token.
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +00003025 auto TokenArray = std::make_unique<Token[]>(1);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003026 TokenArray[0].startToken();
3027 TokenArray[0].setKind(tok::annot_pragma_loop_hint);
3028 TokenArray[0].setLocation(PragmaName.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00003029 TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003030 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
David Blaikie2eabcc92016-02-09 18:52:09 +00003031 PP.EnterTokenStream(std::move(TokenArray), 1,
Ilya Biryukov929af672019-05-17 09:32:05 +00003032 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003033}
Reid Kleckner3f1ec622016-09-07 16:38:32 +00003034
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003035/// Handle the Microsoft \#pragma intrinsic extension.
Reid Kleckner3f1ec622016-09-07 16:38:32 +00003036///
3037/// The syntax is:
3038/// \code
3039/// #pragma intrinsic(memset)
3040/// #pragma intrinsic(strlen, memcpy)
3041/// \endcode
3042///
3043/// Pragma intrisic tells the compiler to use a builtin version of the
3044/// function. Clang does it anyway, so the pragma doesn't really do anything.
3045/// Anyway, we emit a warning if the function specified in \#pragma intrinsic
3046/// isn't an intrinsic in clang and suggest to include intrin.h.
3047void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00003048 PragmaIntroducer Introducer,
Reid Kleckner3f1ec622016-09-07 16:38:32 +00003049 Token &Tok) {
3050 PP.Lex(Tok);
3051
3052 if (Tok.isNot(tok::l_paren)) {
3053 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
3054 << "intrinsic";
3055 return;
3056 }
3057 PP.Lex(Tok);
3058
3059 bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
3060
3061 while (Tok.is(tok::identifier)) {
3062 IdentifierInfo *II = Tok.getIdentifierInfo();
3063 if (!II->getBuiltinID())
3064 PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
3065 << II << SuggestIntrinH;
3066
3067 PP.Lex(Tok);
3068 if (Tok.isNot(tok::comma))
3069 break;
3070 PP.Lex(Tok);
3071 }
3072
3073 if (Tok.isNot(tok::r_paren)) {
3074 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
3075 << "intrinsic";
3076 return;
3077 }
3078 PP.Lex(Tok);
3079
3080 if (Tok.isNot(tok::eod))
3081 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3082 << "intrinsic";
3083}
Hans Wennborg1bbe00e2018-03-20 08:53:11 +00003084
3085// #pragma optimize("gsty", on|off)
3086void PragmaMSOptimizeHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00003087 PragmaIntroducer Introducer,
Hans Wennborg1bbe00e2018-03-20 08:53:11 +00003088 Token &Tok) {
3089 SourceLocation StartLoc = Tok.getLocation();
3090 PP.Lex(Tok);
3091
3092 if (Tok.isNot(tok::l_paren)) {
3093 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "optimize";
3094 return;
3095 }
3096 PP.Lex(Tok);
3097
3098 if (Tok.isNot(tok::string_literal)) {
3099 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_string) << "optimize";
3100 return;
3101 }
3102 // We could syntax check the string but it's probably not worth the effort.
3103 PP.Lex(Tok);
3104
3105 if (Tok.isNot(tok::comma)) {
3106 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_comma) << "optimize";
3107 return;
3108 }
3109 PP.Lex(Tok);
3110
3111 if (Tok.is(tok::eod) || Tok.is(tok::r_paren)) {
3112 PP.Diag(Tok.getLocation(), diag::warn_pragma_missing_argument)
3113 << "optimize" << /*Expected=*/true << "'on' or 'off'";
3114 return;
3115 }
3116 IdentifierInfo *II = Tok.getIdentifierInfo();
3117 if (!II || (!II->isStr("on") && !II->isStr("off"))) {
3118 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)
3119 << PP.getSpelling(Tok) << "optimize" << /*Expected=*/true
3120 << "'on' or 'off'";
3121 return;
3122 }
3123 PP.Lex(Tok);
3124
3125 if (Tok.isNot(tok::r_paren)) {
3126 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "optimize";
3127 return;
3128 }
3129 PP.Lex(Tok);
3130
3131 if (Tok.isNot(tok::eod)) {
3132 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3133 << "optimize";
3134 return;
3135 }
3136 PP.Diag(StartLoc, diag::warn_pragma_optimize);
3137}
3138
Justin Lebar67a78a62016-10-08 22:15:58 +00003139void PragmaForceCUDAHostDeviceHandler::HandlePragma(
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00003140 Preprocessor &PP, PragmaIntroducer Introducer, Token &Tok) {
Justin Lebar67a78a62016-10-08 22:15:58 +00003141 Token FirstTok = Tok;
3142
3143 PP.Lex(Tok);
3144 IdentifierInfo *Info = Tok.getIdentifierInfo();
3145 if (!Info || (!Info->isStr("begin") && !Info->isStr("end"))) {
3146 PP.Diag(FirstTok.getLocation(),
3147 diag::warn_pragma_force_cuda_host_device_bad_arg);
3148 return;
3149 }
3150
3151 if (Info->isStr("begin"))
3152 Actions.PushForceCUDAHostDevice();
3153 else if (!Actions.PopForceCUDAHostDevice())
3154 PP.Diag(FirstTok.getLocation(),
3155 diag::err_pragma_cannot_end_force_cuda_host_device);
3156
3157 PP.Lex(Tok);
3158 if (!Tok.is(tok::eod))
3159 PP.Diag(FirstTok.getLocation(),
3160 diag::warn_pragma_force_cuda_host_device_bad_arg);
3161}
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003162
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003163/// Handle the #pragma clang attribute directive.
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003164///
3165/// The syntax is:
3166/// \code
Erik Pilkington0876cae2018-12-20 22:32:04 +00003167/// #pragma clang attribute push (attribute, subject-set)
Erik Pilkington7d180942018-10-29 17:38:42 +00003168/// #pragma clang attribute push
3169/// #pragma clang attribute (attribute, subject-set)
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003170/// #pragma clang attribute pop
3171/// \endcode
3172///
Erik Pilkington0876cae2018-12-20 22:32:04 +00003173/// There are also 'namespace' variants of push and pop directives. The bare
3174/// '#pragma clang attribute (attribute, subject-set)' version doesn't require a
3175/// namespace, since it always applies attributes to the most recently pushed
3176/// group, regardless of namespace.
3177/// \code
3178/// #pragma clang attribute namespace.push (attribute, subject-set)
3179/// #pragma clang attribute namespace.push
3180/// #pragma clang attribute namespace.pop
3181/// \endcode
3182///
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003183/// The subject-set clause defines the set of declarations which receive the
3184/// attribute. Its exact syntax is described in the LanguageExtensions document
3185/// in Clang's documentation.
3186///
3187/// This directive instructs the compiler to begin/finish applying the specified
3188/// attribute to the set of attribute-specific declarations in the active range
3189/// of the pragma.
3190void PragmaAttributeHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00003191 PragmaIntroducer Introducer,
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003192 Token &FirstToken) {
3193 Token Tok;
3194 PP.Lex(Tok);
3195 auto *Info = new (PP.getPreprocessorAllocator())
3196 PragmaAttributeInfo(AttributesForPragmaAttribute);
3197
Erik Pilkington0876cae2018-12-20 22:32:04 +00003198 // Parse the optional namespace followed by a period.
3199 if (Tok.is(tok::identifier)) {
3200 IdentifierInfo *II = Tok.getIdentifierInfo();
3201 if (!II->isStr("push") && !II->isStr("pop")) {
3202 Info->Namespace = II;
3203 PP.Lex(Tok);
3204
3205 if (!Tok.is(tok::period)) {
3206 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_period)
3207 << II;
3208 return;
3209 }
3210 PP.Lex(Tok);
3211 }
3212 }
3213
Erik Pilkington7d180942018-10-29 17:38:42 +00003214 if (!Tok.isOneOf(tok::identifier, tok::l_paren)) {
3215 PP.Diag(Tok.getLocation(),
3216 diag::err_pragma_attribute_expected_push_pop_paren);
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003217 return;
3218 }
Erik Pilkington7d180942018-10-29 17:38:42 +00003219
3220 // Determine what action this pragma clang attribute represents.
Erik Pilkington0876cae2018-12-20 22:32:04 +00003221 if (Tok.is(tok::l_paren)) {
3222 if (Info->Namespace) {
3223 PP.Diag(Tok.getLocation(),
3224 diag::err_pragma_attribute_namespace_on_attribute);
3225 PP.Diag(Tok.getLocation(),
3226 diag::note_pragma_attribute_namespace_on_attribute);
3227 return;
3228 }
Erik Pilkington7d180942018-10-29 17:38:42 +00003229 Info->Action = PragmaAttributeInfo::Attribute;
Erik Pilkington0876cae2018-12-20 22:32:04 +00003230 } else {
Erik Pilkington7d180942018-10-29 17:38:42 +00003231 const IdentifierInfo *II = Tok.getIdentifierInfo();
3232 if (II->isStr("push"))
3233 Info->Action = PragmaAttributeInfo::Push;
3234 else if (II->isStr("pop"))
3235 Info->Action = PragmaAttributeInfo::Pop;
3236 else {
3237 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument)
3238 << PP.getSpelling(Tok);
3239 return;
3240 }
3241
3242 PP.Lex(Tok);
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003243 }
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003244
3245 // Parse the actual attribute.
Erik Pilkington7d180942018-10-29 17:38:42 +00003246 if ((Info->Action == PragmaAttributeInfo::Push && Tok.isNot(tok::eod)) ||
3247 Info->Action == PragmaAttributeInfo::Attribute) {
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003248 if (Tok.isNot(tok::l_paren)) {
3249 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
3250 return;
3251 }
3252 PP.Lex(Tok);
3253
3254 // Lex the attribute tokens.
3255 SmallVector<Token, 16> AttributeTokens;
3256 int OpenParens = 1;
3257 while (Tok.isNot(tok::eod)) {
3258 if (Tok.is(tok::l_paren))
3259 OpenParens++;
3260 else if (Tok.is(tok::r_paren)) {
3261 OpenParens--;
3262 if (OpenParens == 0)
3263 break;
3264 }
3265
3266 AttributeTokens.push_back(Tok);
3267 PP.Lex(Tok);
3268 }
3269
3270 if (AttributeTokens.empty()) {
3271 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_attribute);
3272 return;
3273 }
3274 if (Tok.isNot(tok::r_paren)) {
3275 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3276 return;
3277 }
3278 SourceLocation EndLoc = Tok.getLocation();
3279 PP.Lex(Tok);
3280
3281 // Terminate the attribute for parsing.
3282 Token EOFTok;
3283 EOFTok.startToken();
3284 EOFTok.setKind(tok::eof);
3285 EOFTok.setLocation(EndLoc);
3286 AttributeTokens.push_back(EOFTok);
3287
3288 Info->Tokens =
3289 llvm::makeArrayRef(AttributeTokens).copy(PP.getPreprocessorAllocator());
3290 }
3291
3292 if (Tok.isNot(tok::eod))
3293 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3294 << "clang attribute";
3295
3296 // Generate the annotated pragma token.
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +00003297 auto TokenArray = std::make_unique<Token[]>(1);
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003298 TokenArray[0].startToken();
3299 TokenArray[0].setKind(tok::annot_pragma_attribute);
3300 TokenArray[0].setLocation(FirstToken.getLocation());
3301 TokenArray[0].setAnnotationEndLoc(FirstToken.getLocation());
3302 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
3303 PP.EnterTokenStream(std::move(TokenArray), 1,
Ilya Biryukov929af672019-05-17 09:32:05 +00003304 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003305}
Hans Wennborg739b4102019-10-09 15:22:38 +02003306
3307// Handle '#pragma clang max_tokens 12345'.
3308void PragmaMaxTokensHereHandler::HandlePragma(Preprocessor &PP,
3309 PragmaIntroducer Introducer,
3310 Token &Tok) {
3311 PP.Lex(Tok);
3312 if (Tok.is(tok::eod)) {
3313 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
3314 << "clang max_tokens_here" << /*Expected=*/true << "integer";
3315 return;
3316 }
3317
3318 SourceLocation Loc = Tok.getLocation();
3319 uint64_t MaxTokens;
3320 if (Tok.isNot(tok::numeric_constant) ||
3321 !PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) {
3322 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer)
3323 << "clang max_tokens_here";
3324 return;
3325 }
3326
3327 if (Tok.isNot(tok::eod)) {
3328 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3329 << "clang max_tokens_here";
3330 return;
3331 }
3332
3333 if (PP.getTokenCount() > MaxTokens) {
3334 PP.Diag(Loc, diag::warn_max_tokens)
3335 << PP.getTokenCount() << (unsigned)MaxTokens;
3336 }
3337}
3338
Hans Wennborg74734e82020-02-07 11:32:24 +01003339// Handle '#pragma clang max_tokens_total 12345'.
Hans Wennborg739b4102019-10-09 15:22:38 +02003340void PragmaMaxTokensTotalHandler::HandlePragma(Preprocessor &PP,
3341 PragmaIntroducer Introducer,
3342 Token &Tok) {
3343 PP.Lex(Tok);
3344 if (Tok.is(tok::eod)) {
3345 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
3346 << "clang max_tokens_total" << /*Expected=*/true << "integer";
3347 return;
3348 }
3349
3350 SourceLocation Loc = Tok.getLocation();
3351 uint64_t MaxTokens;
3352 if (Tok.isNot(tok::numeric_constant) ||
3353 !PP.parseSimpleIntegerLiteral(Tok, MaxTokens)) {
3354 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_integer)
3355 << "clang max_tokens_total";
3356 return;
3357 }
3358
3359 if (Tok.isNot(tok::eod)) {
3360 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3361 << "clang max_tokens_total";
3362 return;
3363 }
3364
3365 PP.overrideMaxTokens(MaxTokens, Loc);
3366}