blob: d589cb690ad8e2be03a163cb000e077e1d417c6b [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
Eli Bendersky06a40422014-06-06 20:31:48 +0000265} // end namespace
266
267void Parser::initializePragmaHandlers() {
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000268 AlignHandler = std::make_unique<PragmaAlignHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000269 PP.AddPragmaHandler(AlignHandler.get());
270
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000271 GCCVisibilityHandler = std::make_unique<PragmaGCCVisibilityHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000272 PP.AddPragmaHandler("GCC", GCCVisibilityHandler.get());
273
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000274 OptionsHandler = std::make_unique<PragmaOptionsHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000275 PP.AddPragmaHandler(OptionsHandler.get());
276
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000277 PackHandler = std::make_unique<PragmaPackHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000278 PP.AddPragmaHandler(PackHandler.get());
279
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000280 MSStructHandler = std::make_unique<PragmaMSStructHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000281 PP.AddPragmaHandler(MSStructHandler.get());
282
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000283 UnusedHandler = std::make_unique<PragmaUnusedHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000284 PP.AddPragmaHandler(UnusedHandler.get());
285
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000286 WeakHandler = std::make_unique<PragmaWeakHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000287 PP.AddPragmaHandler(WeakHandler.get());
288
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000289 RedefineExtnameHandler = std::make_unique<PragmaRedefineExtnameHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000290 PP.AddPragmaHandler(RedefineExtnameHandler.get());
291
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000292 FPContractHandler = std::make_unique<PragmaFPContractHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000293 PP.AddPragmaHandler("STDC", FPContractHandler.get());
294
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000295 STDCFENVHandler = std::make_unique<PragmaSTDC_FENV_ACCESSHandler>();
Steven Wub96a3a42018-01-05 22:45:03 +0000296 PP.AddPragmaHandler("STDC", STDCFENVHandler.get());
297
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000298 STDCCXLIMITHandler = std::make_unique<PragmaSTDC_CX_LIMITED_RANGEHandler>();
Steven Wub96a3a42018-01-05 22:45:03 +0000299 PP.AddPragmaHandler("STDC", STDCCXLIMITHandler.get());
300
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000301 STDCUnknownHandler = std::make_unique<PragmaSTDC_UnknownHandler>();
Steven Wub96a3a42018-01-05 22:45:03 +0000302 PP.AddPragmaHandler("STDC", STDCUnknownHandler.get());
303
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000304 PCSectionHandler = std::make_unique<PragmaClangSectionHandler>(Actions);
Javed Absar2a67c9e2017-06-05 10:11:57 +0000305 PP.AddPragmaHandler("clang", PCSectionHandler.get());
306
Reid Kleckner5b086462014-02-20 22:52:09 +0000307 if (getLangOpts().OpenCL) {
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000308 OpenCLExtensionHandler = std::make_unique<PragmaOpenCLExtensionHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000309 PP.AddPragmaHandler("OPENCL", OpenCLExtensionHandler.get());
310
311 PP.AddPragmaHandler("OPENCL", FPContractHandler.get());
312 }
313 if (getLangOpts().OpenMP)
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000314 OpenMPHandler = std::make_unique<PragmaOpenMPHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000315 else
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000316 OpenMPHandler = std::make_unique<PragmaNoOpenMPHandler>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000317 PP.AddPragmaHandler(OpenMPHandler.get());
318
Saleem Abdulrasoolfd4db532018-02-07 01:46:46 +0000319 if (getLangOpts().MicrosoftExt ||
320 getTargetInfo().getTriple().isOSBinFormatELF()) {
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000321 MSCommentHandler = std::make_unique<PragmaCommentHandler>(Actions);
Reid Kleckner5b086462014-02-20 22:52:09 +0000322 PP.AddPragmaHandler(MSCommentHandler.get());
Yunzhong Gao99efc032015-03-23 20:41:42 +0000323 }
324
325 if (getLangOpts().MicrosoftExt) {
David Blaikiee0cfc042018-11-15 03:04:23 +0000326 MSDetectMismatchHandler =
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000327 std::make_unique<PragmaDetectMismatchHandler>(Actions);
Reid Kleckner5b086462014-02-20 22:52:09 +0000328 PP.AddPragmaHandler(MSDetectMismatchHandler.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000329 MSPointersToMembers = std::make_unique<PragmaMSPointersToMembers>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000330 PP.AddPragmaHandler(MSPointersToMembers.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000331 MSVtorDisp = std::make_unique<PragmaMSVtorDisp>();
Reid Kleckner5b086462014-02-20 22:52:09 +0000332 PP.AddPragmaHandler(MSVtorDisp.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000333 MSInitSeg = std::make_unique<PragmaMSPragma>("init_seg");
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000334 PP.AddPragmaHandler(MSInitSeg.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000335 MSDataSeg = std::make_unique<PragmaMSPragma>("data_seg");
Warren Huntc3b18962014-04-08 22:30:47 +0000336 PP.AddPragmaHandler(MSDataSeg.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000337 MSBSSSeg = std::make_unique<PragmaMSPragma>("bss_seg");
Warren Huntc3b18962014-04-08 22:30:47 +0000338 PP.AddPragmaHandler(MSBSSSeg.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000339 MSConstSeg = std::make_unique<PragmaMSPragma>("const_seg");
Warren Huntc3b18962014-04-08 22:30:47 +0000340 PP.AddPragmaHandler(MSConstSeg.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000341 MSCodeSeg = std::make_unique<PragmaMSPragma>("code_seg");
Warren Huntc3b18962014-04-08 22:30:47 +0000342 PP.AddPragmaHandler(MSCodeSeg.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000343 MSSection = std::make_unique<PragmaMSPragma>("section");
Warren Huntc3b18962014-04-08 22:30:47 +0000344 PP.AddPragmaHandler(MSSection.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000345 MSRuntimeChecks = std::make_unique<PragmaMSRuntimeChecksHandler>();
Hans Wennborg7357bbc2015-10-12 20:47:58 +0000346 PP.AddPragmaHandler(MSRuntimeChecks.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000347 MSIntrinsic = std::make_unique<PragmaMSIntrinsicHandler>();
Reid Kleckner3f1ec622016-09-07 16:38:32 +0000348 PP.AddPragmaHandler(MSIntrinsic.get());
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000349 MSOptimize = std::make_unique<PragmaMSOptimizeHandler>();
Hans Wennborg1bbe00e2018-03-20 08:53:11 +0000350 PP.AddPragmaHandler(MSOptimize.get());
Reid Kleckner5b086462014-02-20 22:52:09 +0000351 }
Eli Bendersky06a40422014-06-06 20:31:48 +0000352
Justin Lebar67a78a62016-10-08 22:15:58 +0000353 if (getLangOpts().CUDA) {
David Blaikiee0cfc042018-11-15 03:04:23 +0000354 CUDAForceHostDeviceHandler =
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000355 std::make_unique<PragmaForceCUDAHostDeviceHandler>(Actions);
Justin Lebar67a78a62016-10-08 22:15:58 +0000356 PP.AddPragmaHandler("clang", CUDAForceHostDeviceHandler.get());
357 }
358
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000359 OptimizeHandler = std::make_unique<PragmaOptimizeHandler>(Actions);
Eli Bendersky06a40422014-06-06 20:31:48 +0000360 PP.AddPragmaHandler("clang", OptimizeHandler.get());
361
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000362 LoopHintHandler = std::make_unique<PragmaLoopHintHandler>();
Eli Bendersky06a40422014-06-06 20:31:48 +0000363 PP.AddPragmaHandler("clang", LoopHintHandler.get());
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000364
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000365 UnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("unroll");
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000366 PP.AddPragmaHandler(UnrollHintHandler.get());
Mark Heffernanc888e412014-07-24 18:09:38 +0000367
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000368 NoUnrollHintHandler = std::make_unique<PragmaUnrollHintHandler>("nounroll");
Mark Heffernanc888e412014-07-24 18:09:38 +0000369 PP.AddPragmaHandler(NoUnrollHintHandler.get());
Adam Nemet60d32642017-04-04 21:18:36 +0000370
David Blaikiee0cfc042018-11-15 03:04:23 +0000371 UnrollAndJamHintHandler =
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000372 std::make_unique<PragmaUnrollHintHandler>("unroll_and_jam");
David Greenc8e39242018-08-01 14:36:12 +0000373 PP.AddPragmaHandler(UnrollAndJamHintHandler.get());
374
David Blaikiee0cfc042018-11-15 03:04:23 +0000375 NoUnrollAndJamHintHandler =
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000376 std::make_unique<PragmaUnrollHintHandler>("nounroll_and_jam");
David Greenc8e39242018-08-01 14:36:12 +0000377 PP.AddPragmaHandler(NoUnrollAndJamHintHandler.get());
378
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000379 FPHandler = std::make_unique<PragmaFPHandler>();
Adam Nemet60d32642017-04-04 21:18:36 +0000380 PP.AddPragmaHandler("clang", FPHandler.get());
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000381
David Blaikiee0cfc042018-11-15 03:04:23 +0000382 AttributePragmaHandler =
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +0000383 std::make_unique<PragmaAttributeHandler>(AttrFactory);
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000384 PP.AddPragmaHandler("clang", AttributePragmaHandler.get());
Eli Bendersky06a40422014-06-06 20:31:48 +0000385}
386
387void Parser::resetPragmaHandlers() {
Reid Kleckner5b086462014-02-20 22:52:09 +0000388 // Remove the pragma handlers we installed.
389 PP.RemovePragmaHandler(AlignHandler.get());
390 AlignHandler.reset();
391 PP.RemovePragmaHandler("GCC", GCCVisibilityHandler.get());
392 GCCVisibilityHandler.reset();
393 PP.RemovePragmaHandler(OptionsHandler.get());
394 OptionsHandler.reset();
395 PP.RemovePragmaHandler(PackHandler.get());
396 PackHandler.reset();
397 PP.RemovePragmaHandler(MSStructHandler.get());
398 MSStructHandler.reset();
399 PP.RemovePragmaHandler(UnusedHandler.get());
400 UnusedHandler.reset();
401 PP.RemovePragmaHandler(WeakHandler.get());
402 WeakHandler.reset();
403 PP.RemovePragmaHandler(RedefineExtnameHandler.get());
404 RedefineExtnameHandler.reset();
405
406 if (getLangOpts().OpenCL) {
407 PP.RemovePragmaHandler("OPENCL", OpenCLExtensionHandler.get());
408 OpenCLExtensionHandler.reset();
409 PP.RemovePragmaHandler("OPENCL", FPContractHandler.get());
410 }
411 PP.RemovePragmaHandler(OpenMPHandler.get());
412 OpenMPHandler.reset();
413
Saleem Abdulrasoolfd4db532018-02-07 01:46:46 +0000414 if (getLangOpts().MicrosoftExt ||
415 getTargetInfo().getTriple().isOSBinFormatELF()) {
Reid Kleckner5b086462014-02-20 22:52:09 +0000416 PP.RemovePragmaHandler(MSCommentHandler.get());
417 MSCommentHandler.reset();
Yunzhong Gao99efc032015-03-23 20:41:42 +0000418 }
419
Javed Absar2a67c9e2017-06-05 10:11:57 +0000420 PP.RemovePragmaHandler("clang", PCSectionHandler.get());
421 PCSectionHandler.reset();
422
Yunzhong Gao99efc032015-03-23 20:41:42 +0000423 if (getLangOpts().MicrosoftExt) {
Reid Kleckner5b086462014-02-20 22:52:09 +0000424 PP.RemovePragmaHandler(MSDetectMismatchHandler.get());
425 MSDetectMismatchHandler.reset();
426 PP.RemovePragmaHandler(MSPointersToMembers.get());
427 MSPointersToMembers.reset();
428 PP.RemovePragmaHandler(MSVtorDisp.get());
429 MSVtorDisp.reset();
Reid Klecknerd3923aa2014-04-03 19:04:24 +0000430 PP.RemovePragmaHandler(MSInitSeg.get());
431 MSInitSeg.reset();
Warren Huntc3b18962014-04-08 22:30:47 +0000432 PP.RemovePragmaHandler(MSDataSeg.get());
433 MSDataSeg.reset();
434 PP.RemovePragmaHandler(MSBSSSeg.get());
435 MSBSSSeg.reset();
436 PP.RemovePragmaHandler(MSConstSeg.get());
437 MSConstSeg.reset();
438 PP.RemovePragmaHandler(MSCodeSeg.get());
439 MSCodeSeg.reset();
440 PP.RemovePragmaHandler(MSSection.get());
441 MSSection.reset();
Hans Wennborg7357bbc2015-10-12 20:47:58 +0000442 PP.RemovePragmaHandler(MSRuntimeChecks.get());
443 MSRuntimeChecks.reset();
Reid Kleckner3f1ec622016-09-07 16:38:32 +0000444 PP.RemovePragmaHandler(MSIntrinsic.get());
445 MSIntrinsic.reset();
Hans Wennborg1bbe00e2018-03-20 08:53:11 +0000446 PP.RemovePragmaHandler(MSOptimize.get());
447 MSOptimize.reset();
Reid Kleckner5b086462014-02-20 22:52:09 +0000448 }
449
Justin Lebar67a78a62016-10-08 22:15:58 +0000450 if (getLangOpts().CUDA) {
451 PP.RemovePragmaHandler("clang", CUDAForceHostDeviceHandler.get());
452 CUDAForceHostDeviceHandler.reset();
453 }
454
Reid Kleckner5b086462014-02-20 22:52:09 +0000455 PP.RemovePragmaHandler("STDC", FPContractHandler.get());
456 FPContractHandler.reset();
Eli Bendersky06a40422014-06-06 20:31:48 +0000457
Steven Wub96a3a42018-01-05 22:45:03 +0000458 PP.RemovePragmaHandler("STDC", STDCFENVHandler.get());
459 STDCFENVHandler.reset();
460
461 PP.RemovePragmaHandler("STDC", STDCCXLIMITHandler.get());
462 STDCCXLIMITHandler.reset();
463
464 PP.RemovePragmaHandler("STDC", STDCUnknownHandler.get());
465 STDCUnknownHandler.reset();
466
Eli Bendersky06a40422014-06-06 20:31:48 +0000467 PP.RemovePragmaHandler("clang", OptimizeHandler.get());
468 OptimizeHandler.reset();
469
470 PP.RemovePragmaHandler("clang", LoopHintHandler.get());
471 LoopHintHandler.reset();
Mark Heffernanbd26f5e2014-07-21 18:08:34 +0000472
473 PP.RemovePragmaHandler(UnrollHintHandler.get());
474 UnrollHintHandler.reset();
Mark Heffernanc888e412014-07-24 18:09:38 +0000475
476 PP.RemovePragmaHandler(NoUnrollHintHandler.get());
477 NoUnrollHintHandler.reset();
Adam Nemet60d32642017-04-04 21:18:36 +0000478
David Greenc8e39242018-08-01 14:36:12 +0000479 PP.RemovePragmaHandler(UnrollAndJamHintHandler.get());
480 UnrollAndJamHintHandler.reset();
481
482 PP.RemovePragmaHandler(NoUnrollAndJamHintHandler.get());
483 NoUnrollAndJamHintHandler.reset();
484
Adam Nemet60d32642017-04-04 21:18:36 +0000485 PP.RemovePragmaHandler("clang", FPHandler.get());
486 FPHandler.reset();
Alex Lorenz9e7bf162017-04-18 14:33:39 +0000487
488 PP.RemovePragmaHandler("clang", AttributePragmaHandler.get());
489 AttributePragmaHandler.reset();
Eli Bendersky06a40422014-06-06 20:31:48 +0000490}
491
Adrian Prantl9fc8faf2018-05-09 01:00:01 +0000492/// Handle the annotation token produced for #pragma unused(...)
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000493///
494/// Each annot_pragma_unused is followed by the argument token so e.g.
495/// "#pragma unused(x,y)" becomes:
496/// annot_pragma_unused 'x' annot_pragma_unused 'y'
497void Parser::HandlePragmaUnused() {
498 assert(Tok.is(tok::annot_pragma_unused));
Richard Smithaf3b3252017-05-18 19:21:48 +0000499 SourceLocation UnusedLoc = ConsumeAnnotationToken();
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +0000500 Actions.ActOnPragmaUnused(Tok, getCurScope(), UnusedLoc);
501 ConsumeToken(); // The argument token.
502}
Eli Friedman570024a2010-08-05 06:57:20 +0000503
Rafael Espindola273fd772012-01-26 02:02:57 +0000504void Parser::HandlePragmaVisibility() {
505 assert(Tok.is(tok::annot_pragma_vis));
506 const IdentifierInfo *VisType =
507 static_cast<IdentifierInfo *>(Tok.getAnnotationValue());
Richard Smithaf3b3252017-05-18 19:21:48 +0000508 SourceLocation VisLoc = ConsumeAnnotationToken();
Rafael Espindola273fd772012-01-26 02:02:57 +0000509 Actions.ActOnPragmaVisibility(VisType, VisLoc);
510}
511
Benjamin Kramere003ca22015-10-28 13:54:16 +0000512namespace {
Eli Friedmanec52f922012-02-23 23:47:16 +0000513struct PragmaPackInfo {
Denis Zobnin10c4f452016-04-29 18:17:40 +0000514 Sema::PragmaMsStackAction Action;
515 StringRef SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +0000516 Token Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +0000517};
Benjamin Kramere003ca22015-10-28 13:54:16 +0000518} // end anonymous namespace
Eli Friedmanec52f922012-02-23 23:47:16 +0000519
520void Parser::HandlePragmaPack() {
521 assert(Tok.is(tok::annot_pragma_pack));
522 PragmaPackInfo *Info =
523 static_cast<PragmaPackInfo *>(Tok.getAnnotationValue());
Alex Lorenz45b40142017-07-28 14:41:21 +0000524 SourceLocation PragmaLoc = Tok.getLocation();
Eli Friedman68be1642012-10-04 02:36:51 +0000525 ExprResult Alignment;
526 if (Info->Alignment.is(tok::numeric_constant)) {
527 Alignment = Actions.ActOnNumericConstant(Info->Alignment);
Alex Lorenz45b40142017-07-28 14:41:21 +0000528 if (Alignment.isInvalid()) {
529 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000530 return;
Alex Lorenz45b40142017-07-28 14:41:21 +0000531 }
Eli Friedman68be1642012-10-04 02:36:51 +0000532 }
Denis Zobnin10c4f452016-04-29 18:17:40 +0000533 Actions.ActOnPragmaPack(PragmaLoc, Info->Action, Info->SlotLabel,
534 Alignment.get());
Alex Lorenz45b40142017-07-28 14:41:21 +0000535 // Consume the token after processing the pragma to enable pragma-specific
536 // #include warnings.
537 ConsumeAnnotationToken();
Eli Friedmanec52f922012-02-23 23:47:16 +0000538}
539
Eli Friedman68be1642012-10-04 02:36:51 +0000540void Parser::HandlePragmaMSStruct() {
541 assert(Tok.is(tok::annot_pragma_msstruct));
Nico Weber779355f2016-03-02 23:22:00 +0000542 PragmaMSStructKind Kind = static_cast<PragmaMSStructKind>(
543 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Eli Friedman68be1642012-10-04 02:36:51 +0000544 Actions.ActOnPragmaMSStruct(Kind);
Richard Smithaf3b3252017-05-18 19:21:48 +0000545 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000546}
547
548void Parser::HandlePragmaAlign() {
549 assert(Tok.is(tok::annot_pragma_align));
550 Sema::PragmaOptionsAlignKind Kind =
551 static_cast<Sema::PragmaOptionsAlignKind>(
552 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Alex Lorenz692821a2018-02-08 21:20:43 +0000553 Actions.ActOnPragmaOptionsAlign(Kind, Tok.getLocation());
554 // Consume the token after processing the pragma to enable pragma-specific
555 // #include warnings.
556 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000557}
558
Richard Smithba3a4f92016-01-12 21:59:26 +0000559void Parser::HandlePragmaDump() {
560 assert(Tok.is(tok::annot_pragma_dump));
561 IdentifierInfo *II =
562 reinterpret_cast<IdentifierInfo *>(Tok.getAnnotationValue());
563 Actions.ActOnPragmaDump(getCurScope(), Tok.getLocation(), II);
Richard Smithaf3b3252017-05-18 19:21:48 +0000564 ConsumeAnnotationToken();
Richard Smithba3a4f92016-01-12 21:59:26 +0000565}
566
Eli Friedman68be1642012-10-04 02:36:51 +0000567void Parser::HandlePragmaWeak() {
568 assert(Tok.is(tok::annot_pragma_weak));
Richard Smithaf3b3252017-05-18 19:21:48 +0000569 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000570 Actions.ActOnPragmaWeakID(Tok.getIdentifierInfo(), PragmaLoc,
571 Tok.getLocation());
572 ConsumeToken(); // The weak name.
573}
574
575void Parser::HandlePragmaWeakAlias() {
576 assert(Tok.is(tok::annot_pragma_weakalias));
Richard Smithaf3b3252017-05-18 19:21:48 +0000577 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000578 IdentifierInfo *WeakName = Tok.getIdentifierInfo();
579 SourceLocation WeakNameLoc = Tok.getLocation();
580 ConsumeToken();
581 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
582 SourceLocation AliasNameLoc = Tok.getLocation();
583 ConsumeToken();
584 Actions.ActOnPragmaWeakAlias(WeakName, AliasName, PragmaLoc,
585 WeakNameLoc, AliasNameLoc);
586
587}
588
589void Parser::HandlePragmaRedefineExtname() {
590 assert(Tok.is(tok::annot_pragma_redefine_extname));
Richard Smithaf3b3252017-05-18 19:21:48 +0000591 SourceLocation RedefLoc = ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000592 IdentifierInfo *RedefName = Tok.getIdentifierInfo();
593 SourceLocation RedefNameLoc = Tok.getLocation();
594 ConsumeToken();
595 IdentifierInfo *AliasName = Tok.getIdentifierInfo();
596 SourceLocation AliasNameLoc = Tok.getLocation();
597 ConsumeToken();
598 Actions.ActOnPragmaRedefineExtname(RedefName, AliasName, RedefLoc,
599 RedefNameLoc, AliasNameLoc);
600}
601
602void Parser::HandlePragmaFPContract() {
603 assert(Tok.is(tok::annot_pragma_fp_contract));
604 tok::OnOffSwitch OOS =
605 static_cast<tok::OnOffSwitch>(
606 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Adam Nemet60d32642017-04-04 21:18:36 +0000607
608 LangOptions::FPContractModeKind FPC;
609 switch (OOS) {
610 case tok::OOS_ON:
611 FPC = LangOptions::FPC_On;
612 break;
613 case tok::OOS_OFF:
614 FPC = LangOptions::FPC_Off;
615 break;
616 case tok::OOS_DEFAULT:
617 FPC = getLangOpts().getDefaultFPContractMode();
618 break;
619 }
620
621 Actions.ActOnPragmaFPContract(FPC);
Richard Smithaf3b3252017-05-18 19:21:48 +0000622 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000623}
624
Kevin P. Neal2c0bc8b2018-08-14 17:06:56 +0000625void Parser::HandlePragmaFEnvAccess() {
626 assert(Tok.is(tok::annot_pragma_fenv_access));
627 tok::OnOffSwitch OOS =
628 static_cast<tok::OnOffSwitch>(
629 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
630
631 LangOptions::FEnvAccessModeKind FPC;
632 switch (OOS) {
633 case tok::OOS_ON:
634 FPC = LangOptions::FEA_On;
635 break;
636 case tok::OOS_OFF:
637 FPC = LangOptions::FEA_Off;
638 break;
639 case tok::OOS_DEFAULT: // FIXME: Add this cli option when it makes sense.
640 FPC = LangOptions::FEA_Off;
641 break;
642 }
643
644 Actions.ActOnPragmaFEnvAccess(FPC);
645 ConsumeAnnotationToken();
646}
647
648
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000649StmtResult Parser::HandlePragmaCaptured()
650{
651 assert(Tok.is(tok::annot_pragma_captured));
Richard Smithaf3b3252017-05-18 19:21:48 +0000652 ConsumeAnnotationToken();
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000653
654 if (Tok.isNot(tok::l_brace)) {
Alp Tokerec543272013-12-24 09:48:30 +0000655 PP.Diag(Tok, diag::err_expected) << tok::l_brace;
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000656 return StmtError();
657 }
658
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000659 SourceLocation Loc = Tok.getLocation();
660
Momchil Velikov57c681f2017-08-10 15:43:06 +0000661 ParseScope CapturedRegionScope(this, Scope::FnScope | Scope::DeclScope |
662 Scope::CompoundStmtScope);
Ben Langmuir37943a72013-05-03 19:00:33 +0000663 Actions.ActOnCapturedRegionStart(Loc, getCurScope(), CR_Default,
664 /*NumParams=*/1);
Tareq A. Siraj6dfa25a2013-04-16 19:37:38 +0000665
666 StmtResult R = ParseCompoundStatement();
667 CapturedRegionScope.Exit();
668
669 if (R.isInvalid()) {
670 Actions.ActOnCapturedRegionError();
671 return StmtError();
672 }
673
674 return Actions.ActOnCapturedRegionEnd(R.get());
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000675}
676
Eli Friedman68be1642012-10-04 02:36:51 +0000677namespace {
Yaxun Liu5b746652016-12-18 05:18:55 +0000678 enum OpenCLExtState : char {
679 Disable, Enable, Begin, End
680 };
681 typedef std::pair<const IdentifierInfo *, OpenCLExtState> OpenCLExtData;
Eli Friedman68be1642012-10-04 02:36:51 +0000682}
683
684void Parser::HandlePragmaOpenCLExtension() {
685 assert(Tok.is(tok::annot_pragma_opencl_extension));
Yaxun Liu5b746652016-12-18 05:18:55 +0000686 OpenCLExtData *Data = static_cast<OpenCLExtData*>(Tok.getAnnotationValue());
687 auto State = Data->second;
688 auto Ident = Data->first;
Eli Friedman68be1642012-10-04 02:36:51 +0000689 SourceLocation NameLoc = Tok.getLocation();
Richard Smithaf3b3252017-05-18 19:21:48 +0000690 ConsumeAnnotationToken();
Eli Friedman68be1642012-10-04 02:36:51 +0000691
Yaxun Liu5b746652016-12-18 05:18:55 +0000692 auto &Opt = Actions.getOpenCLOptions();
693 auto Name = Ident->getName();
Eli Friedman68be1642012-10-04 02:36:51 +0000694 // OpenCL 1.1 9.1: "The all variant sets the behavior for all extensions,
695 // overriding all previously issued extension directives, but only if the
696 // behavior is set to disable."
Yaxun Liu5b746652016-12-18 05:18:55 +0000697 if (Name == "all") {
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000698 if (State == Disable) {
Yaxun Liu5b746652016-12-18 05:18:55 +0000699 Opt.disableAll();
Anastasia Stulovae88e2b92019-02-07 17:32:37 +0000700 Opt.enableSupportedCore(getLangOpts());
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000701 } else {
Yaxun Liu5b746652016-12-18 05:18:55 +0000702 PP.Diag(NameLoc, diag::warn_pragma_expected_predicate) << 1;
Konstantin Zhuravlyovde70a882017-01-06 16:14:41 +0000703 }
Yaxun Liu5b746652016-12-18 05:18:55 +0000704 } else if (State == Begin) {
Anastasia Stulovae88e2b92019-02-07 17:32:37 +0000705 if (!Opt.isKnown(Name) || !Opt.isSupported(Name, getLangOpts())) {
Yaxun Liu5b746652016-12-18 05:18:55 +0000706 Opt.support(Name);
707 }
708 Actions.setCurrentOpenCLExtension(Name);
709 } else if (State == End) {
710 if (Name != Actions.getCurrentOpenCLExtension())
711 PP.Diag(NameLoc, diag::warn_pragma_begin_end_mismatch);
712 Actions.setCurrentOpenCLExtension("");
713 } else if (!Opt.isKnown(Name))
714 PP.Diag(NameLoc, diag::warn_pragma_unknown_extension) << Ident;
Anastasia Stulovae88e2b92019-02-07 17:32:37 +0000715 else if (Opt.isSupportedExtension(Name, getLangOpts()))
Yaxun Liu5b746652016-12-18 05:18:55 +0000716 Opt.enable(Name, State == Enable);
Anastasia Stulovae88e2b92019-02-07 17:32:37 +0000717 else if (Opt.isSupportedCore(Name, getLangOpts()))
Yaxun Liu5b746652016-12-18 05:18:55 +0000718 PP.Diag(NameLoc, diag::warn_pragma_extension_is_core) << Ident;
719 else
720 PP.Diag(NameLoc, diag::warn_pragma_unsupported_extension) << Ident;
Eli Friedman68be1642012-10-04 02:36:51 +0000721}
722
David Majnemer4bb09802014-02-10 19:50:15 +0000723void Parser::HandlePragmaMSPointersToMembers() {
724 assert(Tok.is(tok::annot_pragma_ms_pointers_to_members));
David Majnemer86c318f2014-02-11 21:05:00 +0000725 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod =
726 static_cast<LangOptions::PragmaMSPointersToMembersKind>(
David Majnemer4bb09802014-02-10 19:50:15 +0000727 reinterpret_cast<uintptr_t>(Tok.getAnnotationValue()));
Richard Smithaf3b3252017-05-18 19:21:48 +0000728 SourceLocation PragmaLoc = ConsumeAnnotationToken();
David Majnemer4bb09802014-02-10 19:50:15 +0000729 Actions.ActOnPragmaMSPointersToMembers(RepresentationMethod, PragmaLoc);
730}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000731
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000732void Parser::HandlePragmaMSVtorDisp() {
733 assert(Tok.is(tok::annot_pragma_ms_vtordisp));
734 uintptr_t Value = reinterpret_cast<uintptr_t>(Tok.getAnnotationValue());
Denis Zobnin2290dac2016-04-29 11:27:00 +0000735 Sema::PragmaMsStackAction Action =
736 static_cast<Sema::PragmaMsStackAction>((Value >> 16) & 0xFFFF);
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000737 MSVtorDispAttr::Mode Mode = MSVtorDispAttr::Mode(Value & 0xFFFF);
Richard Smithaf3b3252017-05-18 19:21:48 +0000738 SourceLocation PragmaLoc = ConsumeAnnotationToken();
Denis Zobnin2290dac2016-04-29 11:27:00 +0000739 Actions.ActOnPragmaMSVtorDisp(Action, PragmaLoc, Mode);
Reid Klecknerc0dca6d2014-02-12 23:50:26 +0000740}
Tareq A. Siraj0de0dd42013-04-16 18:41:26 +0000741
Warren Huntc3b18962014-04-08 22:30:47 +0000742void Parser::HandlePragmaMSPragma() {
743 assert(Tok.is(tok::annot_pragma_ms_pragma));
744 // Grab the tokens out of the annotation and enter them into the stream.
David Blaikie2eabcc92016-02-09 18:52:09 +0000745 auto TheTokens =
746 (std::pair<std::unique_ptr<Token[]>, size_t> *)Tok.getAnnotationValue();
Ilya Biryukov929af672019-05-17 09:32:05 +0000747 PP.EnterTokenStream(std::move(TheTokens->first), TheTokens->second, true,
748 /*IsReinject=*/true);
Richard Smithaf3b3252017-05-18 19:21:48 +0000749 SourceLocation PragmaLocation = ConsumeAnnotationToken();
Warren Huntc3b18962014-04-08 22:30:47 +0000750 assert(Tok.isAnyIdentifier());
Reid Kleckner722b1df2014-07-18 00:13:16 +0000751 StringRef PragmaName = Tok.getIdentifierInfo()->getName();
Warren Huntc3b18962014-04-08 22:30:47 +0000752 PP.Lex(Tok); // pragma kind
Reid Kleckner722b1df2014-07-18 00:13:16 +0000753
Warren Huntc3b18962014-04-08 22:30:47 +0000754 // Figure out which #pragma we're dealing with. The switch has no default
755 // because lex shouldn't emit the annotation token for unrecognized pragmas.
Reid Kleckner722b1df2014-07-18 00:13:16 +0000756 typedef bool (Parser::*PragmaHandler)(StringRef, SourceLocation);
Warren Huntc3b18962014-04-08 22:30:47 +0000757 PragmaHandler Handler = llvm::StringSwitch<PragmaHandler>(PragmaName)
758 .Case("data_seg", &Parser::HandlePragmaMSSegment)
759 .Case("bss_seg", &Parser::HandlePragmaMSSegment)
760 .Case("const_seg", &Parser::HandlePragmaMSSegment)
761 .Case("code_seg", &Parser::HandlePragmaMSSegment)
762 .Case("section", &Parser::HandlePragmaMSSection)
763 .Case("init_seg", &Parser::HandlePragmaMSInitSeg);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000764
765 if (!(this->*Handler)(PragmaName, PragmaLocation)) {
766 // Pragma handling failed, and has been diagnosed. Slurp up the tokens
767 // until eof (really end of line) to prevent follow-on errors.
Warren Huntc3b18962014-04-08 22:30:47 +0000768 while (Tok.isNot(tok::eof))
769 PP.Lex(Tok);
770 PP.Lex(Tok);
771 }
772}
773
Reid Kleckner722b1df2014-07-18 00:13:16 +0000774bool Parser::HandlePragmaMSSection(StringRef PragmaName,
775 SourceLocation PragmaLocation) {
776 if (Tok.isNot(tok::l_paren)) {
777 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
778 return false;
779 }
Warren Huntc3b18962014-04-08 22:30:47 +0000780 PP.Lex(Tok); // (
781 // Parsing code for pragma section
Reid Kleckner722b1df2014-07-18 00:13:16 +0000782 if (Tok.isNot(tok::string_literal)) {
783 PP.Diag(PragmaLocation, diag::warn_pragma_expected_section_name)
784 << PragmaName;
785 return false;
786 }
787 ExprResult StringResult = ParseStringLiteralExpression();
788 if (StringResult.isInvalid())
789 return false; // Already diagnosed.
790 StringLiteral *SegmentName = cast<StringLiteral>(StringResult.get());
791 if (SegmentName->getCharByteWidth() != 1) {
792 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
793 << PragmaName;
794 return false;
795 }
David Majnemer48c28fa2014-10-22 21:08:43 +0000796 int SectionFlags = ASTContext::PSF_Read;
797 bool SectionFlagsAreDefault = true;
Warren Huntc3b18962014-04-08 22:30:47 +0000798 while (Tok.is(tok::comma)) {
799 PP.Lex(Tok); // ,
David Majnemer48c28fa2014-10-22 21:08:43 +0000800 // Ignore "long" and "short".
801 // They are undocumented, but widely used, section attributes which appear
802 // to do nothing.
803 if (Tok.is(tok::kw_long) || Tok.is(tok::kw_short)) {
804 PP.Lex(Tok); // long/short
805 continue;
806 }
807
Reid Kleckner722b1df2014-07-18 00:13:16 +0000808 if (!Tok.isAnyIdentifier()) {
809 PP.Diag(PragmaLocation, diag::warn_pragma_expected_action_or_r_paren)
810 << PragmaName;
811 return false;
812 }
Hans Wennborg899ded92014-10-16 20:52:46 +0000813 ASTContext::PragmaSectionFlag Flag =
814 llvm::StringSwitch<ASTContext::PragmaSectionFlag>(
Warren Huntc3b18962014-04-08 22:30:47 +0000815 Tok.getIdentifierInfo()->getName())
Hans Wennborg899ded92014-10-16 20:52:46 +0000816 .Case("read", ASTContext::PSF_Read)
817 .Case("write", ASTContext::PSF_Write)
818 .Case("execute", ASTContext::PSF_Execute)
819 .Case("shared", ASTContext::PSF_Invalid)
820 .Case("nopage", ASTContext::PSF_Invalid)
821 .Case("nocache", ASTContext::PSF_Invalid)
822 .Case("discard", ASTContext::PSF_Invalid)
823 .Case("remove", ASTContext::PSF_Invalid)
824 .Default(ASTContext::PSF_None);
825 if (Flag == ASTContext::PSF_None || Flag == ASTContext::PSF_Invalid) {
826 PP.Diag(PragmaLocation, Flag == ASTContext::PSF_None
Reid Kleckner722b1df2014-07-18 00:13:16 +0000827 ? diag::warn_pragma_invalid_specific_action
828 : diag::warn_pragma_unsupported_action)
Warren Huntc3b18962014-04-08 22:30:47 +0000829 << PragmaName << Tok.getIdentifierInfo()->getName();
Reid Kleckner722b1df2014-07-18 00:13:16 +0000830 return false;
Warren Huntc3b18962014-04-08 22:30:47 +0000831 }
832 SectionFlags |= Flag;
David Majnemer48c28fa2014-10-22 21:08:43 +0000833 SectionFlagsAreDefault = false;
Warren Huntc3b18962014-04-08 22:30:47 +0000834 PP.Lex(Tok); // Identifier
835 }
David Majnemer48c28fa2014-10-22 21:08:43 +0000836 // If no section attributes are specified, the section will be marked as
837 // read/write.
838 if (SectionFlagsAreDefault)
839 SectionFlags |= ASTContext::PSF_Write;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000840 if (Tok.isNot(tok::r_paren)) {
841 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
842 return false;
843 }
Warren Huntc3b18962014-04-08 22:30:47 +0000844 PP.Lex(Tok); // )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000845 if (Tok.isNot(tok::eof)) {
846 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
847 << PragmaName;
848 return false;
849 }
Warren Huntc3b18962014-04-08 22:30:47 +0000850 PP.Lex(Tok); // eof
851 Actions.ActOnPragmaMSSection(PragmaLocation, SectionFlags, SegmentName);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000852 return true;
Warren Huntc3b18962014-04-08 22:30:47 +0000853}
854
Reid Kleckner722b1df2014-07-18 00:13:16 +0000855bool Parser::HandlePragmaMSSegment(StringRef PragmaName,
856 SourceLocation PragmaLocation) {
857 if (Tok.isNot(tok::l_paren)) {
858 PP.Diag(PragmaLocation, diag::warn_pragma_expected_lparen) << PragmaName;
859 return false;
860 }
Warren Huntc3b18962014-04-08 22:30:47 +0000861 PP.Lex(Tok); // (
862 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000863 StringRef SlotLabel;
Warren Huntc3b18962014-04-08 22:30:47 +0000864 if (Tok.isAnyIdentifier()) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000865 StringRef PushPop = Tok.getIdentifierInfo()->getName();
Warren Huntc3b18962014-04-08 22:30:47 +0000866 if (PushPop == "push")
867 Action = Sema::PSK_Push;
868 else if (PushPop == "pop")
869 Action = Sema::PSK_Pop;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000870 else {
871 PP.Diag(PragmaLocation,
872 diag::warn_pragma_expected_section_push_pop_or_name)
873 << PragmaName;
874 return false;
875 }
Warren Huntc3b18962014-04-08 22:30:47 +0000876 if (Action != Sema::PSK_Reset) {
877 PP.Lex(Tok); // push | pop
878 if (Tok.is(tok::comma)) {
879 PP.Lex(Tok); // ,
880 // If we've got a comma, we either need a label or a string.
881 if (Tok.isAnyIdentifier()) {
882 SlotLabel = Tok.getIdentifierInfo()->getName();
883 PP.Lex(Tok); // identifier
884 if (Tok.is(tok::comma))
885 PP.Lex(Tok);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000886 else if (Tok.isNot(tok::r_paren)) {
887 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc)
888 << PragmaName;
889 return false;
890 }
Warren Huntc3b18962014-04-08 22:30:47 +0000891 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000892 } else if (Tok.isNot(tok::r_paren)) {
893 PP.Diag(PragmaLocation, diag::warn_pragma_expected_punc) << PragmaName;
894 return false;
895 }
Warren Huntc3b18962014-04-08 22:30:47 +0000896 }
897 }
898 // Grab the string literal for our section name.
899 StringLiteral *SegmentName = nullptr;
900 if (Tok.isNot(tok::r_paren)) {
Reid Kleckner722b1df2014-07-18 00:13:16 +0000901 if (Tok.isNot(tok::string_literal)) {
902 unsigned DiagID = Action != Sema::PSK_Reset ? !SlotLabel.empty() ?
Warren Huntc3b18962014-04-08 22:30:47 +0000903 diag::warn_pragma_expected_section_name :
904 diag::warn_pragma_expected_section_label_or_name :
905 diag::warn_pragma_expected_section_push_pop_or_name;
Reid Kleckner722b1df2014-07-18 00:13:16 +0000906 PP.Diag(PragmaLocation, DiagID) << PragmaName;
907 return false;
908 }
909 ExprResult StringResult = ParseStringLiteralExpression();
910 if (StringResult.isInvalid())
911 return false; // Already diagnosed.
912 SegmentName = cast<StringLiteral>(StringResult.get());
913 if (SegmentName->getCharByteWidth() != 1) {
914 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
915 << PragmaName;
916 return false;
917 }
Warren Huntc3b18962014-04-08 22:30:47 +0000918 // Setting section "" has no effect
919 if (SegmentName->getLength())
920 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
921 }
Reid Kleckner722b1df2014-07-18 00:13:16 +0000922 if (Tok.isNot(tok::r_paren)) {
923 PP.Diag(PragmaLocation, diag::warn_pragma_expected_rparen) << PragmaName;
924 return false;
925 }
Warren Huntc3b18962014-04-08 22:30:47 +0000926 PP.Lex(Tok); // )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000927 if (Tok.isNot(tok::eof)) {
928 PP.Diag(PragmaLocation, diag::warn_pragma_extra_tokens_at_eol)
929 << PragmaName;
930 return false;
931 }
Warren Huntc3b18962014-04-08 22:30:47 +0000932 PP.Lex(Tok); // eof
933 Actions.ActOnPragmaMSSeg(PragmaLocation, Action, SlotLabel,
934 SegmentName, PragmaName);
Reid Kleckner722b1df2014-07-18 00:13:16 +0000935 return true;
Warren Huntc3b18962014-04-08 22:30:47 +0000936}
937
Reid Kleckner1a711b12014-07-22 00:53:05 +0000938// #pragma init_seg({ compiler | lib | user | "section-name" [, func-name]} )
Reid Kleckner722b1df2014-07-18 00:13:16 +0000939bool Parser::HandlePragmaMSInitSeg(StringRef PragmaName,
940 SourceLocation PragmaLocation) {
David Majnemerad2986e2014-08-14 06:35:08 +0000941 if (getTargetInfo().getTriple().getEnvironment() != llvm::Triple::MSVC) {
942 PP.Diag(PragmaLocation, diag::warn_pragma_init_seg_unsupported_target);
943 return false;
944 }
945
Reid Kleckner1a711b12014-07-22 00:53:05 +0000946 if (ExpectAndConsume(tok::l_paren, diag::warn_pragma_expected_lparen,
947 PragmaName))
948 return false;
949
950 // Parse either the known section names or the string section name.
951 StringLiteral *SegmentName = nullptr;
952 if (Tok.isAnyIdentifier()) {
953 auto *II = Tok.getIdentifierInfo();
954 StringRef Section = llvm::StringSwitch<StringRef>(II->getName())
955 .Case("compiler", "\".CRT$XCC\"")
956 .Case("lib", "\".CRT$XCL\"")
957 .Case("user", "\".CRT$XCU\"")
958 .Default("");
959
960 if (!Section.empty()) {
961 // Pretend the user wrote the appropriate string literal here.
962 Token Toks[1];
963 Toks[0].startToken();
964 Toks[0].setKind(tok::string_literal);
965 Toks[0].setLocation(Tok.getLocation());
966 Toks[0].setLiteralData(Section.data());
967 Toks[0].setLength(Section.size());
968 SegmentName =
969 cast<StringLiteral>(Actions.ActOnStringLiteral(Toks, nullptr).get());
970 PP.Lex(Tok);
971 }
972 } else if (Tok.is(tok::string_literal)) {
973 ExprResult StringResult = ParseStringLiteralExpression();
974 if (StringResult.isInvalid())
975 return false;
976 SegmentName = cast<StringLiteral>(StringResult.get());
977 if (SegmentName->getCharByteWidth() != 1) {
978 PP.Diag(PragmaLocation, diag::warn_pragma_expected_non_wide_string)
979 << PragmaName;
980 return false;
981 }
982 // FIXME: Add support for the '[, func-name]' part of the pragma.
983 }
984
985 if (!SegmentName) {
986 PP.Diag(PragmaLocation, diag::warn_pragma_expected_init_seg) << PragmaName;
987 return false;
988 }
989
990 if (ExpectAndConsume(tok::r_paren, diag::warn_pragma_expected_rparen,
991 PragmaName) ||
992 ExpectAndConsume(tok::eof, diag::warn_pragma_extra_tokens_at_eol,
993 PragmaName))
994 return false;
995
996 Actions.ActOnPragmaMSInitSeg(PragmaLocation, SegmentName);
997 return true;
Eli Bendersky06a40422014-06-06 20:31:48 +0000998}
999
Benjamin Kramere003ca22015-10-28 13:54:16 +00001000namespace {
Eli Bendersky06a40422014-06-06 20:31:48 +00001001struct PragmaLoopHintInfo {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001002 Token PragmaName;
Eli Bendersky06a40422014-06-06 20:31:48 +00001003 Token Option;
Benjamin Kramerfa7f8552015-08-05 09:39:57 +00001004 ArrayRef<Token> Toks;
Eli Bendersky06a40422014-06-06 20:31:48 +00001005};
Benjamin Kramere003ca22015-10-28 13:54:16 +00001006} // end anonymous namespace
Eli Bendersky06a40422014-06-06 20:31:48 +00001007
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001008static std::string PragmaLoopHintString(Token PragmaName, Token Option) {
Sjoerd Meijer90374f72019-08-15 07:39:05 +00001009 StringRef Str = PragmaName.getIdentifierInfo()->getName();
1010 std::string ClangLoopStr = (llvm::Twine("clang loop ") + Str).str();
1011 return llvm::StringSwitch<StringRef>(Str)
1012 .Case("loop", ClangLoopStr)
1013 .Case("unroll_and_jam", Str)
1014 .Case("unroll", Str)
1015 .Default("");
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001016}
1017
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001018bool Parser::HandlePragmaLoopHint(LoopHint &Hint) {
Eli Bendersky06a40422014-06-06 20:31:48 +00001019 assert(Tok.is(tok::annot_pragma_loop_hint));
1020 PragmaLoopHintInfo *Info =
1021 static_cast<PragmaLoopHintInfo *>(Tok.getAnnotationValue());
1022
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001023 IdentifierInfo *PragmaNameInfo = Info->PragmaName.getIdentifierInfo();
1024 Hint.PragmaNameLoc = IdentifierLoc::create(
1025 Actions.Context, Info->PragmaName.getLocation(), PragmaNameInfo);
Eli Bendersky06a40422014-06-06 20:31:48 +00001026
Aaron Ballmanef940aa2014-07-31 21:24:32 +00001027 // It is possible that the loop hint has no option identifier, such as
1028 // #pragma unroll(4).
1029 IdentifierInfo *OptionInfo = Info->Option.is(tok::identifier)
1030 ? Info->Option.getIdentifierInfo()
1031 : nullptr;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001032 Hint.OptionLoc = IdentifierLoc::create(
1033 Actions.Context, Info->Option.getLocation(), OptionInfo);
1034
David Blaikie2eabcc92016-02-09 18:52:09 +00001035 llvm::ArrayRef<Token> Toks = Info->Toks;
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001036
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001037 // Return a valid hint if pragma unroll or nounroll were specified
1038 // without an argument.
Sjoerd Meijer90374f72019-08-15 07:39:05 +00001039 auto IsLoopHint = llvm::StringSwitch<bool>(PragmaNameInfo->getName())
1040 .Cases("unroll", "nounroll", "unroll_and_jam",
1041 "nounroll_and_jam", true)
1042 .Default(false);
1043
1044 if (Toks.empty() && IsLoopHint) {
Richard Smithaf3b3252017-05-18 19:21:48 +00001045 ConsumeAnnotationToken();
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001046 Hint.Range = Info->PragmaName.getLocation();
1047 return true;
1048 }
1049
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001050 // The constant expression is always followed by an eof token, which increases
1051 // the TokSize by 1.
David Blaikie2eabcc92016-02-09 18:52:09 +00001052 assert(!Toks.empty() &&
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001053 "PragmaLoopHintInfo::Toks must contain at least one token.");
1054
1055 // If no option is specified the argument is assumed to be a constant expr.
Tyler Nowicki24853c12015-06-08 23:13:43 +00001056 bool OptionUnroll = false;
David Greenc8e39242018-08-01 14:36:12 +00001057 bool OptionUnrollAndJam = false;
Adam Nemet2de463e2016-06-14 12:04:26 +00001058 bool OptionDistribute = false;
Aaron Ballman9bdf5152019-01-04 17:20:00 +00001059 bool OptionPipelineDisabled = false;
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001060 bool StateOption = false;
Tyler Nowicki24853c12015-06-08 23:13:43 +00001061 if (OptionInfo) { // Pragma Unroll does not specify an option.
1062 OptionUnroll = OptionInfo->isStr("unroll");
David Greenc8e39242018-08-01 14:36:12 +00001063 OptionUnrollAndJam = OptionInfo->isStr("unroll_and_jam");
Adam Nemet2de463e2016-06-14 12:04:26 +00001064 OptionDistribute = OptionInfo->isStr("distribute");
Aaron Ballman9bdf5152019-01-04 17:20:00 +00001065 OptionPipelineDisabled = OptionInfo->isStr("pipeline");
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001066 StateOption = llvm::StringSwitch<bool>(OptionInfo->getName())
1067 .Case("vectorize", true)
1068 .Case("interleave", true)
Sjoerd Meijera48f58c2019-07-25 07:33:13 +00001069 .Case("vectorize_predicate", true)
Adam Nemet2de463e2016-06-14 12:04:26 +00001070 .Default(false) ||
Aaron Ballman9bdf5152019-01-04 17:20:00 +00001071 OptionUnroll || OptionUnrollAndJam || OptionDistribute ||
1072 OptionPipelineDisabled;
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001073 }
1074
Aaron Ballman9bdf5152019-01-04 17:20:00 +00001075 bool AssumeSafetyArg = !OptionUnroll && !OptionUnrollAndJam &&
1076 !OptionDistribute && !OptionPipelineDisabled;
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001077 // Verify loop hint has an argument.
1078 if (Toks[0].is(tok::eof)) {
Richard Smithaf3b3252017-05-18 19:21:48 +00001079 ConsumeAnnotationToken();
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001080 Diag(Toks[0].getLocation(), diag::err_pragma_loop_missing_argument)
David Greenc8e39242018-08-01 14:36:12 +00001081 << /*StateArgument=*/StateOption
1082 << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
Adam Nemet2de463e2016-06-14 12:04:26 +00001083 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001084 return false;
1085 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001086
1087 // Validate the argument.
1088 if (StateOption) {
Richard Smithaf3b3252017-05-18 19:21:48 +00001089 ConsumeAnnotationToken();
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001090 SourceLocation StateLoc = Toks[0].getLocation();
1091 IdentifierInfo *StateInfo = Toks[0].getIdentifierInfo();
Adam Nemet50de4e82016-04-19 22:17:45 +00001092
Aaron Ballman9bdf5152019-01-04 17:20:00 +00001093 bool Valid = StateInfo &&
1094 llvm::StringSwitch<bool>(StateInfo->getName())
1095 .Case("disable", true)
1096 .Case("enable", !OptionPipelineDisabled)
1097 .Case("full", OptionUnroll || OptionUnrollAndJam)
1098 .Case("assume_safety", AssumeSafetyArg)
1099 .Default(false);
Adam Nemet50de4e82016-04-19 22:17:45 +00001100 if (!Valid) {
Aaron Ballman9bdf5152019-01-04 17:20:00 +00001101 if (OptionPipelineDisabled) {
1102 Diag(Toks[0].getLocation(), diag::err_pragma_pipeline_invalid_keyword);
1103 } else {
1104 Diag(Toks[0].getLocation(), diag::err_pragma_invalid_keyword)
1105 << /*FullKeyword=*/(OptionUnroll || OptionUnrollAndJam)
1106 << /*AssumeSafetyKeyword=*/AssumeSafetyArg;
1107 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001108 return false;
1109 }
David Blaikie2eabcc92016-02-09 18:52:09 +00001110 if (Toks.size() > 2)
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001111 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1112 << PragmaLoopHintString(Info->PragmaName, Info->Option);
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001113 Hint.StateLoc = IdentifierLoc::create(Actions.Context, StateLoc, StateInfo);
1114 } else {
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001115 // Enter constant expression including eof terminator into token stream.
Ilya Biryukov929af672019-05-17 09:32:05 +00001116 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/false,
1117 /*IsReinject=*/false);
Richard Smithaf3b3252017-05-18 19:21:48 +00001118 ConsumeAnnotationToken();
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001119
1120 ExprResult R = ParseConstantExpression();
1121
1122 // Tokens following an error in an ill-formed constant expression will
1123 // remain in the token stream and must be removed.
1124 if (Tok.isNot(tok::eof)) {
1125 Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1126 << PragmaLoopHintString(Info->PragmaName, Info->Option);
1127 while (Tok.isNot(tok::eof))
1128 ConsumeAnyToken();
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001129 }
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001130
1131 ConsumeToken(); // Consume the constant expression eof terminator.
1132
1133 if (R.isInvalid() ||
1134 Actions.CheckLoopHintExpr(R.get(), Toks[0].getLocation()))
1135 return false;
1136
1137 // Argument is a constant expression with an integer type.
1138 Hint.ValueExpr = R.get();
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00001139 }
Eli Bendersky06a40422014-06-06 20:31:48 +00001140
Tyler Nowickic724a83e2014-10-12 20:46:07 +00001141 Hint.Range = SourceRange(Info->PragmaName.getLocation(),
David Blaikie2eabcc92016-02-09 18:52:09 +00001142 Info->Toks.back().getLocation());
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00001143 return true;
Eli Bendersky06a40422014-06-06 20:31:48 +00001144}
1145
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001146namespace {
1147struct PragmaAttributeInfo {
Erik Pilkington7d180942018-10-29 17:38:42 +00001148 enum ActionType { Push, Pop, Attribute };
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001149 ParsedAttributes &Attributes;
1150 ActionType Action;
Erik Pilkington0876cae2018-12-20 22:32:04 +00001151 const IdentifierInfo *Namespace = nullptr;
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001152 ArrayRef<Token> Tokens;
1153
1154 PragmaAttributeInfo(ParsedAttributes &Attributes) : Attributes(Attributes) {}
1155};
1156
1157#include "clang/Parse/AttrSubMatchRulesParserStringSwitches.inc"
1158
1159} // end anonymous namespace
1160
1161static StringRef getIdentifier(const Token &Tok) {
1162 if (Tok.is(tok::identifier))
1163 return Tok.getIdentifierInfo()->getName();
1164 const char *S = tok::getKeywordSpelling(Tok.getKind());
1165 if (!S)
1166 return "";
1167 return S;
1168}
1169
1170static bool isAbstractAttrMatcherRule(attr::SubjectMatchRule Rule) {
1171 using namespace attr;
1172 switch (Rule) {
1173#define ATTR_MATCH_RULE(Value, Spelling, IsAbstract) \
1174 case Value: \
1175 return IsAbstract;
1176#include "clang/Basic/AttrSubMatchRulesList.inc"
1177 }
1178 llvm_unreachable("Invalid attribute subject match rule");
1179 return false;
1180}
1181
1182static void diagnoseExpectedAttributeSubjectSubRule(
1183 Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1184 SourceLocation SubRuleLoc) {
1185 auto Diagnostic =
1186 PRef.Diag(SubRuleLoc,
1187 diag::err_pragma_attribute_expected_subject_sub_identifier)
1188 << PrimaryRuleName;
1189 if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1190 Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1191 else
1192 Diagnostic << /*SubRulesSupported=*/0;
1193}
1194
1195static void diagnoseUnknownAttributeSubjectSubRule(
1196 Parser &PRef, attr::SubjectMatchRule PrimaryRule, StringRef PrimaryRuleName,
1197 StringRef SubRuleName, SourceLocation SubRuleLoc) {
1198
1199 auto Diagnostic =
1200 PRef.Diag(SubRuleLoc, diag::err_pragma_attribute_unknown_subject_sub_rule)
1201 << SubRuleName << PrimaryRuleName;
1202 if (const char *SubRules = validAttributeSubjectMatchSubRules(PrimaryRule))
1203 Diagnostic << /*SubRulesSupported=*/1 << SubRules;
1204 else
1205 Diagnostic << /*SubRulesSupported=*/0;
1206}
1207
1208bool Parser::ParsePragmaAttributeSubjectMatchRuleSet(
1209 attr::ParsedSubjectMatchRuleSet &SubjectMatchRules, SourceLocation &AnyLoc,
1210 SourceLocation &LastMatchRuleEndLoc) {
1211 bool IsAny = false;
1212 BalancedDelimiterTracker AnyParens(*this, tok::l_paren);
1213 if (getIdentifier(Tok) == "any") {
1214 AnyLoc = ConsumeToken();
1215 IsAny = true;
1216 if (AnyParens.expectAndConsume())
1217 return true;
1218 }
1219
1220 do {
1221 // Parse the subject matcher rule.
1222 StringRef Name = getIdentifier(Tok);
1223 if (Name.empty()) {
1224 Diag(Tok, diag::err_pragma_attribute_expected_subject_identifier);
1225 return true;
1226 }
1227 std::pair<Optional<attr::SubjectMatchRule>,
1228 Optional<attr::SubjectMatchRule> (*)(StringRef, bool)>
1229 Rule = isAttributeSubjectMatchRule(Name);
1230 if (!Rule.first) {
1231 Diag(Tok, diag::err_pragma_attribute_unknown_subject_rule) << Name;
1232 return true;
1233 }
1234 attr::SubjectMatchRule PrimaryRule = *Rule.first;
1235 SourceLocation RuleLoc = ConsumeToken();
1236
1237 BalancedDelimiterTracker Parens(*this, tok::l_paren);
1238 if (isAbstractAttrMatcherRule(PrimaryRule)) {
1239 if (Parens.expectAndConsume())
1240 return true;
1241 } else if (Parens.consumeOpen()) {
1242 if (!SubjectMatchRules
1243 .insert(
1244 std::make_pair(PrimaryRule, SourceRange(RuleLoc, RuleLoc)))
1245 .second)
1246 Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1247 << Name
1248 << FixItHint::CreateRemoval(SourceRange(
1249 RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleLoc));
1250 LastMatchRuleEndLoc = RuleLoc;
1251 continue;
1252 }
1253
1254 // Parse the sub-rules.
1255 StringRef SubRuleName = getIdentifier(Tok);
1256 if (SubRuleName.empty()) {
1257 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1258 Tok.getLocation());
1259 return true;
1260 }
1261 attr::SubjectMatchRule SubRule;
1262 if (SubRuleName == "unless") {
1263 SourceLocation SubRuleLoc = ConsumeToken();
1264 BalancedDelimiterTracker Parens(*this, tok::l_paren);
1265 if (Parens.expectAndConsume())
1266 return true;
1267 SubRuleName = getIdentifier(Tok);
1268 if (SubRuleName.empty()) {
1269 diagnoseExpectedAttributeSubjectSubRule(*this, PrimaryRule, Name,
1270 SubRuleLoc);
1271 return true;
1272 }
1273 auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/true);
1274 if (!SubRuleOrNone) {
1275 std::string SubRuleUnlessName = "unless(" + SubRuleName.str() + ")";
1276 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1277 SubRuleUnlessName, SubRuleLoc);
1278 return true;
1279 }
1280 SubRule = *SubRuleOrNone;
1281 ConsumeToken();
1282 if (Parens.consumeClose())
1283 return true;
1284 } else {
1285 auto SubRuleOrNone = Rule.second(SubRuleName, /*IsUnless=*/false);
1286 if (!SubRuleOrNone) {
1287 diagnoseUnknownAttributeSubjectSubRule(*this, PrimaryRule, Name,
1288 SubRuleName, Tok.getLocation());
1289 return true;
1290 }
1291 SubRule = *SubRuleOrNone;
1292 ConsumeToken();
1293 }
1294 SourceLocation RuleEndLoc = Tok.getLocation();
1295 LastMatchRuleEndLoc = RuleEndLoc;
1296 if (Parens.consumeClose())
1297 return true;
1298 if (!SubjectMatchRules
1299 .insert(std::make_pair(SubRule, SourceRange(RuleLoc, RuleEndLoc)))
1300 .second) {
1301 Diag(RuleLoc, diag::err_pragma_attribute_duplicate_subject)
1302 << attr::getSubjectMatchRuleSpelling(SubRule)
1303 << FixItHint::CreateRemoval(SourceRange(
1304 RuleLoc, Tok.is(tok::comma) ? Tok.getLocation() : RuleEndLoc));
1305 continue;
1306 }
1307 } while (IsAny && TryConsumeToken(tok::comma));
1308
1309 if (IsAny)
1310 if (AnyParens.consumeClose())
1311 return true;
1312
1313 return false;
1314}
1315
1316namespace {
1317
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00001318/// Describes the stage at which attribute subject rule parsing was interrupted.
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001319enum class MissingAttributeSubjectRulesRecoveryPoint {
1320 Comma,
1321 ApplyTo,
1322 Equals,
1323 Any,
1324 None,
1325};
1326
1327MissingAttributeSubjectRulesRecoveryPoint
1328getAttributeSubjectRulesRecoveryPointForToken(const Token &Tok) {
1329 if (const auto *II = Tok.getIdentifierInfo()) {
1330 if (II->isStr("apply_to"))
1331 return MissingAttributeSubjectRulesRecoveryPoint::ApplyTo;
1332 if (II->isStr("any"))
1333 return MissingAttributeSubjectRulesRecoveryPoint::Any;
1334 }
1335 if (Tok.is(tok::equal))
1336 return MissingAttributeSubjectRulesRecoveryPoint::Equals;
1337 return MissingAttributeSubjectRulesRecoveryPoint::None;
1338}
1339
1340/// Creates a diagnostic for the attribute subject rule parsing diagnostic that
1341/// suggests the possible attribute subject rules in a fix-it together with
1342/// any other missing tokens.
1343DiagnosticBuilder createExpectedAttributeSubjectRulesTokenDiagnostic(
Erich Keanee891aa92018-07-13 15:07:47 +00001344 unsigned DiagID, ParsedAttr &Attribute,
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001345 MissingAttributeSubjectRulesRecoveryPoint Point, Parser &PRef) {
1346 SourceLocation Loc = PRef.getEndOfPreviousToken();
1347 if (Loc.isInvalid())
1348 Loc = PRef.getCurToken().getLocation();
1349 auto Diagnostic = PRef.Diag(Loc, DiagID);
1350 std::string FixIt;
1351 MissingAttributeSubjectRulesRecoveryPoint EndPoint =
1352 getAttributeSubjectRulesRecoveryPointForToken(PRef.getCurToken());
1353 if (Point == MissingAttributeSubjectRulesRecoveryPoint::Comma)
1354 FixIt = ", ";
1355 if (Point <= MissingAttributeSubjectRulesRecoveryPoint::ApplyTo &&
1356 EndPoint > MissingAttributeSubjectRulesRecoveryPoint::ApplyTo)
1357 FixIt += "apply_to";
1358 if (Point <= MissingAttributeSubjectRulesRecoveryPoint::Equals &&
1359 EndPoint > MissingAttributeSubjectRulesRecoveryPoint::Equals)
1360 FixIt += " = ";
1361 SourceRange FixItRange(Loc);
1362 if (EndPoint == MissingAttributeSubjectRulesRecoveryPoint::None) {
1363 // Gather the subject match rules that are supported by the attribute.
1364 SmallVector<std::pair<attr::SubjectMatchRule, bool>, 4> SubjectMatchRuleSet;
1365 Attribute.getMatchRules(PRef.getLangOpts(), SubjectMatchRuleSet);
1366 if (SubjectMatchRuleSet.empty()) {
1367 // FIXME: We can emit a "fix-it" with a subject list placeholder when
1368 // placeholders will be supported by the fix-its.
1369 return Diagnostic;
1370 }
1371 FixIt += "any(";
1372 bool NeedsComma = false;
1373 for (const auto &I : SubjectMatchRuleSet) {
1374 // Ensure that the missing rule is reported in the fix-it only when it's
1375 // supported in the current language mode.
1376 if (!I.second)
1377 continue;
1378 if (NeedsComma)
1379 FixIt += ", ";
1380 else
1381 NeedsComma = true;
1382 FixIt += attr::getSubjectMatchRuleSpelling(I.first);
1383 }
1384 FixIt += ")";
1385 // Check if we need to remove the range
1386 PRef.SkipUntil(tok::eof, Parser::StopBeforeMatch);
1387 FixItRange.setEnd(PRef.getCurToken().getLocation());
1388 }
1389 if (FixItRange.getBegin() == FixItRange.getEnd())
1390 Diagnostic << FixItHint::CreateInsertion(FixItRange.getBegin(), FixIt);
1391 else
1392 Diagnostic << FixItHint::CreateReplacement(
1393 CharSourceRange::getCharRange(FixItRange), FixIt);
1394 return Diagnostic;
1395}
1396
1397} // end anonymous namespace
1398
1399void Parser::HandlePragmaAttribute() {
1400 assert(Tok.is(tok::annot_pragma_attribute) &&
1401 "Expected #pragma attribute annotation token");
1402 SourceLocation PragmaLoc = Tok.getLocation();
1403 auto *Info = static_cast<PragmaAttributeInfo *>(Tok.getAnnotationValue());
1404 if (Info->Action == PragmaAttributeInfo::Pop) {
Richard Smithaf3b3252017-05-18 19:21:48 +00001405 ConsumeAnnotationToken();
Erik Pilkington0876cae2018-12-20 22:32:04 +00001406 Actions.ActOnPragmaAttributePop(PragmaLoc, Info->Namespace);
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001407 return;
1408 }
1409 // Parse the actual attribute with its arguments.
Erik Pilkington7d180942018-10-29 17:38:42 +00001410 assert((Info->Action == PragmaAttributeInfo::Push ||
1411 Info->Action == PragmaAttributeInfo::Attribute) &&
Erik Pilkingtonb287a012018-10-29 03:24:16 +00001412 "Unexpected #pragma attribute command");
Erik Pilkington7d180942018-10-29 17:38:42 +00001413
1414 if (Info->Action == PragmaAttributeInfo::Push && Info->Tokens.empty()) {
1415 ConsumeAnnotationToken();
Erik Pilkington0876cae2018-12-20 22:32:04 +00001416 Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
Erik Pilkington7d180942018-10-29 17:38:42 +00001417 return;
1418 }
1419
Ilya Biryukov929af672019-05-17 09:32:05 +00001420 PP.EnterTokenStream(Info->Tokens, /*DisableMacroExpansion=*/false,
1421 /*IsReinject=*/false);
Richard Smithaf3b3252017-05-18 19:21:48 +00001422 ConsumeAnnotationToken();
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001423
1424 ParsedAttributes &Attrs = Info->Attributes;
1425 Attrs.clearListOnly();
1426
1427 auto SkipToEnd = [this]() {
1428 SkipUntil(tok::eof, StopBeforeMatch);
1429 ConsumeToken();
1430 };
1431
1432 if (Tok.is(tok::l_square) && NextToken().is(tok::l_square)) {
1433 // Parse the CXX11 style attribute.
1434 ParseCXX11AttributeSpecifier(Attrs);
1435 } else if (Tok.is(tok::kw___attribute)) {
1436 ConsumeToken();
1437 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after,
1438 "attribute"))
1439 return SkipToEnd();
1440 if (ExpectAndConsume(tok::l_paren, diag::err_expected_lparen_after, "("))
1441 return SkipToEnd();
1442
1443 if (Tok.isNot(tok::identifier)) {
1444 Diag(Tok, diag::err_pragma_attribute_expected_attribute_name);
1445 SkipToEnd();
1446 return;
1447 }
1448 IdentifierInfo *AttrName = Tok.getIdentifierInfo();
1449 SourceLocation AttrNameLoc = ConsumeToken();
1450
1451 if (Tok.isNot(tok::l_paren))
1452 Attrs.addNew(AttrName, AttrNameLoc, nullptr, AttrNameLoc, nullptr, 0,
Erich Keanee891aa92018-07-13 15:07:47 +00001453 ParsedAttr::AS_GNU);
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001454 else
1455 ParseGNUAttributeArgs(AttrName, AttrNameLoc, Attrs, /*EndLoc=*/nullptr,
1456 /*ScopeName=*/nullptr,
Erich Keanee891aa92018-07-13 15:07:47 +00001457 /*ScopeLoc=*/SourceLocation(), ParsedAttr::AS_GNU,
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001458 /*Declarator=*/nullptr);
1459
1460 if (ExpectAndConsume(tok::r_paren))
1461 return SkipToEnd();
1462 if (ExpectAndConsume(tok::r_paren))
1463 return SkipToEnd();
1464 } else if (Tok.is(tok::kw___declspec)) {
1465 ParseMicrosoftDeclSpecs(Attrs);
1466 } else {
1467 Diag(Tok, diag::err_pragma_attribute_expected_attribute_syntax);
1468 if (Tok.getIdentifierInfo()) {
1469 // If we suspect that this is an attribute suggest the use of
1470 // '__attribute__'.
Erich Keane6a24e802019-09-13 17:39:31 +00001471 if (ParsedAttr::getParsedKind(
1472 Tok.getIdentifierInfo(), /*ScopeName=*/nullptr,
1473 ParsedAttr::AS_GNU) != ParsedAttr::UnknownAttribute) {
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001474 SourceLocation InsertStartLoc = Tok.getLocation();
1475 ConsumeToken();
1476 if (Tok.is(tok::l_paren)) {
1477 ConsumeAnyToken();
1478 SkipUntil(tok::r_paren, StopBeforeMatch);
1479 if (Tok.isNot(tok::r_paren))
1480 return SkipToEnd();
1481 }
1482 Diag(Tok, diag::note_pragma_attribute_use_attribute_kw)
1483 << FixItHint::CreateInsertion(InsertStartLoc, "__attribute__((")
1484 << FixItHint::CreateInsertion(Tok.getEndLoc(), "))");
1485 }
1486 }
1487 SkipToEnd();
1488 return;
1489 }
1490
Erich Keanec480f302018-07-12 21:09:05 +00001491 if (Attrs.empty() || Attrs.begin()->isInvalid()) {
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001492 SkipToEnd();
1493 return;
1494 }
1495
1496 // Ensure that we don't have more than one attribute.
Erich Keanec480f302018-07-12 21:09:05 +00001497 if (Attrs.size() > 1) {
1498 SourceLocation Loc = Attrs[1].getLoc();
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001499 Diag(Loc, diag::err_pragma_attribute_multiple_attributes);
1500 SkipToEnd();
1501 return;
1502 }
1503
Erich Keanee891aa92018-07-13 15:07:47 +00001504 ParsedAttr &Attribute = *Attrs.begin();
Erich Keanec480f302018-07-12 21:09:05 +00001505 if (!Attribute.isSupportedByPragmaAttribute()) {
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001506 Diag(PragmaLoc, diag::err_pragma_attribute_unsupported_attribute)
Erich Keane6a24e802019-09-13 17:39:31 +00001507 << Attribute;
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001508 SkipToEnd();
1509 return;
1510 }
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001511
1512 // Parse the subject-list.
1513 if (!TryConsumeToken(tok::comma)) {
1514 createExpectedAttributeSubjectRulesTokenDiagnostic(
1515 diag::err_expected, Attribute,
1516 MissingAttributeSubjectRulesRecoveryPoint::Comma, *this)
1517 << tok::comma;
1518 SkipToEnd();
1519 return;
1520 }
1521
1522 if (Tok.isNot(tok::identifier)) {
1523 createExpectedAttributeSubjectRulesTokenDiagnostic(
1524 diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute,
1525 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1526 SkipToEnd();
1527 return;
1528 }
1529 const IdentifierInfo *II = Tok.getIdentifierInfo();
1530 if (!II->isStr("apply_to")) {
1531 createExpectedAttributeSubjectRulesTokenDiagnostic(
1532 diag::err_pragma_attribute_invalid_subject_set_specifier, Attribute,
1533 MissingAttributeSubjectRulesRecoveryPoint::ApplyTo, *this);
1534 SkipToEnd();
1535 return;
1536 }
1537 ConsumeToken();
1538
1539 if (!TryConsumeToken(tok::equal)) {
1540 createExpectedAttributeSubjectRulesTokenDiagnostic(
1541 diag::err_expected, Attribute,
1542 MissingAttributeSubjectRulesRecoveryPoint::Equals, *this)
1543 << tok::equal;
1544 SkipToEnd();
1545 return;
1546 }
1547
1548 attr::ParsedSubjectMatchRuleSet SubjectMatchRules;
1549 SourceLocation AnyLoc, LastMatchRuleEndLoc;
1550 if (ParsePragmaAttributeSubjectMatchRuleSet(SubjectMatchRules, AnyLoc,
1551 LastMatchRuleEndLoc)) {
1552 SkipToEnd();
1553 return;
1554 }
1555
1556 // Tokens following an ill-formed attribute will remain in the token stream
1557 // and must be removed.
1558 if (Tok.isNot(tok::eof)) {
1559 Diag(Tok, diag::err_pragma_attribute_extra_tokens_after_attribute);
1560 SkipToEnd();
1561 return;
1562 }
1563
1564 // Consume the eof terminator token.
1565 ConsumeToken();
1566
Erik Pilkington7d180942018-10-29 17:38:42 +00001567 // Handle a mixed push/attribute by desurging to a push, then an attribute.
1568 if (Info->Action == PragmaAttributeInfo::Push)
Erik Pilkington0876cae2018-12-20 22:32:04 +00001569 Actions.ActOnPragmaAttributeEmptyPush(PragmaLoc, Info->Namespace);
Erik Pilkington7d180942018-10-29 17:38:42 +00001570
1571 Actions.ActOnPragmaAttributeAttribute(Attribute, PragmaLoc,
1572 std::move(SubjectMatchRules));
Alex Lorenz9e7bf162017-04-18 14:33:39 +00001573}
1574
Eli Bendersky06a40422014-06-06 20:31:48 +00001575// #pragma GCC visibility comes in two variants:
1576// 'push' '(' [visibility] ')'
1577// 'pop'
Fangrui Song6907ce22018-07-30 19:24:48 +00001578void PragmaGCCVisibilityHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00001579 PragmaIntroducer Introducer,
Douglas Gregorc7d65762010-09-09 22:45:38 +00001580 Token &VisTok) {
Eli Friedman570024a2010-08-05 06:57:20 +00001581 SourceLocation VisLoc = VisTok.getLocation();
1582
1583 Token Tok;
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001584 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001585
1586 const IdentifierInfo *PushPop = Tok.getIdentifierInfo();
1587
Eli Friedman570024a2010-08-05 06:57:20 +00001588 const IdentifierInfo *VisType;
1589 if (PushPop && PushPop->isStr("pop")) {
Craig Topper161e4db2014-05-21 06:02:52 +00001590 VisType = nullptr;
Eli Friedman570024a2010-08-05 06:57:20 +00001591 } else if (PushPop && PushPop->isStr("push")) {
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001592 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001593 if (Tok.isNot(tok::l_paren)) {
1594 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
1595 << "visibility";
1596 return;
1597 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001598 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001599 VisType = Tok.getIdentifierInfo();
1600 if (!VisType) {
1601 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1602 << "visibility";
1603 return;
1604 }
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001605 PP.LexUnexpandedToken(Tok);
Eli Friedman570024a2010-08-05 06:57:20 +00001606 if (Tok.isNot(tok::r_paren)) {
1607 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
1608 << "visibility";
1609 return;
1610 }
1611 } else {
1612 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
1613 << "visibility";
1614 return;
1615 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00001616 SourceLocation EndLoc = Tok.getLocation();
Joerg Sonnenberger869f0b72011-07-20 01:03:50 +00001617 PP.LexUnexpandedToken(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001618 if (Tok.isNot(tok::eod)) {
Eli Friedman570024a2010-08-05 06:57:20 +00001619 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1620 << "visibility";
1621 return;
1622 }
1623
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +00001624 auto Toks = std::make_unique<Token[]>(1);
Rafael Espindola273fd772012-01-26 02:02:57 +00001625 Toks[0].startToken();
1626 Toks[0].setKind(tok::annot_pragma_vis);
1627 Toks[0].setLocation(VisLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001628 Toks[0].setAnnotationEndLoc(EndLoc);
Rafael Espindola273fd772012-01-26 02:02:57 +00001629 Toks[0].setAnnotationValue(
Ilya Biryukov929af672019-05-17 09:32:05 +00001630 const_cast<void *>(static_cast<const void *>(VisType)));
1631 PP.EnterTokenStream(std::move(Toks), 1, /*DisableMacroExpansion=*/true,
1632 /*IsReinject=*/false);
Eli Friedman570024a2010-08-05 06:57:20 +00001633}
1634
Daniel Dunbar921b9682008-10-04 19:21:03 +00001635// #pragma pack(...) comes in the following delicious flavors:
1636// pack '(' [integer] ')'
1637// pack '(' 'show' ')'
1638// pack '(' ('push' | 'pop') [',' identifier] [, integer] ')'
Fangrui Song6907ce22018-07-30 19:24:48 +00001639void PragmaPackHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00001640 PragmaIntroducer Introducer,
Douglas Gregorc7d65762010-09-09 22:45:38 +00001641 Token &PackTok) {
Daniel Dunbar921b9682008-10-04 19:21:03 +00001642 SourceLocation PackLoc = PackTok.getLocation();
1643
1644 Token Tok;
1645 PP.Lex(Tok);
1646 if (Tok.isNot(tok::l_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001647 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001648 return;
1649 }
1650
Denis Zobnin10c4f452016-04-29 18:17:40 +00001651 Sema::PragmaMsStackAction Action = Sema::PSK_Reset;
1652 StringRef SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +00001653 Token Alignment;
1654 Alignment.startToken();
Mike Stump11289f42009-09-09 15:08:12 +00001655 PP.Lex(Tok);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001656 if (Tok.is(tok::numeric_constant)) {
Eli Friedman68be1642012-10-04 02:36:51 +00001657 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001658
1659 PP.Lex(Tok);
Eli Friedman055c9702011-11-02 01:53:16 +00001660
1661 // In MSVC/gcc, #pragma pack(4) sets the alignment without affecting
1662 // the push/pop stack.
1663 // In Apple gcc, #pragma pack(4) is equivalent to #pragma pack(push, 4)
Denis Zobnin10c4f452016-04-29 18:17:40 +00001664 Action =
1665 PP.getLangOpts().ApplePragmaPack ? Sema::PSK_Push_Set : Sema::PSK_Set;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001666 } else if (Tok.is(tok::identifier)) {
1667 const IdentifierInfo *II = Tok.getIdentifierInfo();
Chris Lattnere3d20d92008-11-23 21:45:46 +00001668 if (II->isStr("show")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001669 Action = Sema::PSK_Show;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001670 PP.Lex(Tok);
1671 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001672 if (II->isStr("push")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001673 Action = Sema::PSK_Push;
Chris Lattnere3d20d92008-11-23 21:45:46 +00001674 } else if (II->isStr("pop")) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001675 Action = Sema::PSK_Pop;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001676 } else {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00001677 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001678 return;
Mike Stump11289f42009-09-09 15:08:12 +00001679 }
Daniel Dunbar921b9682008-10-04 19:21:03 +00001680 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001681
Daniel Dunbar921b9682008-10-04 19:21:03 +00001682 if (Tok.is(tok::comma)) {
1683 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001684
Daniel Dunbar921b9682008-10-04 19:21:03 +00001685 if (Tok.is(tok::numeric_constant)) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001686 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
Eli Friedman68be1642012-10-04 02:36:51 +00001687 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001688
1689 PP.Lex(Tok);
1690 } else if (Tok.is(tok::identifier)) {
Denis Zobnin10c4f452016-04-29 18:17:40 +00001691 SlotLabel = Tok.getIdentifierInfo()->getName();
Daniel Dunbar921b9682008-10-04 19:21:03 +00001692 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001693
Daniel Dunbar921b9682008-10-04 19:21:03 +00001694 if (Tok.is(tok::comma)) {
1695 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001696
Daniel Dunbar921b9682008-10-04 19:21:03 +00001697 if (Tok.isNot(tok::numeric_constant)) {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001698 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001699 return;
1700 }
Mike Stump11289f42009-09-09 15:08:12 +00001701
Denis Zobnin10c4f452016-04-29 18:17:40 +00001702 Action = (Sema::PragmaMsStackAction)(Action | Sema::PSK_Set);
Eli Friedman68be1642012-10-04 02:36:51 +00001703 Alignment = Tok;
Daniel Dunbar921b9682008-10-04 19:21:03 +00001704
1705 PP.Lex(Tok);
1706 }
1707 } else {
Chris Lattnere3d20d92008-11-23 21:45:46 +00001708 PP.Diag(Tok.getLocation(), diag::warn_pragma_pack_malformed);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001709 return;
1710 }
1711 }
1712 }
David Blaikiebbafb8a2012-03-11 07:00:24 +00001713 } else if (PP.getLangOpts().ApplePragmaPack) {
Eli Friedman055c9702011-11-02 01:53:16 +00001714 // In MSVC/gcc, #pragma pack() resets the alignment without affecting
1715 // the push/pop stack.
1716 // In Apple gcc #pragma pack() is equivalent to #pragma pack(pop).
Denis Zobnin10c4f452016-04-29 18:17:40 +00001717 Action = Sema::PSK_Pop;
Sebastian Redl17f2c7d2008-12-09 13:15:23 +00001718 }
Daniel Dunbar921b9682008-10-04 19:21:03 +00001719
1720 if (Tok.isNot(tok::r_paren)) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001721 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "pack";
Daniel Dunbar921b9682008-10-04 19:21:03 +00001722 return;
1723 }
1724
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001725 SourceLocation RParenLoc = Tok.getLocation();
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001726 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001727 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001728 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "pack";
1729 return;
1730 }
1731
David Blaikie2eabcc92016-02-09 18:52:09 +00001732 PragmaPackInfo *Info =
1733 PP.getPreprocessorAllocator().Allocate<PragmaPackInfo>(1);
Denis Zobnin10c4f452016-04-29 18:17:40 +00001734 Info->Action = Action;
1735 Info->SlotLabel = SlotLabel;
Eli Friedman68be1642012-10-04 02:36:51 +00001736 Info->Alignment = Alignment;
Eli Friedmanec52f922012-02-23 23:47:16 +00001737
David Blaikie2eabcc92016-02-09 18:52:09 +00001738 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1739 1);
Eli Friedmanec52f922012-02-23 23:47:16 +00001740 Toks[0].startToken();
1741 Toks[0].setKind(tok::annot_pragma_pack);
1742 Toks[0].setLocation(PackLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00001743 Toks[0].setAnnotationEndLoc(RParenLoc);
Eli Friedmanec52f922012-02-23 23:47:16 +00001744 Toks[0].setAnnotationValue(static_cast<void*>(Info));
Ilya Biryukov929af672019-05-17 09:32:05 +00001745 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
1746 /*IsReinject=*/false);
Daniel Dunbar921b9682008-10-04 19:21:03 +00001747}
1748
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001749// #pragma ms_struct on
1750// #pragma ms_struct off
Fangrui Song6907ce22018-07-30 19:24:48 +00001751void PragmaMSStructHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00001752 PragmaIntroducer Introducer,
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001753 Token &MSStructTok) {
Nico Weber779355f2016-03-02 23:22:00 +00001754 PragmaMSStructKind Kind = PMSST_OFF;
1755
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001756 Token Tok;
1757 PP.Lex(Tok);
1758 if (Tok.isNot(tok::identifier)) {
1759 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1760 return;
1761 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00001762 SourceLocation EndLoc = Tok.getLocation();
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001763 const IdentifierInfo *II = Tok.getIdentifierInfo();
1764 if (II->isStr("on")) {
Nico Weber779355f2016-03-02 23:22:00 +00001765 Kind = PMSST_ON;
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001766 PP.Lex(Tok);
1767 }
1768 else if (II->isStr("off") || II->isStr("reset"))
1769 PP.Lex(Tok);
1770 else {
1771 PP.Diag(Tok.getLocation(), diag::warn_pragma_ms_struct);
1772 return;
1773 }
Fangrui Song6907ce22018-07-30 19:24:48 +00001774
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001775 if (Tok.isNot(tok::eod)) {
Daniel Dunbar340cf242012-02-29 01:38:22 +00001776 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
1777 << "ms_struct";
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001778 return;
1779 }
Eli Friedman68be1642012-10-04 02:36:51 +00001780
David Blaikie2eabcc92016-02-09 18:52:09 +00001781 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1782 1);
Eli Friedman68be1642012-10-04 02:36:51 +00001783 Toks[0].startToken();
1784 Toks[0].setKind(tok::annot_pragma_msstruct);
1785 Toks[0].setLocation(MSStructTok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001786 Toks[0].setAnnotationEndLoc(EndLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001787 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1788 static_cast<uintptr_t>(Kind)));
Ilya Biryukov929af672019-05-17 09:32:05 +00001789 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
1790 /*IsReinject=*/false);
Fariborz Jahanian743dda42011-04-25 18:49:15 +00001791}
1792
Javed Absar2a67c9e2017-06-05 10:11:57 +00001793// #pragma clang section bss="abc" data="" rodata="def" text=""
1794void PragmaClangSectionHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00001795 PragmaIntroducer Introducer,
1796 Token &FirstToken) {
Javed Absar2a67c9e2017-06-05 10:11:57 +00001797
1798 Token Tok;
1799 auto SecKind = Sema::PragmaClangSectionKind::PCSK_Invalid;
1800
1801 PP.Lex(Tok); // eat 'section'
1802 while (Tok.isNot(tok::eod)) {
1803 if (Tok.isNot(tok::identifier)) {
1804 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
1805 return;
1806 }
1807
1808 const IdentifierInfo *SecType = Tok.getIdentifierInfo();
1809 if (SecType->isStr("bss"))
1810 SecKind = Sema::PragmaClangSectionKind::PCSK_BSS;
1811 else if (SecType->isStr("data"))
1812 SecKind = Sema::PragmaClangSectionKind::PCSK_Data;
1813 else if (SecType->isStr("rodata"))
1814 SecKind = Sema::PragmaClangSectionKind::PCSK_Rodata;
1815 else if (SecType->isStr("text"))
1816 SecKind = Sema::PragmaClangSectionKind::PCSK_Text;
1817 else {
1818 PP.Diag(Tok.getLocation(), diag::err_pragma_expected_clang_section_name) << "clang section";
1819 return;
1820 }
1821
1822 PP.Lex(Tok); // eat ['bss'|'data'|'rodata'|'text']
1823 if (Tok.isNot(tok::equal)) {
1824 PP.Diag(Tok.getLocation(), diag::err_pragma_clang_section_expected_equal) << SecKind;
1825 return;
1826 }
1827
1828 std::string SecName;
1829 if (!PP.LexStringLiteral(Tok, SecName, "pragma clang section", false))
1830 return;
1831
1832 Actions.ActOnPragmaClangSection(Tok.getLocation(),
1833 (SecName.size()? Sema::PragmaClangSectionAction::PCSA_Set :
1834 Sema::PragmaClangSectionAction::PCSA_Clear),
1835 SecKind, SecName);
1836 }
1837}
1838
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001839// #pragma 'align' '=' {'native','natural','mac68k','power','reset'}
1840// #pragma 'options 'align' '=' {'native','natural','mac68k','power','reset'}
Eli Friedman68be1642012-10-04 02:36:51 +00001841static void ParseAlignPragma(Preprocessor &PP, Token &FirstTok,
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001842 bool IsOptions) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001843 Token Tok;
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001844
1845 if (IsOptions) {
1846 PP.Lex(Tok);
1847 if (Tok.isNot(tok::identifier) ||
1848 !Tok.getIdentifierInfo()->isStr("align")) {
1849 PP.Diag(Tok.getLocation(), diag::warn_pragma_options_expected_align);
1850 return;
1851 }
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001852 }
Daniel Dunbar663e8092010-05-27 18:42:09 +00001853
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001854 PP.Lex(Tok);
1855 if (Tok.isNot(tok::equal)) {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001856 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_expected_equal)
1857 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001858 return;
1859 }
1860
1861 PP.Lex(Tok);
1862 if (Tok.isNot(tok::identifier)) {
1863 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001864 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001865 return;
1866 }
1867
John McCallfaf5fb42010-08-26 23:41:50 +00001868 Sema::PragmaOptionsAlignKind Kind = Sema::POAK_Natural;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001869 const IdentifierInfo *II = Tok.getIdentifierInfo();
Daniel Dunbar663e8092010-05-27 18:42:09 +00001870 if (II->isStr("native"))
John McCallfaf5fb42010-08-26 23:41:50 +00001871 Kind = Sema::POAK_Native;
Daniel Dunbar663e8092010-05-27 18:42:09 +00001872 else if (II->isStr("natural"))
John McCallfaf5fb42010-08-26 23:41:50 +00001873 Kind = Sema::POAK_Natural;
Daniel Dunbar9c84d4a2010-05-27 18:42:17 +00001874 else if (II->isStr("packed"))
John McCallfaf5fb42010-08-26 23:41:50 +00001875 Kind = Sema::POAK_Packed;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001876 else if (II->isStr("power"))
John McCallfaf5fb42010-08-26 23:41:50 +00001877 Kind = Sema::POAK_Power;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001878 else if (II->isStr("mac68k"))
John McCallfaf5fb42010-08-26 23:41:50 +00001879 Kind = Sema::POAK_Mac68k;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001880 else if (II->isStr("reset"))
John McCallfaf5fb42010-08-26 23:41:50 +00001881 Kind = Sema::POAK_Reset;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001882 else {
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001883 PP.Diag(Tok.getLocation(), diag::warn_pragma_align_invalid_option)
1884 << IsOptions;
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001885 return;
1886 }
1887
David Majnemera8f2f1d2015-03-19 00:10:23 +00001888 SourceLocation EndLoc = Tok.getLocation();
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001889 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001890 if (Tok.isNot(tok::eod)) {
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001891 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001892 << (IsOptions ? "options" : "align");
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001893 return;
1894 }
1895
David Blaikie2eabcc92016-02-09 18:52:09 +00001896 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
1897 1);
Eli Friedman68be1642012-10-04 02:36:51 +00001898 Toks[0].startToken();
1899 Toks[0].setKind(tok::annot_pragma_align);
1900 Toks[0].setLocation(FirstTok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00001901 Toks[0].setAnnotationEndLoc(EndLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00001902 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
1903 static_cast<uintptr_t>(Kind)));
Ilya Biryukov929af672019-05-17 09:32:05 +00001904 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
1905 /*IsReinject=*/false);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001906}
1907
Fangrui Song6907ce22018-07-30 19:24:48 +00001908void PragmaAlignHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00001909 PragmaIntroducer Introducer,
Douglas Gregorc7d65762010-09-09 22:45:38 +00001910 Token &AlignTok) {
Eli Friedman68be1642012-10-04 02:36:51 +00001911 ParseAlignPragma(PP, AlignTok, /*IsOptions=*/false);
Daniel Dunbarcb82acb2010-07-31 19:17:07 +00001912}
1913
Fangrui Song6907ce22018-07-30 19:24:48 +00001914void PragmaOptionsHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00001915 PragmaIntroducer Introducer,
Douglas Gregorc7d65762010-09-09 22:45:38 +00001916 Token &OptionsTok) {
Eli Friedman68be1642012-10-04 02:36:51 +00001917 ParseAlignPragma(PP, OptionsTok, /*IsOptions=*/true);
Daniel Dunbar75c9be72010-05-26 23:29:06 +00001918}
1919
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001920// #pragma unused(identifier)
Fangrui Song6907ce22018-07-30 19:24:48 +00001921void PragmaUnusedHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00001922 PragmaIntroducer Introducer,
Douglas Gregorc7d65762010-09-09 22:45:38 +00001923 Token &UnusedTok) {
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001924 // FIXME: Should we be expanding macros here? My guess is no.
1925 SourceLocation UnusedLoc = UnusedTok.getLocation();
Mike Stump11289f42009-09-09 15:08:12 +00001926
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001927 // Lex the left '('.
1928 Token Tok;
1929 PP.Lex(Tok);
1930 if (Tok.isNot(tok::l_paren)) {
1931 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "unused";
1932 return;
1933 }
Mike Stump11289f42009-09-09 15:08:12 +00001934
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001935 // Lex the declaration reference(s).
Chris Lattner0e62c1c2011-07-23 10:55:15 +00001936 SmallVector<Token, 5> Identifiers;
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001937 SourceLocation RParenLoc;
1938 bool LexID = true;
Mike Stump11289f42009-09-09 15:08:12 +00001939
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001940 while (true) {
1941 PP.Lex(Tok);
Mike Stump11289f42009-09-09 15:08:12 +00001942
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001943 if (LexID) {
Mike Stump11289f42009-09-09 15:08:12 +00001944 if (Tok.is(tok::identifier)) {
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001945 Identifiers.push_back(Tok);
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001946 LexID = false;
1947 continue;
1948 }
1949
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001950 // Illegal token!
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001951 PP.Diag(Tok.getLocation(), diag::warn_pragma_unused_expected_var);
1952 return;
1953 }
Mike Stump11289f42009-09-09 15:08:12 +00001954
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001955 // We are execting a ')' or a ','.
1956 if (Tok.is(tok::comma)) {
1957 LexID = true;
1958 continue;
1959 }
Mike Stump11289f42009-09-09 15:08:12 +00001960
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001961 if (Tok.is(tok::r_paren)) {
1962 RParenLoc = Tok.getLocation();
1963 break;
1964 }
Mike Stump11289f42009-09-09 15:08:12 +00001965
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001966 // Illegal token!
David Majnemer88969812014-02-10 19:06:37 +00001967 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_punc) << "unused";
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001968 return;
1969 }
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001970
1971 PP.Lex(Tok);
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00001972 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00001973 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
1974 "unused";
1975 return;
1976 }
1977
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001978 // Verify that we have a location for the right parenthesis.
1979 assert(RParenLoc.isValid() && "Valid '#pragma unused' must have ')'");
Ted Kremenekfb50bf52009-08-03 23:24:57 +00001980 assert(!Identifiers.empty() && "Valid '#pragma unused' must have arguments");
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001981
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +00001982 // For each identifier token, insert into the token stream a
1983 // annot_pragma_unused token followed by the identifier token.
1984 // This allows us to cache a "#pragma unused" that occurs inside an inline
1985 // C++ member function.
1986
David Blaikie2eabcc92016-02-09 18:52:09 +00001987 MutableArrayRef<Token> Toks(
1988 PP.getPreprocessorAllocator().Allocate<Token>(2 * Identifiers.size()),
1989 2 * Identifiers.size());
Argyrios Kyrtzidisee569622011-01-17 18:58:44 +00001990 for (unsigned i=0; i != Identifiers.size(); i++) {
1991 Token &pragmaUnusedTok = Toks[2*i], &idTok = Toks[2*i+1];
1992 pragmaUnusedTok.startToken();
1993 pragmaUnusedTok.setKind(tok::annot_pragma_unused);
1994 pragmaUnusedTok.setLocation(UnusedLoc);
1995 idTok = Identifiers[i];
1996 }
Ilya Biryukov929af672019-05-17 09:32:05 +00001997 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
1998 /*IsReinject=*/false);
Ted Kremenekfd14fad2009-03-23 22:28:25 +00001999}
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002000
2001// #pragma weak identifier
2002// #pragma weak identifier '=' identifier
Fangrui Song6907ce22018-07-30 19:24:48 +00002003void PragmaWeakHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002004 PragmaIntroducer Introducer,
Douglas Gregorc7d65762010-09-09 22:45:38 +00002005 Token &WeakTok) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002006 SourceLocation WeakLoc = WeakTok.getLocation();
2007
2008 Token Tok;
2009 PP.Lex(Tok);
2010 if (Tok.isNot(tok::identifier)) {
2011 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) << "weak";
2012 return;
2013 }
2014
Eli Friedman68be1642012-10-04 02:36:51 +00002015 Token WeakName = Tok;
2016 bool HasAlias = false;
2017 Token AliasName;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002018
2019 PP.Lex(Tok);
2020 if (Tok.is(tok::equal)) {
Eli Friedman68be1642012-10-04 02:36:51 +00002021 HasAlias = true;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002022 PP.Lex(Tok);
2023 if (Tok.isNot(tok::identifier)) {
Mike Stump11289f42009-09-09 15:08:12 +00002024 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002025 << "weak";
2026 return;
2027 }
Eli Friedman68be1642012-10-04 02:36:51 +00002028 AliasName = Tok;
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002029 PP.Lex(Tok);
2030 }
2031
Peter Collingbourne2f1e36b2011-02-28 02:37:51 +00002032 if (Tok.isNot(tok::eod)) {
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002033 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) << "weak";
2034 return;
2035 }
2036
Eli Friedman68be1642012-10-04 02:36:51 +00002037 if (HasAlias) {
David Blaikie2eabcc92016-02-09 18:52:09 +00002038 MutableArrayRef<Token> Toks(
2039 PP.getPreprocessorAllocator().Allocate<Token>(3), 3);
Eli Friedman68be1642012-10-04 02:36:51 +00002040 Token &pragmaUnusedTok = Toks[0];
2041 pragmaUnusedTok.startToken();
2042 pragmaUnusedTok.setKind(tok::annot_pragma_weakalias);
2043 pragmaUnusedTok.setLocation(WeakLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002044 pragmaUnusedTok.setAnnotationEndLoc(AliasName.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00002045 Toks[1] = WeakName;
2046 Toks[2] = AliasName;
Ilya Biryukov929af672019-05-17 09:32:05 +00002047 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2048 /*IsReinject=*/false);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002049 } else {
David Blaikie2eabcc92016-02-09 18:52:09 +00002050 MutableArrayRef<Token> Toks(
2051 PP.getPreprocessorAllocator().Allocate<Token>(2), 2);
Eli Friedman68be1642012-10-04 02:36:51 +00002052 Token &pragmaUnusedTok = Toks[0];
2053 pragmaUnusedTok.startToken();
2054 pragmaUnusedTok.setKind(tok::annot_pragma_weak);
2055 pragmaUnusedTok.setLocation(WeakLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002056 pragmaUnusedTok.setAnnotationEndLoc(WeakLoc);
Eli Friedman68be1642012-10-04 02:36:51 +00002057 Toks[1] = WeakName;
Ilya Biryukov929af672019-05-17 09:32:05 +00002058 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2059 /*IsReinject=*/false);
Eli Friedmanf5867dd2009-06-05 00:49:58 +00002060 }
2061}
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00002062
David Chisnall0867d9c2012-02-18 16:12:34 +00002063// #pragma redefine_extname identifier identifier
Fangrui Song6907ce22018-07-30 19:24:48 +00002064void PragmaRedefineExtnameHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002065 PragmaIntroducer Introducer,
David Chisnall0867d9c2012-02-18 16:12:34 +00002066 Token &RedefToken) {
2067 SourceLocation RedefLoc = RedefToken.getLocation();
2068
2069 Token Tok;
2070 PP.Lex(Tok);
2071 if (Tok.isNot(tok::identifier)) {
2072 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
2073 "redefine_extname";
2074 return;
2075 }
2076
Eli Friedman68be1642012-10-04 02:36:51 +00002077 Token RedefName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00002078 PP.Lex(Tok);
Eli Friedman68be1642012-10-04 02:36:51 +00002079
David Chisnall0867d9c2012-02-18 16:12:34 +00002080 if (Tok.isNot(tok::identifier)) {
2081 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2082 << "redefine_extname";
2083 return;
2084 }
Eli Friedman68be1642012-10-04 02:36:51 +00002085
2086 Token AliasName = Tok;
David Chisnall0867d9c2012-02-18 16:12:34 +00002087 PP.Lex(Tok);
2088
2089 if (Tok.isNot(tok::eod)) {
2090 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2091 "redefine_extname";
2092 return;
2093 }
2094
David Blaikie2eabcc92016-02-09 18:52:09 +00002095 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(3),
2096 3);
Eli Friedman68be1642012-10-04 02:36:51 +00002097 Token &pragmaRedefTok = Toks[0];
2098 pragmaRedefTok.startToken();
2099 pragmaRedefTok.setKind(tok::annot_pragma_redefine_extname);
2100 pragmaRedefTok.setLocation(RedefLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002101 pragmaRedefTok.setAnnotationEndLoc(AliasName.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00002102 Toks[1] = RedefName;
2103 Toks[2] = AliasName;
Ilya Biryukov929af672019-05-17 09:32:05 +00002104 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2105 /*IsReinject=*/false);
David Chisnall0867d9c2012-02-18 16:12:34 +00002106}
2107
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002108void PragmaFPContractHandler::HandlePragma(Preprocessor &PP,
2109 PragmaIntroducer Introducer,
2110 Token &Tok) {
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00002111 tok::OnOffSwitch OOS;
2112 if (PP.LexOnOffSwitch(OOS))
2113 return;
2114
David Blaikie2eabcc92016-02-09 18:52:09 +00002115 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2116 1);
Eli Friedman68be1642012-10-04 02:36:51 +00002117 Toks[0].startToken();
2118 Toks[0].setKind(tok::annot_pragma_fp_contract);
2119 Toks[0].setLocation(Tok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002120 Toks[0].setAnnotationEndLoc(Tok.getLocation());
Eli Friedman68be1642012-10-04 02:36:51 +00002121 Toks[0].setAnnotationValue(reinterpret_cast<void*>(
2122 static_cast<uintptr_t>(OOS)));
Ilya Biryukov929af672019-05-17 09:32:05 +00002123 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2124 /*IsReinject=*/false);
Peter Collingbourne564c0fa2011-02-14 01:42:35 +00002125}
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002126
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002127void PragmaOpenCLExtensionHandler::HandlePragma(Preprocessor &PP,
2128 PragmaIntroducer Introducer,
2129 Token &Tok) {
Tanya Lattneree840b82011-04-14 23:35:31 +00002130 PP.LexUnexpandedToken(Tok);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002131 if (Tok.isNot(tok::identifier)) {
2132 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier) <<
2133 "OPENCL";
2134 return;
2135 }
Yaxun Liu5b746652016-12-18 05:18:55 +00002136 IdentifierInfo *Ext = Tok.getIdentifierInfo();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002137 SourceLocation NameLoc = Tok.getLocation();
2138
2139 PP.Lex(Tok);
2140 if (Tok.isNot(tok::colon)) {
Yaxun Liu5b746652016-12-18 05:18:55 +00002141 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_colon) << Ext;
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002142 return;
2143 }
2144
2145 PP.Lex(Tok);
2146 if (Tok.isNot(tok::identifier)) {
Yaxun Liu5b746652016-12-18 05:18:55 +00002147 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate) << 0;
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002148 return;
2149 }
Yaxun Liu5b746652016-12-18 05:18:55 +00002150 IdentifierInfo *Pred = Tok.getIdentifierInfo();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002151
Yaxun Liu5b746652016-12-18 05:18:55 +00002152 OpenCLExtState State;
2153 if (Pred->isStr("enable")) {
2154 State = Enable;
2155 } else if (Pred->isStr("disable")) {
2156 State = Disable;
2157 } else if (Pred->isStr("begin"))
2158 State = Begin;
2159 else if (Pred->isStr("end"))
2160 State = End;
2161 else {
2162 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_predicate)
2163 << Ext->isStr("all");
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002164 return;
2165 }
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00002166 SourceLocation StateLoc = Tok.getLocation();
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002167
Eli Friedman68be1642012-10-04 02:36:51 +00002168 PP.Lex(Tok);
2169 if (Tok.isNot(tok::eod)) {
2170 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol) <<
2171 "OPENCL EXTENSION";
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002172 return;
2173 }
Eli Friedman68be1642012-10-04 02:36:51 +00002174
Yaxun Liu5b746652016-12-18 05:18:55 +00002175 auto Info = PP.getPreprocessorAllocator().Allocate<OpenCLExtData>(1);
2176 Info->first = Ext;
2177 Info->second = State;
David Blaikie2eabcc92016-02-09 18:52:09 +00002178 MutableArrayRef<Token> Toks(PP.getPreprocessorAllocator().Allocate<Token>(1),
2179 1);
Eli Friedman68be1642012-10-04 02:36:51 +00002180 Toks[0].startToken();
2181 Toks[0].setKind(tok::annot_pragma_opencl_extension);
2182 Toks[0].setLocation(NameLoc);
Yaxun Liu5b746652016-12-18 05:18:55 +00002183 Toks[0].setAnnotationValue(static_cast<void*>(Info));
David Majnemera8f2f1d2015-03-19 00:10:23 +00002184 Toks[0].setAnnotationEndLoc(StateLoc);
Ilya Biryukov929af672019-05-17 09:32:05 +00002185 PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
2186 /*IsReinject=*/false);
Pekka Jaaskelainen1db1da22013-10-12 09:29:48 +00002187
2188 if (PP.getPPCallbacks())
Fangrui Song6907ce22018-07-30 19:24:48 +00002189 PP.getPPCallbacks()->PragmaOpenCLExtension(NameLoc, Ext,
Yaxun Liu5b746652016-12-18 05:18:55 +00002190 StateLoc, State);
Peter Collingbourne7ce13fc2011-02-14 01:42:53 +00002191}
2192
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002193/// Handle '#pragma omp ...' when OpenMP is disabled.
Alexey Bataeva769e072013-03-22 06:34:35 +00002194///
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002195void PragmaNoOpenMPHandler::HandlePragma(Preprocessor &PP,
2196 PragmaIntroducer Introducer,
2197 Token &FirstTok) {
Alp Tokerd4a3f0e2014-06-15 23:30:39 +00002198 if (!PP.getDiagnostics().isIgnored(diag::warn_pragma_omp_ignored,
2199 FirstTok.getLocation())) {
Alexey Bataeva769e072013-03-22 06:34:35 +00002200 PP.Diag(FirstTok, diag::warn_pragma_omp_ignored);
Alp Tokerd576e002014-06-12 11:13:52 +00002201 PP.getDiagnostics().setSeverity(diag::warn_pragma_omp_ignored,
2202 diag::Severity::Ignored, SourceLocation());
Alexey Bataeva769e072013-03-22 06:34:35 +00002203 }
2204 PP.DiscardUntilEndOfDirective();
2205}
2206
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002207/// Handle '#pragma omp ...' when OpenMP is enabled.
Alexey Bataeva769e072013-03-22 06:34:35 +00002208///
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002209void PragmaOpenMPHandler::HandlePragma(Preprocessor &PP,
2210 PragmaIntroducer Introducer,
2211 Token &FirstTok) {
Alexey Bataeva769e072013-03-22 06:34:35 +00002212 SmallVector<Token, 16> Pragma;
2213 Token Tok;
2214 Tok.startToken();
2215 Tok.setKind(tok::annot_pragma_openmp);
Joel E. Denny91f80662019-05-28 19:27:19 +00002216 Tok.setLocation(Introducer.Loc);
Alexey Bataeva769e072013-03-22 06:34:35 +00002217
Alexey Bataev96dae812018-02-16 18:36:44 +00002218 while (Tok.isNot(tok::eod) && Tok.isNot(tok::eof)) {
Alexey Bataeva769e072013-03-22 06:34:35 +00002219 Pragma.push_back(Tok);
2220 PP.Lex(Tok);
Alexey Bataev96dae812018-02-16 18:36:44 +00002221 if (Tok.is(tok::annot_pragma_openmp)) {
2222 PP.Diag(Tok, diag::err_omp_unexpected_directive) << 0;
2223 unsigned InnerPragmaCnt = 1;
2224 while (InnerPragmaCnt != 0) {
2225 PP.Lex(Tok);
2226 if (Tok.is(tok::annot_pragma_openmp))
2227 ++InnerPragmaCnt;
2228 else if (Tok.is(tok::annot_pragma_openmp_end))
2229 --InnerPragmaCnt;
2230 }
2231 PP.Lex(Tok);
2232 }
Alexey Bataeva769e072013-03-22 06:34:35 +00002233 }
2234 SourceLocation EodLoc = Tok.getLocation();
2235 Tok.startToken();
2236 Tok.setKind(tok::annot_pragma_openmp_end);
2237 Tok.setLocation(EodLoc);
2238 Pragma.push_back(Tok);
2239
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +00002240 auto Toks = std::make_unique<Token[]>(Pragma.size());
David Blaikie2eabcc92016-02-09 18:52:09 +00002241 std::copy(Pragma.begin(), Pragma.end(), Toks.get());
2242 PP.EnterTokenStream(std::move(Toks), Pragma.size(),
Ilya Biryukov929af672019-05-17 09:32:05 +00002243 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
Alexey Bataeva769e072013-03-22 06:34:35 +00002244}
Reid Kleckner002562a2013-05-06 21:02:12 +00002245
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002246/// Handle '#pragma pointers_to_members'
David Majnemer4bb09802014-02-10 19:50:15 +00002247// The grammar for this pragma is as follows:
2248//
2249// <inheritance model> ::= ('single' | 'multiple' | 'virtual') '_inheritance'
2250//
2251// #pragma pointers_to_members '(' 'best_case' ')'
2252// #pragma pointers_to_members '(' 'full_generality' [',' inheritance-model] ')'
2253// #pragma pointers_to_members '(' inheritance-model ')'
2254void PragmaMSPointersToMembers::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002255 PragmaIntroducer Introducer,
David Majnemer4bb09802014-02-10 19:50:15 +00002256 Token &Tok) {
2257 SourceLocation PointersToMembersLoc = Tok.getLocation();
2258 PP.Lex(Tok);
2259 if (Tok.isNot(tok::l_paren)) {
2260 PP.Diag(PointersToMembersLoc, diag::warn_pragma_expected_lparen)
2261 << "pointers_to_members";
2262 return;
2263 }
2264 PP.Lex(Tok);
2265 const IdentifierInfo *Arg = Tok.getIdentifierInfo();
2266 if (!Arg) {
2267 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_identifier)
2268 << "pointers_to_members";
2269 return;
2270 }
2271 PP.Lex(Tok);
2272
David Majnemer86c318f2014-02-11 21:05:00 +00002273 LangOptions::PragmaMSPointersToMembersKind RepresentationMethod;
David Majnemer4bb09802014-02-10 19:50:15 +00002274 if (Arg->isStr("best_case")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002275 RepresentationMethod = LangOptions::PPTMK_BestCase;
David Majnemer4bb09802014-02-10 19:50:15 +00002276 } else {
2277 if (Arg->isStr("full_generality")) {
2278 if (Tok.is(tok::comma)) {
2279 PP.Lex(Tok);
2280
2281 Arg = Tok.getIdentifierInfo();
2282 if (!Arg) {
2283 PP.Diag(Tok.getLocation(),
2284 diag::err_pragma_pointers_to_members_unknown_kind)
2285 << Tok.getKind() << /*OnlyInheritanceModels*/ 0;
2286 return;
2287 }
2288 PP.Lex(Tok);
2289 } else if (Tok.is(tok::r_paren)) {
2290 // #pragma pointers_to_members(full_generality) implicitly specifies
2291 // virtual_inheritance.
Craig Topper161e4db2014-05-21 06:02:52 +00002292 Arg = nullptr;
David Majnemer86c318f2014-02-11 21:05:00 +00002293 RepresentationMethod = LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002294 } else {
2295 PP.Diag(Tok.getLocation(), diag::err_expected_punc)
2296 << "full_generality";
2297 return;
2298 }
2299 }
2300
2301 if (Arg) {
2302 if (Arg->isStr("single_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002303 RepresentationMethod =
2304 LangOptions::PPTMK_FullGeneralitySingleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002305 } else if (Arg->isStr("multiple_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002306 RepresentationMethod =
2307 LangOptions::PPTMK_FullGeneralityMultipleInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002308 } else if (Arg->isStr("virtual_inheritance")) {
David Majnemer86c318f2014-02-11 21:05:00 +00002309 RepresentationMethod =
2310 LangOptions::PPTMK_FullGeneralityVirtualInheritance;
David Majnemer4bb09802014-02-10 19:50:15 +00002311 } else {
2312 PP.Diag(Tok.getLocation(),
2313 diag::err_pragma_pointers_to_members_unknown_kind)
2314 << Arg << /*HasPointerDeclaration*/ 1;
2315 return;
2316 }
2317 }
2318 }
2319
2320 if (Tok.isNot(tok::r_paren)) {
2321 PP.Diag(Tok.getLocation(), diag::err_expected_rparen_after)
2322 << (Arg ? Arg->getName() : "full_generality");
2323 return;
2324 }
2325
David Majnemera8f2f1d2015-03-19 00:10:23 +00002326 SourceLocation EndLoc = Tok.getLocation();
David Majnemer4bb09802014-02-10 19:50:15 +00002327 PP.Lex(Tok);
2328 if (Tok.isNot(tok::eod)) {
2329 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2330 << "pointers_to_members";
2331 return;
2332 }
2333
2334 Token AnnotTok;
2335 AnnotTok.startToken();
2336 AnnotTok.setKind(tok::annot_pragma_ms_pointers_to_members);
2337 AnnotTok.setLocation(PointersToMembersLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002338 AnnotTok.setAnnotationEndLoc(EndLoc);
David Majnemer4bb09802014-02-10 19:50:15 +00002339 AnnotTok.setAnnotationValue(
2340 reinterpret_cast<void *>(static_cast<uintptr_t>(RepresentationMethod)));
Ilya Biryukov929af672019-05-17 09:32:05 +00002341 PP.EnterToken(AnnotTok, /*IsReinject=*/true);
David Majnemer4bb09802014-02-10 19:50:15 +00002342}
2343
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002344/// Handle '#pragma vtordisp'
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002345// The grammar for this pragma is as follows:
2346//
2347// <vtordisp-mode> ::= ('off' | 'on' | '0' | '1' | '2' )
2348//
2349// #pragma vtordisp '(' ['push' ','] vtordisp-mode ')'
2350// #pragma vtordisp '(' 'pop' ')'
2351// #pragma vtordisp '(' ')'
2352void PragmaMSVtorDisp::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002353 PragmaIntroducer Introducer, Token &Tok) {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002354 SourceLocation VtorDispLoc = Tok.getLocation();
2355 PP.Lex(Tok);
2356 if (Tok.isNot(tok::l_paren)) {
2357 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_lparen) << "vtordisp";
2358 return;
2359 }
2360 PP.Lex(Tok);
2361
Denis Zobnin2290dac2016-04-29 11:27:00 +00002362 Sema::PragmaMsStackAction Action = Sema::PSK_Set;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002363 const IdentifierInfo *II = Tok.getIdentifierInfo();
2364 if (II) {
2365 if (II->isStr("push")) {
2366 // #pragma vtordisp(push, mode)
2367 PP.Lex(Tok);
2368 if (Tok.isNot(tok::comma)) {
2369 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_punc) << "vtordisp";
2370 return;
2371 }
2372 PP.Lex(Tok);
Denis Zobnin2290dac2016-04-29 11:27:00 +00002373 Action = Sema::PSK_Push_Set;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002374 // not push, could be on/off
2375 } else if (II->isStr("pop")) {
2376 // #pragma vtordisp(pop)
2377 PP.Lex(Tok);
Denis Zobnin2290dac2016-04-29 11:27:00 +00002378 Action = Sema::PSK_Pop;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002379 }
2380 // not push or pop, could be on/off
2381 } else {
2382 if (Tok.is(tok::r_paren)) {
2383 // #pragma vtordisp()
Denis Zobnin2290dac2016-04-29 11:27:00 +00002384 Action = Sema::PSK_Reset;
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002385 }
2386 }
2387
2388
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00002389 uint64_t Value = 0;
Denis Zobnin2290dac2016-04-29 11:27:00 +00002390 if (Action & Sema::PSK_Push || Action & Sema::PSK_Set) {
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002391 const IdentifierInfo *II = Tok.getIdentifierInfo();
2392 if (II && II->isStr("off")) {
2393 PP.Lex(Tok);
2394 Value = 0;
2395 } else if (II && II->isStr("on")) {
2396 PP.Lex(Tok);
2397 Value = 1;
2398 } else if (Tok.is(tok::numeric_constant) &&
2399 PP.parseSimpleIntegerLiteral(Tok, Value)) {
2400 if (Value > 2) {
2401 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_integer)
2402 << 0 << 2 << "vtordisp";
2403 return;
2404 }
2405 } else {
2406 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_action)
2407 << "vtordisp";
2408 return;
2409 }
2410 }
2411
2412 // Finish the pragma: ')' $
2413 if (Tok.isNot(tok::r_paren)) {
2414 PP.Diag(VtorDispLoc, diag::warn_pragma_expected_rparen) << "vtordisp";
2415 return;
2416 }
David Majnemera8f2f1d2015-03-19 00:10:23 +00002417 SourceLocation EndLoc = Tok.getLocation();
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002418 PP.Lex(Tok);
2419 if (Tok.isNot(tok::eod)) {
2420 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2421 << "vtordisp";
2422 return;
2423 }
2424
2425 // Enter the annotation.
2426 Token AnnotTok;
2427 AnnotTok.startToken();
2428 AnnotTok.setKind(tok::annot_pragma_ms_vtordisp);
2429 AnnotTok.setLocation(VtorDispLoc);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002430 AnnotTok.setAnnotationEndLoc(EndLoc);
Reid Klecknera4b3b2d2014-02-13 00:44:34 +00002431 AnnotTok.setAnnotationValue(reinterpret_cast<void *>(
Denis Zobnin2290dac2016-04-29 11:27:00 +00002432 static_cast<uintptr_t>((Action << 16) | (Value & 0xFFFF))));
Ilya Biryukov929af672019-05-17 09:32:05 +00002433 PP.EnterToken(AnnotTok, /*IsReinject=*/false);
Reid Klecknerc0dca6d2014-02-12 23:50:26 +00002434}
2435
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002436/// Handle all MS pragmas. Simply forwards the tokens after inserting
Warren Huntc3b18962014-04-08 22:30:47 +00002437/// an annotation token.
2438void PragmaMSPragma::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002439 PragmaIntroducer Introducer, Token &Tok) {
Warren Huntc3b18962014-04-08 22:30:47 +00002440 Token EoF, AnnotTok;
2441 EoF.startToken();
2442 EoF.setKind(tok::eof);
2443 AnnotTok.startToken();
2444 AnnotTok.setKind(tok::annot_pragma_ms_pragma);
2445 AnnotTok.setLocation(Tok.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002446 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
Warren Huntc3b18962014-04-08 22:30:47 +00002447 SmallVector<Token, 8> TokenVector;
2448 // Suck up all of the tokens before the eod.
David Majnemera8f2f1d2015-03-19 00:10:23 +00002449 for (; Tok.isNot(tok::eod); PP.Lex(Tok)) {
Warren Huntc3b18962014-04-08 22:30:47 +00002450 TokenVector.push_back(Tok);
David Majnemera8f2f1d2015-03-19 00:10:23 +00002451 AnnotTok.setAnnotationEndLoc(Tok.getLocation());
2452 }
Alexander Kornienko2a8c18d2018-04-06 15:14:32 +00002453 // Add a sentinel EoF token to the end of the list.
Warren Huntc3b18962014-04-08 22:30:47 +00002454 TokenVector.push_back(EoF);
2455 // We must allocate this array with new because EnterTokenStream is going to
2456 // delete it later.
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +00002457 auto TokenArray = std::make_unique<Token[]>(TokenVector.size());
David Blaikie2eabcc92016-02-09 18:52:09 +00002458 std::copy(TokenVector.begin(), TokenVector.end(), TokenArray.get());
Warren Huntc3b18962014-04-08 22:30:47 +00002459 auto Value = new (PP.getPreprocessorAllocator())
David Blaikie2eabcc92016-02-09 18:52:09 +00002460 std::pair<std::unique_ptr<Token[]>, size_t>(std::move(TokenArray),
2461 TokenVector.size());
Warren Huntc3b18962014-04-08 22:30:47 +00002462 AnnotTok.setAnnotationValue(Value);
Ilya Biryukov929af672019-05-17 09:32:05 +00002463 PP.EnterToken(AnnotTok, /*IsReinject*/ false);
Reid Klecknerd3923aa2014-04-03 19:04:24 +00002464}
2465
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002466/// Handle the Microsoft \#pragma detect_mismatch extension.
Aaron Ballman5d041be2013-06-04 02:07:14 +00002467///
2468/// The syntax is:
2469/// \code
2470/// #pragma detect_mismatch("name", "value")
2471/// \endcode
2472/// Where 'name' and 'value' are quoted strings. The values are embedded in
2473/// the object file and passed along to the linker. If the linker detects a
2474/// mismatch in the object file's values for the given name, a LNK2038 error
2475/// is emitted. See MSDN for more details.
2476void PragmaDetectMismatchHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002477 PragmaIntroducer Introducer,
Aaron Ballman5d041be2013-06-04 02:07:14 +00002478 Token &Tok) {
Nico Webercbbaeb12016-03-02 19:28:54 +00002479 SourceLocation DetectMismatchLoc = Tok.getLocation();
Aaron Ballman5d041be2013-06-04 02:07:14 +00002480 PP.Lex(Tok);
2481 if (Tok.isNot(tok::l_paren)) {
Nico Webercbbaeb12016-03-02 19:28:54 +00002482 PP.Diag(DetectMismatchLoc, diag::err_expected) << tok::l_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00002483 return;
2484 }
2485
2486 // Read the name to embed, which must be a string literal.
2487 std::string NameString;
2488 if (!PP.LexStringLiteral(Tok, NameString,
2489 "pragma detect_mismatch",
Rui Ueyama49a3ad22019-07-16 04:46:31 +00002490 /*AllowMacroExpansion=*/true))
Aaron Ballman5d041be2013-06-04 02:07:14 +00002491 return;
2492
2493 // Read the comma followed by a second string literal.
2494 std::string ValueString;
2495 if (Tok.isNot(tok::comma)) {
2496 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
2497 return;
2498 }
2499
2500 if (!PP.LexStringLiteral(Tok, ValueString, "pragma detect_mismatch",
Rui Ueyama49a3ad22019-07-16 04:46:31 +00002501 /*AllowMacroExpansion=*/true))
Aaron Ballman5d041be2013-06-04 02:07:14 +00002502 return;
2503
2504 if (Tok.isNot(tok::r_paren)) {
Alp Tokerec543272013-12-24 09:48:30 +00002505 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
Aaron Ballman5d041be2013-06-04 02:07:14 +00002506 return;
2507 }
2508 PP.Lex(Tok); // Eat the r_paren.
2509
2510 if (Tok.isNot(tok::eod)) {
2511 PP.Diag(Tok.getLocation(), diag::err_pragma_detect_mismatch_malformed);
2512 return;
2513 }
2514
Reid Kleckner71966c92014-02-20 23:37:45 +00002515 // If the pragma is lexically sound, notify any interested PPCallbacks.
2516 if (PP.getPPCallbacks())
Nico Webercbbaeb12016-03-02 19:28:54 +00002517 PP.getPPCallbacks()->PragmaDetectMismatch(DetectMismatchLoc, NameString,
Reid Kleckner71966c92014-02-20 23:37:45 +00002518 ValueString);
2519
Nico Webercbbaeb12016-03-02 19:28:54 +00002520 Actions.ActOnPragmaDetectMismatch(DetectMismatchLoc, NameString, ValueString);
Aaron Ballman5d041be2013-06-04 02:07:14 +00002521}
2522
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002523/// Handle the microsoft \#pragma comment extension.
Reid Kleckner002562a2013-05-06 21:02:12 +00002524///
2525/// The syntax is:
2526/// \code
2527/// #pragma comment(linker, "foo")
2528/// \endcode
2529/// 'linker' is one of five identifiers: compiler, exestr, lib, linker, user.
2530/// "foo" is a string, which is fully macro expanded, and permits string
2531/// concatenation, embedded escape characters etc. See MSDN for more details.
2532void PragmaCommentHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002533 PragmaIntroducer Introducer,
Reid Kleckner002562a2013-05-06 21:02:12 +00002534 Token &Tok) {
2535 SourceLocation CommentLoc = Tok.getLocation();
2536 PP.Lex(Tok);
2537 if (Tok.isNot(tok::l_paren)) {
2538 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
2539 return;
2540 }
2541
2542 // Read the identifier.
2543 PP.Lex(Tok);
2544 if (Tok.isNot(tok::identifier)) {
2545 PP.Diag(CommentLoc, diag::err_pragma_comment_malformed);
2546 return;
2547 }
2548
2549 // Verify that this is one of the 5 whitelisted options.
Reid Klecknere43f0fe2013-05-08 13:44:39 +00002550 IdentifierInfo *II = Tok.getIdentifierInfo();
Nico Weber66220292016-03-02 17:28:48 +00002551 PragmaMSCommentKind Kind =
2552 llvm::StringSwitch<PragmaMSCommentKind>(II->getName())
2553 .Case("linker", PCK_Linker)
2554 .Case("lib", PCK_Lib)
2555 .Case("compiler", PCK_Compiler)
2556 .Case("exestr", PCK_ExeStr)
2557 .Case("user", PCK_User)
2558 .Default(PCK_Unknown);
2559 if (Kind == PCK_Unknown) {
Reid Kleckner002562a2013-05-06 21:02:12 +00002560 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_unknown_kind);
2561 return;
2562 }
2563
Saleem Abdulrasoolfd4db532018-02-07 01:46:46 +00002564 if (PP.getTargetInfo().getTriple().isOSBinFormatELF() && Kind != PCK_Lib) {
2565 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
2566 << II->getName();
2567 return;
2568 }
2569
Yunzhong Gao99efc032015-03-23 20:41:42 +00002570 // On PS4, issue a warning about any pragma comments other than
2571 // #pragma comment lib.
Nico Weber66220292016-03-02 17:28:48 +00002572 if (PP.getTargetInfo().getTriple().isPS4() && Kind != PCK_Lib) {
Yunzhong Gao99efc032015-03-23 20:41:42 +00002573 PP.Diag(Tok.getLocation(), diag::warn_pragma_comment_ignored)
2574 << II->getName();
2575 return;
2576 }
2577
Reid Kleckner002562a2013-05-06 21:02:12 +00002578 // Read the optional string if present.
2579 PP.Lex(Tok);
2580 std::string ArgumentString;
2581 if (Tok.is(tok::comma) && !PP.LexStringLiteral(Tok, ArgumentString,
2582 "pragma comment",
Rui Ueyama49a3ad22019-07-16 04:46:31 +00002583 /*AllowMacroExpansion=*/true))
Reid Kleckner002562a2013-05-06 21:02:12 +00002584 return;
2585
Reid Klecknere43f0fe2013-05-08 13:44:39 +00002586 // FIXME: warn that 'exestr' is deprecated.
Reid Kleckner002562a2013-05-06 21:02:12 +00002587 // FIXME: If the kind is "compiler" warn if the string is present (it is
2588 // ignored).
Reid Klecknere43f0fe2013-05-08 13:44:39 +00002589 // The MSDN docs say that "lib" and "linker" require a string and have a short
2590 // whitelist of linker options they support, but in practice MSVC doesn't
2591 // issue a diagnostic. Therefore neither does clang.
Reid Kleckner002562a2013-05-06 21:02:12 +00002592
2593 if (Tok.isNot(tok::r_paren)) {
2594 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
2595 return;
2596 }
2597 PP.Lex(Tok); // eat the r_paren.
2598
2599 if (Tok.isNot(tok::eod)) {
2600 PP.Diag(Tok.getLocation(), diag::err_pragma_comment_malformed);
2601 return;
2602 }
2603
Reid Kleckner71966c92014-02-20 23:37:45 +00002604 // If the pragma is lexically sound, notify any interested PPCallbacks.
2605 if (PP.getPPCallbacks())
2606 PP.getPPCallbacks()->PragmaComment(CommentLoc, II, ArgumentString);
2607
Nico Weber66220292016-03-02 17:28:48 +00002608 Actions.ActOnPragmaMSComment(CommentLoc, Kind, ArgumentString);
Reid Kleckner002562a2013-05-06 21:02:12 +00002609}
Dario Domizioli13a0a382014-05-23 12:13:25 +00002610
2611// #pragma clang optimize off
2612// #pragma clang optimize on
Fangrui Song6907ce22018-07-30 19:24:48 +00002613void PragmaOptimizeHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002614 PragmaIntroducer Introducer,
2615 Token &FirstToken) {
Dario Domizioli13a0a382014-05-23 12:13:25 +00002616 Token Tok;
2617 PP.Lex(Tok);
2618 if (Tok.is(tok::eod)) {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002619 PP.Diag(Tok.getLocation(), diag::err_pragma_missing_argument)
Mark Heffernan450c2382014-07-23 17:31:31 +00002620 << "clang optimize" << /*Expected=*/true << "'on' or 'off'";
Dario Domizioli13a0a382014-05-23 12:13:25 +00002621 return;
2622 }
2623 if (Tok.isNot(tok::identifier)) {
2624 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
2625 << PP.getSpelling(Tok);
2626 return;
2627 }
2628 const IdentifierInfo *II = Tok.getIdentifierInfo();
2629 // The only accepted values are 'on' or 'off'.
2630 bool IsOn = false;
2631 if (II->isStr("on")) {
2632 IsOn = true;
2633 } else if (!II->isStr("off")) {
2634 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_invalid_argument)
2635 << PP.getSpelling(Tok);
2636 return;
2637 }
2638 PP.Lex(Tok);
Fangrui Song6907ce22018-07-30 19:24:48 +00002639
Dario Domizioli13a0a382014-05-23 12:13:25 +00002640 if (Tok.isNot(tok::eod)) {
2641 PP.Diag(Tok.getLocation(), diag::err_pragma_optimize_extra_argument)
2642 << PP.getSpelling(Tok);
2643 return;
2644 }
Eli Bendersky06a40422014-06-06 20:31:48 +00002645
2646 Actions.ActOnPragmaOptimize(IsOn, FirstToken.getLocation());
2647}
2648
Adam Nemet60d32642017-04-04 21:18:36 +00002649namespace {
2650/// Used as the annotation value for tok::annot_pragma_fp.
2651struct TokFPAnnotValue {
2652 enum FlagKinds { Contract };
2653 enum FlagValues { On, Off, Fast };
2654
2655 FlagKinds FlagKind;
2656 FlagValues FlagValue;
2657};
2658} // end anonymous namespace
2659
2660void PragmaFPHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002661 PragmaIntroducer Introducer, Token &Tok) {
Adam Nemet60d32642017-04-04 21:18:36 +00002662 // fp
2663 Token PragmaName = Tok;
2664 SmallVector<Token, 1> TokenList;
2665
2666 PP.Lex(Tok);
2667 if (Tok.isNot(tok::identifier)) {
2668 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
2669 << /*MissingOption=*/true << "";
2670 return;
2671 }
2672
2673 while (Tok.is(tok::identifier)) {
2674 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
2675
2676 auto FlagKind =
2677 llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagKinds>>(
2678 OptionInfo->getName())
2679 .Case("contract", TokFPAnnotValue::Contract)
2680 .Default(None);
2681 if (!FlagKind) {
2682 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option)
2683 << /*MissingOption=*/false << OptionInfo;
2684 return;
2685 }
2686 PP.Lex(Tok);
2687
2688 // Read '('
2689 if (Tok.isNot(tok::l_paren)) {
2690 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
2691 return;
2692 }
2693 PP.Lex(Tok);
2694
2695 if (Tok.isNot(tok::identifier)) {
2696 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
2697 << PP.getSpelling(Tok) << OptionInfo->getName();
2698 return;
2699 }
2700 const IdentifierInfo *II = Tok.getIdentifierInfo();
2701
2702 auto FlagValue =
2703 llvm::StringSwitch<llvm::Optional<TokFPAnnotValue::FlagValues>>(
2704 II->getName())
2705 .Case("on", TokFPAnnotValue::On)
2706 .Case("off", TokFPAnnotValue::Off)
2707 .Case("fast", TokFPAnnotValue::Fast)
2708 .Default(llvm::None);
2709
2710 if (!FlagValue) {
2711 PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument)
2712 << PP.getSpelling(Tok) << OptionInfo->getName();
2713 return;
2714 }
2715 PP.Lex(Tok);
2716
2717 // Read ')'
2718 if (Tok.isNot(tok::r_paren)) {
2719 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
2720 return;
2721 }
2722 PP.Lex(Tok);
2723
2724 auto *AnnotValue = new (PP.getPreprocessorAllocator())
2725 TokFPAnnotValue{*FlagKind, *FlagValue};
2726 // Generate the loop hint token.
2727 Token FPTok;
2728 FPTok.startToken();
2729 FPTok.setKind(tok::annot_pragma_fp);
2730 FPTok.setLocation(PragmaName.getLocation());
2731 FPTok.setAnnotationEndLoc(PragmaName.getLocation());
2732 FPTok.setAnnotationValue(reinterpret_cast<void *>(AnnotValue));
2733 TokenList.push_back(FPTok);
2734 }
2735
2736 if (Tok.isNot(tok::eod)) {
2737 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2738 << "clang fp";
2739 return;
2740 }
2741
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +00002742 auto TokenArray = std::make_unique<Token[]>(TokenList.size());
Adam Nemet60d32642017-04-04 21:18:36 +00002743 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
2744
2745 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
Ilya Biryukov929af672019-05-17 09:32:05 +00002746 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
Adam Nemet60d32642017-04-04 21:18:36 +00002747}
2748
2749void Parser::HandlePragmaFP() {
2750 assert(Tok.is(tok::annot_pragma_fp));
2751 auto *AnnotValue =
2752 reinterpret_cast<TokFPAnnotValue *>(Tok.getAnnotationValue());
2753
2754 LangOptions::FPContractModeKind FPC;
2755 switch (AnnotValue->FlagValue) {
2756 case TokFPAnnotValue::On:
2757 FPC = LangOptions::FPC_On;
2758 break;
2759 case TokFPAnnotValue::Fast:
2760 FPC = LangOptions::FPC_Fast;
2761 break;
2762 case TokFPAnnotValue::Off:
2763 FPC = LangOptions::FPC_Off;
2764 break;
2765 }
2766
2767 Actions.ActOnPragmaFPContract(FPC);
Richard Smithaf3b3252017-05-18 19:21:48 +00002768 ConsumeAnnotationToken();
Adam Nemet60d32642017-04-04 21:18:36 +00002769}
2770
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002771/// Parses loop or unroll pragma hint value and fills in Info.
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002772static bool ParseLoopHintValue(Preprocessor &PP, Token &Tok, Token PragmaName,
2773 Token Option, bool ValueInParens,
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002774 PragmaLoopHintInfo &Info) {
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002775 SmallVector<Token, 1> ValueList;
2776 int OpenParens = ValueInParens ? 1 : 0;
2777 // Read constant expression.
2778 while (Tok.isNot(tok::eod)) {
2779 if (Tok.is(tok::l_paren))
2780 OpenParens++;
2781 else if (Tok.is(tok::r_paren)) {
2782 OpenParens--;
2783 if (OpenParens == 0 && ValueInParens)
2784 break;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002785 }
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002786
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002787 ValueList.push_back(Tok);
2788 PP.Lex(Tok);
2789 }
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002790
2791 if (ValueInParens) {
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002792 // Read ')'
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002793 if (Tok.isNot(tok::r_paren)) {
2794 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
2795 return true;
2796 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002797 PP.Lex(Tok);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002798 }
2799
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002800 Token EOFTok;
2801 EOFTok.startToken();
2802 EOFTok.setKind(tok::eof);
2803 EOFTok.setLocation(Tok.getLocation());
2804 ValueList.push_back(EOFTok); // Terminates expression for parsing.
2805
Benjamin Kramerfa7f8552015-08-05 09:39:57 +00002806 Info.Toks = llvm::makeArrayRef(ValueList).copy(PP.getPreprocessorAllocator());
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002807
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002808 Info.PragmaName = PragmaName;
2809 Info.Option = Option;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002810 return false;
2811}
2812
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002813/// Handle the \#pragma clang loop directive.
Eli Bendersky06a40422014-06-06 20:31:48 +00002814/// #pragma clang 'loop' loop-hints
2815///
2816/// loop-hints:
2817/// loop-hint loop-hints[opt]
2818///
2819/// loop-hint:
2820/// 'vectorize' '(' loop-hint-keyword ')'
2821/// 'interleave' '(' loop-hint-keyword ')'
Mark Heffernan450c2382014-07-23 17:31:31 +00002822/// 'unroll' '(' unroll-hint-keyword ')'
Sjoerd Meijera48f58c2019-07-25 07:33:13 +00002823/// 'vectorize_predicate' '(' loop-hint-keyword ')'
Eli Bendersky06a40422014-06-06 20:31:48 +00002824/// 'vectorize_width' '(' loop-hint-value ')'
2825/// 'interleave_count' '(' loop-hint-value ')'
Eli Bendersky86483b32014-06-11 17:56:26 +00002826/// 'unroll_count' '(' loop-hint-value ')'
Aaron Ballman9bdf5152019-01-04 17:20:00 +00002827/// 'pipeline' '(' disable ')'
2828/// 'pipeline_initiation_interval' '(' loop-hint-value ')'
Eli Bendersky06a40422014-06-06 20:31:48 +00002829///
2830/// loop-hint-keyword:
2831/// 'enable'
2832/// 'disable'
Tyler Nowicki9d268e12015-06-11 23:23:17 +00002833/// 'assume_safety'
Eli Bendersky06a40422014-06-06 20:31:48 +00002834///
Mark Heffernan450c2382014-07-23 17:31:31 +00002835/// unroll-hint-keyword:
Mark Heffernan397a98d2015-08-10 17:29:39 +00002836/// 'enable'
Mark Heffernan450c2382014-07-23 17:31:31 +00002837/// 'disable'
Mark Heffernan397a98d2015-08-10 17:29:39 +00002838/// 'full'
Mark Heffernan450c2382014-07-23 17:31:31 +00002839///
Eli Bendersky06a40422014-06-06 20:31:48 +00002840/// loop-hint-value:
2841/// constant-expression
2842///
2843/// Specifying vectorize(enable) or vectorize_width(_value_) instructs llvm to
2844/// try vectorizing the instructions of the loop it precedes. Specifying
2845/// interleave(enable) or interleave_count(_value_) instructs llvm to try
2846/// interleaving multiple iterations of the loop it precedes. The width of the
2847/// vector instructions is specified by vectorize_width() and the number of
2848/// interleaved loop iterations is specified by interleave_count(). Specifying a
2849/// value of 1 effectively disables vectorization/interleaving, even if it is
2850/// possible and profitable, and 0 is invalid. The loop vectorizer currently
2851/// only works on inner loops.
2852///
Eli Bendersky86483b32014-06-11 17:56:26 +00002853/// The unroll and unroll_count directives control the concatenation
Mark Heffernan397a98d2015-08-10 17:29:39 +00002854/// unroller. Specifying unroll(enable) instructs llvm to unroll the loop
2855/// completely if the trip count is known at compile time and unroll partially
2856/// if the trip count is not known. Specifying unroll(full) is similar to
2857/// unroll(enable) but will unroll the loop only if the trip count is known at
2858/// compile time. Specifying unroll(disable) disables unrolling for the
2859/// loop. Specifying unroll_count(_value_) instructs llvm to try to unroll the
2860/// loop the number of times indicated by the value.
Eli Bendersky06a40422014-06-06 20:31:48 +00002861void PragmaLoopHintHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002862 PragmaIntroducer Introducer,
Eli Bendersky06a40422014-06-06 20:31:48 +00002863 Token &Tok) {
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002864 // Incoming token is "loop" from "#pragma clang loop".
2865 Token PragmaName = Tok;
Eli Bendersky06a40422014-06-06 20:31:48 +00002866 SmallVector<Token, 1> TokenList;
2867
2868 // Lex the optimization option and verify it is an identifier.
2869 PP.Lex(Tok);
2870 if (Tok.isNot(tok::identifier)) {
2871 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
2872 << /*MissingOption=*/true << "";
2873 return;
2874 }
2875
2876 while (Tok.is(tok::identifier)) {
2877 Token Option = Tok;
2878 IdentifierInfo *OptionInfo = Tok.getIdentifierInfo();
2879
Eli Bendersky86483b32014-06-11 17:56:26 +00002880 bool OptionValid = llvm::StringSwitch<bool>(OptionInfo->getName())
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002881 .Case("vectorize", true)
2882 .Case("interleave", true)
2883 .Case("unroll", true)
Adam Nemet2de463e2016-06-14 12:04:26 +00002884 .Case("distribute", true)
Sjoerd Meijera48f58c2019-07-25 07:33:13 +00002885 .Case("vectorize_predicate", true)
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002886 .Case("vectorize_width", true)
2887 .Case("interleave_count", true)
2888 .Case("unroll_count", true)
Aaron Ballman9bdf5152019-01-04 17:20:00 +00002889 .Case("pipeline", true)
2890 .Case("pipeline_initiation_interval", true)
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002891 .Default(false);
Eli Bendersky86483b32014-06-11 17:56:26 +00002892 if (!OptionValid) {
Eli Bendersky06a40422014-06-06 20:31:48 +00002893 PP.Diag(Tok.getLocation(), diag::err_pragma_loop_invalid_option)
2894 << /*MissingOption=*/false << OptionInfo;
2895 return;
2896 }
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002897 PP.Lex(Tok);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002898
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002899 // Read '('
2900 if (Tok.isNot(tok::l_paren)) {
2901 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002902 return;
2903 }
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002904 PP.Lex(Tok);
2905
2906 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2907 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, /*ValueInParens=*/true,
2908 *Info))
2909 return;
NAKAMURA Takumidb9552f2014-07-31 01:52:33 +00002910
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002911 // Generate the loop hint token.
Eli Bendersky06a40422014-06-06 20:31:48 +00002912 Token LoopHintTok;
2913 LoopHintTok.startToken();
2914 LoopHintTok.setKind(tok::annot_pragma_loop_hint);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002915 LoopHintTok.setLocation(PragmaName.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00002916 LoopHintTok.setAnnotationEndLoc(PragmaName.getLocation());
Eli Bendersky06a40422014-06-06 20:31:48 +00002917 LoopHintTok.setAnnotationValue(static_cast<void *>(Info));
2918 TokenList.push_back(LoopHintTok);
2919 }
2920
2921 if (Tok.isNot(tok::eod)) {
2922 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2923 << "clang loop";
2924 return;
2925 }
2926
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +00002927 auto TokenArray = std::make_unique<Token[]>(TokenList.size());
David Blaikie2eabcc92016-02-09 18:52:09 +00002928 std::copy(TokenList.begin(), TokenList.end(), TokenArray.get());
Eli Bendersky06a40422014-06-06 20:31:48 +00002929
David Blaikie2eabcc92016-02-09 18:52:09 +00002930 PP.EnterTokenStream(std::move(TokenArray), TokenList.size(),
Ilya Biryukov929af672019-05-17 09:32:05 +00002931 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
Eli Bendersky06a40422014-06-06 20:31:48 +00002932}
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002933
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00002934/// Handle the loop unroll optimization pragmas.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002935/// #pragma unroll
2936/// #pragma unroll unroll-hint-value
2937/// #pragma unroll '(' unroll-hint-value ')'
Mark Heffernanc888e412014-07-24 18:09:38 +00002938/// #pragma nounroll
David Greenc8e39242018-08-01 14:36:12 +00002939/// #pragma unroll_and_jam
2940/// #pragma unroll_and_jam unroll-hint-value
2941/// #pragma unroll_and_jam '(' unroll-hint-value ')'
2942/// #pragma nounroll_and_jam
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002943///
2944/// unroll-hint-value:
2945/// constant-expression
2946///
Mark Heffernanc888e412014-07-24 18:09:38 +00002947/// Loop unrolling hints can be specified with '#pragma unroll' or
2948/// '#pragma nounroll'. '#pragma unroll' can take a numeric argument optionally
2949/// contained in parentheses. With no argument the directive instructs llvm to
2950/// try to unroll the loop completely. A positive integer argument can be
2951/// specified to indicate the number of times the loop should be unrolled. To
2952/// maximize compatibility with other compilers the unroll count argument can be
2953/// specified with or without parentheses. Specifying, '#pragma nounroll'
2954/// disables unrolling of the loop.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002955void PragmaUnrollHintHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00002956 PragmaIntroducer Introducer,
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002957 Token &Tok) {
Mark Heffernanc888e412014-07-24 18:09:38 +00002958 // Incoming token is "unroll" for "#pragma unroll", or "nounroll" for
2959 // "#pragma nounroll".
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002960 Token PragmaName = Tok;
2961 PP.Lex(Tok);
2962 auto *Info = new (PP.getPreprocessorAllocator()) PragmaLoopHintInfo;
2963 if (Tok.is(tok::eod)) {
Mark Heffernanc888e412014-07-24 18:09:38 +00002964 // nounroll or unroll pragma without an argument.
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002965 Info->PragmaName = PragmaName;
Aaron Ballmand6807da2014-08-01 12:41:37 +00002966 Info->Option.startToken();
David Greenc8e39242018-08-01 14:36:12 +00002967 } else if (PragmaName.getIdentifierInfo()->getName() == "nounroll" ||
2968 PragmaName.getIdentifierInfo()->getName() == "nounroll_and_jam") {
Mark Heffernanc888e412014-07-24 18:09:38 +00002969 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
David Greenc8e39242018-08-01 14:36:12 +00002970 << PragmaName.getIdentifierInfo()->getName();
Mark Heffernanc888e412014-07-24 18:09:38 +00002971 return;
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002972 } else {
2973 // Unroll pragma with an argument: "#pragma unroll N" or
2974 // "#pragma unroll(N)".
Tyler Nowicki0c9b34b2014-07-31 20:15:14 +00002975 // Read '(' if it exists.
2976 bool ValueInParens = Tok.is(tok::l_paren);
2977 if (ValueInParens)
2978 PP.Lex(Tok);
2979
Aaron Ballmand0b090d2014-08-01 12:20:20 +00002980 Token Option;
2981 Option.startToken();
2982 if (ParseLoopHintValue(PP, Tok, PragmaName, Option, ValueInParens, *Info))
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002983 return;
2984
2985 // In CUDA, the argument to '#pragma unroll' should not be contained in
2986 // parentheses.
2987 if (PP.getLangOpts().CUDA && ValueInParens)
Tyler Nowickic724a83e2014-10-12 20:46:07 +00002988 PP.Diag(Info->Toks[0].getLocation(),
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002989 diag::warn_pragma_unroll_cuda_value_in_parens);
2990
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00002991 if (Tok.isNot(tok::eod)) {
2992 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
2993 << "unroll";
2994 return;
2995 }
2996 }
2997
2998 // Generate the hint token.
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +00002999 auto TokenArray = std::make_unique<Token[]>(1);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003000 TokenArray[0].startToken();
3001 TokenArray[0].setKind(tok::annot_pragma_loop_hint);
3002 TokenArray[0].setLocation(PragmaName.getLocation());
David Majnemera8f2f1d2015-03-19 00:10:23 +00003003 TokenArray[0].setAnnotationEndLoc(PragmaName.getLocation());
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003004 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
David Blaikie2eabcc92016-02-09 18:52:09 +00003005 PP.EnterTokenStream(std::move(TokenArray), 1,
Ilya Biryukov929af672019-05-17 09:32:05 +00003006 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
Mark Heffernanbd26f5e2014-07-21 18:08:34 +00003007}
Reid Kleckner3f1ec622016-09-07 16:38:32 +00003008
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003009/// Handle the Microsoft \#pragma intrinsic extension.
Reid Kleckner3f1ec622016-09-07 16:38:32 +00003010///
3011/// The syntax is:
3012/// \code
3013/// #pragma intrinsic(memset)
3014/// #pragma intrinsic(strlen, memcpy)
3015/// \endcode
3016///
3017/// Pragma intrisic tells the compiler to use a builtin version of the
3018/// function. Clang does it anyway, so the pragma doesn't really do anything.
3019/// Anyway, we emit a warning if the function specified in \#pragma intrinsic
3020/// isn't an intrinsic in clang and suggest to include intrin.h.
3021void PragmaMSIntrinsicHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00003022 PragmaIntroducer Introducer,
Reid Kleckner3f1ec622016-09-07 16:38:32 +00003023 Token &Tok) {
3024 PP.Lex(Tok);
3025
3026 if (Tok.isNot(tok::l_paren)) {
3027 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen)
3028 << "intrinsic";
3029 return;
3030 }
3031 PP.Lex(Tok);
3032
3033 bool SuggestIntrinH = !PP.isMacroDefined("__INTRIN_H");
3034
3035 while (Tok.is(tok::identifier)) {
3036 IdentifierInfo *II = Tok.getIdentifierInfo();
3037 if (!II->getBuiltinID())
3038 PP.Diag(Tok.getLocation(), diag::warn_pragma_intrinsic_builtin)
3039 << II << SuggestIntrinH;
3040
3041 PP.Lex(Tok);
3042 if (Tok.isNot(tok::comma))
3043 break;
3044 PP.Lex(Tok);
3045 }
3046
3047 if (Tok.isNot(tok::r_paren)) {
3048 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen)
3049 << "intrinsic";
3050 return;
3051 }
3052 PP.Lex(Tok);
3053
3054 if (Tok.isNot(tok::eod))
3055 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3056 << "intrinsic";
3057}
Hans Wennborg1bbe00e2018-03-20 08:53:11 +00003058
3059// #pragma optimize("gsty", on|off)
3060void PragmaMSOptimizeHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00003061 PragmaIntroducer Introducer,
Hans Wennborg1bbe00e2018-03-20 08:53:11 +00003062 Token &Tok) {
3063 SourceLocation StartLoc = Tok.getLocation();
3064 PP.Lex(Tok);
3065
3066 if (Tok.isNot(tok::l_paren)) {
3067 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_lparen) << "optimize";
3068 return;
3069 }
3070 PP.Lex(Tok);
3071
3072 if (Tok.isNot(tok::string_literal)) {
3073 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_string) << "optimize";
3074 return;
3075 }
3076 // We could syntax check the string but it's probably not worth the effort.
3077 PP.Lex(Tok);
3078
3079 if (Tok.isNot(tok::comma)) {
3080 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_comma) << "optimize";
3081 return;
3082 }
3083 PP.Lex(Tok);
3084
3085 if (Tok.is(tok::eod) || Tok.is(tok::r_paren)) {
3086 PP.Diag(Tok.getLocation(), diag::warn_pragma_missing_argument)
3087 << "optimize" << /*Expected=*/true << "'on' or 'off'";
3088 return;
3089 }
3090 IdentifierInfo *II = Tok.getIdentifierInfo();
3091 if (!II || (!II->isStr("on") && !II->isStr("off"))) {
3092 PP.Diag(Tok.getLocation(), diag::warn_pragma_invalid_argument)
3093 << PP.getSpelling(Tok) << "optimize" << /*Expected=*/true
3094 << "'on' or 'off'";
3095 return;
3096 }
3097 PP.Lex(Tok);
3098
3099 if (Tok.isNot(tok::r_paren)) {
3100 PP.Diag(Tok.getLocation(), diag::warn_pragma_expected_rparen) << "optimize";
3101 return;
3102 }
3103 PP.Lex(Tok);
3104
3105 if (Tok.isNot(tok::eod)) {
3106 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3107 << "optimize";
3108 return;
3109 }
3110 PP.Diag(StartLoc, diag::warn_pragma_optimize);
3111}
3112
Justin Lebar67a78a62016-10-08 22:15:58 +00003113void PragmaForceCUDAHostDeviceHandler::HandlePragma(
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00003114 Preprocessor &PP, PragmaIntroducer Introducer, Token &Tok) {
Justin Lebar67a78a62016-10-08 22:15:58 +00003115 Token FirstTok = Tok;
3116
3117 PP.Lex(Tok);
3118 IdentifierInfo *Info = Tok.getIdentifierInfo();
3119 if (!Info || (!Info->isStr("begin") && !Info->isStr("end"))) {
3120 PP.Diag(FirstTok.getLocation(),
3121 diag::warn_pragma_force_cuda_host_device_bad_arg);
3122 return;
3123 }
3124
3125 if (Info->isStr("begin"))
3126 Actions.PushForceCUDAHostDevice();
3127 else if (!Actions.PopForceCUDAHostDevice())
3128 PP.Diag(FirstTok.getLocation(),
3129 diag::err_pragma_cannot_end_force_cuda_host_device);
3130
3131 PP.Lex(Tok);
3132 if (!Tok.is(tok::eod))
3133 PP.Diag(FirstTok.getLocation(),
3134 diag::warn_pragma_force_cuda_host_device_bad_arg);
3135}
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003136
Adrian Prantl9fc8faf2018-05-09 01:00:01 +00003137/// Handle the #pragma clang attribute directive.
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003138///
3139/// The syntax is:
3140/// \code
Erik Pilkington0876cae2018-12-20 22:32:04 +00003141/// #pragma clang attribute push (attribute, subject-set)
Erik Pilkington7d180942018-10-29 17:38:42 +00003142/// #pragma clang attribute push
3143/// #pragma clang attribute (attribute, subject-set)
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003144/// #pragma clang attribute pop
3145/// \endcode
3146///
Erik Pilkington0876cae2018-12-20 22:32:04 +00003147/// There are also 'namespace' variants of push and pop directives. The bare
3148/// '#pragma clang attribute (attribute, subject-set)' version doesn't require a
3149/// namespace, since it always applies attributes to the most recently pushed
3150/// group, regardless of namespace.
3151/// \code
3152/// #pragma clang attribute namespace.push (attribute, subject-set)
3153/// #pragma clang attribute namespace.push
3154/// #pragma clang attribute namespace.pop
3155/// \endcode
3156///
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003157/// The subject-set clause defines the set of declarations which receive the
3158/// attribute. Its exact syntax is described in the LanguageExtensions document
3159/// in Clang's documentation.
3160///
3161/// This directive instructs the compiler to begin/finish applying the specified
3162/// attribute to the set of attribute-specific declarations in the active range
3163/// of the pragma.
3164void PragmaAttributeHandler::HandlePragma(Preprocessor &PP,
Joel E. Dennyddde0ec2019-05-21 23:51:38 +00003165 PragmaIntroducer Introducer,
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003166 Token &FirstToken) {
3167 Token Tok;
3168 PP.Lex(Tok);
3169 auto *Info = new (PP.getPreprocessorAllocator())
3170 PragmaAttributeInfo(AttributesForPragmaAttribute);
3171
Erik Pilkington0876cae2018-12-20 22:32:04 +00003172 // Parse the optional namespace followed by a period.
3173 if (Tok.is(tok::identifier)) {
3174 IdentifierInfo *II = Tok.getIdentifierInfo();
3175 if (!II->isStr("push") && !II->isStr("pop")) {
3176 Info->Namespace = II;
3177 PP.Lex(Tok);
3178
3179 if (!Tok.is(tok::period)) {
3180 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_period)
3181 << II;
3182 return;
3183 }
3184 PP.Lex(Tok);
3185 }
3186 }
3187
Erik Pilkington7d180942018-10-29 17:38:42 +00003188 if (!Tok.isOneOf(tok::identifier, tok::l_paren)) {
3189 PP.Diag(Tok.getLocation(),
3190 diag::err_pragma_attribute_expected_push_pop_paren);
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003191 return;
3192 }
Erik Pilkington7d180942018-10-29 17:38:42 +00003193
3194 // Determine what action this pragma clang attribute represents.
Erik Pilkington0876cae2018-12-20 22:32:04 +00003195 if (Tok.is(tok::l_paren)) {
3196 if (Info->Namespace) {
3197 PP.Diag(Tok.getLocation(),
3198 diag::err_pragma_attribute_namespace_on_attribute);
3199 PP.Diag(Tok.getLocation(),
3200 diag::note_pragma_attribute_namespace_on_attribute);
3201 return;
3202 }
Erik Pilkington7d180942018-10-29 17:38:42 +00003203 Info->Action = PragmaAttributeInfo::Attribute;
Erik Pilkington0876cae2018-12-20 22:32:04 +00003204 } else {
Erik Pilkington7d180942018-10-29 17:38:42 +00003205 const IdentifierInfo *II = Tok.getIdentifierInfo();
3206 if (II->isStr("push"))
3207 Info->Action = PragmaAttributeInfo::Push;
3208 else if (II->isStr("pop"))
3209 Info->Action = PragmaAttributeInfo::Pop;
3210 else {
3211 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_invalid_argument)
3212 << PP.getSpelling(Tok);
3213 return;
3214 }
3215
3216 PP.Lex(Tok);
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003217 }
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003218
3219 // Parse the actual attribute.
Erik Pilkington7d180942018-10-29 17:38:42 +00003220 if ((Info->Action == PragmaAttributeInfo::Push && Tok.isNot(tok::eod)) ||
3221 Info->Action == PragmaAttributeInfo::Attribute) {
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003222 if (Tok.isNot(tok::l_paren)) {
3223 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::l_paren;
3224 return;
3225 }
3226 PP.Lex(Tok);
3227
3228 // Lex the attribute tokens.
3229 SmallVector<Token, 16> AttributeTokens;
3230 int OpenParens = 1;
3231 while (Tok.isNot(tok::eod)) {
3232 if (Tok.is(tok::l_paren))
3233 OpenParens++;
3234 else if (Tok.is(tok::r_paren)) {
3235 OpenParens--;
3236 if (OpenParens == 0)
3237 break;
3238 }
3239
3240 AttributeTokens.push_back(Tok);
3241 PP.Lex(Tok);
3242 }
3243
3244 if (AttributeTokens.empty()) {
3245 PP.Diag(Tok.getLocation(), diag::err_pragma_attribute_expected_attribute);
3246 return;
3247 }
3248 if (Tok.isNot(tok::r_paren)) {
3249 PP.Diag(Tok.getLocation(), diag::err_expected) << tok::r_paren;
3250 return;
3251 }
3252 SourceLocation EndLoc = Tok.getLocation();
3253 PP.Lex(Tok);
3254
3255 // Terminate the attribute for parsing.
3256 Token EOFTok;
3257 EOFTok.startToken();
3258 EOFTok.setKind(tok::eof);
3259 EOFTok.setLocation(EndLoc);
3260 AttributeTokens.push_back(EOFTok);
3261
3262 Info->Tokens =
3263 llvm::makeArrayRef(AttributeTokens).copy(PP.getPreprocessorAllocator());
3264 }
3265
3266 if (Tok.isNot(tok::eod))
3267 PP.Diag(Tok.getLocation(), diag::warn_pragma_extra_tokens_at_eol)
3268 << "clang attribute";
3269
3270 // Generate the annotated pragma token.
Jonas Devlieghere2b3d49b2019-08-14 23:04:18 +00003271 auto TokenArray = std::make_unique<Token[]>(1);
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003272 TokenArray[0].startToken();
3273 TokenArray[0].setKind(tok::annot_pragma_attribute);
3274 TokenArray[0].setLocation(FirstToken.getLocation());
3275 TokenArray[0].setAnnotationEndLoc(FirstToken.getLocation());
3276 TokenArray[0].setAnnotationValue(static_cast<void *>(Info));
3277 PP.EnterTokenStream(std::move(TokenArray), 1,
Ilya Biryukov929af672019-05-17 09:32:05 +00003278 /*DisableMacroExpansion=*/false, /*IsReinject=*/false);
Alex Lorenz9e7bf162017-04-18 14:33:39 +00003279}